Annotation of uae/src/od-amiga/ami-win.c, revision 1.1.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.