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