|
|
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 "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" 1.1.1.4 ! root 188: #undef BitMap 1.1 root 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.4 ! 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) { 1.1.1.4 ! root 346: ham_conv((void*)linebuf,Line,len); ! 347: myWritePixelLine8(RP, 0, y, len, Line, TempRPort); ! 348: return; 1.1 root 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) { 1.1.1.4 ! root 356: myBltBitMapRastPort(CybBitMap, 0, y, ! 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 */ 1.1 root 361: return; 362: } 363: #endif 364: 365: #if 0 366: if(use_graffiti && !need_dither) { 1.1.1.4 ! root 367: graffiti_WritePixelLine8(0, y, gfxvidinfo.rowbytes, linebuf); 1.1 root 368: } 369: #endif 370: 1.1.1.2 root 371: if(!use_delta_buffer) { 372: dst = linebuf; 373: } else switch(gfxvidinfo.pixbytes) { 1.1.1.4 ! 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; 1.1 root 384: case 2: 1.1.1.4 ! root 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; 1.1 root 397: case 1: 1.1.1.4 ! root 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); ! 409: } break; 1.1 root 410: default: 1.1.1.4 ! root 411: abort(); ! 412: break; 1.1 root 413: } 1.1.1.2 root 414: 1.1 root 415: if (need_dither) { 1.1.1.4 ! root 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.1.4 ! 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.1.4 ! root 431: int len = gfxvidinfo.width; ! 432: myBltBitMapRastPort(CybBitMap, ! 433: 0, ystart, ! 434: RP, XOffset, YOffset+ystart, ! 435: len, ystop-ystart+1, 0xc0); ! 436: return; 1.1 root 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) { 1.1.1.4 ! root 443: myWritePixelArray8(RP, XOffset, ! 444: ystart + YOffset, 1.1.1.2 root 445: XOffset + gfxvidinfo.width - 1, 1.1.1.4 ! root 446: ystop + YOffset, ! 447: gfxvidinfo.bufmem + ystart*gfxvidinfo.rowbytes, 1.1.1.2 root 448: TempRPort); 1.1.1.4 ! root 449: return; 1.1.1.2 root 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) { 1.1.1.4 ! root 503: get_color_failed = 1; ! 504: return 0; 1.1 root 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, 1.1.1.4 ! root 517: int *x, int *y, int *z) 1.1 root 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, 1.1.1.4 ! root 524: int r2, int g2, int b2) 1.1 root 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)); 1.1.1.4 ! root 550: 1.1.1.2 root 551: #ifdef POWERUP 1.1.1.4 ! root 552: if(!RGB_cache && 1.1.1.2 root 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.4 ! root 560: long rgb; ! 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 1.1.1.4 ! root 569: OS ROUTINES :((( */ ! 570: if(RGB_cache) { ! 571: rgb = RGB_cache[i]; 1.1.1.2 root 572: if(rgb<0) rgb = RGB_cache[i] = GetRGB4(CM,i); 573: } else rgb = GetRGB4(CM,i); 574: #else 1.1.1.4 ! root 575: rgb = GetRGB4(CM, i); 1.1.1.2 root 576: #endif 1.1.1.4 ! 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: } 1.1 root 598: } 599: return best; 600: } 601: 602: /****************************************************************************/ 603: 604: static int init_colors(void) 605: { 606: gfxvidinfo.can_double = 0; 607: if (need_dither) { 1.1.1.4 ! root 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 :-( */ 1.1 root 648: } 1.1.1.4 ! root 649: 1.1 root 650: /* No dither */ 651: switch(RPDepth(RP)) { 652: case 6: if (is_halfbrite) { 1.1.1.4 ! root 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; 1.1 root 664: } else if(is_ham) { 1.1.1.4 ! root 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(); 1.1 root 670: } 671: 672: case 1: case 2: case 3: case 4: case 5: case 7: case 8: { 1.1.1.4 ! root 673: int maxcol = 1<<RPDepth(RP); 1.1 root 674: 1.1.1.4 ! root 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; 1.1 root 693: 694: case 15: 1.1.1.4 ! root 695: printf("Using %d bits truecolor.\n",15); ! 696: alloc_colors64k(5,5,5,10,5,0); ! 697: break; 1.1 root 698: 699: case 16: 1.1.1.4 ! root 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; 1.1 root 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 = { 1.1.1.4 ! root 736: 0,0, 800,600, 3, 0,1, ! 737: LACE+HIRES, CUSTOMSCREEN|SCREENQUIET|SCREENBEHIND, ! 738: NULL, (void*)"UAE", NULL, NULL}; 1.1 root 739: static struct NewWindow NewWindowStructure = { 1.1.1.4 ! root 740: 0,0, 800,600, 0,1, ! 741: IDCMP_MOUSEBUTTONS|IDCMP_RAWKEY|IDCMP_DISKINSERTED|IDCMP_DISKREMOVED| ! 742: IDCMP_ACTIVEWINDOW|IDCMP_INACTIVEWINDOW|IDCMP_MOUSEMOVE| ! 743: IDCMP_DELTAMOVE, ! 744: WFLG_SMART_REFRESH|WFLG_BACKDROP|WFLG_RMBTRAP|WFLG_NOCAREREFRESH| ! 745: WFLG_BORDERLESS|WFLG_ACTIVATE|WFLG_REPORTMOUSE, ! 746: NULL, NULL, (void*)"UAE", NULL, NULL, 5,5, 800,600, ! 747: CUSTOMSCREEN}; 1.1 root 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) | 1.1.1.4 ! root 753: (currprefs.gfx_height>256?LACE:NULL); ! 754: 1.1 root 755: do S = (void*)OpenScreen(&NewScreenStructure); 756: while(!S && --NewScreenStructure.Depth); 757: if(!S) { 1.1.1.4 ! root 758: fprintf(stderr, "Can't open custom screen !\n"); ! 759: return 0; 1.1 root 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) { 1.1.1.4 ! root 770: fprintf(stderr, "Can't open window on custom screen !\n"); ! 771: return 0; 1.1 root 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}; 1.1.1.4 ! root 782: 1.1 root 783: S = LockPubScreen(NULL); 784: if(!S) { 1.1.1.4 ! root 785: fprintf(stderr,"No public screen !\n"); ! 786: return 0; 1.1 root 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) { 1.1.1.4 ! root 795: if(currprefs.gfx_height + S->BarHeight + 1 >= S->Height) { ! 796: currprefs.gfx_height >>= 1; ! 797: currprefs.gfx_correct_aspect = 1; ! 798: } 1.1 root 799: } 800: 801: W = OpenWindowTags(NULL, 1.1.1.4 ! root 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| ! 813: IDCMP_DELTAMOVE| ! 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: 1.1 root 828: UnlockPubScreen(NULL, S); 829: 830: if(!W) { 1.1.1.4 ! root 831: fprintf(stderr,"Can't open window on public screen !\n"); ! 832: CM = NULL; ! 833: return 0; 1.1 root 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') { 1.1.1.4 ! root 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; 1.1.1.2 root 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) { 1.1.1.4 ! root 907: fprintf(stderr,"Can't open asl.library v38 !"); ! 908: return 0; 1.1 root 909: } 910: 911: ScreenRequest = AllocAslRequest(ASL_ScreenModeRequest,NULL); 912: if(!ScreenRequest) { 1.1.1.4 ! root 913: fprintf(stderr,"Unable to allocate screen mode requester.\n"); ! 914: return 0; 1.1 root 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, 1.1.1.4 ! root 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: } 1.1 root 944: else DisplayID = INVALID_ID; 1.1.1.2 root 945: } 1.1 root 946: FreeAslRequest(ScreenRequest); 1.1.1.4 ! root 947: 1.1 root 948: if(DisplayID == (ULONG)INVALID_ID) return 0; 949: 1.1.1.4 ! root 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, 1.1.1.4 ! root 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); 1.1 root 978: if(!S) { 1.1.1.4 ! root 979: fprintf(stderr,"Unable to open the screen.\n"); ! 980: return 0; 1.1 root 981: } 1.1.1.4 ! 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, 1.1.1.4 ! root 994: POINTERA_BitMap, (ULONG)&PointerBitMap, ! 995: POINTERA_WordWidth, 1, ! 996: TAG_DONE); 1.1 root 997: if(!Pointer) 1.1.1.4 ! root 998: fprintf(stderr,"Warning: Unable to allocate blank mouse pointer.\n"); 1.1 root 999: 1000: W = OpenWindowTags(NULL, 1.1.1.4 ! root 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, ! 1007: WA_Activate, TRUE, ! 1008: WA_ReportMouse, TRUE, ! 1009: WA_IDCMP, IDCMP_MOUSEBUTTONS| ! 1010: IDCMP_RAWKEY| ! 1011: IDCMP_DISKINSERTED| ! 1012: IDCMP_DISKREMOVED| ! 1013: IDCMP_ACTIVEWINDOW| ! 1014: IDCMP_INACTIVEWINDOW| ! 1015: IDCMP_MOUSEMOVE| ! 1016: IDCMP_DELTAMOVE, ! 1017: (os39?WA_BackFill:TAG_IGNORE), (ULONG)LAYERS_NOBACKFILL, ! 1018: (Pointer?WA_Pointer:TAG_IGNORE), (ULONG)Pointer, ! 1019: TAG_DONE); 1.1 root 1020: 1021: if(!W) { 1.1.1.4 ! root 1022: fprintf(stderr,"Unable to open the window.\n"); ! 1023: CloseScreen(S);S=NULL;RP=NULL;CM=NULL; ! 1024: return 0; 1.1 root 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", 1.1.1.4 ! root 1031: DisplayID,Depth, DisplayID,Depth); ! 1032: 1.1 root 1033: return 1; 1034: } 1035: 1036: /****************************************************************************/ 1037: 1038: static int setup_graffiti(void) 1039: { 1040: static struct NewScreen NewScreenStructure = { 1.1.1.4 ! root 1041: 0,0, 800,600, 4, 0,1, ! 1042: HIRES, CUSTOMSCREEN|SCREENQUIET/*|SCREENBEHIND*/, ! 1043: NULL, (void*)"UAE", NULL, NULL}; 1.1 root 1044: static struct NewWindow NewWindowStructure = { 1.1.1.4 ! root 1045: 0,0, 800,600, 0,1, ! 1046: IDCMP_MOUSEBUTTONS|IDCMP_RAWKEY|IDCMP_DISKINSERTED|IDCMP_DISKREMOVED| ! 1047: IDCMP_ACTIVEWINDOW|IDCMP_INACTIVEWINDOW|IDCMP_MOUSEMOVE| 1.1.1.2 root 1048: IDCMP_DELTAMOVE, 1.1.1.4 ! root 1049: WFLG_SMART_REFRESH|WFLG_BACKDROP|WFLG_RMBTRAP|WFLG_NOCAREREFRESH| ! 1050: WFLG_BORDERLESS|WFLG_ACTIVATE|WFLG_REPORTMOUSE, ! 1051: NULL, NULL, (void*)"UAE", NULL, NULL, 5,5, 800,600, ! 1052: CUSTOMSCREEN}; 1.1 root 1053: static short colarr[] = { 1.1.1.4 ! root 1054: 0x000,0x001,0x008,0x009,0x080,0x081,0x088,0x089, ! 1055: 0x800,0x801,0x808,0x809,0x880,0x881,0x888,0x889}; 1.1 root 1056: int i; 1057: 1058: NewScreenStructure.Width = 2*currprefs.gfx_width; 1059: /* I leave 8 extra lines for palette & mode: */ 1.1.1.4 ! root 1060: NewScreenStructure.Height = currprefs.gfx_height+8; 1.1 root 1061: NewScreenStructure.Depth = 4; 1062: NewScreenStructure.ViewModes = HIRES|GENLOCK_AUDIO/*|GENLOCK_VIDEO*/; 1.1.1.4 ! root 1063: /* ^^ ^^ which one ? */ ! 1064: 1.1 root 1065: S = (void*)OpenScreen(&NewScreenStructure); 1066: if(!S) { 1.1.1.4 ! root 1067: fprintf(stderr, "Can't open graffiti screen !\n"); ! 1068: return 0; 1.1 root 1069: } 1070: 1071: for(i=0;i<15;++i) { 1.1.1.4 ! root 1072: unsigned int rgb = colarr[i]; ! 1073: SetRGB4(&S->ViewPort,i,(rgb>>8)&15,(rgb>>4)&15,rgb&15); 1.1 root 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) { 1.1.1.4 ! root 1084: fprintf(stderr, "Can't open window on graffiti screen !\n"); ! 1085: return 0; 1.1 root 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) { 1.1.1.4 ! root 1092: short *p; ! 1093: int i; ! 1094: p = (void*)RP->BitMap->Planes[d]; ! 1095: for(i=0;i<40*7;++i) p[i] = 0; 1.1 root 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) { 1.1.1.4 ! root 1111: ix_req(NULL, "Abort", NULL, "That version of %s is only for AmigaOS!", __progname); ! 1112: exit(20); ! 1113: } 1.1 root 1114: #endif 1.1.1.2 root 1115: if(((struct ExecBase *)SysBase)->LibNode.lib_Version < 36) { 1.1.1.4 ! root 1116: fprintf(stderr, "UAE needs OS 2.0+ !\n"); ! 1117: return 0; 1.1 root 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) { 1.1.1.4 ! root 1125: fprintf(stderr,"No intuition.library ?\n"); ! 1126: return 0; 1.1 root 1127: } 1128: GfxBase = (void*)OpenLibrary("graphics.library",0L); 1129: if(!GfxBase) { 1.1.1.4 ! root 1130: fprintf(stderr,"No graphics.library ?\n"); ! 1131: return 0; 1.1 root 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; 1.1.1.4 ! root 1150: 1.1 root 1151: if (currprefs.gfx_width < 320) 1.1.1.4 ! root 1152: currprefs.gfx_width = 320; 1.1 root 1153: if (!currprefs.gfx_correct_aspect && (currprefs.gfx_height < 64/*200*/)) 1.1.1.4 ! root 1154: currprefs.gfx_height = 200; 1.1 root 1155: currprefs.gfx_width += 7; 1156: currprefs.gfx_width &= ~7; 1157: 1158: if (currprefs.color_mode > 5) 1.1.1.4 ! root 1159: fprintf(stderr, "Bad color mode selected. Using default.\n"), currprefs.color_mode = 0; ! 1160: 1.1 root 1161: if(currprefs.color_mode == 3) { /* graffiti */ 1.1.1.4 ! root 1162: currprefs.gfx_width = 320; ! 1163: if(currprefs.gfx_height > 256) ! 1164: currprefs.gfx_height = 256; ! 1165: currprefs.gfx_lores = 1; 1.1 root 1166: } /* graffiti */ 1.1.1.4 ! root 1167: 1.1 root 1168: gfxvidinfo.width = currprefs.gfx_width; 1169: gfxvidinfo.height = currprefs.gfx_height; 1170: 1171: switch(currprefs.color_mode) { 1172: case 3: 1.1.1.4 ! root 1173: if(setup_graffiti()) {use_graffiti = 1;break;} ! 1174: fprintf(stderr,"Asking user for screen...\n"); ! 1175: /* fall trough */ 1.1 root 1176: case 2: 1.1.1.4 ! root 1177: if(setup_userscreen()) break; ! 1178: fprintf(stderr,"Trying on public screen...\n"); ! 1179: /* fall trough */ 1.1 root 1180: case 1: 1.1.1.4 ! root 1181: is_halfbrite = 0; ! 1182: if(setup_publicscreen()) {usepub = 1;break;} ! 1183: fprintf(stderr,"Trying on custom screen...\n"); ! 1184: /* fall trough */ 1.1 root 1185: case 0: 1186: default: 1.1.1.4 ! root 1187: if(!setup_customscreen()) return 0; ! 1188: break; 1.1 root 1189: } 1190: 1191: Line = AllocVec((currprefs.gfx_width + 15) & ~15,MEMF_ANY|MEMF_PUBLIC); 1192: if(!Line) { 1.1.1.4 ! root 1193: fprintf(stderr,"Unable to allocate raster buffer.\n"); ! 1194: return 0; 1.1 root 1195: } 1196: BitMap = myAllocBitMap(currprefs.gfx_width,1,8,BMF_CLEAR|BMF_MINPLANES,RP->BitMap); 1197: if(!BitMap) { 1.1.1.4 ! root 1198: fprintf(stderr,"Unable to allocate BitMap.\n"); ! 1199: return 0; 1.1 root 1200: } 1201: TempRPort = AllocVec(sizeof(struct RastPort),MEMF_ANY|MEMF_PUBLIC); 1202: if(!TempRPort) { 1.1.1.4 ! root 1203: fprintf(stderr,"Unable to allocate RastPort.\n"); ! 1204: return 0; 1.1 root 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) { 1.1.1.4 ! root 1214: /* ham 6 */ ! 1215: use_delta_buffer = 0; /* needless as the line must be fully */ ! 1216: need_dither = 0; /* recomputed */ ! 1217: gfxvidinfo.pixbytes = 2; 1.1 root 1218: } else if(bitdepth <= 8) { 1.1.1.4 ! root 1219: /* chunk2planar is slow so we define use_delta_buffer for all modes */ ! 1220: use_delta_buffer = 1; ! 1221: need_dither = use_dither || (bitdepth<=1); ! 1222: gfxvidinfo.pixbytes = need_dither?2:1; 1.1 root 1223: } else { 1.1.1.4 ! root 1224: /* Cybergfx mode */ ! 1225: use_delta_buffer = 0; ! 1226: need_dither = 0; ! 1227: gfxvidinfo.pixbytes = (bitdepth >= 24) ? 4 : (bitdepth >= 12) ? 2 : 1; 1.1 root 1228: } 1.1.1.4 ! root 1229: 1.1.1.2 root 1230: gfxvidinfo.emergmem = 0; 1231: gfxvidinfo.linemem = 0; 1.1 root 1232: if (!use_cyb) { 1.1.1.4 ! root 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 */ 1.1 root 1237: } else { 1238: #ifdef USE_CYBERGFX 1.1.1.4 ! root 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; 1.1 root 1256: #endif 1.1.1.4 ! root 1257: } 1.1 root 1258: if(!gfxvidinfo.bufmem) { 1.1.1.4 ! root 1259: fprintf(stderr,"Not enough memory for video bufmem.\n"); ! 1260: return 0; ! 1261: } 1.1 root 1262: 1.1.1.2 root 1263: if (use_delta_buffer) { 1.1.1.4 ! 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: } 1.1 root 1270: } else { 1.1.1.4 ! root 1271: gfxvidinfo.maxblocklines = 0; /* whatever... */ ! 1272: #ifdef POWERUP ! 1273: gfxvidinfo.maxblocklines = 100; /* sam: this will reduce the number of 68k-OS call */ ! 1274: /* to be done */ 1.1.1.2 root 1275: #endif 1.1 root 1276: } 1277: 1278: if (!init_colors()) { 1.1.1.4 ! root 1279: fprintf(stderr,"Failed to init colors.\n"); ! 1280: return 0; 1.1 root 1281: } 1282: switch (gfxvidinfo.pixbytes) { 1283: case 2: 1.1.1.4 ! root 1284: for (i = 0; i < 4096; i++) xcolors[i] *= 0x00010001; ! 1285: gfxvidinfo.can_double = 1; ! 1286: break; 1.1 root 1287: case 1: 1.1.1.4 ! root 1288: for (i = 0; i < 4096; i++) xcolors[i] *= 0x01010101; ! 1289: gfxvidinfo.can_double = 1; ! 1290: break; 1.1 root 1291: default: 1.1.1.4 ! root 1292: gfxvidinfo.can_double = 0; ! 1293: break; 1.1 root 1294: } 1295: 1296: if(!usepub) ScreenToFront(S); 1297: 1298: buttonstate[0] = buttonstate[1] = buttonstate[2] = 0; 1299: for(i=0; i<256; i++) 1.1.1.4 ! root 1300: keystate[i] = 0; ! 1301: ! 1302: lastmx = lastmy = 0; 1.1 root 1303: newmousecounters = 0; 1304: inwindow = 0; 1305: 1306: rexx_init(); 1307: 1308: if(getenv(UAEIFF) && !use_cyb) { 1.1.1.4 ! root 1309: dump_iff = 1; ! 1310: fprintf(stderr,"Saving to \"%s\"\n",getenv(UAEIFF)); 1.1 root 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) { 1.1.1.4 ! root 1325: WaitBlit(); ! 1326: myFreeBitMap(CybBitMap); ! 1327: CybBitMap = NULL; 1.1 root 1328: } 1329: #endif 1330: if(BitMap) { 1.1.1.4 ! root 1331: WaitBlit(); ! 1332: myFreeBitMap(BitMap); ! 1333: BitMap = NULL; 1.1 root 1334: } 1335: if(TempRPort) { 1.1.1.4 ! root 1336: FreeVec(TempRPort); ! 1337: TempRPort = NULL; 1.1 root 1338: } 1339: if(Line) { 1.1.1.4 ! root 1340: FreeVec(Line); ! 1341: Line = NULL; ! 1342: } 1.1 root 1343: if(CM) { 1.1.1.4 ! root 1344: ReleaseColors(); ! 1345: CM = NULL; 1.1 root 1346: } 1347: if(W) { 1.1.1.4 ! root 1348: CloseWindow(W); ! 1349: W = NULL; 1.1 root 1350: } 1351: if(Sprite) { 1.1.1.4 ! root 1352: FreeVec(Sprite); ! 1353: Sprite = NULL; 1.1 root 1354: } 1355: if(Pointer) { 1.1.1.4 ! root 1356: DisposeObject(Pointer); ! 1357: Pointer = NULL; 1.1 root 1358: } 1359: if(!usepub && S) { 1.1.1.4 ! root 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: } 1.1.1.4 ! root 1369: S = NULL; 1.1 root 1370: } 1371: if(AslBase) { 1.1.1.4 ! root 1372: CloseLibrary((void*)AslBase); ! 1373: AslBase = NULL; 1.1 root 1374: } 1375: if(GfxBase) { 1.1.1.4 ! root 1376: CloseLibrary((void*)GfxBase); ! 1377: GfxBase = NULL; 1.1 root 1378: } 1379: if(IntuitionBase) { 1.1.1.4 ! root 1380: CloseLibrary((void*)IntuitionBase); ! 1381: IntuitionBase = NULL; 1.1 root 1382: } 1383: if(CyberGfxBase) { 1.1.1.4 ! root 1384: CloseLibrary((void*)CyberGfxBase); ! 1385: CyberGfxBase = NULL; 1.1 root 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"); 1.1.1.4 ! root 1396: else printf("display enabled\n"); 1.1.1.2 root 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.1.4 ! root 1408: 1.1 root 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: */ 1.1.1.4 ! root 1419: if(SetSignal(0L, SIGBREAKF_CTRL_C|SIGBREAKF_CTRL_D) & ! 1420: (SIGBREAKF_CTRL_C|SIGBREAKF_CTRL_D)) { ! 1421: activate_debugger(); 1.1 root 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.1.4 ! root 1430: class = msg->Class; ! 1431: code = msg->Code; ! 1432: dmx = msg->MouseX; ! 1433: dmy = msg->MouseY; ! 1434: ReplyMsg((struct Message*)msg); ! 1435: ! 1436: switch(class) { ! 1437: case IDCMP_NEWSIZE: ! 1438: do_inhibit_frame((W->Flags & WFLG_ZOOMED)?1:0); ! 1439: break; ! 1440: ! 1441: case IDCMP_REFRESHWINDOW: ! 1442: if(use_delta_buffer) { ! 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: } ! 1452: } ! 1453: BeginRefresh(W); ! 1454: flush_block(0,currprefs.gfx_height-1); ! 1455: EndRefresh(W, TRUE); 1.1.1.2 root 1456: break; 1.1 root 1457: 1.1.1.4 ! root 1458: case IDCMP_CLOSEWINDOW: ! 1459: activate_debugger(); 1.1.1.2 root 1460: break; 1.1 root 1461: 1.1.1.4 ! root 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: ! 1476: lastmx += dmx; ! 1477: lastmy += dmy; ! 1478: break; ! 1479: ! 1480: case IDCMP_MOUSEBUTTONS: ! 1481: if(code==SELECTDOWN) buttonstate[0]=1; ! 1482: if(code==SELECTUP) buttonstate[0]=0; ! 1483: if(code==MIDDLEDOWN) buttonstate[2]=1; ! 1484: if(code==MIDDLEUP) buttonstate[2]=0; ! 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: } 1.1 root 1511: } 1512: /* "Affengriff" */ 1.1.1.4 ! root 1513: if(keystate[AK_CTRL] && keystate[AK_LAMI] && keystate[AK_RAMI]) ! 1514: m68k_reset(); 1.1 root 1515: 1516: /* PC-like :-) CTRL-ALT-DEL => reboot */ 1.1.1.4 ! root 1517: if(keystate[AK_CTRL] && (keystate[AK_LALT] || keystate[AK_RALT]) && ! 1518: keystate[AK_DEL]) ! 1519: m68k_reset(); 1.1 root 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(); */ 1.1.1.4 ! root 1525: if(keystate[AK_F8]) { ! 1526: uae_quit(); ! 1527: } ! 1528: if(keystate[AK_F9]) { ! 1529: do_inhibit_frame(inhibit_frame != 2 ? inhibit_frame ^ 1 : ! 1530: inhibit_frame); ! 1531: DisplayBeep(NULL); ! 1532: } 1.1 root 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]", 1.1.1.4 ! root 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: 1.1 root 1633: if(!*ScreenTitle) { 1.1.1.4 ! root 1634: sprintf(ScreenTitle, ! 1635: "UAE-%d.%d.%d (%s%s%s) � by Bernd Schmidt & contributors, " 1.1.1.2 root 1636: #ifdef POWERUP 1.1.1.4 ! root 1637: "Amiga Port by Samuel Devulder & Holger Jakob (PPC extensions).", 1.1.1.2 root 1638: #else 1.1.1.4 ! 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.1.4 ! root 1647: SetWindowTitles(W, title, ScreenTitle); 1.1 root 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]) { 1.1.1.4 ! root 1680: int ok = 0; 1.1 root 1681: 1.1.1.4 ! root 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) { ! 1692: DisplayBeep(NULL); ! 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; 1.1 root 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.1.4 ! root 1707: unrecord(AK_CTRL);unrecord(AK_LALT); 1.1 root 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) { 1.1.1.4 ! root 1720: fprintf(stderr,"Can't open asl.library v36 !"); ! 1721: return; 1.1 root 1722: } 1723: 1724: FileRequest = AllocAslRequest(ASL_FileRequest,NULL); 1725: if(!FileRequest) { 1.1.1.4 ! root 1726: fprintf(stderr,"Unable to allocate file requester.\n"); ! 1727: return; 1.1 root 1728: } 1729: 1730: sprintf(buff,"Select file to use for drive DF%d:",drive); 1731: if(AslRequestTags(FileRequest, 1.1.1.4 ! root 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: } 1.1 root 1752: } else { 1.1.1.4 ! root 1753: free(last_file); ! 1754: last_file = NULL; 1.1 root 1755: } 1756: FreeAslRequest(FileRequest); 1757: free(last_dir); 1758: 1759: if(last_file) { 1.1.1.4 ! root 1760: disk_insert(drive,last_file); ! 1761: free(last_file); 1.1 root 1762: } 1763: } 1764: 1765: /****************************************************************************/ 1766: /* 1767: * Routines for OS2.0 (code taken out of mpeg_play by Michael Balzer) 1768: */ 1.1.1.4 ! root 1769: static struct BitMap *myAllocBitMap(ULONG sizex, ULONG sizey, ULONG depth, ! 1770: ULONG flags, struct BitMap *friend_bitmap) 1.1 root 1771: { 1772: struct BitMap *bm; 1773: unsigned long extra; 1.1.1.4 ! root 1774: 1.1 root 1775: if(os39) return AllocBitMap(sizex, sizey, depth, flags, friend_bitmap); 1.1.1.4 ! root 1776: 1.1 root 1777: extra = (depth > 8) ? depth - 8 : 0; 1778: bm = AllocVec( sizeof *bm + (extra * 4), MEMF_CLEAR ); 1.1.1.4 ! root 1779: 1.1 root 1780: if( bm ) 1781: { 1.1.1.4 ! root 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: } 1.1 root 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) { 1.1.1.4 ! root 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++; 1.1 root 1824: } 1825: 1826: if(os39 && usepub && CM) { 1.1.1.4 ! root 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; 1.1 root 1837: } 1838: 1839: colors = is_halfbrite?32:(1<<RPDepth(RP)); 1.1.1.4 ! root 1840: 1.1 root 1841: /* private screen => standard allocation */ 1842: if(!usepub) { 1.1.1.4 ! root 1843: if(maxpen >= colors) return -1; /* no more colors available */ ! 1844: if(os39) SetRGB32(&S->ViewPort, maxpen, r, g, b); 1.1.1.2 root 1845: else SetRGB4 (&S->ViewPort, maxpen, r>>28, g>>28, b>>28); 1.1.1.4 ! root 1846: return maxpen++; 1.1 root 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++ ) { 1.1.1.4 ! root 1854: int rgb = GetRGB4(CM, i); ! 1855: if(rgb == crgb) return i; 1.1 root 1856: } 1857: return -1; 1858: } 1859: 1860: /****************************************************************************/ 1861: /* 1862: * free a color entry 1863: */ 1864: static void ReleaseColors(void) 1865: { 1.1.1.4 ! root 1866: if(os39 && usepub && CM) ! 1867: while(maxpen>0) ReleasePen(CM, pen[--maxpen]); 1.1 root 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; 1.1.1.4 ! root 1877: 1.1 root 1878: wi += W->BorderRight + W->BorderLeft; 1879: he += W->BorderBottom + W->BorderTop; 1880: x = W->LeftEdge; 1881: y = W->TopEdge; 1.1.1.4 ! root 1882: 1.1 root 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) { 1.1.1.4 ! root 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; 1.1 root 1892: } 1.1.1.4 ! root 1893: 1.1 root 1894: x -= W->LeftEdge; 1895: y -= W->TopEdge; 1896: wi -= W->Width; 1897: he -= W->Height; 1.1.1.4 ! root 1898: 1.1 root 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--) { 1.1.1.4 ! root 1929: *(ptr[x&3] + (x>>2)) = *line++; ! 1930: ++x; 1.1 root 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) { 1.1.1.4 ! root 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; 1.1 root 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) { 1.1.1.4 ! root 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; 1.1 root 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; 1.1.1.4 ! root 1969: 1.1 root 1970: struct {ULONG iff_type, iff_length;} chunk; 1971: struct {ULONG fc_type, fc_length, fc_subtype;} FORM; 1972: struct { 1.1.1.4 ! root 1973: UWORD w,h,x,y; ! 1974: UBYTE depth,masking,compression,pad1; ! 1975: UWORD transparentColor; ! 1976: UBYTE xAspect,yAspect; ! 1977: WORD pagewidth,pageheight; 1.1 root 1978: } BMHD; 1.1.1.4 ! root 1979: 1.1 root 1980: BODYsize = scr->BitMap.Depth * scr->BitMap.Rows * 2 * ((scr->Width+15)/16); 1981: modeid = GetVPModeID(&S->ViewPort); 1982: count = scr->ViewPort.ColorMap->Count; 1.1.1.4 ! root 1983: 1.1 root 1984: FORM.fc_type = MAKEID('F','O','R','M'); 1985: FORM.fc_length = 4 + /* ILBM */ 1.1.1.4 ! root 1986: 8 + sizeof(BMHD) + /* BMHD */ ! 1987: 8 + 4 + /* CAMG */ ! 1988: 8 + 3*count + /* CMAP */ ! 1989: 8 + BODYsize; /* BODY */ 1.1 root 1990: FORM.fc_subtype = MAKEID('I','L','B','M'); 1.1.1.4 ! root 1991: 1.1 root 1992: if(!(file = fopen(filename,"w"))) return 0; 1993: if(fwrite(&FORM,sizeof(FORM),1,file)!=1) goto err; 1994: 1.1.1.4 ! root 1995: BMHD.w = 1.1 root 1996: BMHD.pagewidth = scr->Width; 1.1.1.4 ! root 1997: BMHD.h = 1.1 root 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: 1.1.1.4 ! root 2009: if(GetDisplayInfoData(NULL, (UBYTE *)&DI, sizeof(struct DisplayInfo), ! 2010: DTAG_DISP, modeid)) { 1.1 root 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); 1.1.1.4 ! root 2017: if(fwrite(&chunk,sizeof(chunk),1,file)!=1 1.1 root 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: } 1.1.1.4 ! root 2045: 1.1 root 2046: fclose(file); 2047: return 1; 1.1.1.4 ! root 2048: err: 1.1 root 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 1.1.1.4 ! root 2071: t = rgb1^rgb2; 1.1 root 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) { 1.1.1.4 ! root 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 */ 1.1 root 2101: } 2102: /* then hold & modify */ 2103: for(i=0;i<32768;++i) { 1.1.1.4 ! root 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; 1.1 root 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 1.1.1.4 ! root 2123: union { struct { unsigned int _:17, r:5, g:5, b:5; } _; 1.1 root 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--) { 1.1.1.4 ! root 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 1.1.1.4 ! root 2136: if(t<=d_dst[RGB.all]) { 1.1.1.2 root 2137: static int ht[]={32+10,48+5,16+0}; ULONG m; 1.1.1.4 ! root 2138: t &= 3; m = 0x1F<<(ht[t]&15); ! 2139: m = ~m; rgb.all &= m; ! 2140: m = ~m; m &= RGB.all;rgb.all |= m; 1.1.1.2 root 2141: m >>= ht[t]&15; 2142: c = (ht[t]&~15) | m; 1.1.1.4 ! root 2143: } else { 1.1.1.2 root 2144: rgb.all = c; 1.1.1.4 ! root 2145: rgb.all <<= 5; rgb.all |= c; ! 2146: rgb.all <<= 5; rgb.all |= c; ! 2147: } ! 2148: #else ! 2149: if(t<=d_dst[RGB.all]) { ! 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);} } ! 2154: } else rgb._.r = rgb._.g = rgb._.b = c; 1.1.1.2 root 2155: #endif 1.1.1.4 ! root 2156: *buf++ = c; 1.1 root 2157: } 2158: } 2159: 1.1.1.2 root 2160: /****************************************************************************/ 2161: 2162: #ifdef POWERUP 2163: /* sam: here is the code to avoid spilled register trouble */ 1.1.1.4 ! root 2164: static void myBltBitMapRastPort(struct BitMap *srcBitMap, long xSrc, ! 2165: long ySrc, struct RastPort * destRP, ! 2166: long xDest, long yDest, long xSize, 1.1.1.2 root 2167: long ySize, unsigned long minterm) 2168: { 2169: BltBitMapRastPort(srcBitMap,xSrc,ySrc,destRP, 2170: xDest,yDest,xSize,ySize,minterm); 2171: } 1.1.1.4 ! root 2172: static void myWritePixelLine8(struct RastPort* a, int b, int c, 1.1.1.2 root 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.