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