home *** CD-ROM | disk | FTP | other *** search
/ Amiga ISO Collection / AmigaUtilCD1.iso / Emulatoren / UAE061.LZH / uae-0.6.1 / awin.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-08-28  |  31.5 KB  |  1,121 lines

  1.  /* 
  2.   * UAE - The Un*x Amiga Emulator
  3.   * 
  4.   * Amiga interface
  5.   * 
  6.   * Copyright 1995, 1996 Bernd Schmidt
  7.   * Copyright 1996 Samuel Devulder, Olaf `Olsen' Barthel.
  8.   */
  9.  
  10. /*
  11.  * NOTE:
  12.  *      - Im quite unhappy with the color allocation scheme in case of
  13.  *        EXTRA_HALFBRITE...
  14.  */
  15.  
  16. #define USE_CYBERGFX /* undefine this if you don't have CYBERGFX includes */
  17.  
  18. /****************************************************************************/
  19.  
  20. #include <exec/execbase.h>
  21. #include <exec/memory.h>
  22.  
  23. #include <graphics/gfxbase.h>
  24. #include <graphics/displayinfo.h>
  25.  
  26. #include <libraries/asl.h>
  27. #include <intuition/pointerclass.h>
  28.  
  29. #include <proto/intuition.h>
  30. #include <proto/graphics.h>
  31. #include <proto/exec.h>
  32. #include <proto/asl.h>
  33.  
  34. #ifdef USE_CYBERGFX
  35. #include <inline/cybergraphics.h>
  36. #endif
  37.  
  38. /****************************************************************************/
  39.  
  40. #include "sysconfig.h"
  41. #include "sysdeps.h"
  42.  
  43. /****************************************************************************/
  44.  
  45. #include "config.h"
  46. #include "options.h"
  47. #include "memory.h"
  48. #include "custom.h"
  49. #include "newcpu.h"
  50. #include "xwin.h"
  51. #include "keyboard.h"
  52. #include "keybuf.h"
  53. #include "gui.h"
  54.  
  55. /****************************************************************************/
  56.  
  57. static UBYTE *image_mem;
  58. static int need_dither;        /* well.. guess :-) */
  59. static int use_low_bandwidth;  /* this will redraw only needed places */
  60. static int use_cyb;            /* this is for cybergfx */
  61. xcolnr xcolors[4096];
  62.  /* Keyboard and mouse */
  63.  
  64. static int keystate[256];
  65.  
  66. int buttonstate[3];
  67. int lastmx, lastmy;
  68. int newmousecounters;
  69.  
  70. static int inwindow;
  71.  
  72. static int vsize, hsize, hpixels;
  73. static char *oldpixbuf;
  74.  
  75. struct vidbuf_description gfxvidinfo;
  76.  
  77. /****************************************************************************/
  78. /*
  79.  * prototypes & global vars
  80.  */
  81. struct IntuitionBase    *IntuitionBase;
  82. struct GfxBase          *GfxBase;
  83. struct Library          *AslBase;
  84. struct Library          *CyberGfxBase;
  85.  
  86. static UBYTE            *Line;
  87. static struct RastPort  *RP;
  88. static struct Screen    *S;
  89. static struct Window    *W;
  90. static struct RastPort  *TempRPort;
  91. static struct BitMap    *BitMap;
  92. static struct ColorMap  *CM;
  93. static Object           *Pointer; /* for os 39 */
  94. static UWORD            *Sprite;
  95.  
  96. static int os39;        /* kick 39 present */
  97. static int usepub;      /* use public screen */
  98. static int halfv;       /* halve height for non interlaced screen */
  99. static int usecyb;      /* use cybergraphics.library */
  100. static int is_halfbrite;
  101.  
  102. static int   get_color_failed;
  103. static int   maxpen;
  104. static UBYTE pen[256];
  105.  
  106. static struct BitMap *myAllocBitMap(ULONG,ULONG,ULONG,ULONG,struct BitMap *);
  107. static void set_title(void);
  108. static void myFreeBitMap(struct BitMap *);
  109. static LONG ObtainColor(ULONG, ULONG, ULONG);
  110. static void ReleaseColors(void);
  111. static void DoSizeWindow(struct Window *,int,int);
  112.  
  113. /****************************************************************************/
  114.  
  115. __inline__ void flush_line(int y)
  116. {
  117.     int xs, len;
  118.     int yoffset = y*gfxvidinfo.rowbytes;
  119.     char *linebuf = gfxvidinfo.bufmem + yoffset;
  120.     char *src, *dst;
  121.  
  122.     if(halfv && (y&1)) return;
  123.  
  124.     if (gfxvidinfo.maxlinetoscr)
  125.       len = gfxvidinfo.maxlinetoscr;
  126.     else
  127.       len = hsize;
  128.  
  129.     switch(gfxvidinfo.pixbytes) {
  130.       case 4: 
  131.         {   /* sam: we should not arrive here on the amiga */
  132.             fprintf(stderr, "Bug in flush_line() !\n");
  133.             abort();
  134.             return;
  135.         }
  136.         break;
  137.       case 2:
  138.         {
  139.             short *newp = (short *)linebuf;
  140.             short *oldp = (short *)(oldpixbuf + yoffset);
  141.             while (*newp++ == *oldp++) if(!--len) return;
  142.             src   = (char *)--newp;
  143.             dst   = (char *)--oldp; 
  144.             newp += len;
  145.             oldp += len;
  146.             while (*--newp == *--oldp);
  147.             len   = 1 + (oldp - (short *)dst);
  148.             xs    = (src - linebuf)/2;
  149.             CopyMem (src, dst, len * 2);
  150.         } break;
  151.       case 1:
  152.         {
  153.             char *newp = (char *)linebuf;
  154.             char *oldp = (char *)(oldpixbuf + yoffset);
  155.             while (*newp++ == *oldp++) if(!--len) return;
  156.             src   = (char *)--newp;
  157.             dst   = (char *)--oldp; 
  158.             newp += len;
  159.             oldp += len;
  160.             while (*--newp == *--oldp);
  161.             len   = 1 + (oldp - (char *)dst);
  162.             xs    = (src - linebuf);
  163.             CopyMem (src, dst, len);
  164.         } break;
  165.       
  166.       default:
  167.         abort();
  168.         break;
  169.     }
  170.     
  171.     if(halfv) y>>=1;
  172.  
  173.     if (need_dither) {
  174.         DitherLine(Line, (UWORD *)dst, xs, y, (len+3)&~3, 8);
  175.     } else CopyMem(dst, Line, len); 
  176.     
  177.     if (use_cyb) 
  178.         CopyMem(Line, image_mem + xs + yoffset, len);
  179.     else
  180.         WritePixelLine8(RP, xs, y, len, Line, TempRPort);
  181. }
  182.  
  183. /****************************************************************************/
  184.  
  185. void flush_block (int ystart, int ystop)
  186. {
  187.     if(need_dither || !use_cyb) {
  188.       int y;
  189.       for(y=ystart; y<=ystop; ++y) flush_line(y);
  190.     }
  191. }
  192.  
  193. /****************************************************************************/
  194.  
  195. void flush_screen (int ystart, int ystop)
  196. {
  197. /* WaitBOVP() ? */
  198. }
  199.  
  200. /****************************************************************************/
  201.  
  202. void calc_adjustment(void)
  203. {
  204.     switch (screen_res) {
  205.       case 0: case 1: case 2: /* LoRes, 320x200 */
  206.         gfxvidinfo.x_adjust = prev_max_diwstop - 320;
  207.         break;
  208.         
  209.       case 3: /* 640x480 */
  210.         gfxvidinfo.x_adjust = prev_max_diwstop - 640;
  211.         break;
  212.       default:
  213.         gfxvidinfo.x_adjust = 0;
  214.         break;
  215.     }
  216. }
  217.  
  218. /****************************************************************************/
  219.  
  220. static int get_color(int r, int g, int b, xcolnr *cnp)
  221. {
  222.     int col;
  223.  
  224.     r *= 0x11111111;
  225.     g *= 0x11111111;
  226.     b *= 0x11111111;
  227.     col = ObtainColor(r, g, b);
  228.  
  229.     if(col == -1) {
  230.         get_color_failed = 1;
  231.         return 0;
  232.     }
  233.  
  234.     *cnp = col;
  235.     return 1;
  236. }
  237.  
  238. /****************************************************************************/
  239. /*
  240.  * FIXME: find a better way to determine closeness of colors (closer to
  241.  * human perception).
  242.  */
  243. static __inline__ int calc_err(int r1, int g1, int b1,
  244.                                int r2, int g2, int b2)
  245. {
  246.     int err = 0; 
  247.  
  248.     if((r1>7 && r2<=7) || (r1<=7 && r2>7)) err += 1;
  249.     if((g1>7 && g2<=7) || (g1<=7 && g2>7)) err += 1;
  250.     if((b1>7 && b2<=7) || (b1<=7 && b2>7)) err += 1;
  251.  
  252.     r1 -= r2; g1 -= g2; b1 -= b2;
  253.     r1 *= 2;  g1 *= 3;  b1 *= 1;
  254.     err += r1*r1 + g1*g1 + b1*b1;
  255.  
  256.     return err;
  257. }
  258.  
  259. /****************************************************************************/
  260.  
  261. static int get_nearest_color(int r, int g, int b)
  262. {
  263.     int i, best, err, besterr;
  264.     int colors;
  265.     int br=0,bg=0,bb=0;
  266.  
  267.     best    = 0;
  268.     besterr = calc_err(0,0,0, 15,15,15);
  269.     colors  = is_halfbrite?32:(1<<RP->BitMap->Depth);
  270.   
  271.     for(i=0; i<colors; i++ ) {
  272.         long rgb = GetRGB4(CM, i);
  273.         int cr, cg, cb;
  274.         
  275.         cr = (rgb >> 8) & 15;
  276.         cg = (rgb >> 4) & 15;
  277.         cb = (rgb >> 0) & 15;
  278.           
  279.         err = calc_err(r,g,b, cr,cg,cb);
  280.         
  281.         if(err < besterr) {
  282.             best = i;
  283.             besterr = err;
  284.             br=cr; bg=cg; bb=cb;
  285.         }
  286.  
  287.         if(is_halfbrite) {
  288.             cr /= 2; cg /= 2; cb /= 2;
  289.             err = calc_err(r,g,b, cr,cg,cb);
  290.             if(err < besterr) {
  291.                 best = i + 32;
  292.                 besterr = err;
  293.                 br=cr; bg=cg; bb=cb;
  294.             }
  295.         }
  296.     }
  297.     return best;
  298. }
  299.  
  300. /****************************************************************************/
  301.  
  302. static int init_colors(void)
  303. {
  304.     if (need_dither) {
  305.         /* first try color allocation */
  306.         int bitdepth = usepub ? RP->BitMap->Depth : 8;
  307.         int maxcol;
  308.  
  309.         if(bitdepth>=3)
  310.         do {
  311.             get_color_failed = 0;
  312.             setup_dither(bitdepth, get_color);
  313.             if(get_color_failed) ReleaseColors();
  314.         } while(get_color_failed && --bitdepth>=3);
  315.         
  316.         if(bitdepth >= 3) {
  317.             printf("Color dithering with %d bits\n",bitdepth);
  318.             return 1;
  319.         }
  320.  
  321.         /* if that fail then try grey allocation */
  322.         maxcol = 1<<(usepub ? RP->BitMap->Depth : 8);
  323.  
  324.         do {
  325.             get_color_failed = 0;
  326.             setup_greydither_maxcol(maxcol, get_color);
  327.             if(get_color_failed) ReleaseColors();
  328.         } while(get_color_failed && --maxcol>=2);
  329.         
  330.         if (maxcol >= 2) {
  331.             printf("Gray dither with %d shades\n",maxcol);
  332.             return 1;
  333.         }
  334.         
  335.         return 0; /* everything failed :-( */
  336.     }
  337.     
  338.     /* No dither */
  339.     switch(RP->BitMap->Depth) {
  340.       case 6: if (is_halfbrite) {
  341.         static int tab[]={
  342.         0x000, 0x00f, 0x0f0, 0x0ff, 0x08f, 0x0f8, 0xf00, 0xf0f,
  343.         0x80f, 0xff0, 0xfff, 0x88f, 0x8f0, 0x8f8, 0x8ff, 0xf08,
  344.         0xf80, 0xf88, 0xf8f, 0xff8, /* end of regular pattern */
  345.         0xa00, 0x0a0, 0xaa0, 0x00a, 0xa0a, 0x0aa, 0xaaa,
  346.         0xfaa, 0xf6a, 0xa80, 0x06a, 0x6af };
  347.         int i;
  348.         for(i=0;i<32;++i) get_color(tab[i]>>8, (tab[i]>>4)&15, tab[i]&15, xcolors);
  349.         for(i=0;i<4096;++i) xcolors[i] = get_nearest_color(i>>8, (i>>4)&15, i&15);
  350.         break;
  351.       }
  352.  
  353.       case 1: case 2: case 3: case 4: case 5: case 7: case8: {
  354.         int maxcol = 1<<RP->BitMap->Depth;
  355.  
  356.         if(maxcol>=8) do {
  357.             get_color_failed = 0;
  358.             setup_maxcol(maxcol);
  359.             alloc_colors256(get_color);
  360.             if(get_color_failed) ReleaseColors();
  361.         } while(get_color_failed && --maxcol>=8);
  362.         else {
  363.             int i;
  364.             for(i=0;i<maxcol;++i) {
  365.                 get_color((i*15)/(maxcol-1), (i*15)/(maxcol-1), (i*15)/(maxcol-1), xcolors);
  366.             }
  367.         }
  368.         printf("Using %d colors\n",maxcol);
  369.         for(maxcol=0;maxcol<4096;++maxcol) 
  370.             xcolors[maxcol] = get_nearest_color(maxcol>>8, (maxcol>>4)&15, maxcol&15);
  371.         } break;
  372.  
  373.       case 15:
  374.         alloc_colors64k(5,5,5,10,5,0);
  375.         break;
  376.  
  377.       case 16:
  378.         alloc_colors64k(5,6,5,11,5,0);
  379.         break;
  380.  
  381.       case 24: case 32:
  382.         alloc_colors64k(8,8,8,16,8,0);
  383.         break;
  384.     }
  385.     return 1;
  386. }
  387.  
  388. /****************************************************************************/
  389.  
  390. static void setup_sprite(struct Window *W)
  391. {
  392.     Sprite = AllocVec(4+2, MEMF_CHIP|MEMF_CLEAR);
  393.     if(!Sprite) {
  394.        fprintf(stderr, "Warning: Can not alloc sprite buffer !\n");
  395.        return;
  396.     }
  397.     Sprite[2] = 0x8000; Sprite[3] = 0x8000;
  398.     SetPointer(W, Sprite, 1, 16, -1, 0);
  399. }
  400.  
  401. /****************************************************************************/
  402.  
  403. static int setup_customscreen(void)
  404. {
  405.     struct NewScreen NewScreenStructure = {
  406.         0,0, 800,600, 3, 0,1,
  407.         LACE+HIRES, CUSTOMSCREEN|SCREENQUIET|SCREENBEHIND,
  408.         NULL, (void*)"UAE", NULL, NULL};
  409.     struct NewWindow NewWindowStructure = {
  410.         0,0, 800,600, 0,1,
  411.         IDCMP_MOUSEBUTTONS|IDCMP_RAWKEY|IDCMP_DISKINSERTED|IDCMP_DISKREMOVED|
  412.         IDCMP_ACTIVEWINDOW|IDCMP_INACTIVEWINDOW|IDCMP_MOUSEMOVE,
  413.         WFLG_SMART_REFRESH|WFLG_BACKDROP|WFLG_RMBTRAP|WFLG_NOCAREREFRESH|
  414.         WFLG_BORDERLESS|WFLG_WINDOWACTIVE|WFLG_REPORTMOUSE,
  415.         NULL, NULL, (void*)"UAE", NULL, NULL, 5,5, 800,600,
  416.         CUSTOMSCREEN};
  417.  
  418.     NewScreenStructure.Width     = hpixels;
  419.     NewScreenStructure.Height    = vsize;
  420.     NewScreenStructure.Depth     = os39?8:(use_lores?5:4);
  421.     NewScreenStructure.ViewModes = SPRITES | (use_lores ? NULL : HIRES) |
  422.                                    (correct_aspect ? LACE : NULL);
  423.   
  424.     do S = (void*)OpenScreen(&NewScreenStructure);
  425.     while(!S && --NewScreenStructure.Depth);
  426.     if(!S) {
  427.         fprintf(stderr, "Can't open custom screen !\n");
  428.         return 0;
  429.     }
  430.  
  431.     CM = S->ViewPort.ColorMap;
  432.     RP = &S->RastPort;
  433.  
  434.     NewWindowStructure.Width  = S->Width;
  435.     NewWindowStructure.Height = S->Height;
  436.     NewWindowStructure.Screen = S;
  437.     W = (void*)OpenWindow(&NewWindowStructure);
  438.     if(!W) {
  439.         fprintf(stderr, "Can't open window on custom screen !\n");
  440.         return 0;
  441.     }
  442.     setup_sprite(W);
  443.     return 1;
  444. }
  445.  
  446. /****************************************************************************/
  447.  
  448. static int setup_publicscreen(void)
  449. {
  450.     struct NewWindow NewWindowStructure = {
  451.         0,0, 800,600, 0,1,
  452.         IDCMP_MOUSEBUTTONS|IDCMP_RAWKEY|IDCMP_DISKINSERTED|IDCMP_DISKREMOVED|
  453.         IDCMP_ACTIVEWINDOW|IDCMP_INACTIVEWINDOW|IDCMP_MOUSEMOVE,
  454.         WFLG_DRAGBAR|WFLG_DEPTHGADGET|WFLG_SMART_REFRESH|WFLG_REPORTMOUSE|
  455.         WFLG_RMBTRAP|WFLG_GIMMEZEROZERO|WFLG_ACTIVATE|WFLG_NOCAREREFRESH,
  456.         NULL, NULL, (void*)"UAE", NULL, NULL, 5,5, 800,600,
  457.         PUBLICSCREEN};
  458.  
  459.     S = LockPubScreen(NULL);
  460.     if(!S) {
  461.         fprintf(stderr,"No public screen !\n");
  462.         return 0;
  463.     }
  464.  
  465.     CM = S->ViewPort.ColorMap;
  466.  
  467.     halfv = (S->ViewPort.Modes & (HIRES|LACE))==HIRES;
  468.  
  469.     NewWindowStructure.Width  = hpixels;
  470.     NewWindowStructure.Height = vsize >> (halfv?1:0);
  471.     NewWindowStructure.Screen = S;
  472.     
  473.     W = (void*)OpenWindow(&NewWindowStructure);
  474.     UnlockPubScreen(NULL, S);
  475.     if(!W) {
  476.         fprintf(stderr,"Can't open window on public screen !\n");
  477.         CM = NULL;
  478.         return 0;
  479.     }
  480.     DoSizeWindow(W, NewWindowStructure.Width, NewWindowStructure.Height);
  481.     RP = W->RPort;
  482.     setup_sprite(W);
  483.     return 1;
  484. }
  485.  
  486. /****************************************************************************/
  487.  
  488. static int setup_userscreen(void)
  489. {
  490.     struct ScreenModeRequester *ScreenRequest;
  491.     ULONG DisplayID;
  492.     struct BitMap PointerBitMap;
  493.     UWORD PointerLine;
  494.     LONG ScreenWidth=0,ScreenHeight=0,Depth=0;
  495.     UWORD OverscanType=0;
  496.     BOOL AutoScroll=0;
  497.  
  498. #ifdef USE_CYBERGFX
  499.     CyberGfxBase = OpenLibrary("cybergraphics.library",40);
  500. #endif
  501.     AslBase = OpenLibrary("asl.library",38);
  502.     if(!AslBase) {
  503.         fprintf(stderr,"Can't open asl.library v38 !");
  504.         return 0;
  505.     }
  506.  
  507.     ScreenRequest = AllocAslRequest(ASL_ScreenModeRequest,NULL);
  508.     if(!ScreenRequest) {
  509.         fprintf(stderr,"Unable to allocate screen mode requester.\n");
  510.         return 0;
  511.     }
  512.  
  513.     if(AslRequestTags(ScreenRequest,
  514.                       ASLSM_TitleText, (ULONG)"Select screen display mode",
  515.                       ASLSM_InitialDisplayID,    NULL,
  516.                       ASLSM_InitialDisplayDepth, 8,
  517.                       ASLSM_InitialDisplayWidth, hsize,
  518.                       ASLSM_InitialDisplayHeight,vsize,
  519.                       ASLSM_MinWidth,            hsize,
  520.                       ASLSM_MinHeight,           vsize,
  521.                       ASLSM_DoWidth,             TRUE,
  522.                       ASLSM_DoHeight,            TRUE,
  523.                       ASLSM_DoDepth,             TRUE,
  524.                       ASLSM_DoOverscanType,      TRUE,
  525.                       ASLSM_PropertyFlags,       0,
  526.                       ASLSM_PropertyMask,        DIPF_IS_DUALPF | 
  527.                                                  DIPF_IS_PF2PRI | 
  528.                                                  DIPF_IS_HAM    |
  529.                                                  0,
  530.                       TAG_DONE)) {
  531.         ScreenWidth  = ScreenRequest->sm_DisplayWidth;
  532.         ScreenHeight = ScreenRequest->sm_DisplayHeight;
  533.         Depth        = ScreenRequest->sm_DisplayDepth;
  534.         DisplayID    = ScreenRequest->sm_DisplayID;
  535.         OverscanType = ScreenRequest->sm_OverscanType;
  536.         AutoScroll   = ScreenRequest->sm_AutoScroll;
  537.         if(ScreenWidth  < hsize) ScreenWidth  = hsize;
  538.         if(ScreenHeight < vsize) ScreenHeight = vsize;
  539.         }
  540.     else DisplayID = INVALID_ID;
  541.     FreeAslRequest(ScreenRequest);
  542.     
  543.     if(DisplayID == (ULONG)INVALID_ID) return 0;
  544.  
  545. #ifdef USE_CYBERGFX 
  546.     if(CyberGfxBase && IsCyberModeID(DisplayID)) use_cyb = 1;
  547. #endif
  548.  
  549.     S = OpenScreenTags(NULL,
  550.                        SA_DisplayID,                    DisplayID,
  551.                        SA_Width,                        ScreenWidth,
  552.                        SA_Height,                       ScreenHeight,
  553.                        SA_Depth,                        Depth,
  554.                        SA_Overscan,                     OverscanType,
  555.                        SA_AutoScroll,                   AutoScroll,
  556.                        SA_ShowTitle,                    FALSE,
  557.                        SA_Quiet,                        TRUE,
  558.                        SA_Behind,                       TRUE,
  559.                        /* v39 stuff here: */
  560.                        (os39?SA_BackFill:TAG_DONE),     (ULONG)LAYERS_NOBACKFILL,
  561.                        SA_SharePens,                    TRUE,
  562.                        SA_Exclusive,                    (use_cyb?TRUE:FALSE),
  563.                        SA_Draggable,                    (use_cyb?FALSE:TRUE),
  564.                        SA_Interleaved,                  TRUE,
  565.                        TAG_DONE);
  566.     if(!S) {
  567.         fprintf(stderr,"Unable to open the screen.\n");
  568.         return 0;
  569.     }
  570.  
  571.     RP           = &S->RastPort;
  572.     CM           = S->ViewPort.ColorMap;
  573.     is_halfbrite = (S->ViewPort.Modes & EXTRA_HALFBRITE);
  574.  
  575.     PointerLine = 0x0000;
  576.     InitBitMap(&PointerBitMap,2,16,1);
  577.     PointerBitMap.Planes[0] = (PLANEPTR)&PointerLine;
  578.     PointerBitMap.Planes[1] = (PLANEPTR)&PointerLine;
  579.     
  580.     Pointer = NewObject(NULL,POINTERCLASS,
  581.                         POINTERA_BitMap,        (ULONG)&PointerBitMap,
  582.                         POINTERA_WordWidth,     1,
  583.                         TAG_DONE);
  584.     if(!Pointer)
  585.         fprintf(stderr,"Warning: Unable to allocate blank mouse pointer.\n");
  586.  
  587.     W = OpenWindowTags(NULL,
  588.                        WA_Width,                S->Width,
  589.                        WA_Height,               S->Height,
  590.                        WA_CustomScreen,         (ULONG)S,
  591.                        WA_Backdrop,             TRUE,
  592.                        WA_Borderless,           TRUE,
  593.                        WA_RMBTrap,              TRUE,
  594.                        WA_ReportMouse,          TRUE,
  595.                        WA_IDCMP,                IDCMP_MOUSEBUTTONS|
  596.                                                 IDCMP_RAWKEY|
  597.                                                 IDCMP_DISKINSERTED|
  598.                                                 IDCMP_DISKREMOVED|
  599.                                                 IDCMP_ACTIVEWINDOW|
  600.                                                 IDCMP_INACTIVEWINDOW|
  601.                                                 IDCMP_MOUSEMOVE,
  602.                        (os39?WA_BackFill:TAG_IGNORE), (ULONG)LAYERS_NOBACKFILL,
  603.                        (Pointer?WA_Pointer:TAG_IGNORE), (ULONG)Pointer,
  604.                        TAG_DONE);
  605.  
  606.     if(!W) {
  607.         fprintf(stderr,"Unable to open the window.\n");
  608.         CloseScreen(S);S=NULL;RP=NULL;CM=NULL;
  609.         return 0;
  610.     }
  611.     if(!Pointer) setup_sprite(W);
  612.     return 1;
  613. }
  614.  
  615. /****************************************************************************/
  616.  
  617. int graphics_init(void)
  618. {
  619.     int i,bitdepth;
  620.  
  621.     use_low_bandwidth = 0;
  622.     need_dither = 0;
  623.     use_cyb = 0;
  624.     
  625.     if (screen_res < 3) {
  626.         fprintf(stderr, "Low resolution mode selected. Forcing 320x200.\n");
  627.     }
  628.     
  629.     vsize = correct_aspect ? 2*numscrlines : numscrlines;
  630.     switch (screen_res) {
  631.      case 0: case 1: case 2:
  632.         hsize = hpixels = 320;
  633.         break;
  634.      case 3:
  635.         hsize = hpixels = 640;
  636.         break;
  637.      case 4:
  638.         hpixels = 796; hsize = 800; /* ??? */
  639.         break;
  640.     }
  641.     gfxvidinfo.maxlinetoscr = hpixels;
  642.  
  643.     if(SysBase->LibNode.lib_Version < 36) {
  644.         fprintf(stderr, "UAE needs os 2.0+ !\n");
  645.         return 0;
  646.     }
  647.     os39   = (SysBase->LibNode.lib_Version>=39);
  648.  
  649.     atexit(graphics_leave);
  650.  
  651.     IntuitionBase = (void*)OpenLibrary("intuition.library",0L);
  652.     if(!IntuitionBase) {
  653.         fprintf(stderr,"No intuition.library ?\n");
  654.         return 0;
  655.     }
  656.     GfxBase = (void*)OpenLibrary("graphics.library",0L);
  657.     if(!GfxBase) {
  658.         fprintf(stderr,"No graphics.library ?\n");
  659.         return 0;
  660.     }
  661.  
  662.     switch(color_mode) {
  663.       case 2:
  664.         if(setup_userscreen()) break;
  665.         fprintf(stderr,"Trying on public screen...\n");
  666.         /* fall trough */
  667.       case 1:
  668.         is_halfbrite = 0;
  669.         if(setup_publicscreen()) {usepub = 1;break;}
  670.         fprintf(stderr,"Trying on custom screen...\n");
  671.         /* fall trough */
  672.       case 0:
  673.         if(!setup_customscreen()) return 0;
  674.         break;
  675.     }
  676.  
  677.     Line = AllocVec((hsize + 15) & ~15,MEMF_ANY|MEMF_PUBLIC);
  678.     if(!Line) {
  679.         fprintf(stderr,"Unable to allocate raster buffer.\n");
  680.         return 0;
  681.     }
  682.     BitMap = myAllocBitMap(hsize,1,8,BMF_CLEAR|BMF_MINPLANES,RP->BitMap);
  683.     if(!BitMap) {
  684.         fprintf(stderr,"Unable to allocate BitMap.\n");
  685.         return 0;
  686.     }
  687.     TempRPort = AllocVec(sizeof(struct RastPort),MEMF_ANY|MEMF_PUBLIC);
  688.     if(!TempRPort) {
  689.         fprintf(stderr,"Unable to allocate RastPort.\n");
  690.         return 0;
  691.     }
  692.     CopyMem(RP,TempRPort,sizeof(struct RastPort));
  693.     TempRPort->Layer  = NULL;
  694.     TempRPort->BitMap = BitMap;
  695.  
  696.     if(usepub) set_title();
  697.  
  698.     bitdepth = RP->BitMap->Depth;
  699.     if(bitdepth <= 8) {
  700.         gfxvidinfo.pixbytes = use_xhair?1:2;
  701.         /* chunk2planar is slow so we define use_low_bandwidth for all modes
  702.            except cybergraphics modes */
  703.         use_low_bandwidth = 1; 
  704.         need_dither = use_xhair && (bitdepth>1) ? 0 : 1;
  705.     } else {
  706.         gfxvidinfo.pixbytes = (bitdepth == 24 || bitdepth == 32 ? 4
  707.                                : bitdepth == 12 || bitdepth == 16 ? 2
  708.                                : 1);
  709.     }
  710.     
  711.     if (!use_cyb) {
  712.         gfxvidinfo.rowbytes = gfxvidinfo.pixbytes * hsize;
  713.         gfxvidinfo.bufmem = (char *)calloc(gfxvidinfo.rowbytes, vsize+1);
  714.         /*                                                           ^^ */
  715.         /*            This is because DitherLine may read one extra row */
  716.     } else {
  717. #ifdef USE_CYBERGFX
  718.         if(!need_dither) {
  719.             gfxvidinfo.bufmem   = (char *)GetCyberMapAttr(RP->BitMap,
  720.                                                           CYBRMATTR_DISPADR);
  721.             gfxvidinfo.rowbytes = GetCyberMapAttr(RP->BitMap,CYBRMATTR_XMOD);
  722.             gfxvidinfo.pixbytes = GetCyberMapAttr(RP->BitMap,CYBRMATTR_BPPIX);
  723.         } else {
  724.             image_mem = (char *)GetCyberMapAttr(RP->BitMap,CYBRMATTR_DISPADR);
  725.             gfxvidinfo.rowbytes = GetCyberMapAttr(RP->BitMap,CYBRMATTR_XMOD);
  726.             gfxvidinfo.pixbytes = GetCyberMapAttr(RP->BitMap,CYBRMATTR_BPPIX);
  727.             gfxvidinfo.bufmem = (char *)calloc(gfxvidinfo.rowbytes, vsize+1);
  728.         }
  729. #endif
  730.     } 
  731.     if(!gfxvidinfo.bufmem) {
  732.         fprintf(stderr,"Not enough memory.\n");
  733.         return 0;
  734.     } 
  735.  
  736.     gfxvidinfo.maxline = 100000; /* no limit */
  737.  
  738.     if (use_low_bandwidth) {
  739.         gfxvidinfo.maxblocklines = vsize; /* it seems to increase the speed */
  740.         oldpixbuf = (char *)calloc(gfxvidinfo.rowbytes, vsize);
  741.         if(!oldpixbuf) {
  742.             fprintf(stderr,"Not enough memory.\n");
  743.             return 0;
  744.         }
  745.     } else {
  746.         gfxvidinfo.maxblocklines = 100; /* whatever... */
  747.     }
  748.  
  749.     if (!init_colors())
  750.         return 0;
  751.  
  752.     if(!usepub) ScreenToFront(S);
  753.  
  754.     buttonstate[0] = buttonstate[1] = buttonstate[2] = 0;
  755.     for(i=0; i<256; i++)
  756.         keystate[i] = 0;
  757.     
  758.     lastmx = lastmy = 0; 
  759.     newmousecounters = 0;
  760.     inwindow = 0;
  761.     
  762.     return 1;
  763. }
  764.  
  765. /****************************************************************************/
  766.  
  767. void graphics_leave(void)
  768. {
  769.     if(BitMap) {
  770.         WaitBlit();
  771.         myFreeBitMap(BitMap);
  772.         BitMap = NULL;
  773.     }
  774.     if(TempRPort) {
  775.         FreeVec(TempRPort);
  776.         TempRPort = NULL;
  777.     }
  778.     if(Line) {
  779.         FreeVec(Line);
  780.         Line = NULL;
  781.     } 
  782.     if(CM) {
  783.         ReleaseColors();
  784.         CM = NULL;
  785.     }
  786.     if(W) {
  787.         CloseWindow(W);
  788.         W = NULL;
  789.     }
  790.     if(Sprite) {
  791.         FreeVec(Sprite);
  792.         Sprite = NULL;
  793.     }
  794.     if(Pointer) {
  795.         DisposeObject(Pointer);
  796.         Pointer = NULL;
  797.     }
  798.     if(!usepub && S) {
  799.         CloseScreen(S);
  800.         S = NULL;
  801.     }
  802.     if(AslBase) {
  803.         CloseLibrary((void*)AslBase);
  804.         AslBase = NULL;
  805.     }
  806.     if(GfxBase) {
  807.         CloseLibrary((void*)GfxBase);
  808.         GfxBase = NULL;
  809.     }
  810.     if(IntuitionBase) {
  811.         CloseLibrary((void*)IntuitionBase);
  812.         IntuitionBase = NULL;
  813.     }
  814.     if(CyberGfxBase) {
  815.         CloseLibrary((void*)CyberGfxBase);
  816.         CyberGfxBase = NULL;
  817.     }
  818. }
  819.  
  820.  
  821. /***************************************************************************/
  822.  
  823. void handle_events(void)
  824. {
  825.     struct IntuiMessage *msg;
  826.     int mx,my,class,code;
  827.   
  828.     newmousecounters = 0;
  829.     gui_handle_events();
  830.  
  831.     while((msg=(struct IntuiMessage*)GetMsg(W->UserPort))) {
  832.         class = msg->Class;
  833.         code  = msg->Code;
  834.         mx    = msg->MouseX;
  835.         my    = msg->MouseY;
  836.         ReplyMsg((struct Message*)msg);
  837.  
  838.         if(usepub) {
  839.             mx -= W->BorderLeft;
  840.             my -= W->BorderTop;
  841.         }
  842.       
  843.         switch(class) {
  844.           case RAWKEY: {
  845.               int kc       = code&127;
  846.               int released = code&128?1:0;
  847.             
  848.               if(released) {
  849.                   keystate[kc] = 0;
  850.                   record_key ((kc << 1) | 1);
  851.               } else if (!keystate[kc])  {
  852.                   keystate[kc] = 1;
  853.                   record_key (kc << 1);
  854.               }
  855.           } break;
  856.           
  857.           case MOUSEMOVE:
  858.             if(inwindow) {
  859.                 lastmx = mx;
  860.                 lastmy = my << (halfv?1:0);
  861.             } break;
  862.  
  863.           case MOUSEBUTTONS:
  864.             if(code==SELECTDOWN) buttonstate[0]=1;
  865.             if(code==SELECTUP)   buttonstate[0]=0;
  866.             if(code==MENUDOWN)   buttonstate[2]=1;
  867.             if(code==MENUUP)     buttonstate[2]=0;
  868.             break;
  869.         
  870.           /* Those 2 could be of some use later. */
  871.           case DISKINSERTED:
  872.         /*printf("diskinserted(%d)\n",code);*/
  873.             break;
  874.           
  875.           case DISKREMOVED:
  876.             /*printf("diskremoved(%d)\n",code);*/
  877.             break;
  878.                         
  879.           case ACTIVEWINDOW:
  880.             inwindow = 1;
  881.             newmousecounters = 1;
  882.             lastmx = mx;
  883.             lastmy = my<<(halfv?1:0);
  884.             break;
  885.                         
  886.           case INACTIVEWINDOW:
  887.             inwindow = 0;
  888.             break;
  889.           
  890.           default:
  891.             fprintf(stderr, "Unknown class: %d\n",class);
  892.             break;
  893.         }
  894.     }
  895.     /* "Affengriff" */
  896.     if(keystate[AK_CTRL] && keystate[AK_LAMI] && keystate[AK_RAMI]) 
  897.         MC68000_reset();
  898.  
  899.     /* PC-like :-) CTRL-ALT-DEL => reboot */
  900.     if(keystate[AK_CTRL] && (keystate[AK_LALT] || keystate[AK_RALT]) && 
  901.        keystate[AK_DEL]) 
  902.         MC68000_reset();
  903.  
  904.   /* CTRL+LSHIFT+LALT+F10 on amiga => F12 on X11 */
  905.     if(keystate[AK_CTRL] && keystate[AK_LSH] && keystate[AK_LALT] && keystate[AK_F10])
  906.         togglemouse();
  907. }
  908.  
  909. /***************************************************************************/
  910.  
  911. void target_specific_usage(void)
  912. {
  913.     printf("\n");
  914.     printf("----------------------------------------------------------------------------\n");
  915.     printf("AMIGA SPECIFIC USAGE:\n");
  916.     printf("  -x                       : Does not use dithering\n");
  917.     printf("  On the amiga, Valid resolution (see -d) are:\n");
  918.     printf("     0, 1, 2 (320x256); 3 (640x512); 4 (800x600).\n");
  919.     printf("  And valid color modes (see -H) are:\n");
  920.     printf("     0 => 256 cols max on customscreen;\n");
  921.     printf("     1 => OpenWindow on default public screen;\n");
  922.     printf("     2 => Ask the user to select a screen mode with ASL requester.\n");
  923.     printf("----------------------------------------------------------------------------\n");
  924.     printf("\n");
  925. }
  926.  
  927. /***************************************************************************/
  928.  
  929. int debuggable(void)
  930. {
  931.     return 1;
  932. }
  933.  
  934. /***************************************************************************/
  935.  
  936. int needmousehack(void)
  937. {
  938.     return 1;
  939. }
  940.  
  941. /***************************************************************************/
  942.  
  943. void LED(int on)
  944. {
  945. }
  946.  
  947. /***************************************************************************/
  948.  
  949. static int led_state[5];
  950.  
  951. static void set_title(void)
  952. {
  953.     static char title[80];
  954.  
  955.     if(!usepub) return;
  956.     sprintf(title,"UAE - Power: [%c] Drives: [%c] [%c] [%c] [%c]",
  957.             led_state[0]?'X':' ',
  958.             led_state[1]?'0':' ',
  959.             led_state[2]?'1':' ',
  960.             led_state[3]?'2':' ',
  961.             led_state[4]?'3':' ');
  962.     
  963.     SetWindowTitles(W,title,(char*)-1);
  964. }
  965.  
  966. /***************************************************************************/
  967. /*
  968.  * gui code
  969.  */
  970. int quit_program;
  971.  
  972. static void sigchldhandler(int foo)
  973. {
  974. }
  975.  
  976. int gui_init(void)
  977. {
  978.     quit_program = 0;
  979.     return 0;
  980. }
  981.  
  982. void gui_exit(void)
  983. {
  984. }
  985.  
  986. void gui_led(int led, int on)
  987. {
  988.   if(led>=0 && led<=4) led_state[led] = on;
  989.   set_title();
  990. }
  991.  
  992. void gui_filename(int num, char *name)
  993. {
  994. }
  995.  
  996. static void getline(char *p)
  997. {
  998. }
  999.  
  1000. void gui_handle_events(void)
  1001. {
  1002. }
  1003.  
  1004. /****************************************************************************/
  1005. /*
  1006.  * Routines for OS2.0 (code taken out of mpeg_play by Michael Balzer)
  1007.  */
  1008. static struct BitMap *myAllocBitMap(ULONG sizex, ULONG sizey, ULONG depth, 
  1009.                                     ULONG flags, struct BitMap *friend_bitmap)
  1010. {
  1011.     struct BitMap *bm;
  1012.     unsigned long extra;
  1013.     
  1014.     if(os39) return AllocBitMap(sizex, sizey, depth, flags, friend_bitmap);
  1015.     
  1016.     extra = (depth > 8) ? depth - 8 : 0;
  1017.     bm = AllocVec( sizeof *bm + (extra * 4), MEMF_CLEAR );
  1018.     
  1019.     if( bm )
  1020.       {
  1021.           ULONG i;
  1022.           InitBitMap(bm, depth, sizex, sizey);
  1023.           for( i=0; i<depth; i++ )
  1024.             {
  1025.                 if( !(bm->Planes[i] = AllocRaster(sizex, sizey)) )
  1026.                   {
  1027.                       while(i--) FreeRaster(bm->Planes[i], sizex, sizey);
  1028.                       FreeVec(bm);
  1029.                       bm = 0;
  1030.                       break;
  1031.                   }
  1032.             }
  1033.       }
  1034.     return bm;
  1035. }
  1036.  
  1037. /****************************************************************************/
  1038.  
  1039. static void myFreeBitMap(struct BitMap *bm)
  1040. {
  1041.     if(os39) {FreeBitMap(bm);return;}
  1042.     while(bm->Depth--)
  1043.       FreeRaster(bm->Planes[bm->Depth], bm->BytesPerRow*8, bm->Rows);
  1044.     FreeVec(bm);
  1045. }
  1046.  
  1047. /****************************************************************************/
  1048. /*
  1049.  * find the best appropriate color return -1 if none is available
  1050.  */
  1051. static LONG ObtainColor(ULONG r,ULONG g,ULONG b)
  1052. {
  1053.     int i, crgb;
  1054.     int colors;
  1055.  
  1056.     if(os39 && usepub) {
  1057.         i = ObtainBestPen(CM,r,g,b,
  1058.                           OBP_Precision, PRECISION_EXACT,
  1059.                           OBP_FailIfBad, TRUE,
  1060.                           TAG_DONE);
  1061.         if(i != -1) {
  1062.             if(maxpen<256) pen[maxpen++] = i;
  1063.             else i = -1;
  1064.         }
  1065.         return i;
  1066.     }
  1067.  
  1068.     r >>= 28; g >>= 28; b >>= 28;
  1069.         
  1070.     colors = is_halfbrite?32:(1<<RP->BitMap->Depth);
  1071.   
  1072.     /* private screen => standard allocation */
  1073.     if(!usepub) {
  1074.         if(maxpen >= colors) return -1; /* no more colors available */
  1075.         SetRGB4(&S->ViewPort, maxpen, r, g, b);
  1076.         return maxpen++;
  1077.     }
  1078.  
  1079.     /* public => find exact match */
  1080.     crgb = (r<<8)|(g<<4)|b;
  1081.     for(i=0; i<colors; i++ ) {
  1082.         int rgb = GetRGB4(CM, i);
  1083.         if(rgb == crgb) return i;
  1084.     }
  1085.     return -1;
  1086. }
  1087.  
  1088. /****************************************************************************/
  1089. /*
  1090.  * free a color entry
  1091.  */
  1092. static void ReleaseColors(void)
  1093. {
  1094.     if(os39 && usepub && CM) 
  1095.         while(maxpen>0) ReleasePen(CM, pen[--maxpen]);
  1096.     else maxpen = 0;
  1097. }
  1098.  
  1099. /****************************************************************************/
  1100.  
  1101. static void DoSizeWindow(struct Window *W,int wi,int he)
  1102. {
  1103.     register int x,y;
  1104.     
  1105.     wi += W->BorderRight + W->BorderLeft;
  1106.     he += W->BorderBottom + W->BorderTop;
  1107.     x   = W->LeftEdge;
  1108.     y   = W->TopEdge;
  1109.     
  1110.     if(x + wi >= W->WScreen->Width)  x = W->WScreen->Width - wi;
  1111.     if(y + he >= W->WScreen->Height) y = W->WScreen->Height - he;
  1112.     
  1113.     x  -= W->LeftEdge;
  1114.     y  -= W->TopEdge;
  1115.     wi -= W->Width;
  1116.     he -= W->Height;
  1117.     
  1118.     if(x|y)   MoveWindow(W,x,y);
  1119.     if(wi|he) SizeWindow(W,wi,he);
  1120. }
  1121.