Annotation of uae/src/od-amiga/ami-win.c, revision 1.1

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: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.