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

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

unix.superglobalmegacorp.com

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