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

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

unix.superglobalmegacorp.com

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