|
|
1.1 root 1: /*
2: * UAE - The Un*x Amiga Emulator
3: *
4: * Amiga interface
5: *
6: * Copyright 1996,1997 Samuel Devulder.
7: */
8:
9: /*
10: * NOTE:
11: * - Im quite unhappy with the color allocation scheme in case of
12: * EXTRA_HALFBRITE...
13: */
14:
15: /*
16: * History: (Day/Month/Year)
17: * 16/10/96 - Rewrote cybergfx support. (there is still a bug if the memory
18: * is not linear).
19: * 15/11/96 - Inhibit the drive in readdevice().
20: * 23/11/96 - Added call to rexx_init() and gui_handle_event().
21: * 14/12/96 - Added support for graffiti screens.
22: * 14/02/97 - Now uses SetRGB32() for cybergfx screens.
23: * 15/02/97 - Dump iff file when ENV:UAEIFF is defined.
24: * 25/02/97 - Get rid of cybergfx screen direct access.. Now uses
25: * BltBitMapRastPort(). Thanks to Mats Eirik Hansen for
26: * his patch from which I'm widely inspired.
27: * 10/05/97 - Use OpenWindowTag() for public screen. Uses Zoom,
28: * SimpleRefresh.
29: * 20/08/97 - Removed halfv stuff (use correct_aspect instead).
30: * 21/08/97 - Added HAM support (yeah!).
31: * 05/10/97 - Added drag&drop support.
32: * 13/10/97 - Fixed CyberGFX crash (a missing "return" in flush_line()).
33: * 31/10/97 - Added support for gray output (-T). Added missing "Cyb"
34: * prefix to BitMap=NULL in graphics_leave().
35: * 07/12/97 - New calc_err(). UAE screen (-H2) is now a public screen.
36: */
37:
38: #define USE_CYBERGFX /* undefine this if you don't have CYBERGFX includes */
39:
40: /****************************************************************************/
41:
42: #include <exec/execbase.h>
43: #include <exec/memory.h>
44:
45: #include <dos/dos.h>
46:
47: #include <graphics/gfxbase.h>
48: #include <graphics/displayinfo.h>
49:
50: #include <libraries/asl.h>
51: #include <intuition/pointerclass.h>
52:
53: #include <proto/intuition.h>
54: #include <proto/graphics.h>
55: #include <proto/exec.h>
56: #include <proto/asl.h>
57:
58: #ifdef USE_CYBERGFX
59: #ifdef __SASC
60: #include <cybergraphics/cybergraphics.h>
61: #include <proto/cybergraphics.h>
62: #else
63: #include <inline/cybergraphics.h>
64: #endif
65: #ifndef BMF_SPECIALFMT
66: #define BMF_SPECIALFMT 0x80 /* should be cybergraphics.h but isn't for */
67: /* some strange reason */
68: #endif
69: #endif
70:
71: /****************************************************************************/
72:
73: #include "sysconfig.h"
74: #include "sysdeps.h"
75:
76: #include <ctype.h>
77: #include <signal.h>
78: #ifdef __GNUC__
79: #include <ix.h>
80: #endif
81: #ifdef __SASC
82: extern struct ExecBase *SysBase;
83: #endif
84:
85: /****************************************************************************/
86:
87: #include "config.h"
88: #include "options.h"
89: #include "threaddep/penguin.h"
90: #include "uae.h"
91: #include "memory.h"
92: #include "custom.h"
93: #include "readcpu.h"
94: #include "osdep/memory.h" /* for implicit decl. of get_long() in newcpu.h */
95: #include "newcpu.h"
96: #include "xwin.h"
97: #include "keyboard.h"
98: #include "keybuf.h"
99: #include "gui.h"
100: #include "debug.h"
101: #include "disk.h"
102:
103: #define BitMap Picasso96BitMap /* Argh! */
104: #include "picasso96.h"
105: #undef BitMap
106:
107: /****************************************************************************/
108:
109: #define use_dither (!currprefs.no_xhair)
110: #define use_gray (currprefs.use_mitshm)
111:
112: #define UAEIFF "UAEIFF" /* env: var to trigger iff dump */
113:
114: static int need_dither; /* well.. guess :-) */
115: static int use_low_bandwidth; /* this will redraw only needed places */
116: static int use_cyb; /* this is for cybergfx */
117: static int use_graffiti;
118: static int use_approx_color;
119: int dump_iff;
120:
121: extern xcolnr xcolors[4096];
122:
123: /* Keyboard and mouse */
124:
125: static int keystate[256];
126:
127: extern int buttonstate[3];
128: extern int lastmx, lastmy;
129: extern int newmousecounters;
130:
131: static int inwindow;
132:
133: static char *oldpixbuf;
134:
135: /****************************************************************************/
136: /*
137: * prototypes & global vars
138: */
139: struct IntuitionBase *IntuitionBase;
140: struct GfxBase *GfxBase;
141: struct Library *AslBase;
142: struct Library *CyberGfxBase;
143:
144: static UBYTE *Line;
145: static struct RastPort *RP;
146: static struct Screen *S;
147: static struct Window *W;
148: static struct RastPort *TempRPort;
149: static struct BitMap *BitMap;
150: #ifdef USE_CYBERGFX
151: static struct BitMap *CybBitMap;
152: #endif
153: static struct ColorMap *CM;
154: static Object *Pointer; /* for os 39 */
155: static UWORD *Sprite;
156: static int XOffset,YOffset;
157:
158: static int os39; /* kick 39 present */
159: static int usepub; /* use public screen */
160: static int usecyb; /* use cybergraphics.library */
161: static int is_halfbrite;
162: static int is_ham;
163:
164: static int get_color_failed;
165: static int maxpen;
166: static UBYTE pen[256];
167:
168: static struct BitMap *myAllocBitMap(ULONG,ULONG,ULONG,ULONG,struct BitMap *);
169: static void set_title(void);
170: static void myFreeBitMap(struct BitMap *);
171: static LONG ObtainColor(ULONG, ULONG, ULONG);
172: static void ReleaseColors(void);
173: static int DoSizeWindow(struct Window *,int,int);
174: static void disk_hotkeys(void);
175: static void graffiti_SetRGB(int,int,int,int);
176: static void graffiti_WritePixelLine8(int,int,short,char*);
177: static int SaveIFF(char *filename, struct Screen *scr);
178: static int init_ham(void);
179: static void ham_conv(UWORD *src, UBYTE *buf, UWORD len);
180: static int RPDepth(struct RastPort *RP);
181:
182: /****************************************************************************/
183:
184: void main_window_led(int led, int on);
185:
186: extern int rexx_init(void);
187: extern void rexx_exit(void);
188: extern void initpseudodevices(void);
189: extern void closepseudodevices(void);
190: extern char *to_unix_path(char *s);
191: extern char *from_unix_path(char *s);
192: extern void split_dir_file(char *src, char **dir, char **file);
193: extern void appw_init(struct Window *W);
194: extern void appw_exit(void);
195: extern void appw_events(void);
196:
197: extern int ievent_alive;
198:
199: /****************************************************************************/
200:
201: static RETSIGTYPE sigbrkhandler(int foo)
202: {
203: activate_debugger();
204: }
205:
206: void setup_brkhandler(void)
207: {
208: #ifdef HAVE_SIGACTION
209: struct sigaction sa;
210: sa.sa_handler = (void*)sigbrkhandler;
211: sa.sa_flags = 0;
212: sa.sa_flags = SA_RESTART;
213: sigemptyset(&sa.sa_mask);
214: sigaction(SIGINT, &sa, NULL);
215: #else
216: signal(SIGINT,sigbrkhandler);
217: #endif
218: }
219:
220: /****************************************************************************/
221:
222: extern UBYTE cidx[4][8*4096];
223:
224: __inline__ void flush_line(int y)
225: {
226: int xs = 0, len;
227: int yoffset = y*gfxvidinfo.rowbytes;
228: char *linebuf = gfxvidinfo.bufmem + yoffset;
229: char *src, *dst;
230:
231: if(y<0 || y>=gfxvidinfo.height) {
232: /* printf("flush_line out of window: %d\n", y); */
233: return;
234: }
235:
236: len = gfxvidinfo.width;
237:
238: if(is_ham) {
239: ham_conv((void*)linebuf,Line,len);
240: WritePixelLine8(RP, 0, y, len, Line, TempRPort);
241: return;
242: }
243:
244: #ifdef USE_CYBERGFX
245: /*
246: * cybergfx bitmap && no dither
247: */
248: if(use_cyb && !need_dither) {
249: BltBitMapRastPort(CybBitMap, 0, y,
250: RP, XOffset, YOffset+y,
251: len, 1, 0xc0);
252: /* sam: I'm worried because BltBitMapRastPort() is known to */
253: /* produce spilled registers with gcc */
254: return;
255: }
256: #endif
257:
258: #if 0
259: if(use_graffiti && !need_dither) {
260: graffiti_WritePixelLine8(0, y, gfxvidinfo.rowbytes, linebuf);
261: }
262: #endif
263:
264: /*
265: * cybergfx && dither \_ LOW_BANDWIDTH and 1 byte per pixel in the output
266: * or standard screen /
267: */
268:
269: switch(gfxvidinfo.pixbytes) {
270: case 4:
271: { /* sam: we should not arrive here on the amiga */
272: fprintf(stderr, "Bug in flush_line() !\n");
273: fprintf(stderr, "use_cyb=%d\n",use_cyb);
274: fprintf(stderr, "need_dither=%d\n",need_dither);
275: fprintf(stderr, "depth=%d\n",RPDepth(RP));
276: fprintf(stderr, "Please return those values to maintainer.\n");
277: abort();
278: return;
279: } break;
280: case 2:
281: { short *newp = (short *)linebuf;
282: short *oldp = (short *)(oldpixbuf + yoffset);
283: while (*newp++ == *oldp++) if(!--len) return;
284: src = (char *)--newp;
285: dst = (char *)--oldp;
286: newp += len;
287: oldp += len;
288: while (*--newp == *--oldp);
289: len = 1 + (oldp - (short *)dst);
290: xs = (src - linebuf)/2;
291: CopyMem (src, dst, len * 2);
292: } break;
293: case 1:
294: { char *newp = (char *)linebuf;
295: char *oldp = (char *)(oldpixbuf + yoffset);
296: while (*newp++ == *oldp++) if(!--len) return;
297: src = (char *)--newp;
298: dst = (char *)--oldp;
299: newp += len;
300: oldp += len;
301: while (*--newp == *--oldp);
302: len = 1 + (oldp - (char *)dst);
303: xs = (src - linebuf);
304: CopyMem (src, dst, len);
305: } break;
306: default:
307: abort();
308: break;
309: }
310:
311: if (need_dither) {
312: DitherLine(Line, (UWORD *)dst, xs, y, (len+3)&~3, 8);
313: } else CopyMem(dst, Line, len);
314:
315: if (use_cyb) { /* pixbyte == 1 */
316: #ifdef USE_CYBERGFX
317: BltBitMapRastPort(CybBitMap, xs, y,
318: RP, XOffset+xs, YOffset+y,
319: len, 1, 0xc0);
320: #endif
321: } else if(use_graffiti) {
322: graffiti_WritePixelLine8(xs, y, len, Line);
323: } else WritePixelLine8(RP, xs + XOffset, y + YOffset, len, Line, TempRPort);
324: }
325:
326: /****************************************************************************/
327:
328: void flush_block (int ystart, int ystop)
329: {
330: int y;
331: #ifdef USE_CYBERGFX
332: if(use_cyb && !need_dither) {
333: int len = gfxvidinfo.width;
334: BltBitMapRastPort(CybBitMap,
335: 0, ystart,
336: RP, XOffset, YOffset+ystart,
337: len, ystop-ystart+1, 0xc0);
338: return;
339: }
340: #endif
341: for(y=ystart; y<=ystop; ++y) flush_line(y);
342: }
343:
344: /****************************************************************************/
345:
346: void flush_screen (int ystart, int ystop)
347: {
348: /* WaitBOVP() ? */
349: char *file;
350: static int cpt = 0;
351: char name[80];
352:
353: if(!dump_iff) return;
354: if(!(file = getenv(UAEIFF))) return;
355: if(strchr(file,'%')) sprintf(name,file,cpt++);
356: else sprintf(name,"%s.%05d",file,cpt++);
357: if(W->WScreen) SaveIFF(name,W->WScreen);
358: }
359:
360: /****************************************************************************/
361:
362: static int RPDepth(struct RastPort *RP)
363: {
364: #ifdef USE_CYBERGFX
365: if(use_cyb) return GetCyberMapAttr(RP->BitMap,(LONG)CYBRMATTR_DEPTH);
366: #endif
367: if(use_graffiti) return 8;
368: return RP->BitMap->Depth;
369: }
370:
371: /****************************************************************************/
372:
373: static int get_color(int r, int g, int b, xcolnr *cnp)
374: {
375: int col;
376:
377: if(use_gray) r = g = b = (77*r + 151*g + 29*b) / 256;
378:
379: r *= 0x11111111;
380: g *= 0x11111111;
381: b *= 0x11111111;
382: col = ObtainColor(r, g, b);
383:
384: if(col == -1) {
385: get_color_failed = 1;
386: return 0;
387: }
388:
389: *cnp = col;
390: return 1;
391: }
392:
393: /****************************************************************************/
394: /*
395: * FIXME: find a better way to determine closeness of colors (closer to
396: * human perception).
397: */
398: static __inline__ void rgb2xyz(int r, int g, int b,
399: int *x, int *y, int *z)
400: {
401: *x = r*1024 - (g+b)*512;
402: *y = 886*(g-b);
403: *z = (r+g+b)*341;
404: }
405: static __inline__ int calc_err(int r1, int g1, int b1,
406: int r2, int g2, int b2)
407: {
408: int x1,y1,z1,x2,y2,z2;
409:
410: rgb2xyz(r1,g1,b1,&x1,&y1,&z1);
411: rgb2xyz(r2,g2,b2,&x2,&y2,&z2);
412: x1 -= x2; y1 -= y2; z1 -= z2;
413: return x1*x1 + y1*y1 + z1*z1;
414: }
415:
416: /****************************************************************************/
417:
418: static int get_nearest_color(int r, int g, int b)
419: {
420: int i, best, err, besterr;
421: int colors;
422: int br=0,bg=0,bb=0;
423:
424: if(use_gray) r = g = b = (77*r + 151*g + 29*b) / 256;
425:
426: best = 0;
427: besterr = calc_err(0,0,0, 15,15,15);
428: colors = is_halfbrite?32:(1<<RPDepth(RP));
429:
430: for(i=0; i<colors; i++ ) {
431: long rgb = GetRGB4(CM, i);
432: int cr, cg, cb;
433:
434: cr = (rgb >> 8) & 15;
435: cg = (rgb >> 4) & 15;
436: cb = (rgb >> 0) & 15;
437:
438: err = calc_err(r,g,b, cr,cg,cb);
439:
440: if(err < besterr) {
441: best = i;
442: besterr = err;
443: br=cr; bg=cg; bb=cb;
444: }
445:
446: if(is_halfbrite) {
447: cr /= 2; cg /= 2; cb /= 2;
448: err = calc_err(r,g,b, cr,cg,cb);
449: if(err < besterr) {
450: best = i + 32;
451: besterr = err;
452: br=cr; bg=cg; bb=cb;
453: }
454: }
455: }
456: return best;
457: }
458:
459: /****************************************************************************/
460:
461: static int init_colors(void)
462: {
463: gfxvidinfo.can_double = 0;
464: if (need_dither) {
465: /* first try color allocation */
466: int bitdepth = usepub ? 8 : RPDepth(RP);
467: int maxcol;
468:
469: if(!use_gray && bitdepth>=3)
470: do {
471: get_color_failed = 0;
472: setup_dither(bitdepth, get_color);
473: if(get_color_failed) ReleaseColors();
474: } while(get_color_failed && --bitdepth>=3);
475:
476: if(!use_gray && bitdepth>=3) {
477: printf("Color dithering with %d bits\n",bitdepth);
478: return 1;
479: }
480:
481: /* if that fail then try grey allocation */
482: maxcol = 1<<(usepub ? 8 : RPDepth(RP));
483:
484: do {
485: get_color_failed = 0;
486: setup_greydither_maxcol(maxcol, get_color);
487: if(get_color_failed) ReleaseColors();
488: } while(get_color_failed && --maxcol>=2);
489:
490: /* extra pass with approximated colors */
491: if(get_color_failed) do {
492: maxcol=2;
493: use_approx_color = 1;
494: get_color_failed = 0;
495: setup_greydither_maxcol(maxcol, get_color);
496: if(get_color_failed) ReleaseColors();
497: } while(get_color_failed && --maxcol>=2);
498:
499: if (maxcol >= 2) {
500: printf("Gray dither with %d shades.\n",maxcol);
501: return 1;
502: }
503:
504: return 0; /* everything failed :-( */
505: }
506:
507: /* No dither */
508: switch(RPDepth(RP)) {
509: case 6: if (is_halfbrite) {
510: static int tab[]={
511: 0x000, 0x00f, 0x0f0, 0x0ff, 0x08f, 0x0f8, 0xf00, 0xf0f,
512: 0x80f, 0xff0, 0xfff, 0x88f, 0x8f0, 0x8f8, 0x8ff, 0xf08,
513: 0xf80, 0xf88, 0xf8f, 0xff8, /* end of regular pattern */
514: 0xa00, 0x0a0, 0xaa0, 0x00a, 0xa0a, 0x0aa, 0xaaa,
515: 0xfaa, 0xf6a, 0xa80, 0x06a, 0x6af };
516: int i;
517: for(i=0;i<32;++i) get_color(tab[i]>>8, (tab[i]>>4)&15, tab[i]&15, xcolors);
518: for(i=0;i<4096;++i) xcolors[i] = get_nearest_color(i>>8, (i>>4)&15, i&15);
519: printf("Using %d colors + halfbrite\n",32);
520: break;
521: } else if(is_ham) {
522: int i;
523: for(i=0;i<16;++i) get_color(i,i,i, xcolors);
524: printf("Using %d bits pseudo-truecolor (HAM).\n",12);
525: alloc_colors64k(4,4,4,10,5,0);
526: return init_ham();
527: }
528:
529: case 1: case 2: case 3: case 4: case 5: case 7: case 8: {
530: int maxcol = 1<<RPDepth(RP);
531:
532: if(maxcol>=8 && !use_gray) do {
533: get_color_failed = 0;
534: setup_maxcol(maxcol);
535: alloc_colors256(get_color);
536: if(get_color_failed) ReleaseColors();
537: } while(get_color_failed && --maxcol>=8);
538: else {
539: int i;
540: for(i=0;i<maxcol;++i) {
541: get_color((i*15)/(maxcol-1), (i*15)/(maxcol-1),
542: (i*15)/(maxcol-1), xcolors);
543: }
544: }
545: printf("Using %d colors.\n",maxcol);
546: for(maxcol=0; maxcol<4096; ++maxcol)
547: xcolors[maxcol] = get_nearest_color(maxcol>>8, (maxcol>>4)&15,
548: maxcol&15);
549: } break;
550:
551: case 15:
552: printf("Using %d bits truecolor.\n",15);
553: alloc_colors64k(5,5,5,10,5,0);
554: break;
555:
556: case 16:
557: printf("Using %d bits truecolor.\n",16);
558: alloc_colors64k(5,6,5,11,5,0);
559: break;
560:
561: case 24:
562: printf("Using %d bits truecolor.\n",24);
563: alloc_colors64k(8,8,8,16,8,0);
564: break;
565:
566: case 32:
567: printf("Using %d bits truecolor.\n",32);
568: alloc_colors64k(8,8,8,16,8,0);
569: break;
570: }
571: return 1;
572: }
573:
574: /****************************************************************************/
575:
576: static void setup_sprite(struct Window *W)
577: {
578: Sprite = AllocVec(4+2, MEMF_CHIP|MEMF_CLEAR);
579: if(!Sprite) {
580: fprintf(stderr, "Warning: Can't alloc sprite buffer !\n");
581: return;
582: }
583: Sprite[2] = 0x8000; Sprite[3] = 0x8000;
584: SetPointer(W, Sprite, 1, 16, -1, 0);
585: }
586:
587: /****************************************************************************/
588:
589: static int setup_customscreen(void)
590: {
591: /* hum some of old programming style here :) */
592: static struct NewScreen NewScreenStructure = {
593: 0,0, 800,600, 3, 0,1,
594: LACE+HIRES, CUSTOMSCREEN|SCREENQUIET|SCREENBEHIND,
595: NULL, (void*)"UAE", NULL, NULL};
596: static struct NewWindow NewWindowStructure = {
597: 0,0, 800,600, 0,1,
598: IDCMP_MOUSEBUTTONS|IDCMP_RAWKEY|IDCMP_DISKINSERTED|IDCMP_DISKREMOVED|
599: IDCMP_ACTIVEWINDOW|IDCMP_INACTIVEWINDOW|IDCMP_MOUSEMOVE,
600: WFLG_SMART_REFRESH|WFLG_BACKDROP|WFLG_RMBTRAP|WFLG_NOCAREREFRESH|
601: WFLG_BORDERLESS|WFLG_WINDOWACTIVE|WFLG_REPORTMOUSE,
602: NULL, NULL, (void*)"UAE", NULL, NULL, 5,5, 800,600,
603: CUSTOMSCREEN};
604:
605: NewScreenStructure.Width = currprefs.gfx_width;
606: NewScreenStructure.Height = currprefs.gfx_height;
607: NewScreenStructure.Depth = os39?8:(currprefs.gfx_lores?5:4);
608: NewScreenStructure.ViewModes = SPRITES | (currprefs.gfx_lores?NULL:HIRES) |
609: (currprefs.gfx_height>256?LACE:NULL);
610:
611: do S = (void*)OpenScreen(&NewScreenStructure);
612: while(!S && --NewScreenStructure.Depth);
613: if(!S) {
614: fprintf(stderr, "Can't open custom screen !\n");
615: return 0;
616: }
617:
618: CM = S->ViewPort.ColorMap;
619: RP = &S->RastPort;
620:
621: NewWindowStructure.Width = S->Width;
622: NewWindowStructure.Height = S->Height;
623: NewWindowStructure.Screen = S;
624: W = (void*)OpenWindow(&NewWindowStructure);
625: if(!W) {
626: fprintf(stderr, "Can't open window on custom screen !\n");
627: return 0;
628: }
629: setup_sprite(W);
630: return 1;
631: }
632:
633: /****************************************************************************/
634:
635: static int setup_publicscreen(void)
636: {
637: UWORD ZoomArray[4] = {0,0,0,0};
638:
639: S = LockPubScreen(NULL);
640: if(!S) {
641: fprintf(stderr,"No public screen !\n");
642: return 0;
643: }
644:
645: ZoomArray[2] = 128;
646: ZoomArray[3] = S->BarHeight+1;
647:
648: CM = S->ViewPort.ColorMap;
649:
650: if((S->ViewPort.Modes & (HIRES|LACE))==HIRES) {
651: if(currprefs.gfx_height + S->BarHeight + 1 >= S->Height) {
652: currprefs.gfx_height >>= 1;
653: currprefs.gfx_correct_aspect = 1;
654: }
655: }
656:
657: #ifdef USE_CYBERGFX
658: if(CyberGfxBase && IsCyberModeID(GetVPModeID(&S->ViewPort))) use_cyb = 1;
659: #endif
660: W = OpenWindowTags(NULL,
661: WA_Title, (ULONG)"UAE",
662: WA_AutoAdjust, TRUE,
663: WA_InnerWidth, currprefs.gfx_width,
664: WA_InnerHeight, currprefs.gfx_height,
665: WA_PubScreen, (ULONG)S,
666: WA_Zoom, (ULONG)ZoomArray,
667: WA_IDCMP, IDCMP_MOUSEBUTTONS|
668: IDCMP_RAWKEY|
669: IDCMP_ACTIVEWINDOW|
670: IDCMP_INACTIVEWINDOW|
671: IDCMP_MOUSEMOVE|
672: IDCMP_CLOSEWINDOW|
673: IDCMP_REFRESHWINDOW|
674: IDCMP_NEWSIZE|
675: 0,
676: WA_Flags, WFLG_DRAGBAR|
677: WFLG_DEPTHGADGET|
678: WFLG_REPORTMOUSE|
679: WFLG_RMBTRAP|
680: WFLG_ACTIVATE|
681: WFLG_CLOSEGADGET|
682: WFLG_SMART_REFRESH|
683: 0,
684: TAG_DONE);
685:
686: UnlockPubScreen(NULL, S);
687:
688: if(!W) {
689: fprintf(stderr,"Can't open window on public screen !\n");
690: CM = NULL;
691: return 0;
692: }
693:
694: gfxvidinfo.width = (W->Width - W->BorderRight - W->BorderLeft);
695: gfxvidinfo.height = (W->Height - W->BorderTop - W->BorderBottom);
696: XOffset = W->BorderLeft;
697: YOffset = W->BorderTop;
698:
699: RP = W->RPort;
700: setup_sprite(W);
701:
702: appw_init(W);
703:
704: return 1;
705: }
706:
707: /****************************************************************************/
708:
709: static int setup_userscreen(void)
710: {
711: struct ScreenModeRequester *ScreenRequest;
712: ULONG DisplayID;
713: static struct BitMap PointerBitMap;
714: UWORD *PointerLine;
715: LONG ScreenWidth=0,ScreenHeight=0,Depth=0;
716: UWORD OverscanType=0;
717: BOOL AutoScroll=0;
718:
719: if(!AslBase) AslBase = OpenLibrary("asl.library",38);
720: if(!AslBase) {
721: fprintf(stderr,"Can't open asl.library v38 !");
722: return 0;
723: }
724:
725: ScreenRequest = AllocAslRequest(ASL_ScreenModeRequest,NULL);
726: if(!ScreenRequest) {
727: fprintf(stderr,"Unable to allocate screen mode requester.\n");
728: return 0;
729: }
730:
731: if(AslRequestTags(ScreenRequest,
732: ASLSM_TitleText, (ULONG)"Select screen display mode",
733: ASLSM_InitialDisplayID, NULL,
734: ASLSM_InitialDisplayDepth, 8,
735: ASLSM_InitialDisplayWidth, currprefs.gfx_width,
736: ASLSM_InitialDisplayHeight,currprefs.gfx_height,
737: ASLSM_MinWidth, currprefs.gfx_width,
738: ASLSM_MinHeight, currprefs.gfx_height,
739: ASLSM_DoWidth, TRUE,
740: ASLSM_DoHeight, TRUE,
741: ASLSM_DoDepth, TRUE,
742: ASLSM_DoOverscanType, TRUE,
743: ASLSM_PropertyFlags, 0,
744: ASLSM_PropertyMask, DIPF_IS_DUALPF |
745: DIPF_IS_PF2PRI |
746: /* DIPF_IS_HAM | */
747: 0,
748: TAG_DONE)) {
749: ScreenWidth = ScreenRequest->sm_DisplayWidth;
750: ScreenHeight = ScreenRequest->sm_DisplayHeight;
751: Depth = ScreenRequest->sm_DisplayDepth;
752: DisplayID = ScreenRequest->sm_DisplayID;
753: OverscanType = ScreenRequest->sm_OverscanType;
754: AutoScroll = ScreenRequest->sm_AutoScroll;
755: if(ScreenWidth < currprefs.gfx_width) ScreenWidth = currprefs.gfx_width;
756: if(ScreenHeight < currprefs.gfx_height) ScreenHeight = currprefs.gfx_height;
757: }
758: else DisplayID = INVALID_ID;
759: FreeAslRequest(ScreenRequest);
760:
761: if(DisplayID == (ULONG)INVALID_ID) return 0;
762:
763: #ifdef USE_CYBERGFX
764: if(CyberGfxBase && IsCyberModeID(DisplayID)) use_cyb = 1;
765: #endif
766: if(DisplayID & DIPF_IS_HAM) Depth = 6; /* only ham6 for the moment */
767:
768: S = OpenScreenTags(NULL,
769: SA_DisplayID, DisplayID,
770: SA_Width, ScreenWidth,
771: SA_Height, ScreenHeight,
772: SA_Depth, Depth,
773: SA_Overscan, OverscanType,
774: SA_AutoScroll, AutoScroll,
775: SA_ShowTitle, FALSE,
776: SA_Quiet, TRUE,
777: SA_Behind, TRUE,
778: SA_PubName, (ULONG)"UAE",
779: /* v39 stuff here: */
780: (os39?SA_BackFill:TAG_DONE), (ULONG)LAYERS_NOBACKFILL,
781: SA_SharePens, TRUE,
782: SA_Exclusive, (use_cyb?TRUE:FALSE),
783: SA_Draggable, (use_cyb?FALSE:TRUE),
784: SA_Interleaved, TRUE,
785: TAG_DONE);
786: if(!S) {
787: fprintf(stderr,"Unable to open the screen.\n");
788: return 0;
789: }
790:
791: CM = S->ViewPort.ColorMap;
792: is_halfbrite = (S->ViewPort.Modes & EXTRA_HALFBRITE);
793: is_ham = (S->ViewPort.Modes & HAM);
794:
795: PointerLine = malloc(4);/* autodocs says it needs not be in chip memory */
796: if(PointerLine) PointerLine[0]=PointerLine[1]=0;
797: InitBitMap(&PointerBitMap,2,16,1);
798: PointerBitMap.Planes[0] = (PLANEPTR)&PointerLine[0];
799: PointerBitMap.Planes[1] = (PLANEPTR)&PointerLine[1];
800:
801: Pointer = NewObject(NULL,POINTERCLASS,
802: POINTERA_BitMap, (ULONG)&PointerBitMap,
803: POINTERA_WordWidth, 1,
804: TAG_DONE);
805: if(!Pointer)
806: fprintf(stderr,"Warning: Unable to allocate blank mouse pointer.\n");
807:
808: W = OpenWindowTags(NULL,
809: WA_Width, S->Width,
810: WA_Height, S->Height,
811: WA_CustomScreen, (ULONG)S,
812: WA_Backdrop, TRUE,
813: WA_Borderless, TRUE,
814: WA_RMBTrap, TRUE,
815: WA_ReportMouse, TRUE,
816: WA_IDCMP, IDCMP_MOUSEBUTTONS|
817: IDCMP_RAWKEY|
818: IDCMP_DISKINSERTED|
819: IDCMP_DISKREMOVED|
820: IDCMP_ACTIVEWINDOW|
821: IDCMP_INACTIVEWINDOW|
822: IDCMP_MOUSEMOVE,
823: (os39?WA_BackFill:TAG_IGNORE), (ULONG)LAYERS_NOBACKFILL,
824: (Pointer?WA_Pointer:TAG_IGNORE), (ULONG)Pointer,
825: TAG_DONE);
826:
827: if(!W) {
828: fprintf(stderr,"Unable to open the window.\n");
829: CloseScreen(S);S=NULL;RP=NULL;CM=NULL;
830: return 0;
831: }
832: if(!Pointer) setup_sprite(W);
833:
834: RP = W->RPort; /* &S->Rastport if screen is not public */
835: PubScreenStatus(S, 0);
836:
837: return 1;
838: }
839:
840: /****************************************************************************/
841:
842: static int setup_graffiti(void)
843: {
844: static struct NewScreen NewScreenStructure = {
845: 0,0, 800,600, 4, 0,1,
846: HIRES, CUSTOMSCREEN|SCREENQUIET/*|SCREENBEHIND*/,
847: NULL, (void*)"UAE", NULL, NULL};
848: static struct NewWindow NewWindowStructure = {
849: 0,0, 800,600, 0,1,
850: IDCMP_MOUSEBUTTONS|IDCMP_RAWKEY|IDCMP_DISKINSERTED|IDCMP_DISKREMOVED|
851: IDCMP_ACTIVEWINDOW|IDCMP_INACTIVEWINDOW|IDCMP_MOUSEMOVE,
852: WFLG_SMART_REFRESH|WFLG_BACKDROP|WFLG_RMBTRAP|WFLG_NOCAREREFRESH|
853: WFLG_BORDERLESS|WFLG_WINDOWACTIVE|WFLG_REPORTMOUSE,
854: NULL, NULL, (void*)"UAE", NULL, NULL, 5,5, 800,600,
855: CUSTOMSCREEN};
856: static short colarr[] = {
857: 0x000,0x001,0x008,0x009,0x080,0x081,0x088,0x089,
858: 0x800,0x801,0x808,0x809,0x880,0x881,0x888,0x889};
859: int i;
860:
861: NewScreenStructure.Width = 2*currprefs.gfx_width;
862: /* I leave 8 extra lines for palette & mode: */
863: NewScreenStructure.Height = currprefs.gfx_height+8;
864: NewScreenStructure.Depth = 4;
865: NewScreenStructure.ViewModes = HIRES|GENLOCK_AUDIO/*|GENLOCK_VIDEO*/;
866: /* ^^ ^^ which one ? */
867:
868: S = (void*)OpenScreen(&NewScreenStructure);
869: if(!S) {
870: fprintf(stderr, "Can't open graffiti screen !\n");
871: return 0;
872: }
873:
874: for(i=0;i<15;++i) {
875: unsigned int rgb = colarr[i];
876: SetRGB4(&S->ViewPort,i,(rgb>>8)&15,(rgb>>4)&15,rgb&15);
877: }
878:
879: CM = S->ViewPort.ColorMap;
880: RP = &S->RastPort;
881:
882: NewWindowStructure.Width = S->Width;
883: NewWindowStructure.Height = S->Height;
884: NewWindowStructure.Screen = S;
885: W = (void*)OpenWindow(&NewWindowStructure);
886: if(!W) {
887: fprintf(stderr, "Can't open window on graffiti screen !\n");
888: return 0;
889: }
890: setup_sprite(W);
891: {
892: /* make sure cmd part is cleared */
893: int d;
894: for(d = 0; d < 4; ++d) {
895: short *p;
896: int i;
897: p = (void*)RP->BitMap->Planes[d];
898: for(i=0;i<40*7;++i) p[i] = 0;
899: }
900: /* set graffiti mode to lores */
901: *((short*)RP->BitMap->Planes[3]+8*40-1) = 0x0800;
902: for(d=0;d<256;++d) graffiti_SetRGB(d,0,0,0);
903: }
904:
905: return 1;
906: }
907:
908: /****************************************************************************/
909:
910: int graphics_setup(void)
911: {
912: #ifdef __GNUC__
913: if(ix_os != OS_IS_AMIGAOS) {
914: ix_req(NULL, "Abort", NULL, "That version of %s is only for AmigaOS!", __progname);
915: exit(20);
916: }
917: #endif
918: if(SysBase->LibNode.lib_Version < 36) {
919: fprintf(stderr, "UAE needs OS 2.0+ !\n");
920: return 0;
921: }
922: os39 = (SysBase->LibNode.lib_Version>=39);
923:
924: atexit(graphics_leave);
925:
926: IntuitionBase = (void*)OpenLibrary("intuition.library",0L);
927: if(!IntuitionBase) {
928: fprintf(stderr,"No intuition.library ?\n");
929: return 0;
930: }
931: GfxBase = (void*)OpenLibrary("graphics.library",0L);
932: if(!GfxBase) {
933: fprintf(stderr,"No graphics.library ?\n");
934: return 0;
935: }
936: #ifdef USE_CYBERGFX
937: if(!CyberGfxBase) CyberGfxBase = OpenLibrary("cybergraphics.library",40);
938: #endif
939: initpseudodevices();
940:
941: return 1;
942: }
943:
944: /****************************************************************************/
945:
946: int graphics_init(void)
947: {
948: int i,bitdepth;
949:
950: use_low_bandwidth = 0;
951: need_dither = 0;
952: use_cyb = 0;
953:
954: if (currprefs.gfx_width < 320)
955: currprefs.gfx_width = 320;
956: if (!currprefs.gfx_correct_aspect && (currprefs.gfx_height < 64/*200*/))
957: currprefs.gfx_height = 200;
958: currprefs.gfx_width += 7;
959: currprefs.gfx_width &= ~7;
960:
961: if (currprefs.color_mode > 5)
962: fprintf(stderr, "Bad color mode selected. Using default.\n"), currprefs.color_mode = 0;
963:
964: if(currprefs.color_mode == 3) { /* graffiti */
965: currprefs.gfx_width = 320;
966: if(currprefs.gfx_height > 256)
967: currprefs.gfx_height = 256;
968: currprefs.gfx_lores = 1;
969: } /* graffiti */
970:
971: gfxvidinfo.width = currprefs.gfx_width;
972: gfxvidinfo.height = currprefs.gfx_height;
973:
974: switch(currprefs.color_mode) {
975: case 3:
976: if(setup_graffiti()) {use_graffiti = 1;break;}
977: fprintf(stderr,"Asking user for screen...\n");
978: /* fall trough */
979: case 2:
980: if(setup_userscreen()) break;
981: fprintf(stderr,"Trying on public screen...\n");
982: /* fall trough */
983: case 1:
984: is_halfbrite = 0;
985: if(setup_publicscreen()) {usepub = 1;break;}
986: fprintf(stderr,"Trying on custom screen...\n");
987: /* fall trough */
988: case 0:
989: default:
990: if(!setup_customscreen()) return 0;
991: break;
992: }
993:
994: Line = AllocVec((currprefs.gfx_width + 15) & ~15,MEMF_ANY|MEMF_PUBLIC);
995: if(!Line) {
996: fprintf(stderr,"Unable to allocate raster buffer.\n");
997: return 0;
998: }
999: BitMap = myAllocBitMap(currprefs.gfx_width,1,8,BMF_CLEAR|BMF_MINPLANES,RP->BitMap);
1000: if(!BitMap) {
1001: fprintf(stderr,"Unable to allocate BitMap.\n");
1002: return 0;
1003: }
1004: TempRPort = AllocVec(sizeof(struct RastPort),MEMF_ANY|MEMF_PUBLIC);
1005: if(!TempRPort) {
1006: fprintf(stderr,"Unable to allocate RastPort.\n");
1007: return 0;
1008: }
1009: CopyMem(RP,TempRPort,sizeof(struct RastPort));
1010: TempRPort->Layer = NULL;
1011: TempRPort->BitMap = BitMap;
1012:
1013: if(usepub) set_title();
1014:
1015: bitdepth = RPDepth(RP);
1016: if(is_ham) {
1017: /* ham 6 */
1018: use_low_bandwidth = 0; /* needless as the line must be fully */
1019: need_dither = 0; /* recomputed */
1020: gfxvidinfo.pixbytes = 2;
1021: } else if(bitdepth <= 8) {
1022: /* chunk2planar is slow so we define use_low_bandwidth for all modes
1023: except cybergraphics modes */
1024: use_low_bandwidth = 1;
1025: need_dither = use_dither || (bitdepth<=1);
1026: gfxvidinfo.pixbytes = need_dither?2:1;
1027: } else {
1028: /* Cybergfx mode */
1029: gfxvidinfo.pixbytes = (bitdepth == 24 || bitdepth == 32) ? 4 :
1030: (bitdepth == 12 || bitdepth == 16) ? 2 : 1;
1031: }
1032:
1033: if (!use_cyb) {
1034: gfxvidinfo.rowbytes = gfxvidinfo.pixbytes * currprefs.gfx_width;
1035: gfxvidinfo.bufmem = (char *)calloc(gfxvidinfo.rowbytes, currprefs.gfx_height+1);
1036: /* ^^ */
1037: /* This is because DitherLine may read one extra row */
1038: } else {
1039: #ifdef USE_CYBERGFX
1040: ULONG fmt = 0;
1041: switch(bitdepth) {
1042: case 8: fmt = PIXFMT_LUT8; break;
1043: case 15: fmt = PIXFMT_RGB15; break;
1044: case 16: fmt = PIXFMT_RGB16; break;
1045: case 24: fmt = PIXFMT_RGB24; break;
1046: case 32: fmt = PIXFMT_ARGB32; break;
1047: default: fprintf(stderr,"Unsupported bitdepth %d.\n",bitdepth); return 0;
1048: }
1049: CybBitMap = myAllocBitMap(currprefs.gfx_width, currprefs.gfx_height+1,
1050: bitdepth,
1051: (fmt<<24)|BMF_SPECIALFMT|BMF_MINPLANES,
1052: NULL);
1053: if(CybBitMap) {
1054: gfxvidinfo.rowbytes = GetCyberMapAttr(CybBitMap,CYBRMATTR_XMOD);
1055: gfxvidinfo.pixbytes = GetCyberMapAttr(CybBitMap,CYBRMATTR_BPPIX);
1056: gfxvidinfo.bufmem = (char *)GetCyberMapAttr(CybBitMap,CYBRMATTR_DISPADR);
1057: } else gfxvidinfo.bufmem = NULL;
1058: #endif
1059: }
1060: if(!gfxvidinfo.bufmem) {
1061: fprintf(stderr,"Not enough memory for video bufmem.\n");
1062: return 0;
1063: }
1064:
1065: if (use_low_bandwidth) {
1066: gfxvidinfo.maxblocklines = currprefs.gfx_height-1; /* it seems to increase the speed */
1067: oldpixbuf = (char *)calloc(gfxvidinfo.rowbytes, currprefs.gfx_height);
1068: if(!oldpixbuf) {
1069: fprintf(stderr,"Not enough memory for oldpixbuf.\n");
1070: return 0;
1071: }
1072: } else {
1073: gfxvidinfo.maxblocklines = 0; /* whatever... */
1074: }
1075:
1076: if (!init_colors()) {
1077: fprintf(stderr,"Failed to init colors.\n");
1078: return 0;
1079: }
1080: switch (gfxvidinfo.pixbytes) {
1081: case 2:
1082: for (i = 0; i < 4096; i++) xcolors[i] *= 0x00010001;
1083: gfxvidinfo.can_double = 1;
1084: break;
1085: case 1:
1086: for (i = 0; i < 4096; i++) xcolors[i] *= 0x01010101;
1087: gfxvidinfo.can_double = 1;
1088: break;
1089: default:
1090: gfxvidinfo.can_double = 0;
1091: break;
1092: }
1093:
1094: if(!usepub) ScreenToFront(S);
1095:
1096: buttonstate[0] = buttonstate[1] = buttonstate[2] = 0;
1097: for(i=0; i<256; i++)
1098: keystate[i] = 0;
1099:
1100: lastmx = lastmy = 0;
1101: newmousecounters = 0;
1102: inwindow = 0;
1103:
1104: rexx_init();
1105:
1106: if(getenv(UAEIFF) && !use_cyb) {
1107: dump_iff = 1;
1108: fprintf(stderr,"Saving to \"%s\"\n",getenv(UAEIFF));
1109: }
1110:
1111: return 1;
1112: }
1113:
1114: /****************************************************************************/
1115:
1116: void graphics_leave(void)
1117: {
1118: rexx_exit();
1119: closepseudodevices();
1120: appw_exit();
1121: #ifdef USE_CYBERGFX
1122: if(CybBitMap) {
1123: WaitBlit();
1124: myFreeBitMap(CybBitMap);
1125: CybBitMap = NULL;
1126: }
1127: #endif
1128: if(BitMap) {
1129: WaitBlit();
1130: myFreeBitMap(BitMap);
1131: BitMap = NULL;
1132: }
1133: if(TempRPort) {
1134: FreeVec(TempRPort);
1135: TempRPort = NULL;
1136: }
1137: if(Line) {
1138: FreeVec(Line);
1139: Line = NULL;
1140: }
1141: if(CM) {
1142: ReleaseColors();
1143: CM = NULL;
1144: }
1145: if(W) {
1146: CloseWindow(W);
1147: W = NULL;
1148: }
1149: if(Sprite) {
1150: FreeVec(Sprite);
1151: Sprite = NULL;
1152: }
1153: if(Pointer) {
1154: DisposeObject(Pointer);
1155: Pointer = NULL;
1156: }
1157: if(!usepub && S) {
1158: int warn = 0;
1159: if(!CloseScreen(S)) {
1160: fprintf(stderr,"Please close all opened windows on UAE's "
1161: "screen.\n");
1162: do Delay(50); while(!CloseScreen(S));
1163: }
1164: S = NULL;
1165: }
1166: if(AslBase) {
1167: CloseLibrary((void*)AslBase);
1168: AslBase = NULL;
1169: }
1170: if(GfxBase) {
1171: CloseLibrary((void*)GfxBase);
1172: GfxBase = NULL;
1173: }
1174: if(IntuitionBase) {
1175: CloseLibrary((void*)IntuitionBase);
1176: IntuitionBase = NULL;
1177: }
1178: if(CyberGfxBase) {
1179: CloseLibrary((void*)CyberGfxBase);
1180: CyberGfxBase = NULL;
1181: }
1182: }
1183:
1184:
1185: /***************************************************************************/
1186:
1187: void handle_events(void)
1188: {
1189: struct IntuiMessage *msg;
1190: int mx,my,class,code;
1191:
1192: newmousecounters = 0;
1193:
1194: /*
1195: * This is a hack to simulate ^C as is seems that break_handler
1196: * is lost when system() is called.
1197: */
1198: if(SetSignal(0L, SIGBREAKF_CTRL_C|SIGBREAKF_CTRL_D) &
1199: (SIGBREAKF_CTRL_C|SIGBREAKF_CTRL_D)) {
1200: activate_debugger();
1201: }
1202:
1203: while((msg=(struct IntuiMessage*)GetMsg(W->UserPort))) {
1204: class = msg->Class;
1205: code = msg->Code;
1206: mx = msg->MouseX;
1207: my = msg->MouseY;
1208: ReplyMsg((struct Message*)msg);
1209:
1210: mx -= XOffset;
1211: my -= YOffset;
1212:
1213: if(use_graffiti) {
1214: my -= 8;
1215: }
1216:
1217: switch(class) {
1218: case IDCMP_NEWSIZE:
1219: inhibit_frame = (W->Flags & WFLG_ZOOMED)?1:0;
1220: set_title();
1221: break;
1222:
1223: case IDCMP_REFRESHWINDOW:
1224: if(use_low_bandwidth) {
1225: /* hack: this forces refresh */
1226: char *ptr = oldpixbuf;
1227: int i, len = gfxvidinfo.width;
1228: len *= gfxvidinfo.pixbytes;
1229: for(i=0;i<currprefs.gfx_height;++i) {
1230: ptr[00000] ^= 255;
1231: ptr[len-1] ^= 255;
1232: ptr += gfxvidinfo.rowbytes;
1233: }
1234: BeginRefresh(W);
1235: flush_block(0,currprefs.gfx_height-1);
1236: EndRefresh(W, TRUE);
1237: } else {
1238: BeginRefresh(W);
1239: EndRefresh(W, TRUE);
1240: } break;
1241:
1242: case IDCMP_CLOSEWINDOW:
1243: activate_debugger();
1244: break;
1245:
1246: case IDCMP_RAWKEY: {
1247: int kc = code&127;
1248: int released = code&128?1:0;
1249:
1250: if(released) {
1251: keystate[kc] = 0;
1252: record_key ((kc << 1) | 1);
1253: } else if (!keystate[kc]) {
1254: keystate[kc] = 1;
1255: record_key (kc << 1);
1256: }
1257: } break;
1258:
1259: case IDCMP_MOUSEMOVE:
1260: if(inwindow) {
1261: lastmx = mx >> (use_graffiti?1:0);
1262: lastmy = my;
1263: if(!ievent_alive) {
1264: if(currprefs.gfx_lores) lastmx <<= 1;
1265: if(currprefs.gfx_height < 512) {
1266: lastmy *= 512;
1267: lastmy /= currprefs.gfx_height;
1268: }
1269: }
1270: } break;
1271:
1272: case IDCMP_MOUSEBUTTONS:
1273: if(code==SELECTDOWN) buttonstate[0]=1;
1274: if(code==SELECTUP) buttonstate[0]=0;
1275: if(code==MENUDOWN) buttonstate[2]=1;
1276: if(code==MENUUP) buttonstate[2]=0;
1277: break;
1278:
1279: /* Those 2 could be of some use later. */
1280: case IDCMP_DISKINSERTED:
1281: /*printf("diskinserted(%d)\n",code);*/
1282: break;
1283:
1284: case IDCMP_DISKREMOVED:
1285: /*printf("diskremoved(%d)\n",code);*/
1286: break;
1287:
1288: case IDCMP_ACTIVEWINDOW:
1289: inwindow = 1;
1290: newmousecounters = 1;
1291: break;
1292:
1293: case IDCMP_INACTIVEWINDOW:
1294: inwindow = 0;
1295: break;
1296:
1297: default:
1298: fprintf(stderr, "Unknown class: %d\n",class);
1299: break;
1300: }
1301: }
1302: /* "Affengriff" */
1303: if(keystate[AK_CTRL] && keystate[AK_LAMI] && keystate[AK_RAMI])
1304: m68k_reset();
1305:
1306: /* PC-like :-) CTRL-ALT-DEL => reboot */
1307: if(keystate[AK_CTRL] && (keystate[AK_LALT] || keystate[AK_RALT]) &&
1308: keystate[AK_DEL])
1309: m68k_reset();
1310:
1311: /* CTRL+LSHIFT+LALT+F10 on amiga => F12 on X11 */
1312: /* F9 => ScrollLock on X11 (inhibit_frame) */
1313: if(keystate[AK_CTRL] && keystate[AK_LSH] && keystate[AK_LALT]) {
1314: if(keystate[AK_F10]) togglemouse();
1315: if(keystate[AK_F9]) {
1316: inhibit_frame = inhibit_frame != 2 ? inhibit_frame ^ 1 :
1317: inhibit_frame;
1318: set_title();
1319: if(inhibit_frame) printf("display disabled\n");
1320: else printf("display enabled\n");
1321: }
1322: }
1323:
1324: disk_hotkeys();
1325: gui_handle_events();
1326: appw_events();
1327: }
1328:
1329: /***************************************************************************/
1330:
1331: int debuggable(void)
1332: {
1333: return 1;
1334: }
1335:
1336: /***************************************************************************/
1337:
1338: int needmousehack(void)
1339: {
1340: return 1;
1341: }
1342:
1343: /***************************************************************************/
1344:
1345: void LED(int on)
1346: {
1347: }
1348:
1349: /***************************************************************************/
1350:
1351: /* sam: need to put all this in a separate module */
1352:
1353: #ifdef PICASSO96
1354:
1355: void DX_Invalidate (int first, int last)
1356: {
1357: }
1358:
1359: int DX_BitsPerCannon (void)
1360: {
1361: return 8;
1362: }
1363:
1364: void DX_SetPalette(int start, int count)
1365: {
1366: }
1367:
1368: int DX_FillResolutions (uae_u16 *ppixel_format)
1369: {
1370: return 0;
1371: }
1372:
1373: void gfx_set_picasso_modeinfo (int w, int h, int depth)
1374: {
1375: }
1376:
1377: void gfx_set_picasso_baseaddr (uaecptr a)
1378: {
1379: }
1380:
1381: void gfx_set_picasso_state (int on)
1382: {
1383: }
1384:
1385: void begindrawing (void)
1386: {
1387: }
1388:
1389: void enddrawing (void)
1390: {
1391: }
1392:
1393: uae_u8 *lockscr (void)
1394: {
1395: return NULL;
1396: }
1397:
1398: void unlockscr (void)
1399: {
1400: }
1401: #endif
1402:
1403: /***************************************************************************/
1404:
1405: static int led_state[5];
1406:
1407: static void set_title(void)
1408: {
1409: static char title[80];
1410: static char ScreenTitle[100];
1411:
1412: if(!usepub) return;
1413:
1414: sprintf(title,"%sPower: [%c] Drives: [%c] [%c] [%c] [%c]",
1415: inhibit_frame?"UAE (PAUSED) - ":"UAE � ",
1416: led_state[0]?'X':' ',
1417: led_state[1]?'0':' ',
1418: led_state[2]?'1':' ',
1419: led_state[3]?'2':' ',
1420: led_state[4]?'3':' ');
1421:
1422: if(!*ScreenTitle) {
1423: sprintf(ScreenTitle,
1424: "UAE-%d.%d.%d � by Bernd Schmidt & contributors, "
1425: "Amiga Port by Samuel Devulder.",
1426: (version / 100) % 10, (version / 10) % 10, version % 10);
1427: SetWindowTitles(W, title, ScreenTitle);
1428: } else SetWindowTitles(W, title, (char*)-1);
1429: }
1430:
1431: /****************************************************************************/
1432:
1433: void main_window_led(int led, int on) /* is used in amigui.c */
1434: {
1435: if(led>=0 && led<=4) led_state[led] = on;
1436: set_title();
1437: }
1438:
1439: /****************************************************************************/
1440:
1441: static void unrecord(int kc)
1442: {
1443: keystate[kc] = 0;
1444: record_key ((kc << 1) | 1);
1445: }
1446:
1447: /****************************************************************************/
1448:
1449: static void disk_hotkeys(void)
1450: {
1451: struct FileRequester *FileRequest;
1452: char buff[80];
1453: int drive;
1454: char *last_file,*last_dir,*s;
1455:
1456: if(!(keystate[AK_CTRL] && keystate[AK_LALT])) return;
1457:
1458: /* CTRL-LSHIFT-LALT F1-F4 => eject_disk */
1459: if(keystate[AK_LSH]) {
1460: int ok = 0;
1461:
1462: if(keystate[AK_F1]) {ok=1;disk_eject(0);
1463: printf("drive DF0: ejected\n");}
1464: if(keystate[AK_F2]) {ok=1;disk_eject(1);
1465: printf("drive DF1: ejected\n");}
1466: if(keystate[AK_F3]) {ok=1;disk_eject(2);
1467: printf("drive DF2: ejected\n");}
1468: if(keystate[AK_F4]) {ok=1;disk_eject(3);
1469: printf("drive DF3: ejected\n");}
1470:
1471: if(ok) {
1472: unrecord(AK_CTRL);unrecord(AK_LALT);unrecord(AK_LSH);
1473: unrecord(AK_F1);unrecord(AK_F2);
1474: unrecord(AK_F3);unrecord(AK_F4);
1475: }
1476: return;
1477: }
1478:
1479: /* CTRL-LALT F1-F4 => insert_disk */
1480: if(keystate[AK_F1]) {drive = 0;unrecord(AK_F1);}
1481: else if(keystate[AK_F2]) {drive = 1;unrecord(AK_F2);}
1482: else if(keystate[AK_F3]) {drive = 2;unrecord(AK_F3);}
1483: else if(keystate[AK_F4]) {drive = 3;unrecord(AK_F4);}
1484: else return;
1485: unrecord(AK_CTRL);unrecord(AK_LALT);
1486:
1487: switch(drive) {
1488: case 0: case 1: case 2: case 3: last_file = currprefs.df[drive]; break;
1489: default: return;
1490: }
1491:
1492: split_dir_file(from_unix_path(last_file), &last_dir, &last_file);
1493: if(!last_file) return;
1494: if(!last_dir) return;
1495:
1496: if(!AslBase) AslBase = OpenLibrary("asl.library",36);
1497: if(!AslBase) {
1498: fprintf(stderr,"Can't open asl.library v36 !");
1499: return;
1500: }
1501:
1502: FileRequest = AllocAslRequest(ASL_FileRequest,NULL);
1503: if(!FileRequest) {
1504: fprintf(stderr,"Unable to allocate file requester.\n");
1505: return;
1506: }
1507:
1508: sprintf(buff,"Select file to use for drive DF%d:",drive);
1509: if(AslRequestTags(FileRequest,
1510: use_graffiti?TAG_IGNORE:
1511: ASLFR_Window, (ULONG)W,
1512: ASLFR_TitleText, (ULONG)buff,
1513: ASLFR_InitialDrawer, (ULONG)last_dir,
1514: ASLFR_InitialFile, (ULONG)last_file,
1515: ASLFR_InitialPattern, (ULONG)"(#?.ad(f|z)#?|df?|?)",
1516: ASLFR_DoPatterns, TRUE,
1517: ASLFR_RejectIcons, TRUE,
1518: TAG_DONE)) {
1519: free(last_file);
1520: last_file = malloc(3 + strlen(FileRequest->fr_Drawer) +
1521: strlen(FileRequest->fr_File));
1522: if((last_file)) {
1523: s = last_file;
1524: strcpy(s,FileRequest->fr_Drawer);
1525: if(*s && !(s[strlen(s)-1]==':' || s[strlen(s)-1]=='/'))
1526: strcat(s,"/");
1527: strcat(s,FileRequest->fr_File);
1528: last_file = to_unix_path(s);free(s);
1529: }
1530: } else {
1531: free(last_file);
1532: last_file = NULL;
1533: }
1534: FreeAslRequest(FileRequest);
1535: free(last_dir);
1536:
1537: if(last_file) {
1538: disk_insert(drive,last_file);
1539: free(last_file);
1540: }
1541: }
1542:
1543: /****************************************************************************/
1544: /*
1545: * Routines for OS2.0 (code taken out of mpeg_play by Michael Balzer)
1546: */
1547: static struct BitMap *myAllocBitMap(ULONG sizex, ULONG sizey, ULONG depth,
1548: ULONG flags, struct BitMap *friend_bitmap)
1549: {
1550: struct BitMap *bm;
1551: unsigned long extra;
1552:
1553: if(os39) return AllocBitMap(sizex, sizey, depth, flags, friend_bitmap);
1554:
1555: extra = (depth > 8) ? depth - 8 : 0;
1556: bm = AllocVec( sizeof *bm + (extra * 4), MEMF_CLEAR );
1557:
1558: if( bm )
1559: {
1560: ULONG i;
1561: InitBitMap(bm, depth, sizex, sizey);
1562: for( i=0; i<depth; i++ )
1563: {
1564: if( !(bm->Planes[i] = AllocRaster(sizex, sizey)) )
1565: {
1566: while(i--) FreeRaster(bm->Planes[i], sizex, sizey);
1567: FreeVec(bm);
1568: bm = 0;
1569: break;
1570: }
1571: }
1572: }
1573: return bm;
1574: }
1575:
1576: /****************************************************************************/
1577:
1578: static void myFreeBitMap(struct BitMap *bm)
1579: {
1580: if(os39) {FreeBitMap(bm);return;}
1581: while(bm->Depth--)
1582: FreeRaster(bm->Planes[bm->Depth], bm->BytesPerRow*8, bm->Rows);
1583: FreeVec(bm);
1584: }
1585:
1586: /****************************************************************************/
1587: /*
1588: * find the best appropriate color. return -1 if none is available
1589: */
1590: static LONG ObtainColor(ULONG r,ULONG g,ULONG b)
1591: {
1592: int i, crgb;
1593: int colors;
1594:
1595: if(use_graffiti) {
1596: if(maxpen >= 256) {
1597: fprintf(stderr,"Asking more than 256 colors for graffiti ?\n");
1598: abort();
1599: }
1600: graffiti_SetRGB(maxpen, r>>24, g>>24, b>>24);
1601: return maxpen++;
1602: }
1603:
1604: if(os39 && usepub && CM) {
1605: i = ObtainBestPen(CM,r,g,b,
1606: OBP_Precision, (use_approx_color?PRECISION_GUI:
1607: PRECISION_EXACT),
1608: OBP_FailIfBad, TRUE,
1609: TAG_DONE);
1610: if(i != -1) {
1611: if(maxpen<256) pen[maxpen++] = i;
1612: else i = -1;
1613: }
1614: return i;
1615: }
1616:
1617: if(os39 && use_cyb) {
1618: if(maxpen >= 256) return -1;
1619: SetRGB32(&S->ViewPort, maxpen, r, g, b);
1620: return maxpen++;
1621: }
1622:
1623: r >>= 28; g >>= 28; b >>= 28;
1624:
1625: colors = is_halfbrite?32:(1<<RPDepth(RP));
1626:
1627: /* private screen => standard allocation */
1628: if(!usepub) {
1629: if(maxpen >= colors) return -1; /* no more colors available */
1630: SetRGB4(&S->ViewPort, maxpen, r, g, b);
1631: return maxpen++;
1632: }
1633:
1634: /* public => find exact match */
1635: if(use_approx_color) return get_nearest_color(r,g,b);
1636: crgb = (r<<8)|(g<<4)|b;
1637: for(i=0; i<colors; i++ ) {
1638: int rgb = GetRGB4(CM, i);
1639: if(rgb == crgb) return i;
1640: }
1641: return -1;
1642: }
1643:
1644: /****************************************************************************/
1645: /*
1646: * free a color entry
1647: */
1648: static void ReleaseColors(void)
1649: {
1650: if(os39 && usepub && CM)
1651: while(maxpen>0) ReleasePen(CM, pen[--maxpen]);
1652: else maxpen = 0;
1653: }
1654:
1655: /****************************************************************************/
1656:
1657: static int DoSizeWindow(struct Window *W,int wi,int he)
1658: {
1659: register int x,y;
1660: int ret = 1;
1661:
1662: wi += W->BorderRight + W->BorderLeft;
1663: he += W->BorderBottom + W->BorderTop;
1664: x = W->LeftEdge;
1665: y = W->TopEdge;
1666:
1667: if(x + wi >= W->WScreen->Width) x = W->WScreen->Width - wi;
1668: if(y + he >= W->WScreen->Height) y = W->WScreen->Height - he;
1669:
1670: if(x<0 || y<0) {
1671: fprintf(stderr, "Working screen too small to open window (%dx%d)!\n",
1672: wi, he);
1673: if(x<0) {x = 0; wi = W->WScreen->Width;}
1674: if(y<0) {y = 0; he = W->WScreen->Height;}
1675: ret = 0;
1676: }
1677:
1678: x -= W->LeftEdge;
1679: y -= W->TopEdge;
1680: wi -= W->Width;
1681: he -= W->Height;
1682:
1683: if(x|y) MoveWindow(W,x,y);
1684: if(wi|he) SizeWindow(W,wi,he);
1685: return ret;
1686: }
1687:
1688: /****************************************************************************/
1689: /*
1690: * support code for graffiti card
1691: */
1692: static void graffiti_SetRGB(int i, int r, int g, int b)
1693: {
1694: UWORD **ptr = (void*)RP->BitMap->Planes;
1695:
1696: *(*ptr++ + i) = 0x0406;
1697: *(*ptr++ + i) = (i<<8)|((g>>2)&0x3f);
1698: *(*ptr++ + i) = 0x0606;
1699: *(*ptr + i) = ((r<<6)&0x3f00)|((b>>2)&0x3f);
1700: }
1701:
1702: /****************************************************************************/
1703:
1704: static void graffiti_WritePixelLine8(int x, int y, short len, char *line)
1705: {
1706: #if 0
1707: /* standard code */
1708: char **ptr = (void*)RP->BitMap->Planes;
1709:
1710: y += 8;
1711: x += (y*80)<<2;
1712: while(len--) {
1713: *(ptr[x&3] + (x>>2)) = *line++;
1714: ++x;
1715: }
1716: #else
1717: /* this one must be quite fast for 680x0 processor */
1718: char **ptr;
1719: char *ptr0,*ptr1,*ptr2,*ptr3;
1720: ptr = (void*)RP->BitMap->Planes;
1721: switch(x&3) {
1722: case 0: ptr0=*ptr++; ptr1=*ptr++; ptr2=*ptr++; ptr3=*ptr; break;
1723: case 1: ptr3=*ptr++ + 1; ptr0=*ptr++; ptr1=*ptr++; ptr2=*ptr; break;
1724: case 2: ptr2=*ptr++ + 1; ptr3=*ptr++ + 1; ptr0=*ptr++; ptr1=*ptr; break;
1725: default:
1726: case 3: ptr1=*ptr++ + 1; ptr2=*ptr++ + 1; ptr3=*ptr++ + 1; ptr0=*ptr; break;
1727: }
1728: x >>= 2; x += (80*(y+8));
1729: ptr0 += x; ptr1 += x; ptr2 += x; ptr3 += x;
1730: ++len;
1731: /* full speed here */
1732: while(1) {
1733: if(--len) *ptr0++ = *line++; else break;
1734: if(--len) *ptr1++ = *line++; else break;
1735: if(--len) *ptr2++ = *line++; else break;
1736: if(--len) *ptr3++ = *line++; else break;
1737: }
1738: #endif
1739: }
1740:
1741: /****************************************************************************/
1742:
1743: #define MAKEID(a,b,c,d) ((a<<24)|(b<<16)|(c<<8)|d)
1744:
1745: static int SaveIFF(char *filename, struct Screen *scr)
1746: {
1747: struct DisplayInfo DI;
1748: FILE *file;
1749: ULONG BODYsize;
1750: ULONG modeid;
1751: ULONG count;
1752: ULONG i;
1753:
1754: struct {ULONG iff_type, iff_length;} chunk;
1755: struct {ULONG fc_type, fc_length, fc_subtype;} FORM;
1756: struct {
1757: UWORD w,h,x,y;
1758: UBYTE depth,masking,compression,pad1;
1759: UWORD transparentColor;
1760: UBYTE xAspect,yAspect;
1761: WORD pagewidth,pageheight;
1762: } BMHD;
1763:
1764: BODYsize = scr->BitMap.Depth * scr->BitMap.Rows * 2 * ((scr->Width+15)/16);
1765: modeid = GetVPModeID(&S->ViewPort);
1766: count = scr->ViewPort.ColorMap->Count;
1767:
1768: FORM.fc_type = MAKEID('F','O','R','M');
1769: FORM.fc_length = 4 + /* ILBM */
1770: 8 + sizeof(BMHD) + /* BMHD */
1771: 8 + 4 + /* CAMG */
1772: 8 + 3*count + /* CMAP */
1773: 8 + BODYsize; /* BODY */
1774: FORM.fc_subtype = MAKEID('I','L','B','M');
1775:
1776: if(!(file = fopen(filename,"w"))) return 0;
1777: if(fwrite(&FORM,sizeof(FORM),1,file)!=1) goto err;
1778:
1779: BMHD.w =
1780: BMHD.pagewidth = scr->Width;
1781: BMHD.h =
1782: BMHD.pageheight = scr->Height;
1783: BMHD.x = 0;
1784: BMHD.y = 0;
1785: BMHD.depth = scr->BitMap.Depth;
1786: BMHD.masking = 0;
1787: BMHD.compression = 0;
1788: BMHD.pad1 = 0;
1789: BMHD.transparentColor = 0;
1790: BMHD.xAspect = 22;
1791: BMHD.yAspect = 11;
1792:
1793: if(GetDisplayInfoData(NULL, (UBYTE *)&DI, sizeof(struct DisplayInfo),
1794: DTAG_DISP, modeid)) {
1795: BMHD.xAspect = DI.Resolution.x;
1796: BMHD.yAspect = DI.Resolution.y;
1797: }
1798:
1799: chunk.iff_type = MAKEID('B','M','H','D');
1800: chunk.iff_length = sizeof(BMHD);
1801: if(fwrite(&chunk,sizeof(chunk),1,file)!=1
1802: || fwrite(&BMHD, sizeof(BMHD), 1,file)!=1) goto err;
1803:
1804: chunk.iff_type = MAKEID('C','A','M','G');
1805: chunk.iff_length = sizeof(modeid);
1806: if(fwrite(&chunk, sizeof(chunk), 1,file)!=1
1807: || fwrite(&modeid,chunk.iff_length,1,file)!=1) goto err;
1808:
1809: chunk.iff_type = MAKEID('C','M','A','P');
1810: chunk.iff_length = 3 * count;
1811: if(fwrite(&chunk,sizeof(chunk),1,file)!=1) goto err;
1812: for(i=0; i<count; ++i) {
1813: ULONG c = GetRGB4(scr->ViewPort.ColorMap, i);
1814: UBYTE d;
1815: d = (c>>8)&15;d |= d<<4;if(fwrite(&d,1,1,file)!=1) goto err;
1816: d = (c>>4)&15;d |= d<<4;if(fwrite(&d,1,1,file)!=1) goto err;
1817: d = (c>>0)&15;d |= d<<4;if(fwrite(&d,1,1,file)!=1) goto err;
1818: }
1819:
1820: chunk.iff_type = MAKEID('B','O','D','Y');
1821: chunk.iff_length = BODYsize;
1822: if(fwrite(&chunk,sizeof(chunk),1,file)!=1) goto err;
1823: {
1824: int r,p;
1825: struct BitMap *bm = S->RastPort.BitMap;
1826: for(r=0; r<bm->Rows; ++r) for(p=0; p<bm->Depth; ++p)
1827: if(fwrite(bm->Planes[p] + r*bm->BytesPerRow, 2*((S->Width+15)/16), 1, file)!=1) goto err;
1828: }
1829:
1830: fclose(file);
1831: return 1;
1832: err:
1833: fprintf(stderr,"Error writing to \"%s\"\n",filename);
1834: fclose(file);
1835: return 0;
1836: }
1837:
1838: void write_log (const char *buf)
1839: {
1840: fprintf (stderr, buf);
1841: }
1842:
1843: /****************************************************************************/
1844: /* Here lies an algorithm to convert a 12bits truecolor buffer into a HAM
1845: * buffer. That algorithm is quite fast and if you study it closely, you'll
1846: * understand why there is no need for MMX cpu to subtract three numbers in
1847: * the same time. I can think of a quicker algorithm but it'll need 4096*4096
1848: * = 1<<24 = 16Mb of memory. That's why I'm quite proud of this one which
1849: * only need roughly 64Kb (could be reduced down to 40Kb, but it's not
1850: * worth as I use cidx as a buffer which is 128Kb long)..
1851: ****************************************************************************/
1852:
1853: static int dist4(LONG rgb1, LONG rgb2) /* computes distance very quickly */
1854: {
1855: int d = 0, t;
1856: t = (rgb1&0xF00)-(rgb2&0xF00); t>>=8; if (t<0) d -= t; else d += t;
1857: t = (rgb1&0x0F0)-(rgb2&0x0F0); t>>=4; if (t<0) d -= t; else d += t;
1858: t = (rgb1&0x00F)-(rgb2&0x00F); t>>=0; if (t<0) d -= t; else d += t;
1859: #if 0
1860: t = rgb1^rgb2;
1861: if(t&15) ++d; t>>=4;
1862: if(t&15) ++d; t>>=4;
1863: if(t&15) ++d;
1864: #endif
1865: return d;
1866: }
1867:
1868: #define d_dst (00000+(UBYTE*)cidx) /* let's use cidx as a buffer */
1869: #define d_cmd (16384+(UBYTE*)cidx)
1870: #define h_buf (32768+(UBYTE*)cidx)
1871:
1872: static int init_ham(void)
1873: {
1874: int i,t,RGB;
1875:
1876: /* try direct color first */
1877: for(RGB=0;RGB<4096;++RGB) {
1878: int c,d;
1879: c = d = 50;
1880: for(i=0;i<16;++i) {
1881: t = dist4(i*0x111, RGB);
1882: if(t<d) {
1883: d = t;
1884: c = i;
1885: }
1886: }
1887: i = (RGB&0x00F) | ((RGB&0x0F0)<<1) | ((RGB&0xF00)<<2);
1888: d_dst[i] = (d<<2)|3; /* the "|3" is a trick to speedup comparison */
1889: d_cmd[i] = c; /* in the conversion process */
1890: }
1891: /* then hold & modify */
1892: for(i=0;i<32768;++i) {
1893: int dr, dg, db, d, c;
1894: dr = (i>>10) & 0x1F; dr -= 0x10;if(dr<0) dr = -dr;
1895: dg = (i>>5) & 0x1F; dg -= 0x10;if(dg<0) dg = -dg;
1896: db = (i>>0) & 0x1F; db -= 0x10;if(db<0) db = -db;
1897: c = 0; d = 50;
1898: t = dist4(0, 0*256 + dg*16 + db); if(t < d) {d = t;c = 0;}
1899: t = dist4(0, dr*256 + 0*16 + db); if(t < d) {d = t;c = 1;}
1900: t = dist4(0, dr*256 + dg*16 + 0); if(t < d) {d = t;c = 2;}
1901: h_buf[i] = (d<<2) | c;
1902: }
1903: return 1;
1904: }
1905:
1906: /* great algorithm: convert trucolor into ham using precalc buffers */
1907: static void ham_conv(UWORD *src, UBYTE *buf, UWORD len)
1908: {
1909: /* A good compiler (ie. gcc :) will use bfext/bfins instructions */
1910: #ifdef __SASC
1911: union { struct { unsigned int _:17, r:5, g:5, b:5; } _;
1912: int all;} rgb, RGB;
1913: #else
1914: union { struct { UWORD _:1,r:5,g:5,b:5;} _; UWORD all;} rgb, RGB;
1915: #endif
1916: rgb.all = 0;
1917: while(len--) {
1918: UBYTE c,t;
1919: RGB.all = *src++;
1920: c = d_cmd[RGB.all];
1921: /* cowabonga! */
1922: t = h_buf[16912 + RGB.all - rgb.all];
1923: if(t<=d_dst[RGB.all]) {
1924: if(!(t&=3)) {c = 32; c |= (rgb._.r = RGB._.r);}
1925: else if(!--t) {c = 48; c |= (rgb._.g = RGB._.g);}
1926: else {c = 16; c |= (rgb._.b = RGB._.b);}
1927: } else rgb._.r = rgb._.g = rgb._.b = c;
1928: *buf++ = c;
1929: }
1930: }
1931:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.