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