|
|
1.1 root 1: /*
2: * UAE - The Un*x Amiga Emulator
3: *
4: * Amiga interface
5: *
6: * Copyright 1996 Samuel Devulder, Olaf `Olsen' Barthel.
7: */
8:
9: /*
10: * NOTE:
11: * - Im quite unhappy with the color allocation scheme in case of
12: * EXTRA_HALFBRITE...
13: * - It would be better to split this huge file into smaller pieces,
14: * but I think UAE has already too many different files, so please
15: * cope with that big one.
16: */
17:
18: /*
19: * History:
20: * 16/10/96 - Rewrote cybergfx support. (there is still a bug if the memory
21: * is not linear).
22: * 15/11/96 - Inhibit the drive in readdevice().
23: * 23/11/96 - Added call to rexx_init() and gui_handle_event().
24: * 14/12/96 - Added support for graffiti screens.
25: */
26:
27: #define USE_CYBERGFX /* undefine this if you don't have CYBERGFX includes */
28:
29: /****************************************************************************/
30:
31: #include <exec/execbase.h>
32: #include <exec/memory.h>
33: #include <exec/devices.h>
34: #include <exec/io.h>
35:
36: #include <dos/dos.h>
37:
38: #include <graphics/gfxbase.h>
39: #include <graphics/displayinfo.h>
40:
41: #include <libraries/asl.h>
42: #include <intuition/pointerclass.h>
43:
44: #include <devices/trackdisk.h>
45:
46: #include <proto/intuition.h>
47: #include <proto/graphics.h>
48: #include <proto/exec.h>
49: #include <proto/asl.h>
50: #include <proto/alib.h>
51: #include <proto/dos.h>
52:
53: #ifdef USE_CYBERGFX
54: #include <inline/cybergraphics.h>
55: #endif
56:
57: /****************************************************************************/
58:
59: #include "sysconfig.h"
60: #include "sysdeps.h"
61:
62: #include <ctype.h>
63: #include <signal.h>
64:
65: /****************************************************************************/
66:
67: #include "uae.h"
68: #include "config.h"
69: #include "options.h"
70: #include "../include/memory.h"
71: #include "custom.h"
72: #include "readcpu.h"
73: #include "newcpu.h"
74: #include "xwin.h"
75: #include "keyboard.h"
76: #include "keybuf.h"
77: #include "disk.h"
78: #include "debug.h"
79: #include "gui.h"
80:
81: /****************************************************************************/
82:
83: #define use_dither (!no_xhair)
84:
85: static int need_dither; /* well.. guess :-) */
86: static int use_low_bandwidth; /* this will redraw only needed places */
87: static int use_cyb; /* this is for cybergfx */
88: static int use_graffiti;
89:
90: xcolnr xcolors[4096];
91:
92: /* Keyboard and mouse */
93:
94: static int keystate[256];
95:
96: int buttonstate[3];
97: int lastmx, lastmy;
98: int newmousecounters;
99:
100: static int inwindow;
101:
102: static char *oldpixbuf;
103:
104: struct vidbuf_description gfxvidinfo;
105:
106: /****************************************************************************/
107: /*
108: * prototypes & global vars
109: */
110: struct IntuitionBase *IntuitionBase;
111: struct GfxBase *GfxBase;
112: struct Library *AslBase;
113: struct Library *CyberGfxBase;
114:
115: static UBYTE *Line;
116: static struct RastPort *RP;
117: static struct Screen *S;
118: static struct Window *W;
119: static struct RastPort *TempRPort;
120: static struct BitMap *BitMap;
121: static struct ColorMap *CM;
122: static Object *Pointer; /* for os 39 */
123: static UWORD *Sprite;
124:
125: static int os39; /* kick 39 present */
126: static int usepub; /* use public screen */
127: static int halfv; /* halve height for non interlaced screen */
128: static int usecyb; /* use cybergraphics.library */
129: static int is_halfbrite;
130:
131: static int get_color_failed;
132: static int maxpen;
133: static UBYTE pen[256];
134:
135: static struct BitMap *myAllocBitMap(ULONG,ULONG,ULONG,ULONG,struct BitMap *);
136: static void set_title(void);
137: static void myFreeBitMap(struct BitMap *);
138: static LONG ObtainColor(ULONG, ULONG, ULONG);
139: static void ReleaseColors(void);
140: static void DoSizeWindow(struct Window *,int,int);
141: static void disk_hotkeys(void);
142: static void graffiti_SetRGB(int,int,int,int);
143: static void graffiti_WritePixelLine8(int,int,short,char*);
144:
145: /****************************************************************************/
146:
147: void main_window_led(int led, int on);
148:
149: extern int rexx_init(void);
150: extern void rexx_exit(void);
151: extern void initpseudodevices(void);
152: extern void closepseudodevices(void);
153: extern char *to_unix_path(char *s);
154: extern char *from_unix_path(char *s);
155: extern void split_dir_file(char *src, char **dir, char **file);
156:
157: /****************************************************************************/
158:
159: static RETSIGTYPE sigbrkhandler(int foo)
160: {
161: activate_debugger();
162: }
163:
164: void setup_brkhandler(void)
165: {
166: struct sigaction sa;
167: sa.sa_handler = sigbrkhandler;
168: sa.sa_flags = 0;
169: sa.sa_flags = SA_RESTART;
170: sigemptyset(&sa.sa_mask);
171: sigaction(SIGINT, &sa, NULL);
172: }
173:
174: /****************************************************************************/
175:
176: __inline__ void flush_line(int y)
177: {
178: int xs = 0, len;
179: int yoffset = y*gfxvidinfo.rowbytes;
180: char *linebuf = gfxvidinfo.bufmem + yoffset;
181: char *src, *dst;
182:
183: if(y<0 || y>=gfx_requested_height) {
184: /* printf("flush_line out of window: %d\n", y); */
185: return;
186: }
187:
188: if(halfv && (y&1)) return;
189:
190: /*
191: * cybergfx bitmap && no dither
192: */
193: if(use_cyb && !need_dither) {
194: APTR handle;
195: char *baseaddr;
196:
197: handle = LockBitMapTags(RP,LBMI_BASEADDRESS,(LONG)&baseaddr,TAG_DONE);
198: if(handle) {
199: CopyMem(linebuf, baseaddr + yoffset, gfxvidinfo.rowbytes);
200: UnLockBitMap(handle);
201: }
202: return;
203: }
204:
205: #if 0
206: if(use_graffiti && !need_dither) {
207: graffiti_WritePixelLine8(0, y, gfxvidinfo.rowbytes, linebuf);
208: }
209: #endif
210:
211: /*
212: * cybergfx && dither \_ LOW_BANDWIDTH and 1 byte per pixel in the output
213: * or standard screen /
214: */
215: len = gfxvidinfo.maxlinetoscr?gfxvidinfo.maxlinetoscr:gfx_requested_width;
216:
217: switch(gfxvidinfo.pixbytes) {
218: case 4:
219: { /* sam: we should not arrive here on the amiga */
220: fprintf(stderr, "Bug in flush_line() !\n");
221: abort();
222: return;
223: } break;
224: case 2:
225: { short *newp = (short *)linebuf;
226: short *oldp = (short *)(oldpixbuf + yoffset);
227: while (*newp++ == *oldp++) if(!--len) return;
228: src = (char *)--newp;
229: dst = (char *)--oldp;
230: newp += len;
231: oldp += len;
232: while (*--newp == *--oldp);
233: len = 1 + (oldp - (short *)dst);
234: xs = (src - linebuf)/2;
235: CopyMem (src, dst, len * 2);
236: } break;
237: case 1:
238: { char *newp = (char *)linebuf;
239: char *oldp = (char *)(oldpixbuf + yoffset);
240: while (*newp++ == *oldp++) if(!--len) return;
241: src = (char *)--newp;
242: dst = (char *)--oldp;
243: newp += len;
244: oldp += len;
245: while (*--newp == *--oldp);
246: len = 1 + (oldp - (char *)dst);
247: xs = (src - linebuf);
248: CopyMem (src, dst, len);
249: } break;
250: default:
251: abort();
252: break;
253: }
254:
255: if(halfv) y>>=1;
256:
257: if (need_dither) {
258: DitherLine(Line, (UWORD *)dst, xs, y, (len+3)&~3, 8);
259: } else CopyMem(dst, Line, len);
260:
261: if (use_cyb) { /* pixbyte == 1 */
262: APTR handle;
263: char *baseaddr;
264:
265: handle = LockBitMapTags(RP,LBMI_BASEADDRESS,(LONG)&baseaddr,TAG_DONE);
266: if(handle) {
267: CopyMem(Line, baseaddr + yoffset + xs, len);
268: UnLockBitMap(handle);
269: }
270: } else if(use_graffiti) {
271: graffiti_WritePixelLine8(xs, y, len, Line);
272: } else WritePixelLine8(RP, xs, y, len, Line, TempRPort);
273: }
274:
275: /****************************************************************************/
276:
277: void flush_block (int ystart, int ystop)
278: {
279: int y;
280: for(y=ystart; y<=ystop; ++y) flush_line(y);
281: }
282:
283: /****************************************************************************/
284:
285: void flush_screen (int ystart, int ystop)
286: {
287: /* WaitBOVP() ? */
288: }
289:
290: /****************************************************************************/
291:
292: static int RPDepth(struct RastPort *RP)
293: {
294: #ifdef USE_CYBERGFX
295: if(use_cyb) return GetCyberMapAttr(RP->BitMap,CYBRMATTR_DEPTH);
296: #endif
297: if(use_graffiti) return 8;
298: return RP->BitMap->Depth;
299: }
300:
301: /****************************************************************************/
302:
303: static int get_color(int r, int g, int b, xcolnr *cnp)
304: {
305: int col;
306:
307: r *= 0x11111111;
308: g *= 0x11111111;
309: b *= 0x11111111;
310: col = ObtainColor(r, g, b);
311:
312: if(col == -1) {
313: get_color_failed = 1;
314: return 0;
315: }
316:
317: *cnp = col;
318: return 1;
319: }
320:
321: /****************************************************************************/
322: /*
323: * FIXME: find a better way to determine closeness of colors (closer to
324: * human perception).
325: */
326: static __inline__ int calc_err(int r1, int g1, int b1,
327: int r2, int g2, int b2)
328: {
329: int err = 0;
330:
331: if((r1>7 && r2<=7) || (r1<=7 && r2>7)) err += 1;
332: if((g1>7 && g2<=7) || (g1<=7 && g2>7)) err += 1;
333: if((b1>7 && b2<=7) || (b1<=7 && b2>7)) err += 1;
334:
335: r1 -= r2; g1 -= g2; b1 -= b2;
336: r1 *= 2; g1 *= 3; b1 *= 1;
337: err += r1*r1 + g1*g1 + b1*b1;
338:
339: return err;
340: }
341:
342: /****************************************************************************/
343:
344: static int get_nearest_color(int r, int g, int b)
345: {
346: int i, best, err, besterr;
347: int colors;
348: int br=0,bg=0,bb=0;
349:
350: best = 0;
351: besterr = calc_err(0,0,0, 15,15,15);
352: colors = is_halfbrite?32:(1<<RPDepth(RP));
353:
354: for(i=0; i<colors; i++ ) {
355: long rgb = GetRGB4(CM, i);
356: int cr, cg, cb;
357:
358: cr = (rgb >> 8) & 15;
359: cg = (rgb >> 4) & 15;
360: cb = (rgb >> 0) & 15;
361:
362: err = calc_err(r,g,b, cr,cg,cb);
363:
364: if(err < besterr) {
365: best = i;
366: besterr = err;
367: br=cr; bg=cg; bb=cb;
368: }
369:
370: if(is_halfbrite) {
371: cr /= 2; cg /= 2; cb /= 2;
372: err = calc_err(r,g,b, cr,cg,cb);
373: if(err < besterr) {
374: best = i + 32;
375: besterr = err;
376: br=cr; bg=cg; bb=cb;
377: }
378: }
379: }
380: return best;
381: }
382:
383: /****************************************************************************/
384:
385: static int init_colors(void)
386: {
387: if (need_dither) {
388: /* first try color allocation */
389: int bitdepth = usepub ? RPDepth(RP) : 8;
390: int maxcol;
391:
392: if(bitdepth>=3)
393: do {
394: get_color_failed = 0;
395: setup_dither(bitdepth, get_color);
396: if(get_color_failed) ReleaseColors();
397: } while(get_color_failed && --bitdepth>=3);
398:
399: if(bitdepth >= 3) {
400: printf("Color dithering with %d bits\n",bitdepth);
401: return 1;
402: }
403:
404: /* if that fail then try grey allocation */
405: maxcol = 1<<(usepub ? RPDepth(RP) : 8);
406:
407: do {
408: get_color_failed = 0;
409: setup_greydither_maxcol(maxcol, get_color);
410: if(get_color_failed) ReleaseColors();
411: } while(get_color_failed && --maxcol>=2);
412:
413: if (maxcol >= 2) {
414: printf("Gray dither with %d shades\n",maxcol);
415: return 1;
416: }
417:
418: return 0; /* everything failed :-( */
419: }
420:
421: /* No dither */
422: switch(RPDepth(RP)) {
423: case 6: if (is_halfbrite) {
424: static int tab[]={
425: 0x000, 0x00f, 0x0f0, 0x0ff, 0x08f, 0x0f8, 0xf00, 0xf0f,
426: 0x80f, 0xff0, 0xfff, 0x88f, 0x8f0, 0x8f8, 0x8ff, 0xf08,
427: 0xf80, 0xf88, 0xf8f, 0xff8, /* end of regular pattern */
428: 0xa00, 0x0a0, 0xaa0, 0x00a, 0xa0a, 0x0aa, 0xaaa,
429: 0xfaa, 0xf6a, 0xa80, 0x06a, 0x6af };
430: int i;
431: for(i=0;i<32;++i) get_color(tab[i]>>8, (tab[i]>>4)&15, tab[i]&15, xcolors);
432: for(i=0;i<4096;++i) xcolors[i] = get_nearest_color(i>>8, (i>>4)&15, i&15);
433: break;
434: }
435:
436: case 1: case 2: case 3: case 4: case 5: case 7: case 8: {
437: int maxcol = 1<<RPDepth(RP);
438:
439: if(maxcol>=8) do {
440: get_color_failed = 0;
441: setup_maxcol(maxcol);
442: alloc_colors256(get_color);
443: if(get_color_failed) ReleaseColors();
444: } while(get_color_failed && --maxcol>=8);
445: else {
446: int i;
447: for(i=0;i<maxcol;++i) {
448: get_color((i*15)/(maxcol-1), (i*15)/(maxcol-1),
449: (i*15)/(maxcol-1), xcolors);
450: }
451: }
452: printf("Using %d colors\n",maxcol);
453: for(maxcol=0;maxcol<4096;++maxcol)
454: xcolors[maxcol] = get_nearest_color(maxcol>>8, (maxcol>>4)&15,
455: maxcol&15);
456: } break;
457:
458: case 15:
459: alloc_colors64k(5,5,5,10,5,0);
460: break;
461:
462: case 16:
463: alloc_colors64k(5,6,5,11,5,0);
464: break;
465:
466: case 24: case 32:
467: alloc_colors64k(8,8,8,16,8,0);
468: break;
469: }
470: return 1;
471: }
472:
473: /****************************************************************************/
474:
475: static void setup_sprite(struct Window *W)
476: {
477: Sprite = AllocVec(4+2, MEMF_CHIP|MEMF_CLEAR);
478: if(!Sprite) {
479: fprintf(stderr, "Warning: Can not alloc sprite buffer !\n");
480: return;
481: }
482: Sprite[2] = 0x8000; Sprite[3] = 0x8000;
483: SetPointer(W, Sprite, 1, 16, -1, 0);
484: }
485:
486: /****************************************************************************/
487:
488: static int setup_customscreen(void)
489: {
490: static struct NewScreen NewScreenStructure = {
491: 0,0, 800,600, 3, 0,1,
492: LACE+HIRES, CUSTOMSCREEN|SCREENQUIET|SCREENBEHIND,
493: NULL, (void*)"UAE", NULL, NULL};
494: static struct NewWindow NewWindowStructure = {
495: 0,0, 800,600, 0,1,
496: IDCMP_MOUSEBUTTONS|IDCMP_RAWKEY|IDCMP_DISKINSERTED|IDCMP_DISKREMOVED|
497: IDCMP_ACTIVEWINDOW|IDCMP_INACTIVEWINDOW|IDCMP_MOUSEMOVE,
498: WFLG_SMART_REFRESH|WFLG_BACKDROP|WFLG_RMBTRAP|WFLG_NOCAREREFRESH|
499: WFLG_BORDERLESS|WFLG_WINDOWACTIVE|WFLG_REPORTMOUSE,
500: NULL, NULL, (void*)"UAE", NULL, NULL, 5,5, 800,600,
501: CUSTOMSCREEN};
502:
503: NewScreenStructure.Width = gfx_requested_width;
504: NewScreenStructure.Height = gfx_requested_height;
505: NewScreenStructure.Depth = os39?8:(gfx_requested_lores?5:4);
506: NewScreenStructure.ViewModes = SPRITES | (gfx_requested_lores ? NULL : HIRES) |
507: (correct_aspect ? LACE : NULL);
508:
509: do S = (void*)OpenScreen(&NewScreenStructure);
510: while(!S && --NewScreenStructure.Depth);
511: if(!S) {
512: fprintf(stderr, "Can't open custom screen !\n");
513: return 0;
514: }
515:
516: CM = S->ViewPort.ColorMap;
517: RP = &S->RastPort;
518:
519: NewWindowStructure.Width = S->Width;
520: NewWindowStructure.Height = S->Height;
521: NewWindowStructure.Screen = S;
522: W = (void*)OpenWindow(&NewWindowStructure);
523: if(!W) {
524: fprintf(stderr, "Can't open window on custom screen !\n");
525: return 0;
526: }
527: setup_sprite(W);
528: return 1;
529: }
530:
531: /****************************************************************************/
532:
533: static int setup_publicscreen(void)
534: {
535: static struct NewWindow NewWindowStructure = {
536: 0,0, 800,600, 0,1,
537: IDCMP_MOUSEBUTTONS|IDCMP_RAWKEY|IDCMP_DISKINSERTED|IDCMP_DISKREMOVED|
538: IDCMP_ACTIVEWINDOW|IDCMP_INACTIVEWINDOW|IDCMP_MOUSEMOVE|
539: IDCMP_CLOSEWINDOW,
540: WFLG_DRAGBAR|WFLG_DEPTHGADGET|WFLG_SMART_REFRESH|WFLG_REPORTMOUSE|
541: WFLG_RMBTRAP|WFLG_GIMMEZEROZERO|WFLG_ACTIVATE|WFLG_NOCAREREFRESH|
542: WFLG_CLOSEGADGET,
543: NULL, NULL, (void*)"UAE", NULL, NULL, 5,5, 800,600,
544: PUBLICSCREEN};
545:
546: S = LockPubScreen(NULL);
547: if(!S) {
548: fprintf(stderr,"No public screen !\n");
549: return 0;
550: }
551:
552: CM = S->ViewPort.ColorMap;
553:
554: halfv = (S->ViewPort.Modes & (HIRES|LACE))==HIRES;
555:
556: NewWindowStructure.Width = gfx_requested_width;
557: NewWindowStructure.Height = gfx_requested_height >> (halfv?1:0);
558: NewWindowStructure.Screen = S;
559:
560: W = (void*)OpenWindow(&NewWindowStructure);
561: UnlockPubScreen(NULL, S);
562: if(!W) {
563: fprintf(stderr,"Can't open window on public screen !\n");
564: CM = NULL;
565: return 0;
566: }
567: DoSizeWindow(W, NewWindowStructure.Width, NewWindowStructure.Height);
568: RP = W->RPort;
569: setup_sprite(W);
570: return 1;
571: }
572:
573: /****************************************************************************/
574:
575: static int setup_userscreen(void)
576: {
577: struct ScreenModeRequester *ScreenRequest;
578: ULONG DisplayID;
579: static struct BitMap PointerBitMap;
580: UWORD *PointerLine;
581: LONG ScreenWidth=0,ScreenHeight=0,Depth=0;
582: UWORD OverscanType=0;
583: BOOL AutoScroll=0;
584:
585: #ifdef USE_CYBERGFX
586: if(!CyberGfxBase) CyberGfxBase = OpenLibrary("cybergraphics.library",40);
587: #endif
588: if(!AslBase) AslBase = OpenLibrary("asl.library",38);
589: if(!AslBase) {
590: fprintf(stderr,"Can't open asl.library v38 !");
591: return 0;
592: }
593:
594: ScreenRequest = AllocAslRequest(ASL_ScreenModeRequest,NULL);
595: if(!ScreenRequest) {
596: fprintf(stderr,"Unable to allocate screen mode requester.\n");
597: return 0;
598: }
599:
600: if(AslRequestTags(ScreenRequest,
601: ASLSM_TitleText, (ULONG)"Select screen display mode",
602: ASLSM_InitialDisplayID, NULL,
603: ASLSM_InitialDisplayDepth, 8,
604: ASLSM_InitialDisplayWidth, gfx_requested_width,
605: ASLSM_InitialDisplayHeight,gfx_requested_height,
606: ASLSM_MinWidth, gfx_requested_width,
607: ASLSM_MinHeight, gfx_requested_height,
608: ASLSM_DoWidth, TRUE,
609: ASLSM_DoHeight, TRUE,
610: ASLSM_DoDepth, TRUE,
611: ASLSM_DoOverscanType, TRUE,
612: ASLSM_PropertyFlags, 0,
613: ASLSM_PropertyMask, DIPF_IS_DUALPF |
614: DIPF_IS_PF2PRI |
615: DIPF_IS_HAM |
616: 0,
617: TAG_DONE)) {
618: ScreenWidth = ScreenRequest->sm_DisplayWidth;
619: ScreenHeight = ScreenRequest->sm_DisplayHeight;
620: Depth = ScreenRequest->sm_DisplayDepth;
621: DisplayID = ScreenRequest->sm_DisplayID;
622: OverscanType = ScreenRequest->sm_OverscanType;
623: AutoScroll = ScreenRequest->sm_AutoScroll;
624: if(ScreenWidth < gfx_requested_width) ScreenWidth = gfx_requested_width;
625: if(ScreenHeight < gfx_requested_height) ScreenHeight = gfx_requested_height;
626: }
627: else DisplayID = INVALID_ID;
628: FreeAslRequest(ScreenRequest);
629:
630: if(DisplayID == (ULONG)INVALID_ID) return 0;
631:
632: #ifdef USE_CYBERGFX
633: if(CyberGfxBase && IsCyberModeID(DisplayID)) use_cyb = 1;
634: #endif
635:
636: S = OpenScreenTags(NULL,
637: SA_DisplayID, DisplayID,
638: SA_Width, ScreenWidth,
639: SA_Height, ScreenHeight,
640: SA_Depth, Depth,
641: SA_Overscan, OverscanType,
642: SA_AutoScroll, AutoScroll,
643: SA_ShowTitle, FALSE,
644: SA_Quiet, TRUE,
645: SA_Behind, TRUE,
646: /* v39 stuff here: */
647: (os39?SA_BackFill:TAG_DONE), (ULONG)LAYERS_NOBACKFILL,
648: SA_SharePens, TRUE,
649: SA_Exclusive, (use_cyb?TRUE:FALSE),
650: SA_Draggable, (use_cyb?FALSE:TRUE),
651: SA_Interleaved, TRUE,
652: TAG_DONE);
653: if(!S) {
654: fprintf(stderr,"Unable to open the screen.\n");
655: return 0;
656: }
657:
658: RP = &S->RastPort;
659: CM = S->ViewPort.ColorMap;
660: is_halfbrite = (S->ViewPort.Modes & EXTRA_HALFBRITE);
661:
662: #ifdef USE_CYBERGFX
663: if(CyberGfxBase && !GetCyberMapAttr(RP->BitMap,CYBRMATTR_ISLINEARMEM)) {
664: fprintf(stderr,"Cybergraphic screen is not in linear memory!\n");
665: CloseScreen(S); S = NULL;
666: use_cyb = 0;
667: return 0;
668: }
669: #endif
670:
671: PointerLine = malloc(4);/* autodocs says it needs not be in chip memory */
672: if(PointerLine) PointerLine[0]=PointerLine[1]=0;
673: InitBitMap(&PointerBitMap,2,16,1);
674: PointerBitMap.Planes[0] = (PLANEPTR)&PointerLine[0];
675: PointerBitMap.Planes[1] = (PLANEPTR)&PointerLine[1];
676:
677: Pointer = NewObject(NULL,POINTERCLASS,
678: POINTERA_BitMap, (ULONG)&PointerBitMap,
679: POINTERA_WordWidth, 1,
680: TAG_DONE);
681: if(!Pointer)
682: fprintf(stderr,"Warning: Unable to allocate blank mouse pointer.\n");
683:
684: W = OpenWindowTags(NULL,
685: WA_Width, S->Width,
686: WA_Height, S->Height,
687: WA_CustomScreen, (ULONG)S,
688: WA_Backdrop, TRUE,
689: WA_Borderless, TRUE,
690: WA_RMBTrap, TRUE,
691: WA_ReportMouse, TRUE,
692: WA_IDCMP, IDCMP_MOUSEBUTTONS|
693: IDCMP_RAWKEY|
694: IDCMP_DISKINSERTED|
695: IDCMP_DISKREMOVED|
696: IDCMP_ACTIVEWINDOW|
697: IDCMP_INACTIVEWINDOW|
698: IDCMP_MOUSEMOVE,
699: (os39?WA_BackFill:TAG_IGNORE), (ULONG)LAYERS_NOBACKFILL,
700: (Pointer?WA_Pointer:TAG_IGNORE), (ULONG)Pointer,
701: TAG_DONE);
702:
703: if(!W) {
704: fprintf(stderr,"Unable to open the window.\n");
705: CloseScreen(S);S=NULL;RP=NULL;CM=NULL;
706: return 0;
707: }
708: if(!Pointer) setup_sprite(W);
709: return 1;
710: }
711:
712: /****************************************************************************/
713:
714: static int setup_graffiti(void)
715: {
716: static struct NewScreen NewScreenStructure = {
717: 0,-8, 800,600, 4, 0,1,
718: HIRES, CUSTOMSCREEN|SCREENQUIET|SCREENBEHIND,
719: NULL, (void*)"UAE", NULL, NULL};
720: static struct NewWindow NewWindowStructure = {
721: 0,0, 800,600, 0,1,
722: IDCMP_MOUSEBUTTONS|IDCMP_RAWKEY|IDCMP_DISKINSERTED|IDCMP_DISKREMOVED|
723: IDCMP_ACTIVEWINDOW|IDCMP_INACTIVEWINDOW|IDCMP_MOUSEMOVE,
724: WFLG_SMART_REFRESH|WFLG_BACKDROP|WFLG_RMBTRAP|WFLG_NOCAREREFRESH|
725: WFLG_BORDERLESS|WFLG_WINDOWACTIVE|WFLG_REPORTMOUSE,
726: NULL, NULL, (void*)"UAE", NULL, NULL, 5,5, 800,600,
727: CUSTOMSCREEN};
728: static short colarr[] = {
729: 0x000,0x001,0x008,0x009,0x080,0x081,0x088,0x089,
730: 0x800,0x801,0x808,0x809,0x880,0x881,0x888,0x889};
731: int i;
732:
733: NewScreenStructure.Width = 2*gfx_requested_width;
734: /* I leave 8 extra lines for palette & mode: */
735: NewScreenStructure.Height = gfx_requested_height+8;
736: NewScreenStructure.Depth = 4;
737: NewScreenStructure.ViewModes = HIRES|GENLOCK_AUDIO|GENLOCK_VIDEO;
738:
739: S = (void*)OpenScreen(&NewScreenStructure);
740: if(!S) {
741: fprintf(stderr, "Can't open graffiti screen !\n");
742: return 0;
743: }
744:
745: for(i=0;i<15;++i) {
746: unsigned int rgb = colarr[i];
747: SetRGB4(&S->ViewPort,i,(rgb>>8)&15,(rgb>>4)&15,rgb&15);
748: }
749:
750: CM = S->ViewPort.ColorMap;
751: RP = &S->RastPort;
752:
753: NewWindowStructure.Width = S->Width;
754: NewWindowStructure.Height = S->Height;
755: NewWindowStructure.Screen = S;
756: W = (void*)OpenWindow(&NewWindowStructure);
757: if(!W) {
758: fprintf(stderr, "Can't open window on graffiti screen !\n");
759: return 0;
760: }
761: setup_sprite(W);
762: {
763: /* make sure cmd part is cleared */
764: int d;
765: for(d = 0;d < 4; ++d) {
766: short *p;
767: int i;
768: p = (void*)RP->BitMap->Planes[d];
769: for(i=0;i<40*7;++i) p[i] = 0;
770: }
771: /* set graffiti mode to lores */
772: *((short*)RP->BitMap->Planes[3]+8*40-1) = 0x0800;
773: for(d=0;d<256;++d) graffiti_SetRGB(d,0,0,0);
774: }
775:
776: return 1;
777: }
778:
779: /****************************************************************************/
780:
781: int graphics_init(void)
782: {
783: int i,bitdepth;
784:
785: use_low_bandwidth = 0;
786: need_dither = 0;
787: use_cyb = 0;
788:
789: if (gfx_requested_width < 320)
790: gfx_requested_width = 320;
791: if (gfx_requested_height < 200)
792: gfx_requested_height = 200;
793: gfx_requested_width += 7;
794: gfx_requested_width &= ~7;
795:
796: gfxvidinfo.maxlinetoscr = gfx_requested_width;
797: gfxvidinfo.maxline = gfx_requested_height;
798:
799: if(color_mode == 3) {
800: gfx_requested_width = 320;
801: gfx_requested_height = 320;
802: gfx_requested_lores = 1;
803: } /* graffiti */
804:
805: if(SysBase->LibNode.lib_Version < 36) {
806: fprintf(stderr, "UAE needs OS 2.0+ !\n");
807: return 0;
808: }
809: os39 = (SysBase->LibNode.lib_Version>=39);
810:
811: atexit(graphics_leave);
812:
813: IntuitionBase = (void*)OpenLibrary("intuition.library",0L);
814: if(!IntuitionBase) {
815: fprintf(stderr,"No intuition.library ?\n");
816: return 0;
817: }
818: GfxBase = (void*)OpenLibrary("graphics.library",0L);
819: if(!GfxBase) {
820: fprintf(stderr,"No graphics.library ?\n");
821: return 0;
822: }
823:
824: switch(color_mode) {
825: case 3:
826: if(setup_graffiti()) {use_graffiti = 1;break;}
827: fprintf(stderr,"Asking user for screen...\n");
828: /* fall trough */
829: case 2:
830: if(setup_userscreen()) break;
831: fprintf(stderr,"Trying on public screen...\n");
832: /* fall trough */
833: case 1:
834: is_halfbrite = 0;
835: if(setup_publicscreen()) {usepub = 1;break;}
836: fprintf(stderr,"Trying on custom screen...\n");
837: /* fall trough */
838: case 0:
839: default:
840: if(!setup_customscreen()) return 0;
841: break;
842: }
843:
844: Line = AllocVec((gfx_requested_width + 15) & ~15,MEMF_ANY|MEMF_PUBLIC);
845: if(!Line) {
846: fprintf(stderr,"Unable to allocate raster buffer.\n");
847: return 0;
848: }
849: BitMap = myAllocBitMap(gfx_requested_width,1,8,BMF_CLEAR|BMF_MINPLANES,RP->BitMap);
850: if(!BitMap) {
851: fprintf(stderr,"Unable to allocate BitMap.\n");
852: return 0;
853: }
854: TempRPort = AllocVec(sizeof(struct RastPort),MEMF_ANY|MEMF_PUBLIC);
855: if(!TempRPort) {
856: fprintf(stderr,"Unable to allocate RastPort.\n");
857: return 0;
858: }
859: CopyMem(RP,TempRPort,sizeof(struct RastPort));
860: TempRPort->Layer = NULL;
861: TempRPort->BitMap = BitMap;
862:
863: if(usepub) set_title();
864:
865: bitdepth = RPDepth(RP);
866: if(bitdepth <= 8) {
867: /* chunk2planar is slow so we define use_low_bandwidth for all modes
868: except cybergraphics modes */
869: use_low_bandwidth = 1;
870: need_dither = use_dither || (bitdepth<=1);
871: gfxvidinfo.pixbytes = need_dither?2:1;
872: } else {
873: /* Cybergfx mode */
874: gfxvidinfo.pixbytes = (bitdepth == 24 || bitdepth == 32 ? 4
875: : bitdepth == 12 || bitdepth == 16 ? 2
876: : 1);
877: }
878:
879: if (!use_cyb) {
880: gfxvidinfo.rowbytes = gfxvidinfo.pixbytes * gfx_requested_width;
881: gfxvidinfo.bufmem = (char *)calloc(gfxvidinfo.rowbytes, gfx_requested_height+1);
882: /* ^^ */
883: /* This is because DitherLine may read one extra row */
884: } else {
885: #ifdef USE_CYBERGFX
886: gfxvidinfo.rowbytes = GetCyberMapAttr(RP->BitMap,CYBRMATTR_XMOD);
887: gfxvidinfo.pixbytes = GetCyberMapAttr(RP->BitMap,CYBRMATTR_BPPIX);
888: gfxvidinfo.bufmem = (char *)calloc(gfxvidinfo.rowbytes, gfx_requested_height+1);
889: #endif
890: }
891: if(!gfxvidinfo.bufmem) {
892: fprintf(stderr,"Not enough memory.\n");
893: return 0;
894: }
895:
896: if (use_low_bandwidth) {
897: gfxvidinfo.maxblocklines = gfx_requested_height-1; /* it seems to increase the speed */
898: oldpixbuf = (char *)calloc(gfxvidinfo.rowbytes, gfx_requested_height);
899: if(!oldpixbuf) {
900: fprintf(stderr,"Not enough memory for oldpixbuf.\n");
901: return 0;
902: }
903: } else {
904: gfxvidinfo.maxblocklines = 100; /* whatever... */
905: }
906:
907: if (!init_colors())
908: return 0;
909:
910: if(!usepub) ScreenToFront(S);
911:
912: buttonstate[0] = buttonstate[1] = buttonstate[2] = 0;
913: for(i=0; i<256; i++)
914: keystate[i] = 0;
915:
916: lastmx = lastmy = 0;
917: newmousecounters = 0;
918: inwindow = 0;
919:
920: rexx_init();
921: initpseudodevices();
922:
923: return 1;
924: }
925:
926: /****************************************************************************/
927:
928: void graphics_leave(void)
929: {
930: rexx_exit();
931: closepseudodevices();
932: if(BitMap) {
933: WaitBlit();
934: myFreeBitMap(BitMap);
935: BitMap = NULL;
936: }
937: if(TempRPort) {
938: FreeVec(TempRPort);
939: TempRPort = NULL;
940: }
941: if(Line) {
942: FreeVec(Line);
943: Line = NULL;
944: }
945: if(CM) {
946: ReleaseColors();
947: CM = NULL;
948: }
949: if(W) {
950: CloseWindow(W);
951: W = NULL;
952: }
953: if(Sprite) {
954: FreeVec(Sprite);
955: Sprite = NULL;
956: }
957: if(Pointer) {
958: DisposeObject(Pointer);
959: Pointer = NULL;
960: }
961: if(!usepub && S) {
962: CloseScreen(S);
963: S = NULL;
964: }
965: if(AslBase) {
966: CloseLibrary((void*)AslBase);
967: AslBase = NULL;
968: }
969: if(GfxBase) {
970: CloseLibrary((void*)GfxBase);
971: GfxBase = NULL;
972: }
973: if(IntuitionBase) {
974: CloseLibrary((void*)IntuitionBase);
975: IntuitionBase = NULL;
976: }
977: if(CyberGfxBase) {
978: CloseLibrary((void*)CyberGfxBase);
979: CyberGfxBase = NULL;
980: }
981: }
982:
983:
984: /***************************************************************************/
985:
986: void handle_events(void)
987: {
988: struct IntuiMessage *msg;
989: int mx,my,class,code;
990:
991: newmousecounters = 0;
992:
993: /*
994: * This is a hack to simulate ^C as is seems that break_handler
995: * is lost when system() is called.
996: */
997: if(SetSignal(0L, SIGBREAKF_CTRL_C|SIGBREAKF_CTRL_D) &
998: (SIGBREAKF_CTRL_C|SIGBREAKF_CTRL_D)) {
999: activate_debugger();
1000: }
1001:
1002: while((msg=(struct IntuiMessage*)GetMsg(W->UserPort))) {
1003: class = msg->Class;
1004: code = msg->Code;
1005: mx = msg->MouseX;
1006: my = msg->MouseY;
1007: ReplyMsg((struct Message*)msg);
1008:
1009: if(usepub) {
1010: mx -= W->BorderLeft;
1011: my -= W->BorderTop;
1012: }
1013:
1014: if(use_graffiti) {
1015: my -= 8;
1016: }
1017:
1018: switch(class) {
1019: case CLOSEWINDOW:
1020: activate_debugger();
1021: break;
1022:
1023: case RAWKEY: {
1024: int kc = code&127;
1025: int released = code&128?1:0;
1026:
1027: if(released) {
1028: keystate[kc] = 0;
1029: record_key ((kc << 1) | 1);
1030: } else if (!keystate[kc]) {
1031: keystate[kc] = 1;
1032: record_key (kc << 1);
1033: }
1034: } break;
1035:
1036: case MOUSEMOVE:
1037: if(inwindow) {
1038: lastmx = mx >> (use_graffiti?1:0);
1039: lastmy = my << (halfv?1:0);
1040: } break;
1041:
1042: case MOUSEBUTTONS:
1043: if(code==SELECTDOWN) buttonstate[0]=1;
1044: if(code==SELECTUP) buttonstate[0]=0;
1045: if(code==MENUDOWN) buttonstate[2]=1;
1046: if(code==MENUUP) buttonstate[2]=0;
1047: break;
1048:
1049: /* Those 2 could be of some use later. */
1050: case DISKINSERTED:
1051: /*printf("diskinserted(%d)\n",code);*/
1052: break;
1053:
1054: case DISKREMOVED:
1055: /*printf("diskremoved(%d)\n",code);*/
1056: break;
1057:
1058: case ACTIVEWINDOW:
1059: inwindow = 1;
1060: newmousecounters = 1;
1061: /* lastmx = mx >> ((use_graffiti?1:0);
1062: lastmy = my<<(halfv?1:0); */
1063: break;
1064:
1065: case INACTIVEWINDOW:
1066: inwindow = 0;
1067: break;
1068:
1069: default:
1070: fprintf(stderr, "Unknown class: %d\n",class);
1071: break;
1072: }
1073: }
1074: /* "Affengriff" */
1075: if(keystate[AK_CTRL] && keystate[AK_LAMI] && keystate[AK_RAMI])
1076: m68k_reset();
1077:
1078: /* PC-like :-) CTRL-ALT-DEL => reboot */
1079: if(keystate[AK_CTRL] && (keystate[AK_LALT] || keystate[AK_RALT]) &&
1080: keystate[AK_DEL])
1081: m68k_reset();
1082:
1083: /* CTRL+LSHIFT+LALT+F10 on amiga => F12 on X11 */
1084: /* F9 => ScrollLock on X11 (inhibit_frame) */
1085: if(keystate[AK_CTRL] && keystate[AK_LSH] && keystate[AK_LALT]) {
1086: if(keystate[AK_F10]) togglemouse();
1087: if(keystate[AK_F9]) {
1088: inhibit_frame ^= 1;
1089: if(inhibit_frame) printf("display disabled\n");
1090: else printf("display enabled\n");
1091: }
1092: }
1093:
1094: disk_hotkeys();
1095: gui_handle_events();
1096: }
1097:
1098: /***************************************************************************/
1099:
1100: void target_specific_usage(void)
1101: {
1102: printf("\n");
1103: printf("----------------------------------------------------------------------------\n");
1104: printf("AMIGA SPECIFIC USAGE:\n");
1105: printf(" -S n : Sound emulation accuracy (n = 0, 1, 2 or 3)\n"
1106: " For sound emulation, n = 2 is recommended\n");
1107: printf(" -R n : Use n Hz to output sound. Common values are\n"
1108: " 22050 Hz or 44100 Hz\n");
1109: printf(" -B n : Use a sound buffer of n bytes (use small\n"
1110: " values on fast machines)\n");
1111: printf(" -p command : Use command to pipe printer output to.\n");
1112: printf(" -I device : Name of the used serial device (i.e. /dev/ttyS1\n");
1113: printf(" -x : Does not use dithering\n");
1114: printf(" On the amiga, Valid resolution (see -d) are:\n");
1115: printf(" 0, 1, 2 (320x256); 3 (640x512); 4 (800x600).\n");
1116: printf(" And valid color modes (see -H) are:\n");
1117: printf(" 0 => 256 cols max on customscreen;\n");
1118: printf(" 1 => OpenWindow on default public screen;\n");
1119: printf(" 2 => Ask the user to select a screen mode with ASL requester;\n");
1120: printf(" 3 => use a 320x256 graffiti screen.\n");
1121: printf("----------------------------------------------------------------------------\n");
1122: printf("\n");
1123: }
1124:
1125: /***************************************************************************/
1126:
1127: int debuggable(void)
1128: {
1129: return 1;
1130: }
1131:
1132: /***************************************************************************/
1133:
1134: int needmousehack(void)
1135: {
1136: return 1;
1137: }
1138:
1139: /***************************************************************************/
1140:
1141: void LED(int on)
1142: {
1143: }
1144:
1145: /***************************************************************************/
1146:
1147: static int led_state[5];
1148:
1149: static void set_title(void)
1150: {
1151: static char title[80];
1152: static char ScreenTitle[100];
1153:
1154: if(!usepub) return;
1155:
1156: sprintf(title,"UAE - Power: [%c] Drives: [%c] [%c] [%c] [%c]",
1157: led_state[0]?'X':' ',
1158: led_state[1]?'0':' ',
1159: led_state[2]?'1':' ',
1160: led_state[3]?'2':' ',
1161: led_state[4]?'3':' ');
1162:
1163: if(!*ScreenTitle) {
1164: sprintf(ScreenTitle,
1165: "UAE-%d.%d.%d � by Bernd Schmidt & contributors, "
1166: "Amiga Port by Samuel Devulder.",
1167: (version / 100) % 10, (version / 10) % 10, version % 10);
1168: SetWindowTitles(W, title, ScreenTitle);
1169: } else SetWindowTitles(W, title, (char*)-1);
1170: }
1171:
1172: /****************************************************************************/
1173:
1174: void main_window_led(int led, int on) /* is used in amigui.c */
1175: {
1176: if(led>=0 && led<=4) led_state[led] = on;
1177: set_title();
1178: }
1179:
1180: /****************************************************************************/
1181:
1182: static void unrecord(int kc)
1183: {
1184: keystate[kc] = 0;
1185: record_key ((kc << 1) | 1);
1186: }
1187:
1188: /****************************************************************************/
1189:
1190: static void disk_hotkeys(void)
1191: {
1192: struct FileRequester *FileRequest;
1193: char buff[80];
1194: int drive;
1195: char *last_file,*last_dir,*s;
1196:
1197: if(!(keystate[AK_CTRL] && keystate[AK_LALT])) return;
1198:
1199: /* CTRL-LSHIFT-LALT F1-F4 => eject_disk */
1200: if(keystate[AK_LSH]) {
1201: int ok = 0;
1202:
1203: if(keystate[AK_F1]) {ok=1;disk_eject(0);
1204: printf("drive DF0: ejected\n");}
1205: if(keystate[AK_F2]) {ok=1;disk_eject(1);
1206: printf("drive DF1: ejected\n");}
1207: if(keystate[AK_F3]) {ok=1;disk_eject(2);
1208: printf("drive DF2: ejected\n");}
1209: if(keystate[AK_F4]) {ok=1;disk_eject(3);
1210: printf("drive DF3: ejected\n");}
1211:
1212: if(ok) {
1213: unrecord(AK_CTRL);unrecord(AK_LALT);unrecord(AK_LSH);
1214: unrecord(AK_F1);unrecord(AK_F2);
1215: unrecord(AK_F3);unrecord(AK_F4);
1216: }
1217: return;
1218: }
1219:
1220: /* CTRL-LALT F1-F4 => insert_disk */
1221: if(keystate[AK_F1]) {drive = 0;unrecord(AK_F1);}
1222: else if(keystate[AK_F2]) {drive = 1;unrecord(AK_F2);}
1223: else if(keystate[AK_F3]) {drive = 2;unrecord(AK_F3);}
1224: else if(keystate[AK_F4]) {drive = 3;unrecord(AK_F4);}
1225: else return;
1226: unrecord(AK_CTRL);unrecord(AK_LALT);
1227:
1228: switch(drive) {
1229: case 0: last_file = df0; break;
1230: case 1: last_file = df1; break;
1231: case 2: last_file = df2; break;
1232: case 3: last_file = df3; break;
1233: default: return;
1234: }
1235:
1236: split_dir_file(from_unix_path(last_file), &last_dir, &last_file);
1237: if(!last_file) return;
1238: if(!last_dir) return;
1239:
1240: if(!AslBase) AslBase = OpenLibrary("asl.library",36);
1241: if(!AslBase) {
1242: fprintf(stderr,"Can't open asl.library v36 !");
1243: return;
1244: }
1245:
1246: FileRequest = AllocAslRequest(ASL_FileRequest,NULL);
1247: if(!FileRequest) {
1248: fprintf(stderr,"Unable to allocate file requester.\n");
1249: return;
1250: }
1251:
1252: sprintf(buff,"Select file to use for drive DF%d:",drive);
1253: if(AslRequestTags(FileRequest,
1254: use_graffiti?TAG_IGNORE:
1255: ASLFR_Window, (ULONG)W,
1256: ASLFR_TitleText, (ULONG)buff,
1257: ASLFR_InitialDrawer, (ULONG)last_dir,
1258: ASLFR_InitialFile, (ULONG)last_file,
1259: ASLFR_InitialPattern, (ULONG)"(#?.adf#?|df?|?)",
1260: ASLFR_DoPatterns, TRUE,
1261: ASLFR_RejectIcons, TRUE,
1262: TAG_DONE)) {
1263: free(last_file);
1264: last_file = malloc(3 + strlen(FileRequest->fr_Drawer) +
1265: strlen(FileRequest->fr_File));
1266: if((last_file)) {
1267: s = last_file;
1268: strcpy(s,FileRequest->fr_Drawer);
1269: if(*s && !(s[strlen(s)-1]==':' || s[strlen(s)-1]=='/'))
1270: strcat(s,"/");
1271: strcat(s,FileRequest->fr_File);
1272: last_file = to_unix_path(s);free(s);
1273: }
1274: } else {
1275: free(last_file);
1276: last_file = NULL;
1277: }
1278: FreeAslRequest(FileRequest);
1279: free(last_dir);
1280:
1281: if(last_file) {
1282: disk_insert(drive,last_file);
1283: free(last_file);
1284: }
1285: }
1286:
1287: /****************************************************************************/
1288: /*
1289: * Routines for OS2.0 (code taken out of mpeg_play by Michael Balzer)
1290: */
1291: static struct BitMap *myAllocBitMap(ULONG sizex, ULONG sizey, ULONG depth,
1292: ULONG flags, struct BitMap *friend_bitmap)
1293: {
1294: struct BitMap *bm;
1295: unsigned long extra;
1296:
1297: if(os39) return AllocBitMap(sizex, sizey, depth, flags, friend_bitmap);
1298:
1299: extra = (depth > 8) ? depth - 8 : 0;
1300: bm = AllocVec( sizeof *bm + (extra * 4), MEMF_CLEAR );
1301:
1302: if( bm )
1303: {
1304: ULONG i;
1305: InitBitMap(bm, depth, sizex, sizey);
1306: for( i=0; i<depth; i++ )
1307: {
1308: if( !(bm->Planes[i] = AllocRaster(sizex, sizey)) )
1309: {
1310: while(i--) FreeRaster(bm->Planes[i], sizex, sizey);
1311: FreeVec(bm);
1312: bm = 0;
1313: break;
1314: }
1315: }
1316: }
1317: return bm;
1318: }
1319:
1320: /****************************************************************************/
1321:
1322: static void myFreeBitMap(struct BitMap *bm)
1323: {
1324: if(os39) {FreeBitMap(bm);return;}
1325: while(bm->Depth--)
1326: FreeRaster(bm->Planes[bm->Depth], bm->BytesPerRow*8, bm->Rows);
1327: FreeVec(bm);
1328: }
1329:
1330: /****************************************************************************/
1331: /*
1332: * find the best appropriate color return -1 if none is available
1333: */
1334: static LONG ObtainColor(ULONG r,ULONG g,ULONG b)
1335: {
1336: int i, crgb;
1337: int colors;
1338:
1339: if(use_graffiti) {
1340: if(maxpen >= 256) {
1341: fprintf(stderr,"Asking more than 256 colors for graffiti ?\n");
1342: abort();
1343: }
1344: graffiti_SetRGB(maxpen, r>>24, g>>24, b>>24);
1345: return maxpen++;
1346: }
1347:
1348: if(os39 && usepub) {
1349: i = ObtainBestPen(CM,r,g,b,
1350: OBP_Precision, PRECISION_EXACT,
1351: OBP_FailIfBad, TRUE,
1352: TAG_DONE);
1353: if(i != -1) {
1354: if(maxpen<256) pen[maxpen++] = i;
1355: else i = -1;
1356: }
1357: return i;
1358: }
1359:
1360: r >>= 28; g >>= 28; b >>= 28;
1361:
1362: colors = is_halfbrite?32:(1<<RP->BitMap->Depth);
1363:
1364: /* private screen => standard allocation */
1365: if(!usepub) {
1366: if(maxpen >= colors) return -1; /* no more colors available */
1367: SetRGB4(&S->ViewPort, maxpen, r, g, b);
1368: return maxpen++;
1369: }
1370:
1371: /* public => find exact match */
1372: crgb = (r<<8)|(g<<4)|b;
1373: for(i=0; i<colors; i++ ) {
1374: int rgb = GetRGB4(CM, i);
1375: if(rgb == crgb) return i;
1376: }
1377: return -1;
1378: }
1379:
1380: /****************************************************************************/
1381: /*
1382: * free a color entry
1383: */
1384: static void ReleaseColors(void)
1385: {
1386: if(os39 && usepub && CM)
1387: while(maxpen>0) ReleasePen(CM, pen[--maxpen]);
1388: else maxpen = 0;
1389: }
1390:
1391: /****************************************************************************/
1392:
1393: static void DoSizeWindow(struct Window *W,int wi,int he)
1394: {
1395: register int x,y;
1396:
1397: wi += W->BorderRight + W->BorderLeft;
1398: he += W->BorderBottom + W->BorderTop;
1399: x = W->LeftEdge;
1400: y = W->TopEdge;
1401:
1402: if(x + wi >= W->WScreen->Width) x = W->WScreen->Width - wi;
1403: if(y + he >= W->WScreen->Height) y = W->WScreen->Height - he;
1404:
1405: if(x<0 || y<0) {
1406: fprintf(stderr, "Working screen too small to open window (%dx%d)!\n",
1407: wi,he);
1408: return;
1409: }
1410:
1411: x -= W->LeftEdge;
1412: y -= W->TopEdge;
1413: wi -= W->Width;
1414: he -= W->Height;
1415:
1416: if(x|y) MoveWindow(W,x,y);
1417: if(wi|he) SizeWindow(W,wi,he);
1418: }
1419:
1420: /****************************************************************************/
1421: /*
1422: * support code for graffiti card
1423: */
1424: static void graffiti_SetRGB(int i, int r, int g, int b)
1425: {
1426: UWORD **ptr = (void*)RP->BitMap->Planes;
1427:
1428: *(*ptr++ + i) = 0x0406;
1429: *(*ptr++ + i) = (i<<8)|((g>>2)&0x3f);
1430: *(*ptr++ + i) = 0x0606;
1431: *(*ptr + i) = ((r<<6)&0x3f00)|((b>>2)&0x3f);
1432: }
1433:
1434: /****************************************************************************/
1435:
1436: static void graffiti_WritePixelLine8(int x, int y, short len, char *line)
1437: {
1438: #if 0
1439: /* standard code */
1440: char **ptr = (void*)RP->BitMap->Planes;
1441:
1442: y += 8;
1443: x += (y*80)<<2;
1444: while(len--) {
1445: *(ptr[x&3] + (x>>2)) = *line++;
1446: ++x;
1447: }
1448: #else
1449: /* this one must be quite fast for 680x0 processor */
1450: char **ptr;
1451: char *ptr0,*ptr1,*ptr2,*ptr3;
1452: ptr = (void*)RP->BitMap->Planes;
1453: switch(x&3) {
1454: case 0: ptr0=*ptr++; ptr1=*ptr++; ptr2=*ptr++; ptr3=*ptr; break;
1455: case 1: ptr3=*ptr++ + 1; ptr0=*ptr++; ptr1=*ptr++; ptr2=*ptr; break;
1456: case 2: ptr2=*ptr++ + 1; ptr3=*ptr++ + 1; ptr0=*ptr++; ptr1=*ptr; break;
1457: default:
1458: case 3: ptr1=*ptr++ + 1; ptr2=*ptr++ + 1; ptr3=*ptr++ + 1; ptr0=*ptr; break;
1459: }
1460: x >>= 2; x += (80*(y+8));
1461: ptr0 += x; ptr1 += x; ptr2 += x; ptr3 += x;
1462: ++len;
1463: /* full speed here */
1464: while(1) {
1465: if(--len) *ptr0++ = *line++; else break;
1466: if(--len) *ptr1++ = *line++; else break;
1467: if(--len) *ptr2++ = *line++; else break;
1468: if(--len) *ptr3++ = *line++; else break;
1469: }
1470: #endif
1471: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.