home *** CD-ROM | disk | FTP | other *** search
/ Aminet 18 / aminetcdnumber181997.iso / Aminet / misc / emu / gbuk.lha / src / OPTIONS.C < prev    next >
C/C++ Source or Header  |  1997-02-08  |  71KB  |  2,899 lines

  1. #include    <stdio.h>
  2. #include    <string.h>
  3. #include    <time.h>
  4. #include    "picture.h"
  5. #include    "gb.h"
  6. #include    "gfxfunc.h"
  7. #include    "font.h"
  8. #include    "options.h"
  9. #include    "main.h"
  10. #include    "prefs.h"
  11. #include    "keycodes.h"
  12. #include    "system.h"
  13.  
  14. #define    DEMO    1
  15. #define    DEMO_TIME    (60*10+3)        // 10 minutes 3 seconds
  16. //    Palette layout
  17.  
  18. //    0-15        Colors used by fonts, cursor, backdrop
  19. //    16-31        Gameboy display palette
  20. //    32-47        Workspace for palette prefs screen
  21. //    48-79        Backdrop palette
  22. //    80-111        Gadgets palette
  23. //    112+        Unused
  24.  
  25. //***************************************************//
  26. //*                                                    *//
  27. //*    DEFINES                                            *//
  28. //*                                                    *//
  29. //***************************************************//
  30.  
  31. //    Where different bits are situated in the palette
  32. #define    GAMEBOY_BASE    16
  33. #define    BACKDROP_BASE    48
  34. #define    GADGETS_BASE    80
  35.  
  36. #define    ELEMENTS(x)    (sizeof(x)/sizeof(x[0]))
  37. #define    KILLMEM(x)    if(x)GXFreeMem(x);
  38.  
  39. #define    KEYOPTIONS_TITLE_Y    10
  40. #define    KEYOPTIONS_Y    30
  41. #define    KEYOPTIONS_DY    16
  42.  
  43. #define    ITEM_STRING        0
  44. #define    ITEM_COLORFILL    1    
  45. #define    GAMEBOY_X    0
  46. #define    GAMEBOY_Y    0
  47.  
  48. #define    DISPLAY_X    0
  49. #define    DISPLAY_Y    0
  50.  
  51. #define    PALETTE_PICTURE_X    4
  52. #define    PALETTE_PICTURE_Y    20
  53.  
  54.  
  55. #define    SLIDEBOTTOM_X            6
  56. #define    SLIDEBOTTOM_Y            185
  57.  
  58. #define    DIRECTORYNAME_X            5
  59. #define    DIRECTORYNAME_Y            3
  60. #define    DIRECTORYNAME_WIDTH        212
  61. #define    DIRECTORYNAME_HEIGHT    12
  62. #define    SIDEPANEL_X                230
  63. #define    SIDEPANEL_Y                0
  64.  
  65. #define    UPARROW_X    208
  66. #define    UPARROW_Y    21
  67.  
  68. #define    DOWNARROW_X    208
  69. #define    DOWNARROW_Y    181
  70.  
  71. #define    BUTTONS_X    234
  72. #define    BUTTONS_Y    66
  73. #define    BUTTONS_DY    23
  74.  
  75. #define    BUTTONID_DOWNARROW        0
  76. #define    BUTTONID_UPARROW        1
  77. #define    BUTTONID_PARENT            2
  78. #define    BUTTONID_VOLUMES        3
  79. #define    BUTTONID_OK                4
  80. #define    BUTTONID_CANCEL            5
  81. #define    BUTTONID_LIST            6
  82. #define    BUTTONID_STRINGGADGET    7
  83.  
  84. #define    LISTTYPE_FILES        0
  85. #define    LISTTYPE_VOLUMES    1
  86.  
  87. #define    MAINBUTTON_LOAD        0
  88. #define    MAINBUTTON_PALETTE    1
  89. #define    MAINBUTTON_KEYS        2
  90. #define    MAINBUTTON_SAVE        3
  91. #define    MAINBUTTON_GRAB        4
  92. #define    MAINBUTTON_QUIT        5
  93. #define    MAINBUTTON_CANCEL    6
  94. #define    MAINBUTTON_NUMBER    7
  95.  
  96. #define    MAINBUTTON_DUMPGFX    7
  97. #define    MENUBUTTON_Y    26
  98.  
  99. //************************************************************
  100. //    Stuff to do with palette requestor
  101. //************************************************************
  102. #define    COLOR0_X            244
  103. #define    COLOR0_Y            27
  104. #define    COLOR_WIDTH            9
  105. #define    COLOR_HEIGHT        9
  106. #define    COLORSEPERATION_X    16
  107. #define    COLORSEPERATION_Y    19
  108.  
  109. #define    PALETTE_OKAY_X        4
  110. #define    PALETTE_OKAY_Y        170
  111.  
  112. #define    PALETTE_CANCEL_X    89
  113. #define    PALETTE_CANCEL_Y    170
  114.  
  115. #define    RGB_X                239
  116. #define    RGB_Y                111
  117. #define    RGB_DY                29
  118.  
  119. #define    PALETTE_SECTION_X                205
  120. #define    PALETTE_SECTION_Y                31
  121. #define    PALETTE_SECTION_DY                19
  122.  
  123. #define    RGB_SLIDER_MINX    168
  124. #define    RGB_SLIDER_MAXX    304
  125. #define    RGB_SLIDER_Y    118
  126. #define    RGB_SLIDER_DY    29
  127. #define    SLIDER_RANGE    (RGB_SLIDER_MAXX-RGB_SLIDER_MINX)
  128.  
  129. #define    RGB_SLIDER_GFX_X    168
  130. #define    RGB_SLIDER_GFX_Y    104
  131. #define    RGB_SLIDER_GFX_DY    29
  132.  
  133. #define    RGB_PALETTE_LINE_GFX_X    168
  134. #define    RGB_PALETTE_LINE_GFX_Y    22
  135. #define    RGB_PALETTE_LINE_GFX_DY    19
  136.  
  137.  
  138.  
  139. //***************************************************//
  140. //*                                                    *//
  141. //*    STRUCTURES                                        *//
  142. //*                                                    *//
  143. //***************************************************//
  144. typedef struct{
  145.     int            Type;
  146.     GXOBLONG    Oblong;
  147.     char        *String;
  148.     int            Color;
  149.     int            BackColor;
  150.     TXFONT        *Font;
  151.     int            File;
  152.     int            ListOrder;
  153. }ITEMDATA;
  154.  
  155. typedef struct{
  156.     int        X,Y;
  157.     int        MaxX,MaxY;
  158.     int        Width,Height;
  159.     TXFONT    *Font;
  160.     char    *Text;
  161.     GXIMAGE    *Image;
  162.     int        NItem;
  163.     ITEMDATA    **Item;
  164.     int        BackColor;
  165. }SCROLLWINDOW;
  166.  
  167. typedef struct{
  168.     GXIMAGE    *Image;
  169.     long    MinX,MinY;
  170.     long    MaxX,MaxY;
  171.     long    X,Y;
  172.     long    Width,Height;
  173.     long    Vertical;
  174.     long    Position;
  175.     long    BackColor;
  176. }SLIDER;
  177.  
  178. typedef struct{
  179.     UBYTE        Grab;
  180.     long        X;        //x coordinate of slider relative to origin
  181. }RGBSLIDER;    
  182.  
  183. typedef struct{
  184.     GXOBLONG    Area;
  185.     char        *String;
  186.     int            CursorPosition;
  187. }STRINGGADGET;
  188.  
  189. //***************************************************//
  190. //*                                                    *//
  191. //*    PROTOTYPES                                        *//
  192. //*                                                    *//
  193. //***************************************************//
  194. void            PrintLoadingMessage(void);
  195. void            UpdateSlider(SLIDER *s, long fraction, GXIMAGE *screen);
  196. int                MakeFileList(SCROLLWINDOW *window, char *dir);
  197. void            MakeVolumeList(SCROLLWINDOW *window);
  198. void            ScrollWindow(SCROLLWINDOW *window, int x, int y);
  199. SCROLLWINDOW    *MakeScrollWindow(int width, int height);
  200. void            KillScrollWindow(SCROLLWINDOW *window);
  201. int                UpdateButtons(GXOBLONG *button, int nbutton);
  202. void            DrawLine(SCROLLWINDOW *window, int ydraw);
  203. void            DrawWindow(SCROLLWINDOW *window, int x, int y, GXIMAGE *image);
  204. int                GetFileSelection(int y, ITEMDATA **list);
  205. void            RedrawItem(SCROLLWINDOW *window, ITEMDATA *item);
  206. ITEMDATA         **MakeItemData(int NItem, char **name, TXFONT **font, int *ListOrder);
  207. void            KillWindowItemData(SCROLLWINDOW *window);
  208. int                ListHeight(ITEMDATA **ItemList);
  209. void            PrintDirectoryName(GXIMAGE *Screen, TXFONT *TheFont, char *name);
  210. void            ClearWindow(SCROLLWINDOW *window, long color);
  211. void            SaveScreen(void);
  212. void            RestoreScreen(void);
  213. int                DoMenu(char *title, char **options, int NOptions);
  214. void            PalettePrefs(void);
  215. void            DrawPalette(int    j, GXIMAGE *image, int highlight);
  216. void            ResetButtons(void);
  217. void            MoveSlider(int is, int NewX, GXIMAGE *ToImage);
  218. void            KeyOptions(void);
  219. void            DrawButton(GXIMAGE *dest, char *text, long x, long y);
  220. char            *KeyName(long RawCode);
  221. STRINGGADGET    *MakeStringGadget(char *StartString, GXOBLONG *Area, GXIMAGE *ToImage);
  222. void            UpdateStringGadge(STRINGGADGET *sg, int AsciiKey, GXIMAGE *ToImage);
  223. int                RawToAscii(int RawKey);
  224. int                SaveSnapshot(char *name);
  225. int                LoadSnapshot(char *name);
  226. void            ChangeKeySelection(int selection, int NewSelection, GXIMAGE *ScreenImage);
  227. void            PrintStringGadget(STRINGGADGET *sg, GXIMAGE *ToImage, int cursoron);
  228. void            UpdateStringGadget(STRINGGADGET *sg, int AsciiKey, GXIMAGE *ToImage, 
  229.                                     int active);
  230. void            ChangeStringGadget(char *str, STRINGGADGET *sg, GXIMAGE *ToImage);
  231. char            *GetStringGadget(STRINGGADGET *sg);
  232. void            KillStringGadget(STRINGGADGET *sg);
  233. int                MouseClick(void);
  234. void            MakeWaitMessageList(SCROLLWINDOW *window);
  235. void            TimeOutCheck();
  236. void            TimeOutMessage(void);
  237. void            WaitNoKeys(void);
  238. void            DrawSlider(int is, int x, GXIMAGE *ToImage);
  239. void            DrawBackground(GXIMAGE *image, GXOBLONG *area);
  240.  
  241.  
  242. //***************************************************//
  243. //*                                                    *//
  244. //*    STATIC STUFF                                    *//
  245. //*                                                    *//
  246. //***************************************************//
  247. GXIMAGE        *GameBoyImage=0,*GadgetsImage=0;
  248. TXFONT        *BlackFont,*RedFont,*WhiteFont;
  249. GXPALETTE    White={0xff,0xff,0xff,0};
  250. GXPALETTE    Black={0x00,0x00,0x00,0};
  251. GXPALETTE    Red={0xff,0x00,0x00,0};
  252. GXPALETTE    Orange={255, 156, 0, 0};
  253. GXPALETTE    Grey={112,112,112,0};
  254. int            WhiteIndex,BlackIndex,RedIndex,OrangeIndex,GreyIndex;
  255.  
  256. //            Location of all the buttons & stuff in the source gfx
  257. GXOBLONG    FileSelector={0,0,320,196};
  258. GXOBLONG    SidePanel={230,19,90,200};
  259. GXOBLONG    ButtonUp={0,197,75,17};
  260. GXOBLONG    SliderDown={76,197,10,11};
  261. GXOBLONG    SliderUp={76,209,10,11};
  262. GXOBLONG    AcrossKnob={76,221,19,6};
  263. GXOBLONG    DownKnob={87,203,6,13};
  264. GXOBLONG    MessageBox={122,197,198,59};
  265. GXOBLONG    PaletteRequestor={0,234,320,196};
  266. GXOBLONG    PaletteNormal={132,203,15,15};
  267. GXOBLONG    PaletteHighlight={178,203,15,15};
  268. GXOBLONG    StringGadget={5,181,201,12};
  269. GXOBLONG    FileTitle={12,3,301,12};
  270. GXOBLONG    TitleBox={0,0,320,18};
  271. GXOBLONG    List={10,20,192,156};
  272. GXOBLONG    SlideSide={209,32,8,149};
  273.  
  274. GXOBLONG    CornerTL={232,203,7,7};
  275. GXOBLONG    CornerTR={239,203,7,7};
  276. GXOBLONG    CornerBR={239,211,7,7};
  277. GXOBLONG    CornerBL={232,211,7,7};
  278.  
  279. GXOBLONG    PaletteSlider={177,255-29,142,30};
  280. GXOBLONG    PaletteLine={1,511-276,142,20};
  281. GXOBLONG    BackTile={145,218,31,31};
  282.  
  283. long        ScreenWidth,ScreenHeight;
  284. GXOBLONG    GameBoyDisplay={64+32,33,160,144};    
  285. GXOBLONG    MainButtonLocation[MAINBUTTON_NUMBER];
  286. long        BackdropX=8+32,BackdropY=0;    //where the backrop image is drawn to
  287. int            CurrentButton=-1;
  288. GXIMAGE        *ScreenSaveImage=0;
  289.  
  290. #if    DEMO
  291. //**********************************************************************
  292. //    TimeOutCheck()
  293. //**********************************************************************
  294. //    Description: Halt the game after a short period for demo version
  295. //    Input: None
  296. //    Output: None
  297. //**********************************************************************
  298. void    TimeOutCheck()
  299. {
  300.     int        DemoTime;
  301.     static    long    TimeOut=DEMO_TIME,StartTime=0;
  302.  
  303.     if(!StartTime){
  304.         StartTime=GXTimer();
  305.     }else{
  306.         DemoTime=(GXTimer()-StartTime)/GXTicksPerSecond();
  307.         if(DemoTime>TimeOut){
  308.             TimeOutMessage();
  309.             GXQuitCode("Done\n");
  310.         }
  311.     }
  312. }
  313. //**********************************************************************
  314. //    TimeOutMessage()
  315. //**********************************************************************
  316. //    Description: Print goodbye message for demo version
  317. //    Input: None
  318. //    Output: None
  319. //**********************************************************************
  320. void    TimeOutMessage(void)
  321. {
  322.     GXIMAGE        *ScreenImage;
  323.     long        x,y,StartTime,seconds;
  324.     GXMOUSEINFO    MouseInfo;
  325.     int            LeftReleased=0,MiddleReleased=0,RightReleased=0,j;
  326.     
  327.     SaveScreen();
  328.     ScreenImage=GXStartDrawing(0);
  329.  
  330.     DrawBackground(ScreenImage, 0);
  331.     y=(ScreenHeight-NTimeOutStrings*TXFONTHeight(RedFont))/2;
  332.     for(j=0; j<NTimeOutStrings; j++){
  333.         x=(ScreenWidth-TXStringWidth(TimeOutStrings[j], RedFont))/2;
  334.         TXPrintString(TimeOutStrings[j], x, y, ScreenImage, RedFont);
  335.         y+=TXFONTHeight(RedFont);
  336.     }
  337.     GXDoBlit();
  338.     StartTime=GXTimer();
  339.     do{
  340.         GXSystemUpdate();
  341.  
  342.         //    quit after 10 seconds
  343.         seconds=(GXTimer()-StartTime)/GXTicksPerSecond();
  344.         if(seconds>10)break;
  345.         
  346.  
  347.         //    When any mouse button is pressed after being released,
  348.         //    exit.
  349.         GXReadMouse(&MouseInfo);
  350.         if(!MouseInfo.LeftButton)LeftReleased=1;
  351.         if(!MouseInfo.MiddleButton)MiddleReleased=1;
  352.         if(!MouseInfo.RightButton)RightReleased=1;
  353.  
  354.         if(MouseInfo.LeftButton&&LeftReleased)break;
  355.         if(MouseInfo.MiddleButton&&MiddleReleased)break;
  356.         if(MouseInfo.RightButton&&RightReleased)break;
  357.     }while(1);
  358.     RestoreScreen();
  359. }
  360. #endif
  361.  
  362. void    ResetButtons(void)
  363. {
  364.     CurrentButton=-1;
  365. }
  366.  
  367. //**********************************************************************
  368. //    UpdateButtons()
  369. //**********************************************************************
  370. //    Description: Find out if any buttons have been pressed
  371. //    Input: arrays telling where the buttons are, number of buttons, 
  372. //            output for structure to be filled with button info
  373. //    Output: Button pressed?
  374. //**********************************************************************
  375. int    UpdateButtons(GXOBLONG *button, int nbutton)
  376. {
  377.     long                x,y;
  378.     long                ibutton=-1;
  379.     int                    j;
  380.     GXMOUSEINFO            mouse;
  381.  
  382.     GXReadMouse(&mouse);
  383.     for(j=0; j<nbutton; j++,button++){
  384.         x=mouse.X-button->X;
  385.         if(x<0)continue;
  386.         if(x>button->Width)continue;
  387.         y=mouse.Y-button->Y;
  388.         if(y<0)continue;
  389.         if(y>button->Height)continue;
  390.         ibutton=j;
  391.         break;
  392.     }
  393.     return ibutton;
  394. }
  395.  
  396. //**********************************************************************
  397. //    DrawWindow()
  398. //**********************************************************************
  399. //    Description: Copy window to image
  400. //    Input: window, location to be drawn to in image, image 
  401. //    Output: none
  402. //**********************************************************************
  403. void    DrawWindow(SCROLLWINDOW *window, int x, int y, GXIMAGE *image)
  404. {
  405.     GXBLITLIST    *b;
  406.     int            xp,yp,xm,ym;
  407.  
  408.     xp=window->X%window->Width;
  409.     yp=window->Y%window->Height;
  410.     xm=window->Width-xp;
  411.     ym=window->Height-yp;
  412.  
  413.     if(xm&&ym){
  414.         //    Part A
  415.         b=GXNextBlit();
  416.         b->Type=BLIT_IMAGE;
  417.         b->FromImage=window->Image;
  418.         b->ToImage=image;
  419.         b->From.Width=xm;
  420.         b->From.Height=ym;
  421.         b->From.X=xp;
  422.         b->From.Y=yp;
  423.         b->XTo=x;
  424.         b->YTo=y;
  425.     }
  426.     if(xp&&ym){
  427.         //    Part B
  428.         b=GXNextBlit();
  429.         b->Type=BLIT_IMAGE;
  430.         b->FromImage=window->Image;
  431.         b->ToImage=image;
  432.         b->From.Width=xp;
  433.         b->From.Height=ym;
  434.         b->From.X=0;
  435.         b->From.Y=yp;
  436.         b->XTo=xm+x;
  437.         b->YTo=y;
  438.     }
  439.     if(xm&&yp){
  440.         //    Part C
  441.         b=GXNextBlit();
  442.         b->Type=BLIT_IMAGE;
  443.         b->FromImage=window->Image;
  444.         b->ToImage=image;
  445.         b->From.Width=xm;
  446.         b->From.Height=yp;
  447.         b->From.X=xp;
  448.         b->From.Y=0;
  449.         b->XTo=x;
  450.         b->YTo=y+ym;
  451.     }
  452.     if(xp&&yp){
  453.         //    Part D
  454.         b=GXNextBlit();
  455.         b->Type=BLIT_IMAGE;
  456.         b->FromImage=window->Image;
  457.         b->ToImage=image;
  458.         b->From.Width=xp;
  459.         b->From.Height=yp;
  460.         b->From.X=0;
  461.         b->From.Y=0;
  462.         b->XTo=x+xm;
  463.         b->YTo=y+ym;
  464.     }
  465. }
  466.  
  467. //**********************************************************************
  468. //    ScrollWindow()
  469. //**********************************************************************
  470. //    Description: Move the corner of the window
  471. //    Input: window, coordinates wanted for screen corner 
  472. //    Output: none
  473. //**********************************************************************
  474. void    ScrollWindow(SCROLLWINDOW *window, int x, int y)
  475. {
  476.     int    nloop,ydraw;
  477.     
  478.     //////////////////////////////////
  479.     //    Y Scrolling                    //
  480.     //////////////////////////////////
  481.     nloop=y-window->Y;
  482.     if(nloop>0){
  483.         if(nloop>window->Height){    //dont draw more than a whole screen
  484.             ydraw=y;
  485.             nloop=window->Height;
  486.         }else{
  487.             ydraw=window->Y+window->Height;
  488.         }
  489.         do{
  490.             DrawLine(window, ydraw);
  491.             ydraw++;
  492.             nloop--;
  493.         }while(nloop);
  494.     }else if(nloop<0){
  495.         if(nloop>window->Height){    //dont draw more than a whole screen
  496.             nloop=window->Height;        
  497.             ydraw=y+window->Height-1;
  498.         }else{
  499.             nloop*=-1;
  500.             ydraw=window->Y-1;
  501.         }
  502.         do{
  503.             DrawLine(window, ydraw);
  504.             ydraw--;
  505.             nloop--;
  506.         }while(nloop);
  507.     }
  508.     window->Y=y;
  509. }
  510.  
  511.  
  512. //**********************************************************************
  513. //    DrawLine()
  514. //**********************************************************************
  515. //    Description: Draw line on window
  516. //    Input: window, y value of line to draw 
  517. //    Output: none
  518. //**********************************************************************
  519. void    DrawLine(SCROLLWINDOW *window, int ydraw)
  520. {
  521.     ITEMDATA        *item,**ItemList;
  522.     TXFONT            *font;
  523.     unsigned char    *str,letter;
  524.     TXCUTDATA        *CutData,*cut;
  525.     GXBLITLIST        *b;
  526.     int                YItem,xs,xe,x0,x1,yto;
  527.     
  528.     yto=ydraw%window->Height;
  529.     ItemList=window->Item;
  530.     if(!ItemList){
  531.         return;
  532.     }
  533.     while(1){
  534.         item=*ItemList++;
  535.         if(!item){
  536.             break;
  537.         }
  538.         YItem=ydraw-item->Oblong.Y;
  539.         if( (YItem>=0) && (YItem<item->Oblong.Height) ){
  540.             if(item->Type==ITEM_STRING){    
  541.                 //////////////////////////////
  542.                 //    Draw a string            //
  543.                 //////////////////////////////
  544.  
  545.                 //    Draw background    
  546.                 b=GXNextBlit();
  547.                 b->Type=BLIT_COLORFILL;
  548.                 b->ToImage=window->Image;
  549.                 b->From.Width=window->Width;
  550.                 b->From.Height=1;
  551.                 b->XTo=0;
  552.                 b->YTo=yto;
  553.                 b->Color=item->BackColor;
  554.  
  555.                 xs=item->Oblong.X - window->X;
  556.                 str=(unsigned char *)item->String;
  557.                 font=item->Font;
  558.                 CutData=font->Cut;
  559.                 while(letter=*str++){
  560.                     if(xs>=window->Width)
  561.                         break;                //gone past end of window
  562.                     cut=CutData+letter;
  563.                     if(cut->Control){
  564.                         //    Control character
  565.                         xs+=font->Width;
  566.                     }else{
  567.                         //    Normal character
  568.                         xe=xs+cut->Oblong.Width-1;    //=x value last pixel drawn
  569.                         if(xe>=0){            //inside left edge
  570.                             if(xs<0){
  571.                                 x0=0;
  572.                             }else{
  573.                                 x0=xs;
  574.                             }
  575.                             if(xe>=window->Width){
  576.                                 x1=window->Width-1;
  577.                             }else{
  578.                                 x1=xe;
  579.                             }
  580.                             b=GXNextBlit();
  581.                             b->Type=BLIT_IMAGE;
  582.                             b->FromImage=font->Image;
  583.                             b->ToImage=window->Image;
  584.                             b->From.X=x0-xs+cut->Oblong.X;
  585.                             b->From.Y=YItem;
  586.                             b->From.Width=x1-x0+1;
  587.                             b->From.Height=1;
  588.                             b->XTo=x0;
  589.                             b->YTo=yto;
  590.                         }
  591.                         xs+=(cut->Oblong.Width+cut->XOffset);
  592.                     }
  593.                 }
  594.             }else{
  595.                 //////////////////////////
  596.                 //    Draw a rectangle    //
  597.                 //////////////////////////
  598.                 GXQuitCode("Called dodgy code\n");
  599.                 xs=item->Oblong.X - window->X;
  600.                 if(xs<window->Width){
  601.                     if(xs<0){
  602.                         x0=0;
  603.                     }else{
  604.                         x0=xs;
  605.                     }
  606.                     xe=xs+item->Oblong.Width-1;
  607.                     if(xe>=0){
  608.                         if(xe>=window->Width){
  609.                             x1=window->Width-1;
  610.                         }else{
  611.                             x1=xe;
  612.                         }
  613.                         b=GXNextBlit();
  614.                         b->Type=BLIT_COLORFILL;
  615.                         b->ToImage=window->Image;
  616.                         b->From.Width=x1-x0+1;
  617.                         b->From.Height=1;
  618.                         b->XTo=x0;
  619.                         b->YTo=yto;
  620.                         b->Color=item->Color;
  621.                     }
  622.                 }
  623.             }            
  624.         }
  625.     }
  626. }
  627.  
  628. //**********************************************************************
  629. //    MakeScrollWindow()
  630. //**********************************************************************
  631. //    Description: Make scrollwindow
  632. //    Input: size 
  633. //    Output: window
  634. //**********************************************************************
  635. SCROLLWINDOW    *MakeScrollWindow(int width, int height)
  636. {
  637.     SCROLLWINDOW    *window=0;
  638.     
  639.     window=(SCROLLWINDOW *)GXGetMem(sizeof(SCROLLWINDOW), MEMF_ABORT|MEMF_ZERO);
  640.     window->Image=GXMakeImage(width, height);
  641.     if(!window->Image){
  642.         GXPrintf("MakeScrollWindow(): Couldnt make image\n");
  643.         goto fail;
  644.     }    
  645.     window->Width=width;
  646.     window->Height=height;
  647.     window->X=window->Y=0;
  648.     window->BackColor=WhiteIndex;
  649.     return window;
  650. fail:
  651.     GXQuitCode("Failed in scroll window creation\n");
  652.     return    0;
  653. }
  654.  
  655. //**********************************************************************
  656. //    KillScrollWindow()
  657. //**********************************************************************
  658. //    Description: Kill window made above
  659. //    Input: window
  660. //    Output: none
  661. //**********************************************************************
  662. void    KillScrollWindow(SCROLLWINDOW *window)
  663. {
  664.     GXKillImage(window->Image);
  665.     GXFreeMem(window);
  666. }
  667.  
  668.  
  669. //**********************************************************************
  670. //    SetupGFX()
  671. //**********************************************************************
  672. //    Description: Load in all the graphics and fonts needed
  673. //    Input: none
  674. //    Output: none
  675. //**********************************************************************
  676. void    SetupGFX(void)
  677. {
  678.     GXPICTURE    *GadgetsPic,*GameBoyPic,*pic;
  679.     GXIMAGE        *ScreenImage;
  680.     int            j;
  681.  
  682.     ScreenImage=GXStartDrawing(0);    
  683.     ScreenWidth=GXImageWidth(ScreenImage);
  684.     ScreenHeight=GXImageHeight(ScreenImage);
  685.  
  686.     for(j=0; j<256; j++){
  687.         GXSetPaletteRange(&Black, j, 1);
  688.     }
  689.  
  690.     GXSetPaletteRange(GameBoyPalette, GAMEBOY_BASE, 16);
  691.     GXReserveColors(0, 256,    0);
  692.     GXReserveColors(GAMEBOY_BASE, 32, 1);
  693.     GXReserveColors(0, 1, 1);
  694.  
  695.     GXSetPaletteRange(&Black, 1, 1);
  696.     BlackIndex=1;
  697.     GXSetPaletteRange(&White, 2, 1);
  698.     WhiteIndex=2;
  699.     GXSetPaletteRange(&Red, 3, 1);
  700.     RedIndex=3;
  701.     GXSetPaletteRange(&Orange, 4, 1);
  702.     OrangeIndex=4;
  703.     GXSetPaletteRange(&Grey, 5, 1);
  704.     GreyIndex=5;
  705.     
  706.     //    Load pics
  707.     GadgetsPic=LoadPicture("gfx/gadgets.pic");
  708.     if(!GadgetsPic)goto fail;
  709.     GameBoyPic=LoadPicture("gfx/gameboy.pic");
  710.     if(!GameBoyPic)goto fail;
  711.  
  712.     //    Set palette range used by gadgets & gameboy
  713.     GXSetPaletteRange(GadgetsPic->Palette, GADGETS_BASE, 32);
  714.     GXSetPaletteRange(GameBoyPic->Palette, BACKDROP_BASE, 32); 
  715.  
  716.     //    Create gadgets & gameboy images
  717.     GadgetsImage=GXPictureToImage(GadgetsPic, 1, 0);
  718.     if(!GadgetsImage)goto fail;
  719.     GameBoyImage=GXPictureToImage(GameBoyPic, 0, 0);
  720.     if(!GameBoyImage)goto fail;
  721.     KillPicture(GadgetsPic);
  722.     KillPicture(GameBoyPic);
  723.     
  724.     //    Load fonts    
  725.     pic=LoadPicture(FontGfxName);
  726.     BlackFont=TXLoadFont(pic, FontCutName, &Black);
  727.     if(!BlackFont)goto fail;
  728.     RedFont=TXLoadFont(pic, FontCutName, &Red);
  729.     if(!RedFont)goto fail;
  730.     WhiteFont=TXLoadFont(pic, FontCutName, &White);
  731.     if(!WhiteFont)goto fail;
  732.     KillPicture(pic);
  733.     return;
  734. fail:
  735.     GXQuitCode("Failed to find setup graphics\n");    
  736. }
  737.  
  738. //**********************************************************************
  739. //    ClearWindow()
  740. //**********************************************************************
  741. //    Description: Fill window with given color
  742. //    Input: window, color
  743. //    Output: none
  744. //**********************************************************************
  745. void    ClearWindow(SCROLLWINDOW *window, long color)
  746. {
  747.     GXBLITLIST    *b;
  748.  
  749.     b=GXNextBlit();
  750.     b->Type=BLIT_COLORFILL;
  751.     b->From.Width=window->Width;
  752.     b->From.Height=window->Height;
  753.     b->Color=color;
  754.     b->XTo=0;
  755.     b->YTo=0;
  756.     b->ToImage=window->Image;
  757.     GXDoBlit();
  758. }
  759. //**********************************************************************
  760. //    MakeWaitMessageList()
  761. //**********************************************************************
  762. //    Description: Set up list to show "Loading..." message
  763. //    Input: window
  764. //    Output: none
  765. //**********************************************************************
  766. void    MakeWaitMessageList(SCROLLWINDOW *window)
  767. {
  768.     char    *list[1];
  769.     int        ListOrder[]={1};
  770.     TXFONT    *font[1];
  771.  
  772.     list[0]=FileStrings[4];
  773.     font[0]=BlackFont;
  774.     window->Item=MakeItemData(1, list, font, ListOrder);
  775. }
  776.  
  777. //**********************************************************************
  778. //    MakeVolumeList()
  779. //**********************************************************************
  780. //    Description: Make item data for list of volumes and attach it to
  781. //                 a window
  782. //    Input: window
  783. //    Output: none
  784. //**********************************************************************
  785. void    MakeVolumeList(SCROLLWINDOW *window)
  786. {
  787.     GXVOLUME    *Volume;
  788.     long        NVolume;
  789.     char        **strings;
  790.     TXFONT        **fonts;
  791.     int            *ListOrder;
  792.     int            NItem,j;
  793.  
  794.  
  795.     Volume=GXMakeVolumeInfo(&NVolume);
  796.     strings=(char **)GXGetMem(NVolume*sizeof(char *), MEMF_ABORT);
  797.     fonts=(TXFONT **)GXGetMem(NVolume*sizeof(TXFONT *), MEMF_ABORT);
  798.     ListOrder=(int *)GXGetMem(NVolume*sizeof(int), MEMF_ABORT);
  799.     NItem=NVolume;
  800.     for(j=0; j<NItem; j++){
  801.         strings[j]=Volume[j].Name;
  802.         fonts[j]=BlackFont;
  803.         ListOrder[j]=0;
  804.     }
  805.     window->Item=MakeItemData(NItem, strings, fonts, ListOrder);
  806.     GXKillVolumeInfo(Volume);
  807.     GXFreeMem(strings);
  808.     GXFreeMem(fonts);
  809.     GXFreeMem(ListOrder);
  810.  
  811.     ClearWindow(window, WhiteIndex);
  812.     for(j=0; j<window->Height; j++){
  813.         DrawLine(window, j);
  814.     }
  815.     window->MaxY=ListHeight(window->Item)-window->Height;
  816.     if(window->MaxY<0)window->MaxY=0;
  817. }
  818.  
  819. //**********************************************************************
  820. //    MakeFileList()
  821. //**********************************************************************
  822. //    Description: Make item data for directory listing and attach it to
  823. //                    a window
  824. //    Input: window, directory name
  825. //    Output: Did i get a list?
  826. //**********************************************************************
  827. int    MakeFileList(SCROLLWINDOW *window, char *dir)
  828. {
  829.     GXFILEINFO    *FileInfo=0,*info;
  830.     int            NItem,j;
  831.     char        **strings;
  832.     TXFONT        **fonts;
  833.     int            *ListOrder;
  834.     ITEMDATA    **ItemList;
  835.  
  836.     if(!GXMakeDirectoryInfo(dir, &FileInfo)){
  837.         return 0;
  838.     }
  839.     info=FileInfo;
  840.     if(!info){
  841.         window->MaxY=0;
  842.         ClearWindow(window, WhiteIndex);
  843.         GXDoBlit();
  844.         return 1;
  845.     }
  846.     NItem=0;
  847.     while(info){
  848.         NItem++;
  849.         info=(GXFILEINFO *)info->Next;
  850.     }
  851.     strings=(char **)GXGetMem(NItem*sizeof(char *), MEMF_ABORT);
  852.     fonts=(TXFONT **)GXGetMem(NItem*sizeof(TXFONT *), MEMF_ABORT);
  853.     ListOrder=(int *)GXGetMem(NItem*sizeof(int), MEMF_ABORT);
  854.     info=FileInfo;
  855.     for(j=0; j<NItem; j++){
  856.         strings[j]=info->Name;
  857.         if(info->File){
  858.             ListOrder[j]=0;
  859.             fonts[j]=BlackFont;
  860.         }else{
  861.             ListOrder[j]=1;
  862.             fonts[j]=RedFont;
  863.         }
  864.         info=(GXFILEINFO *)info->Next;
  865.     }
  866.     ItemList=MakeItemData(NItem, strings, fonts, ListOrder);
  867.     GXKillDirectoryInfo(FileInfo);
  868.     GXFreeMem(strings);
  869.     GXFreeMem(fonts);
  870.     GXFreeMem(ListOrder);
  871.  
  872.     window->Item=ItemList;
  873.     
  874.     //    Get scroll limits
  875.     window->MaxY=ListHeight(window->Item)-window->Height;
  876.     if(window->MaxY<0)window->MaxY=0;
  877.     GXPrintf("MaxY=%d\n",window->MaxY);
  878.  
  879.     ClearWindow(window, WhiteIndex);
  880.  
  881.     for(j=0; j<window->Height; j++){
  882.         DrawLine(window, j);
  883.     }
  884.     GXDoBlit();
  885.     return 1;
  886. }
  887.  
  888. //**********************************************************************
  889. //    MakeItemData()
  890. //**********************************************************************
  891. //    Description: Make item data for scroll window
  892. //    Input:  number of items, array of name, array of fonts, array 
  893. //            giving priority in list        
  894. //    Output: item data or zero if it went wrong
  895. //**********************************************************************
  896. ITEMDATA **MakeItemData(int NItem, char **name, TXFONT **font, int *ListOrder)
  897. {
  898.     ITEMDATA     **ItemList,*item,*item2;
  899.     size_t        size;
  900.     int            j,k;
  901.     long        y;
  902.     char        *str,*str2,letter,letter2;
  903.     int            swap;
  904.  
  905.     size=(NItem + 1)*sizeof(ITEMDATA *);
  906.     ItemList=(ITEMDATA **)GXGetMem(size, MEMF_ABORT);
  907.  
  908.     for(j=0; j<NItem; j++){
  909.         size=sizeof(ITEMDATA) + strlen(name[j]) + 1;
  910.         ItemList[j]=item=(ITEMDATA *)GXGetMem(size, MEMF_ABORT|MEMF_ZERO);
  911.  
  912.         item->String=(char *)(item+1);
  913.         strcpy(item->String, name[j]);
  914.  
  915.         item->Font=font[j];
  916.         item->Type=ITEM_STRING;
  917.         item->ListOrder=ListOrder[j];
  918.         item->BackColor=WhiteIndex;
  919.     }
  920.     ItemList[j]=0;
  921.     
  922.     //    Sort entries
  923.     for(j=0; j<(NItem-1); j++){
  924.         item=ItemList[j];
  925.         for(k=j+1; k<NItem; k++){
  926.             item2=ItemList[k];
  927.             if(item2->ListOrder>item->ListOrder){
  928.                 //    Directories come before files
  929.                 ItemList[k]=item;
  930.                 ItemList[j]=item2;
  931.                 item=item2;
  932.             }else if(item2->ListOrder==item->ListOrder){
  933.                 //    Entries are of same type so compare alpabetically
  934.                 str=item->String;
  935.                 str2=item2->String;
  936.                 while(1){
  937.                     letter=*str++;
  938.                     letter2=*str2++;
  939.                     if(!letter2){
  940.                         swap=1;
  941.                         break;                    
  942.                     }
  943.                     if(!letter){
  944.                         swap=0;
  945.                         break;
  946.                     }
  947.                     if( (letter>='a')&&(letter<='z') ){
  948.                         letter+=('A'-'a');
  949.                     }
  950.                     if( (letter2>='a')&&(letter2<='z') ){
  951.                         letter2+=('A'-'a');
  952.                     }
  953.                     if(letter2<letter){
  954.                         swap=1;
  955.                         break;
  956.                     }else if(letter2>letter){
  957.                         swap=0;
  958.                         break;
  959.                     }
  960.                 }
  961.                 if(swap){
  962.                     ItemList[k]=item;
  963.                     ItemList[j]=item2;
  964.                     item=item2;
  965.                 }
  966.             }
  967.         }    
  968.     }
  969.  
  970.     //    Figure out positions
  971.     y=0;
  972.     for(j=0; j<NItem; j++){
  973.         item=ItemList[j];
  974.         item->Oblong.X=0;
  975.         item->Oblong.Y=y;
  976.         item->Oblong.Width=TXStringWidth(item->String, item->Font);
  977.         item->Oblong.Height=item->Font->Height;
  978.         y+=item->Font->Height;
  979.     }
  980.     return    ItemList;
  981. }
  982.  
  983.  
  984. //**********************************************************************
  985. //    KillWindowItemData()
  986. //**********************************************************************
  987. //    Description: Free up item list made with above functions
  988. //    Input: item list
  989. //    Output: none
  990. //**********************************************************************
  991. void    KillWindowItemData(SCROLLWINDOW *window)
  992. {
  993.     ITEMDATA *item,**from;
  994.     
  995.     if(!window->Item){
  996.         return;
  997.     }
  998.     from=window->Item;
  999.     while(item=*from++){
  1000.         GXFreeMem(item);
  1001.     }
  1002.     GXFreeMem(window->Item);
  1003.     window->Item=0;
  1004. }
  1005.  
  1006. //**********************************************************************
  1007. //    ListHeight()
  1008. //**********************************************************************
  1009. //    Description: Find maximum y value for item list
  1010. //    Input: item list
  1011. //    Output: maximum y
  1012. //**********************************************************************
  1013. int    ListHeight(ITEMDATA **ItemList)
  1014. {
  1015.     ITEMDATA *item;
  1016.     
  1017.     
  1018.     while(*ItemList++)
  1019.         ;
  1020.     item=*(ItemList-2);
  1021.     return    (item->Oblong.Y+item->Oblong.Height);
  1022. }
  1023.  
  1024. //**********************************************************************
  1025. //    PrintDirectoryName()
  1026. //**********************************************************************
  1027. //    Description: Print directory name at top of screen
  1028. //    Input: screen image, font, directory
  1029. //    Output: none
  1030. //**********************************************************************
  1031. void    PrintDirectoryName(GXIMAGE *Screen, TXFONT *TheFont, char *name)
  1032. {
  1033.     long        XPlot,YPlot;
  1034.     GXBLITLIST    *b;
  1035.     char        *DirName=" ";
  1036.     
  1037.     if(*name){
  1038.         DirName=name;
  1039.     }
  1040.     while(*DirName){
  1041.         if( TXStringWidth(DirName, TheFont) <= DIRECTORYNAME_WIDTH ){
  1042.             break;
  1043.         }
  1044.         DirName++;
  1045.     }
  1046.     if(!(*DirName)){
  1047.         GXQuitCode("PrintDirectoryName(): Couldnt get Directory name to fit\n");
  1048.     }    
  1049.     
  1050.     //    Figure out plot position
  1051.     XPlot=(DIRECTORYNAME_WIDTH - TXStringWidth(DirName, TheFont))/2;
  1052.     if(XPlot<0){
  1053.         XPlot=DIRECTORYNAME_X;
  1054.     }else{
  1055.         XPlot+=DIRECTORYNAME_X;
  1056.     }
  1057.     YPlot=(DIRECTORYNAME_HEIGHT - TXFONTHeight(TheFont))/2;
  1058.     if(YPlot<0){
  1059.         YPlot=DIRECTORYNAME_Y;
  1060.     }else{
  1061.         YPlot+=DIRECTORYNAME_Y;
  1062.     }
  1063.     
  1064.     //    Clear out last string
  1065.     b=GXNextBlit();
  1066.     b->Type=BLIT_COLORFILL;
  1067.     b->From.Width=DIRECTORYNAME_WIDTH;
  1068.     b->From.Height=DIRECTORYNAME_HEIGHT;
  1069.     b->Color=WhiteIndex;
  1070.     b->XTo=DIRECTORYNAME_X;
  1071.     b->YTo=DIRECTORYNAME_Y;
  1072.     b->ToImage=Screen;
  1073.     GXDoBlit();
  1074.     
  1075.     //    Print new string
  1076.     TXPrintString(DirName, XPlot, YPlot, Screen, TheFont);
  1077. }
  1078.  
  1079. //**********************************************************************
  1080. //    GetFileSelection()
  1081. //**********************************************************************
  1082. //    Description: Find what item correspnds to a given Y value in a
  1083. //                    window.
  1084. //    Input:  y value, items 
  1085. //    Output: Number of item or -1 if none found
  1086. //**********************************************************************
  1087. int    GetFileSelection(int y, ITEMDATA **list)
  1088. {
  1089.     int            yy,n;
  1090.     ITEMDATA    *item;
  1091.     
  1092.     if(!list){
  1093.         return -1;
  1094.     }
  1095.     n=0;
  1096.     while(item=*list++){
  1097.         yy=y-item->Oblong.Y;
  1098.         if( (yy>0) && (yy<item->Oblong.Height) ){
  1099.             return    n;
  1100.         }
  1101.         n++;
  1102.     }
  1103.     return -1;
  1104. }
  1105.  
  1106. //*****************************************************************************
  1107. //    WaitNoKeys()
  1108. //*****************************************************************************
  1109. //    Description: Wait until no keys are pressed
  1110. //    input:  None
  1111. //    output: None
  1112. //*****************************************************************************
  1113. void    WaitNoKeys(void)
  1114. {
  1115.     long    j;
  1116.  
  1117.     //    Wait till no keys are pressed
  1118.     do{
  1119.         GXSystemUpdate();
  1120.         for(j=0; j<256; j++){
  1121.             if(GXKeyDown(j)){
  1122.                 break;
  1123.             }
  1124.         }
  1125.     }while(j!=256);
  1126.  
  1127.     //    Empty keyboard buffer
  1128.     while(GXNextKey())
  1129.         ;
  1130. }
  1131.  
  1132. //*****************************************************************************
  1133. //    DoMenu()
  1134. //*****************************************************************************
  1135. //    Description: Let the user choose from options on a side panel
  1136. //    input:  menu title, strings for options, number of options
  1137. //    output: option chosen or -1 if none
  1138. //*****************************************************************************
  1139. #define    CLICK_SELECT    30    //how quick double click must be to select
  1140. int        DoMenu(char *title, char **options, int NOptions)
  1141. {
  1142.     GXBLITLIST    *b;
  1143.     long        x,y,j;
  1144.     GXOBLONG    *Buttons=0;    
  1145.     GXMOUSEINFO    MouseInfo,LastMouseInfo;
  1146.     GXIMAGE        *ScreenImage;
  1147.     long        selection;
  1148.     long        frame=0,JustPressed=0,NewSelection,delay,xx,tt,number;
  1149.     long        DoubleClick,DoubleClickDelay,moving;
  1150.  
  1151.     WaitNoKeys();
  1152.     SaveScreen();
  1153.     ScreenImage=GXStartDrawing(0);
  1154.  
  1155.     //    Draw backdrop
  1156.     DrawBackground(ScreenImage, 0);
  1157.     b=GXNextBlit();
  1158.     b->Type=BLIT_IMAGE;
  1159.     b->From=TitleBox;
  1160.     b->XTo=b->YTo=0;
  1161.     b->FromImage=GadgetsImage;
  1162.     b->ToImage=ScreenImage;
  1163.     
  1164.     //    Print title
  1165.     x=TitleBox.Width/2 + TitleBox.X - TXStringWidth(title, BlackFont)/2;
  1166.     y=TitleBox.Height/2 + TitleBox.Y - TXFONTHeight(BlackFont)/2;
  1167.     TXPrintString(title, x, y, ScreenImage, BlackFont);
  1168.  
  1169.     //    Print menu options & initialize button data
  1170.     Buttons=(GXOBLONG *)GXGetMem(NOptions*sizeof(GXOBLONG), MEMF_ZERO|MEMF_ABORT);
  1171.     for(j=0; j<NOptions; j++){
  1172.         y=KEYOPTIONS_Y+KEYOPTIONS_DY*j;    
  1173.         Buttons[j].Width=TXStringWidth(options[j], BlackFont);
  1174.         Buttons[j].Height=TXFONTHeight(BlackFont);
  1175.         Buttons[j].X=(ScreenWidth-Buttons[j].Width)/2;
  1176.         Buttons[j].Y=y;
  1177.         if(j){
  1178.             TXPrintString(options[j], Buttons[j].X, Buttons[j].Y, ScreenImage, BlackFont);
  1179.         }else{
  1180.             TXPrintString(options[j], Buttons[j].X, Buttons[j].Y, ScreenImage, RedFont);
  1181.         }
  1182.         y+=Buttons[j].Height;
  1183.     }    
  1184.  
  1185.     selection=0;
  1186.     delay=GXTicksPerSecond()/60;
  1187.     DoubleClickDelay=CLICK_SELECT+1;
  1188.     if(!delay)delay=1;
  1189.     GXReadMouse(&LastMouseInfo);
  1190.     moving=0;
  1191.     do{
  1192.         //    Wait till next sixtieth to do next frame
  1193.         xx=GXTimer();
  1194.         do{
  1195.             tt=GXTimer()-xx;
  1196.             if(tt<0)break;
  1197.         }while(tt< delay );
  1198.         frame++;
  1199.  
  1200.         //    Update everything
  1201.         GXSystemUpdate();
  1202.         GXReadMouse(&MouseInfo);
  1203.         GXDoBlit();
  1204.         while(GXNextKey())
  1205.             ;
  1206.  
  1207.         //    Update menu selection due to mouse
  1208.         NewSelection=selection;
  1209.         JustPressed=MouseInfo.LeftButton&(!LastMouseInfo.LeftButton);
  1210.         if( (number=UpdateButtons(Buttons, NOptions)) != -1 ){
  1211.             if(JustPressed){
  1212.                 NewSelection=number;
  1213.             }
  1214.         }
  1215.         DoubleClick=0;
  1216.         if(JustPressed){
  1217.             if( (DoubleClickDelay<CLICK_SELECT) && (NewSelection==selection) ){
  1218.                 DoubleClick=1;
  1219.             }
  1220.             DoubleClickDelay=0;
  1221.         }else{
  1222.             DoubleClickDelay++;
  1223.         }
  1224.  
  1225.         //    Update menu selection due to keyboard/joypad
  1226.         if( (frame==20) || (!moving) ){
  1227.             if(GXKeyDown(KeyPrefs[3])){
  1228.                 if(selection==(NOptions-1)){
  1229.                     NewSelection=0;
  1230.                 }else{
  1231.                     NewSelection=selection+1;
  1232.                 }
  1233.                 moving=1;
  1234.             }else if(GXKeyDown(KeyPrefs[2])){
  1235.                 if(!selection){
  1236.                     NewSelection=NOptions-1;
  1237.                 }else{
  1238.                     NewSelection=selection-1;
  1239.                 }
  1240.                 moving=1;
  1241.             }else{
  1242.                 moving=0;
  1243.             }
  1244.             frame=0;
  1245.         }
  1246.         //    Check for menu exit
  1247.         if( DoubleClick || GXKeyDown(KeyPrefs[4]) || GXKeyDown(KEY_RETURN) ){
  1248.             break;
  1249.         }
  1250.  
  1251.         //    Update highlighted option
  1252.         if(selection!=NewSelection){
  1253.             TXPrintString(options[selection], 
  1254.                 Buttons[selection].X, Buttons[selection].Y, ScreenImage, BlackFont);
  1255.             selection=NewSelection;
  1256.             TXPrintString(options[selection], 
  1257.                 Buttons[selection].X, Buttons[selection].Y, ScreenImage, RedFont);
  1258.         }
  1259.         //    Save mouse input for use next frame
  1260.         LastMouseInfo=MouseInfo;
  1261.     }while(1);
  1262.  
  1263.     //    Free up everything and restore screen
  1264.     if(Buttons)GXFreeMem(Buttons);
  1265.     RestoreScreen();
  1266.     return selection;
  1267. }    
  1268. //*****************************************************************************
  1269. //    MakeGameScreen()
  1270. //*****************************************************************************
  1271. //    Description: Draw the in-game screen
  1272. //    input: none
  1273. //    output: none
  1274. //*****************************************************************************
  1275. void    MakeGameScreen(void)
  1276. {
  1277.     GXBLITLIST    *b;
  1278.     GXIMAGE        *ScreenImage;
  1279.     long        GameBoyY;
  1280.     long        xx,width,height,YStep;
  1281.  
  1282.     ScreenImage=GXStartDrawing(0);
  1283.     b=GXNextBlit();
  1284.     b->Type=BLIT_COLORFILL;
  1285.     b->From.Width=ScreenWidth;
  1286.     b->From.Height=ScreenHeight;
  1287.     b->Color=BlackIndex;
  1288.     b->XTo=0;
  1289.     b->YTo=0;
  1290.     b->ToImage=ScreenImage;
  1291.  
  1292.     //    Scroll in gameboy
  1293.     width=GXImageWidth(GameBoyImage);
  1294.     xx=ScreenWidth-BackdropX;
  1295.     if(xx<width){
  1296.         width=xx;
  1297.     }
  1298.     GameBoyY=ScreenHeight-1;
  1299.     YStep=ScreenHeight/25;        //scroll up in 50 frames
  1300.     if(!YStep)YStep=1;
  1301.     do{
  1302.         b=GXNextBlit();
  1303.         b->Type=BLIT_IMAGE;
  1304.         b->From.X=b->From.Y=0;
  1305.         b->From.Width=width;
  1306.  
  1307.         height=GXImageHeight(GameBoyImage);
  1308.         xx=ScreenHeight-GameBoyY;
  1309.         if(xx<height)height=xx;
  1310.         b->From.Height=height;
  1311.     
  1312.         b->XTo=BackdropX;
  1313.         b->YTo=GameBoyY;
  1314.         b->FromImage=GameBoyImage;
  1315.         b->ToImage=ScreenImage;
  1316.         GXDoBlit();
  1317.         if(GameBoyY==BackdropY)break;
  1318.         GameBoyY-=YStep;
  1319.         if(GameBoyY<BackdropY)GameBoyY=BackdropY;
  1320.         GXSystemUpdate();
  1321.     }while(1);
  1322.  
  1323.     //    Clear out area to be drawn to by gameboy
  1324.     b=GXNextBlit();
  1325.     b->Type=BLIT_COLORFILL;
  1326.     b->From=GameBoyDisplay;
  1327.     b->Color=GAMEBOY_BASE;
  1328.     b->XTo=GameBoyDisplay.X;
  1329.     b->YTo=GameBoyDisplay.Y;
  1330.     b->ToImage=ScreenImage;
  1331.     GXDoBlit();
  1332. }
  1333.  
  1334.     GXIMAGE            *ScreenImage;
  1335.  
  1336. //*****************************************************************************
  1337. //    FileRequestor()
  1338. //*****************************************************************************
  1339. //    Description: Gets file name selection
  1340. //    input: address of output string
  1341. //    output: file chosen ?
  1342. //*****************************************************************************
  1343. int    FileRequestor(char *output, char *title)
  1344. {
  1345.     GXBLITLIST        *b;
  1346.     GXMOUSEINFO        MouseInfo,OldMouseInfo;
  1347.     SCROLLWINDOW    *window=0;
  1348.     ITEMDATA        *item;
  1349.     long            Y;
  1350.     int                j;
  1351.     long            yy,xx,ScrollY,Grab;
  1352.     SLIDER            Up;
  1353.     GXOBLONG        Buttons[8];
  1354.     char            letter;
  1355.     int                selection;
  1356.     long            ClickInterval;
  1357.     long            ListType;
  1358.     static    char    DirectoryString[256]="";
  1359.     static    char    FileString[256]="";
  1360.     static    char    DeviceString[256]="";
  1361.     char            ss[256];
  1362.     char            *from;
  1363.     int                NSlash;
  1364.     int                finished,Highlight;
  1365.     STRINGGADGET    *sg=0;
  1366.     int                ActiveGadget,key;
  1367.     int                JustPressed,number;
  1368.     int                success=0;
  1369.     
  1370.     //    Set parameters for sliders
  1371.     Up.Width=DownKnob.Width;
  1372.     Up.Height=DownKnob.Height;
  1373.     Up.MinX=Up.MaxX=SlideSide.X+1;
  1374.     Up.MinY=SlideSide.Y+1;
  1375.     Up.MaxY=Up.MinY+SlideSide.Height-Up.Height-2;
  1376.     Up.Vertical=1;
  1377.     Up.Position=0;
  1378.     Up.X=Up.MinX;
  1379.     Up.Y=Up.MinY;
  1380.     Up.BackColor=WhiteIndex;
  1381.  
  1382.     //////////////////////////////////
  1383.     //    Set up the scroll window    //
  1384.     //////////////////////////////////
  1385.     window=MakeScrollWindow(List.Width,List.Height);
  1386.     sprintf(ss,"%s%s",DeviceString,DirectoryString);
  1387.     if(!MakeFileList(window, ss)){
  1388.         strcpy(DeviceString,"");
  1389.         strcpy(DirectoryString,"");            //fixit
  1390.         if(!MakeFileList(window, ss)){
  1391.             GXQuitCode(ErrorString[1]);
  1392.         }
  1393.     }
  1394.     ListType=LISTTYPE_FILES;
  1395.  
  1396.     ScreenImage=GXStartDrawing(0);
  1397.     b=GXNextBlit();
  1398.     b->Type=BLIT_COLORFILL;
  1399.     b->From.Width=GXImageWidth(ScreenImage);
  1400.     b->From.Height=GXImageHeight(ScreenImage);
  1401.     b->Color=BlackIndex;
  1402.     b->XTo=0;
  1403.     b->YTo=0;
  1404.     b->ToImage=ScreenImage;
  1405.  
  1406.     b=GXNextBlit();
  1407.     b->Type=BLIT_IMAGE;
  1408.     b->From=FileSelector;
  1409.     b->XTo=0;
  1410.     b->YTo=0;
  1411.     b->FromImage=GadgetsImage;
  1412.     b->ToImage=ScreenImage;
  1413.     DrawWindow(window, List.X, List.Y, ScreenImage);
  1414.  
  1415.     b=GXNextBlit();
  1416.     b->Type=BLIT_IMAGE;
  1417.     b->From=SliderUp;
  1418.     b->XTo=UPARROW_X;
  1419.     b->YTo=UPARROW_Y;
  1420.     b->FromImage=GadgetsImage;
  1421.     b->ToImage=ScreenImage;
  1422.     
  1423.     b=GXNextBlit();
  1424.     b->Type=BLIT_IMAGE;
  1425.     b->From=SliderDown;
  1426.     b->XTo=DOWNARROW_X;
  1427.     b->YTo=DOWNARROW_Y;
  1428.     b->FromImage=GadgetsImage;
  1429.     b->ToImage=ScreenImage;
  1430.     
  1431.     sprintf(ss,"%s%s",DeviceString,DirectoryString);
  1432.  
  1433.     //    DrawButtons
  1434.     for(j=0; j<4; j++){
  1435.         DrawButton(ScreenImage, FileStrings[j], BUTTONS_X, BUTTONS_Y+j*BUTTONS_DY);
  1436.     }    
  1437.     
  1438.     //    Title
  1439.     xx=(FileTitle.Width/2) - TXStringWidth(title, BlackFont)/2 + FileTitle.X;
  1440.     yy=(FileTitle.Height/2) - TXFONTHeight(BlackFont)/2 + FileTitle.Y;
  1441.     TXPrintString(title, xx, yy, ScreenImage, BlackFont);
  1442.  
  1443.     
  1444.     //    Make buttons
  1445.     Buttons[0]=SliderDown;
  1446.     Buttons[0].X=DOWNARROW_X;
  1447.     Buttons[0].Y=DOWNARROW_Y;
  1448.         
  1449.     Buttons[1]=SliderUp;
  1450.     Buttons[1].X=UPARROW_X;
  1451.     Buttons[1].Y=UPARROW_Y;
  1452.  
  1453.     //    Parent button
  1454.     Buttons[2]=ButtonUp;
  1455.     Buttons[2].X=BUTTONS_X;
  1456.     Buttons[2].Y=BUTTONS_Y;
  1457.  
  1458.     //    Volumes button
  1459.     Buttons[3]=Buttons[2];
  1460.     Buttons[3].Y+=BUTTONS_DY;
  1461.     
  1462.     //    OK button
  1463.     Buttons[4]=Buttons[3];
  1464.     Buttons[4].Y+=BUTTONS_DY;
  1465.  
  1466.     //    CANCEL
  1467.     Buttons[5]=Buttons[4];
  1468.     Buttons[5].Y+=BUTTONS_DY;
  1469.     
  1470.     //    LIST BOX
  1471.     Buttons[6].X=List.X;
  1472.     Buttons[6].Y=List.Y;
  1473.     Buttons[6].Width=List.Width;
  1474.     Buttons[6].Height=List.Height;
  1475.  
  1476.     //    STRING GADGET
  1477.     Buttons[7]=StringGadget;
  1478.  
  1479.     sg=MakeStringGadget(FileString, &StringGadget, ScreenImage);
  1480.     /************************************************/
  1481.     /*                                                */
  1482.     /*    INPUT LOOP                                    */
  1483.     /*                                                */
  1484.     /************************************************/
  1485. #define    LIST_VOLUMES    {                            \
  1486.                         PrintLoadingMessage();        \
  1487.                         MakeVolumeList(window);        \
  1488.                         ListType=LISTTYPE_VOLUMES;    \
  1489.                         ScrollY=0;                    \
  1490.                         Y=Up.MinY;                    \
  1491.                         Highlight=-1;                \
  1492.                         break;                        \
  1493.                         }
  1494.  
  1495.     ScrollY=0;
  1496.     GXReadMouse(&OldMouseInfo);
  1497.     Y=Up.MinY;
  1498.     Grab=0;
  1499.     Highlight=-1;
  1500.     selection=-1;
  1501.     ClickInterval=0;
  1502.     finished=0;
  1503.     ActiveGadget=-1;
  1504.     while(!finished){
  1505.         //********************************************
  1506.         //    Update input devices and system
  1507.         //********************************************
  1508.         ClickInterval++;
  1509.         GXSystemUpdate();
  1510.         GXReadMouse(&MouseInfo);
  1511.         JustPressed=MouseClick();
  1512.         key=GXNextKey();
  1513.         while(GXNextKey())
  1514.             ;
  1515.         
  1516.         //********************************************
  1517.         //    Update string gadget
  1518.         //********************************************
  1519.         UpdateStringGadget(sg, RawToAscii(key), ScreenImage, (ActiveGadget==7));
  1520.  
  1521.         //********************************************
  1522.         //    Update slider
  1523.         //********************************************
  1524.         if(JustPressed){
  1525.             //    Check for grabbing slider
  1526.             xx=MouseInfo.X-Up.X;
  1527.             if( (xx>=0) && (xx<Up.Width) ){
  1528.                 yy=MouseInfo.Y-Up.Y;
  1529.                 if( (yy>=0) && (yy<Up.Height) ){
  1530.                     Grab=1;
  1531.                 }
  1532.             }
  1533.         }
  1534.         if(!MouseInfo.LeftButton){
  1535.             Grab=0;
  1536.         }
  1537.         if(Grab){
  1538.             Y+=(MouseInfo.Y-OldMouseInfo.Y);
  1539.             if(Y<Up.MinY){
  1540.                 Y=Up.MinY;
  1541.             }else if(Y>Up.MaxY){
  1542.                 Y=Up.MaxY;
  1543.             }
  1544.             ScrollY=(Y-Up.MinY)*window->MaxY/(Up.MaxY-Up.MinY);
  1545.         }else if( (number=UpdateButtons(Buttons, 8)) != -1 ){
  1546.             //********************************************
  1547.             //    Update buttons
  1548.             //********************************************
  1549.             if(JustPressed){
  1550.                 ActiveGadget=number;
  1551.             }
  1552.             switch(number){
  1553.             case BUTTONID_STRINGGADGET:
  1554.                 break;
  1555.             case BUTTONID_DOWNARROW: 
  1556.                 if(!MouseInfo.LeftButton)break;
  1557.                 if(window->MaxY){
  1558.                     ScrollY++;    
  1559.                     if(ScrollY>window->MaxY){
  1560.                         ScrollY=window->MaxY;
  1561.                     }
  1562.                     Y=(Up.MaxY-Up.MinY)*ScrollY/window->MaxY;
  1563.                     Y+=Up.MinY;
  1564.                 }
  1565.                 break;
  1566.             case BUTTONID_UPARROW: 
  1567.                 if(!MouseInfo.LeftButton)break;
  1568.                 if(window->MaxY){
  1569.                     ScrollY--;    
  1570.                     if(ScrollY<0){
  1571.                         ScrollY=0;
  1572.                     }
  1573.                     Y=(Up.MaxY-Up.MinY)*ScrollY/window->MaxY;
  1574.                     Y+=Up.MinY;
  1575.                 }
  1576.                 break;
  1577.             case BUTTONID_PARENT:
  1578.                 if(!JustPressed){
  1579.                     break;
  1580.                 }
  1581.                 Highlight=-1;
  1582.                 KillWindowItemData(window);
  1583.                 PrintLoadingMessage();
  1584.                 if( !DirectoryString[0] ){
  1585.                     MakeVolumeList(window);
  1586.                     ListType=LISTTYPE_VOLUMES;
  1587.                     ScrollY=0;
  1588.                     Y=Up.MinY;
  1589.                     break;
  1590.                 }else{
  1591.                     from=DirectoryString;
  1592.                     NSlash=0;
  1593.                     while(letter=*from++){
  1594.                         if(letter=='/')NSlash++;
  1595.                     }
  1596.                     if(NSlash>1){
  1597.                         from=DirectoryString+strlen(DirectoryString)-2;                    
  1598.                         while(letter=*from--){
  1599.                             if(letter=='/')break;
  1600.                         }
  1601.                         from[2]=0;
  1602.                     }else{
  1603.                         DirectoryString[0]=0;
  1604.                     }
  1605.                 }
  1606.                 sprintf(ss,"%s%s",DeviceString,DirectoryString);
  1607.                 //PrintDirectoryName(ScreenImage, BlackFont, ss);
  1608.                 PrintLoadingMessage();
  1609.                 if(!MakeFileList(window, ss)){
  1610.                     LIST_VOLUMES
  1611.                     break;
  1612.                 }
  1613.                 ListType=LISTTYPE_FILES;
  1614.                 Y=Up.MinY;
  1615.                 ScrollY=0;
  1616.                 break;
  1617.             case BUTTONID_VOLUMES:
  1618.                 if(JustPressed){
  1619.                     KillWindowItemData(window);
  1620.                     LIST_VOLUMES
  1621.                 }
  1622.                 break;
  1623.             case BUTTONID_OK:
  1624.                 if(JustPressed){
  1625.                     if( ListType==LISTTYPE_FILES ){
  1626.                         success=1;
  1627.                         finished=1;
  1628.                     }
  1629.                 }
  1630.                 break;
  1631.             case BUTTONID_CANCEL:
  1632.                 if(JustPressed){
  1633.                     *output=0;
  1634.                     finished=1;                    
  1635.                 }
  1636.                 break;
  1637.             case BUTTONID_LIST:
  1638.                 if(!JustPressed){
  1639.                     break;
  1640.                 }
  1641.                 xx=GetFileSelection(MouseInfo.Y-List.Y+window->Y, window->Item);
  1642.                 if(xx==-1)break;
  1643.                 selection=xx;
  1644.                 if(selection==Highlight){    //clicked twice on same item
  1645.                     if(ClickInterval<GXTicksPerSecond()){
  1646.                         //****************************************
  1647.                         //    Double clicked
  1648.                         //****************************************
  1649.                         if(ListType==LISTTYPE_FILES){
  1650.                             item=window->Item[selection];
  1651.                             if(item->ListOrder==1){
  1652.                                 //    directory
  1653.                                 strcat(DirectoryString, item->String);
  1654.                                 strcat(DirectoryString, "/");
  1655.                                 KillWindowItemData(window);
  1656.                                 sprintf(ss,"%s%s",DeviceString,DirectoryString);
  1657.                                 //PrintDirectoryName(ScreenImage, BlackFont, ss);
  1658.                                 PrintLoadingMessage();
  1659.                                 if(!MakeFileList(window, ss)){
  1660.                                     GXPrintf("*** Failed to make list of files!!\n");
  1661.                                     LIST_VOLUMES;
  1662.                                     break;
  1663.                                 }else{
  1664.                                     GXPrintf("*** Made file list\n");
  1665.                                 }
  1666.                                 ListType=LISTTYPE_FILES;
  1667.                                 Y=Up.MinY;
  1668.                                 ScrollY=0;
  1669.                                 Highlight=-1;
  1670.                             }else{
  1671.                                 //    file
  1672.                                 success=1;
  1673.                                 finished=1;
  1674.                             }
  1675.                         }else{
  1676.                             strcpy(DeviceString, window->Item[selection]->String);
  1677.                             strcpy(DirectoryString,"");
  1678.                             KillWindowItemData(window);
  1679.                             //PrintDirectoryName(ScreenImage, BlackFont, DeviceString);
  1680.                             PrintLoadingMessage();
  1681.                             if(!MakeFileList(window, DeviceString)){
  1682.                                 LIST_VOLUMES;
  1683.                                 break;
  1684.                             }
  1685.                             ListType=LISTTYPE_FILES;
  1686.                             Y=Up.MinY;
  1687.                             ScrollY=0;
  1688.                             GXPrintf("Volume selected!!\n");
  1689.                             GXPrintf("%s\n",DeviceString);
  1690.                             Highlight=-1;
  1691.                         }
  1692.                     }
  1693.                 }else{
  1694.                     item=window->Item[selection];
  1695.                     if( (ListType==LISTTYPE_FILES) && (item->ListOrder==0)){
  1696.                         ChangeStringGadget(item->String, sg, ScreenImage);                                            
  1697.                     }
  1698.                     if(item->ListOrder==0){
  1699.                         item->BackColor=BlackIndex;
  1700.                     }else{
  1701.                         item->BackColor=RedIndex;
  1702.                     }
  1703.                     item->Font=WhiteFont;
  1704.                     RedrawItem(window, item);
  1705.                     if(Highlight!=-1){
  1706.                         item=window->Item[Highlight];
  1707.                         if(item->ListOrder==0){
  1708.                             item->Font=BlackFont;
  1709.                         }else{
  1710.                             item->Font=RedFont;
  1711.                         }
  1712.                         item->BackColor=WhiteIndex;
  1713.                         RedrawItem(window, item);
  1714.                     }
  1715.                     Highlight=selection;
  1716.                 }
  1717.                 ClickInterval=0;
  1718.                 break;
  1719.             case -1:
  1720.                 break;
  1721.             default:
  1722.                 GXQuitCode("Invalid button\n");
  1723.             }
  1724.         }
  1725.         //    Check cursor keys
  1726.         if(GXKeyDown(KEY_CURSORDOWN)){ 
  1727.             if(window->MaxY){
  1728.                 ScrollY+=2;    
  1729.                 if(ScrollY>window->MaxY){
  1730.                     ScrollY=window->MaxY;
  1731.                 }
  1732.                 Y=(Up.MaxY-Up.MinY)*ScrollY/window->MaxY;
  1733.                 Y+=Up.MinY;
  1734.             }
  1735.         }
  1736.         if(GXKeyDown(KEY_CURSORUP)){
  1737.             if(window->MaxY){
  1738.                 ScrollY-=2;    
  1739.                 if(ScrollY<0){
  1740.                     ScrollY=0;
  1741.                 }
  1742.                 Y=(Up.MaxY-Up.MinY)*ScrollY/window->MaxY;
  1743.                 Y+=Up.MinY;
  1744.             }
  1745.         }
  1746.         if(GXKeyDown(KEY_RETURN)){
  1747.             if(ListType==LISTTYPE_FILES){
  1748.                 success=1;
  1749.                 finished=1;
  1750.             }
  1751.         }
  1752.         ScrollWindow(window, 0, ScrollY);
  1753.         DrawWindow(window, List.X, List.Y, ScreenImage);
  1754.         UpdateSlider(&Up, Y, ScreenImage);
  1755.         GXDoBlit();
  1756.         OldMouseInfo=MouseInfo;
  1757.     }
  1758.     if(success){
  1759.         sprintf(output, "%s%s%s",
  1760.             DeviceString, DirectoryString, GetStringGadget(sg));
  1761.     }else{
  1762.         *output=0;
  1763.     }
  1764.     KillWindowItemData(window);
  1765.     KillScrollWindow(window);
  1766.     if(sg)KillStringGadget(sg);
  1767.  
  1768.     return success;
  1769. }
  1770.  
  1771. int    MouseClick(void)
  1772. {
  1773.     int            jj;
  1774.     GXMOUSEINFO    mouse;
  1775.     static        GXMOUSEINFO    LastMouse;    
  1776.     
  1777.     GXReadMouse(&mouse);
  1778.     jj=(mouse.LeftButton)&(!LastMouse.LeftButton);
  1779.     LastMouse=mouse;
  1780.     return jj;
  1781. }
  1782.  
  1783. //**********************************************************************
  1784. //    PrintLoadingMessage()
  1785. //**********************************************************************
  1786. //    Description:print "READING..." message in the file list to let
  1787. //                the user know that a directory or volume list is being
  1788. //                read.
  1789. //    Input: none
  1790. //    Output: none
  1791. //**********************************************************************
  1792. void    PrintLoadingMessage(void)
  1793. {
  1794.     GXBLITLIST    *b;
  1795.     
  1796.     //    Clear out list window then print message
  1797.     b=GXNextBlit();
  1798.     b->Type=BLIT_COLORFILL;
  1799.     b->From.Width=List.Width;
  1800.     b->From.Height=List.Height;
  1801.     b->XTo=List.X;
  1802.     b->YTo=List.Y;
  1803.     b->ToImage=ScreenImage;
  1804.     b->Color=WhiteIndex;
  1805.  
  1806.     TXPrintString(FileStrings[4], List.X, List.Y, ScreenImage, BlackFont);
  1807.     GXDoBlit();                
  1808.     GXSystemUpdate();    //could possibly mess up input.
  1809. }
  1810.  
  1811. //**********************************************************************
  1812. //    RedrawItem()
  1813. //**********************************************************************
  1814. //    Description: Redraw and item in a window
  1815. //    Input: window, item
  1816. //    Output: none
  1817. //**********************************************************************
  1818. void    RedrawItem(SCROLLWINDOW *window, ITEMDATA *item)
  1819. {
  1820.     int    y0,y1,y,n;
  1821.  
  1822.     y=item->Oblong.Y;
  1823.     y0=window->Y;
  1824.     y1=window->Y+window->Height;
  1825.     for(n=item->Oblong.Height; n; n--){
  1826.         if( (y>=y0)&&(y<y1) ){
  1827.             DrawLine(window, y);
  1828.         }
  1829.         y++;
  1830.     }
  1831. }
  1832.  
  1833. //**********************************************************************
  1834. //    UpdateSlider()
  1835. //**********************************************************************
  1836. //    Description: Move slider to new position on screen
  1837. //    Input:  slider data, new y value wanted, screen image 
  1838. //    Output: none
  1839. //**********************************************************************
  1840. void    UpdateSlider(SLIDER *s, long y, GXIMAGE *screen)
  1841. {
  1842.     GXBLITLIST    *b;
  1843.     long        height;
  1844.  
  1845.     if(y<s->MinY){
  1846.         y=s->MinY;
  1847.     }else if(y>s->MaxY){
  1848.         y=s->MaxY;
  1849.     }
  1850.     height=y-s->Y;
  1851.     if(height>0){
  1852.         b=GXNextBlit();
  1853.         b->Type=BLIT_COLORFILL;
  1854.         b->From.Width=DownKnob.Width;
  1855.         b->From.Height=height;
  1856.         b->XTo=s->X;
  1857.         b->YTo=s->Y;
  1858.         b->ToImage=screen;
  1859.         b->Color=s->BackColor;
  1860.     }else if(height<0){
  1861.         b=GXNextBlit();
  1862.         b->Type=BLIT_COLORFILL;
  1863.         b->From.Width=DownKnob.Width;
  1864.         b->From.Height=-height;
  1865.         b->XTo=s->X;
  1866.         b->YTo=y+DownKnob.Height;
  1867.         b->ToImage=screen;
  1868.         b->Color=s->BackColor;
  1869.     }
  1870.     b=GXNextBlit();
  1871.     b->Type=BLIT_IMAGE;
  1872.     b->From=DownKnob;
  1873.     b->XTo=s->X;
  1874.     b->YTo=y;
  1875.     b->FromImage=GadgetsImage;
  1876.     b->ToImage=screen;
  1877.     s->Y=y;
  1878. }
  1879.  
  1880. //**********************************************************************
  1881. //    IngameUpdate()
  1882. //**********************************************************************
  1883. //    Description: routine called to update menus etc.. while game is
  1884. //                running. called from end of ScreenRefresh()
  1885. //    Input:  none
  1886. //    Output: none
  1887. //**********************************************************************
  1888. void    IngameUpdate(void)
  1889. {
  1890.     GXMOUSEINFO    MouseInfo;
  1891.     int            option;
  1892.     char        LoadGame[256];
  1893.     GXPICTURE    *pic;
  1894.  
  1895.     GXSystemUpdate();
  1896.     #if    DEMO
  1897.         TimeOutCheck();
  1898.     #endif
  1899.     GXReadMouse(&MouseInfo);
  1900.     if( MouseInfo.RightButton || GXKeyDown(KEY_F2) ){
  1901.         switch( option=DoMenu(MenuStrings[0], &MenuStrings[1], MAINBUTTON_NUMBER) ){
  1902.         case    MAINBUTTON_GRAB:
  1903.             SaveScreen();
  1904.             if( FileRequestor(LoadGame, TitleStrings[2]) ){
  1905.                 pic=GXGetPicture(ScreenSaveImage, &GameBoyDisplay);
  1906.                 SavePicture(LoadGame, pic, PICTURE_LBM);
  1907.                 KillPicture(pic);                            //assume this is alright for killing
  1908.             }
  1909.             RestoreScreen();
  1910.             break;
  1911.         case    MAINBUTTON_LOAD:
  1912.             SaveScreen();
  1913.             if( FileRequestor(LoadGame, TitleStrings[0]) ){
  1914.                 CPURunning=0;
  1915.                 strcpy(GameToLoad, LoadGame);
  1916.                 GameOption=GAMEOPTION_LOAD;
  1917.             }
  1918.             RestoreScreen();
  1919.             break;
  1920.         case    MAINBUTTON_QUIT:
  1921.             CPURunning=0;
  1922.             GameOption=GAMEOPTION_QUIT;
  1923.             break;
  1924.         case     MAINBUTTON_PALETTE:
  1925.             PalettePrefs();    
  1926.             break;
  1927.         case    MAINBUTTON_KEYS:
  1928.             KeyOptions();
  1929.             break;
  1930.         case    MAINBUTTON_SAVE:
  1931.             SaveScreen();
  1932.             if(FileRequestor(LoadGame,TitleStrings[1])){
  1933.                 SaveSnapshot(LoadGame);
  1934.             }
  1935.             RestoreScreen();
  1936.             break;
  1937.         case    MAINBUTTON_CANCEL:
  1938.         case    -1:
  1939.             break;
  1940.         default:
  1941.             GXQuitCode("Unknown menu option\n");
  1942.         }
  1943.     }
  1944. }
  1945.  
  1946. void    SaveScreen(void)
  1947. {
  1948.     GXIMAGE        *ScreenImage;
  1949.     GXBLITLIST    *b;
  1950.     
  1951.     ScreenImage=GXStartDrawing(0);
  1952.     ScreenSaveImage=GXMakeImage(ScreenWidth, ScreenHeight);
  1953.     b=GXNextBlit();
  1954.     b->Type=BLIT_IMAGE;
  1955.     b->FromImage=ScreenImage;
  1956.     b->ToImage=ScreenSaveImage;
  1957.     b->From.Width=ScreenWidth;
  1958.     b->From.Height=ScreenHeight;
  1959.     b->From.X=0;
  1960.     b->From.Y=0;
  1961.     b->XTo=0;
  1962.     b->YTo=0;
  1963.     GXDoBlit();
  1964. }
  1965. void    RestoreScreen(void)
  1966. {
  1967.     GXIMAGE    *ScreenImage;
  1968.     GXBLITLIST    *b;
  1969.     
  1970.     ScreenImage=GXStartDrawing(0);
  1971.     b=GXNextBlit();
  1972.     b->Type=BLIT_IMAGE;
  1973.     b->FromImage=ScreenSaveImage;
  1974.     b->ToImage=ScreenImage;
  1975.     b->From.Width=ScreenWidth;
  1976.     b->From.Height=ScreenHeight;
  1977.     b->From.X=0;
  1978.     b->From.Y=0;
  1979.     b->XTo=0;
  1980.     b->YTo=0;
  1981.     GXDoBlit();
  1982.     GXKillImage(ScreenSaveImage);
  1983. }
  1984. //******************************************************
  1985. //    DrawBackground()
  1986. //******************************************************
  1987. //    Tile background on given are on given image
  1988. //    input: image to tile on to, area to be tiled
  1989. //    output: none
  1990. //******************************************************
  1991. void    DrawBackground(GXIMAGE *image, GXOBLONG *area)
  1992. {
  1993.     GXBLITLIST    *b;
  1994.     long        width,height,nx,ny,xplot,yplot,ix,iy,xx;
  1995.     long        ImageWidth,ImageHeight,x0,y0,x1,y1, xend, yend;
  1996.     long        xfrom, yfrom, xto, yto;
  1997.     
  1998.     ImageWidth=GXImageWidth(image);
  1999.     ImageHeight=GXImageHeight(image);
  2000.     if(!area){
  2001.         x0=0;
  2002.         y0=0;
  2003.         x1=ImageWidth;
  2004.         y1=ImageHeight;
  2005.     }else{
  2006.         x0=area->X;
  2007.         y0=area->Y;
  2008.         x1=x0+area->Width;
  2009.         y1=y0+area->Height;
  2010.     }
  2011.  
  2012.     //Draw tiles
  2013.     nx=(ImageWidth/BackTile.Width);
  2014.     if( (ImageWidth%BackTile.Width) ){
  2015.         nx++;
  2016.     }
  2017.     ny=(ImageHeight/BackTile.Height);
  2018.     if( (ImageHeight%BackTile.Height) ){
  2019.         ny++;
  2020.     }
  2021.     yplot=0;
  2022.     for(iy=ny; iy; iy--,yplot+=BackTile.Height){
  2023.         if(yplot>=y1)break;
  2024.         yend=yplot+BackTile.Height;
  2025.         if(yend<=y0)continue;
  2026.         if(yplot<y0){
  2027.             if(yend>y1){
  2028.                 height=area->Height;
  2029.             }else{
  2030.                 height=yend-y0;
  2031.             }
  2032.             yto=y0;
  2033.             yfrom=y0-yplot+BackTile.Y;            
  2034.         }else if(yend>y1){
  2035.             yto=yplot;
  2036.             height=y1-yplot;
  2037.             yfrom=BackTile.Y;            
  2038.         }else{
  2039.             yto=yplot;
  2040.             height=BackTile.Height;
  2041.             yfrom=BackTile.Y;
  2042.         }
  2043.         xplot=0;
  2044.         for(ix=nx; ix; ix--,xplot+=BackTile.Width){
  2045.             if(xplot>=x1)break;
  2046.             xend=xplot+BackTile.Width;
  2047.             if(xend<=x0)continue;
  2048.             if(xplot<x0){
  2049.                 if(xend>x1){
  2050.                     width=area->Width;
  2051.                 }else{
  2052.                     width=xend-x0;
  2053.                 }
  2054.                 xto=x0;
  2055.                 xfrom=x0-xplot+BackTile.X;            
  2056.             }else if(xend>x1){
  2057.                 xto=xplot;
  2058.                 width=x1-xplot;
  2059.                 xfrom=BackTile.X;            
  2060.             }else{
  2061.                 xto=xplot;
  2062.                 width=BackTile.Width;
  2063.                 xfrom=BackTile.X;
  2064.             }
  2065.             b=GXNextBlit();    
  2066.             b->Type=BLIT_IMAGE;
  2067.             b->FromImage=GadgetsImage;
  2068.             b->ToImage=image;    
  2069.             b->XTo=xto;
  2070.             b->YTo=yto;
  2071.             b->From.X=xfrom;    
  2072.             b->From.Y=yfrom;
  2073.             b->From.Width=width;
  2074.             b->From.Height=height;        
  2075.         }
  2076.     }
  2077.  
  2078.     // Draw corners
  2079.     b=GXNextBlit();
  2080.     b->Type=BLIT_IMAGE;
  2081.     b->FromImage=GadgetsImage;
  2082.     b->ToImage=image;
  2083.     b->XTo=b->YTo=0;
  2084.     b->From=CornerTL;
  2085.     
  2086.     b=GXNextBlit();
  2087.     b->Type=BLIT_IMAGE;
  2088.     b->FromImage=GadgetsImage;
  2089.     b->ToImage=image;
  2090.     b->XTo=ImageWidth-CornerTR.Width;
  2091.     b->YTo=0;
  2092.     b->From=CornerTR;
  2093.  
  2094.     b=GXNextBlit();
  2095.     b->Type=BLIT_IMAGE;
  2096.     b->FromImage=GadgetsImage;
  2097.     b->ToImage=image;
  2098.     b->XTo=ImageWidth-CornerBR.Width;
  2099.     b->YTo=ImageHeight-CornerBR.Height;
  2100.     b->From=CornerBR;
  2101.  
  2102.     b=GXNextBlit();
  2103.     b->Type=BLIT_IMAGE;
  2104.     b->FromImage=GadgetsImage;
  2105.     b->ToImage=image;
  2106.     b->XTo=0;
  2107.     b->YTo=ImageHeight-CornerBL.Height;
  2108.     b->From=CornerBL;
  2109. }
  2110.  
  2111. void    ErrorMessage(char *message)
  2112. {
  2113.     GXIMAGE        *ScreenImage;
  2114.     long        x,y;
  2115.     GXMOUSEINFO    MouseInfo;
  2116.     int            LeftReleased=0,MiddleReleased=0,RightReleased=0;
  2117.     
  2118.     SaveScreen();
  2119.     ScreenImage=GXStartDrawing(0);
  2120.  
  2121.     DrawBackground(ScreenImage, 0);
  2122.     x=(ScreenWidth-TXStringWidth(message, RedFont))/2;
  2123.     y=(ScreenHeight-TXFONTHeight(RedFont))/2;
  2124.     TXPrintString(message, x, y, ScreenImage, RedFont);
  2125.     GXDoBlit();
  2126.     GXPrintf(message);
  2127.     do{
  2128.         GXSystemUpdate();
  2129.         GXReadMouse(&MouseInfo);
  2130.  
  2131.         //    When any mouse button is pressed after being released,
  2132.         //    exit.
  2133.         if(!MouseInfo.LeftButton)LeftReleased=1;
  2134.         if(!MouseInfo.MiddleButton)MiddleReleased=1;
  2135.         if(!MouseInfo.RightButton)RightReleased=1;
  2136.  
  2137.         if(MouseInfo.LeftButton&&LeftReleased)break;
  2138.         if(MouseInfo.MiddleButton&&MiddleReleased)break;
  2139.         if(MouseInfo.RightButton&&RightReleased)break;
  2140.     }while(1);
  2141.     RestoreScreen();
  2142. }
  2143.  
  2144.  
  2145.  
  2146.     RGBSLIDER        slider[3];
  2147.  
  2148. void    PalettePrefs(void)
  2149. {
  2150.     GXIMAGE            *ScreenImage;
  2151.     GXBLITLIST        *b;
  2152.     GXMOUSEINFO        MouseInfo;
  2153.     int                j, ix, iy, x, y, is;
  2154.     int                SelectedColor=0;
  2155.     GXOBLONG        *buttons=0;
  2156.     RGBSLIDER        *pslider;
  2157.     int                StartMouseX, StartSliderX;
  2158.     GXPALETTE        color,*OldPalette=0,*GameBoyPalette2=0;
  2159.     int                JustPressed;
  2160.     int                number,changed=0;
  2161.  
  2162.     //    Save screen & palette
  2163.     SaveScreen();
  2164.     OldPalette=(GXPALETTE *)GXGetMem(16*sizeof(GXPALETTE), MEMF_ZERO|MEMF_ABORT);
  2165.     GameBoyPalette2=(GXPALETTE *)GXGetMem(16*sizeof(GXPALETTE), MEMF_ZERO|MEMF_ABORT);
  2166.     memcpy(GameBoyPalette2, GameBoyPalette, 16*sizeof(GXPALETTE));
  2167.     GXGetPaletteRange(OldPalette, GAMEBOY_BASE, 16);
  2168.     GXSetPaletteRange(GameBoyPalette2, GAMEBOY_BASE+16, 16);
  2169.     ScreenImage=GXStartDrawing(0);
  2170.     
  2171.     DrawBackground(ScreenImage, 0);
  2172.  
  2173.     b=GXNextBlit();
  2174.     b->Type=BLIT_IMAGE;
  2175.     b->From=TitleBox;
  2176.     b->XTo=b->YTo=0;
  2177.     b->FromImage=GadgetsImage;
  2178.     b->ToImage=ScreenImage;
  2179.  
  2180.     b=GXNextBlit();
  2181.     b->Type=BLIT_IMAGE;
  2182.     b->From=GameBoyDisplay;
  2183.     b->XTo=PALETTE_PICTURE_X;
  2184.     b->YTo=PALETTE_PICTURE_Y;
  2185.     b->FromImage=ScreenSaveImage;
  2186.     b->ToImage=ScreenImage;
  2187.  
  2188.     //    Draw slider background
  2189.     for(j=0; j<3; j++){
  2190.         b=GXNextBlit();
  2191.         b->Type=BLIT_IMAGE;
  2192.         b->From=PaletteSlider;
  2193.         b->XTo=RGB_SLIDER_GFX_X;
  2194.         b->YTo=RGB_SLIDER_GFX_Y+RGB_SLIDER_GFX_DY*j;
  2195.         b->FromImage=GadgetsImage;
  2196.         b->ToImage=ScreenImage;
  2197.     }
  2198.  
  2199.     //    Draw palette buttons background
  2200.     for(j=0; j<4; j++){
  2201.         b=GXNextBlit();
  2202.         b->Type=BLIT_IMAGE;
  2203.         b->From=PaletteLine;
  2204.         b->XTo=RGB_PALETTE_LINE_GFX_X;
  2205.         b->YTo=RGB_PALETTE_LINE_GFX_Y+j*RGB_PALETTE_LINE_GFX_DY;
  2206.         b->FromImage=GadgetsImage;
  2207.         b->ToImage=ScreenImage;
  2208.     }
  2209.  
  2210.     for(j=0; j<16; j++){
  2211.         DrawPalette(j, ScreenImage, j==SelectedColor);
  2212.     }
  2213.     
  2214.     //    Make up buttons
  2215.     buttons=(GXOBLONG *)GXGetMem(21*sizeof(GXOBLONG), MEMF_ZERO|MEMF_ABORT);
  2216.     for(j=0; j<16; j++){
  2217.         ix=j%4;
  2218.         iy=j/4;
  2219.         buttons[j].X=COLOR0_X + ix*COLORSEPERATION_X;
  2220.         buttons[j].Y=COLOR0_Y + iy*COLORSEPERATION_Y;
  2221.         buttons[j].Width=COLOR_WIDTH;
  2222.         buttons[j].Height=COLOR_HEIGHT;
  2223.     }
  2224.     buttons[16]=ButtonUp;
  2225.     buttons[16].X=PALETTE_OKAY_X;
  2226.     buttons[16].Y=PALETTE_OKAY_Y;
  2227.  
  2228.     buttons[17]=ButtonUp;
  2229.     buttons[17].X=PALETTE_CANCEL_X;
  2230.     buttons[17].Y=PALETTE_CANCEL_Y;
  2231.     
  2232.     for(j=0; j<3; j++){
  2233.         buttons[j+18]=DownKnob;
  2234.         buttons[j+18].X=RGB_SLIDER_MINX;
  2235.         buttons[j+18].Y=RGB_SLIDER_Y+RGB_SLIDER_DY*j;
  2236.     }
  2237.  
  2238.     //    Print palette section names
  2239.     x=PALETTE_SECTION_X;
  2240.     y=PALETTE_SECTION_Y;
  2241.     for(j=0; j<4; j++){
  2242.         TXPrintString(    PaletteStrings[j+5], 
  2243.                         (x-TXStringWidth(PaletteStrings[j+5], BlackFont)/2),
  2244.                         (y-TXFONTHeight(BlackFont)/2),
  2245.                         ScreenImage, BlackFont);
  2246.         y+=PALETTE_SECTION_DY;
  2247.     }
  2248.     
  2249.     //    Print title
  2250.     x=TitleBox.Width/2 + TitleBox.X - TXStringWidth(TitleStrings[3], BlackFont)/2;
  2251.     y=TitleBox.Height/2 + TitleBox.Y - TXFONTHeight(BlackFont)/2;
  2252.     TXPrintString(TitleStrings[3], x, y, ScreenImage, BlackFont);
  2253.         
  2254.     //    Draw okay & cancel buttons
  2255.     DrawButton(ScreenImage, PaletteStrings[3], PALETTE_OKAY_X, PALETTE_OKAY_Y);
  2256.     DrawButton(ScreenImage, PaletteStrings[4], PALETTE_CANCEL_X, PALETTE_CANCEL_Y);
  2257.     
  2258.     //    initialize sliders
  2259.     memset(slider, 0, sizeof(slider));
  2260.  
  2261.     color=GameBoyPalette2[SelectedColor];
  2262.     x=((int)color.Red)*SLIDER_RANGE/255;
  2263.     DrawSlider(0, x, ScreenImage); 
  2264.     buttons[18].X=slider[0].X+RGB_SLIDER_MINX;
  2265.     buttons[18].Y=RGB_SLIDER_Y;
  2266.  
  2267.     x=((int)color.Green)*SLIDER_RANGE/255;
  2268.     DrawSlider(1, x, ScreenImage); 
  2269.     buttons[19].X=slider[1].X+RGB_SLIDER_MINX;
  2270.     buttons[19].Y=RGB_SLIDER_Y+RGB_SLIDER_DY;
  2271.  
  2272.     x=((int)color.Red)*SLIDER_RANGE/255;
  2273.     DrawSlider(2, x, ScreenImage); 
  2274.     buttons[20].X=slider[2].X+RGB_SLIDER_MINX;
  2275.     buttons[20].Y=RGB_SLIDER_Y+2*RGB_SLIDER_DY;
  2276.  
  2277.     GXDoBlit();
  2278.     ResetButtons();
  2279.     is=-1;
  2280.     do{
  2281.         GXSystemUpdate();
  2282.         GXReadMouse(&MouseInfo);
  2283.         JustPressed=MouseClick();
  2284.         if( (number=UpdateButtons(buttons, 21)) != -1){
  2285.             if(JustPressed){
  2286.                 if( (number>=0) &&
  2287.                     (number<16) ){
  2288.                     DrawPalette(SelectedColor, ScreenImage, 0);
  2289.                     SelectedColor=number;
  2290.                     DrawPalette(SelectedColor, ScreenImage, 1);
  2291.                     color=GameBoyPalette2[SelectedColor];
  2292.  
  2293.                     x=((long)color.Red)*SLIDER_RANGE/255;
  2294.                     MoveSlider(0, x, ScreenImage); 
  2295.                     buttons[18].X=x+RGB_SLIDER_MINX;
  2296.                     buttons[18].Y=RGB_SLIDER_Y;
  2297.  
  2298.                     x=((long)color.Green)*SLIDER_RANGE/255;
  2299.                     MoveSlider(1, x, ScreenImage); 
  2300.                     buttons[19].X=x+RGB_SLIDER_MINX;
  2301.                     buttons[19].Y=RGB_SLIDER_Y+RGB_SLIDER_DY;
  2302.  
  2303.                     x=((long)color.Blue)*SLIDER_RANGE/255;
  2304.                     MoveSlider(2, x, ScreenImage); 
  2305.                     buttons[20].X=x+RGB_SLIDER_MINX;
  2306.                     buttons[20].Y=RGB_SLIDER_Y+2*RGB_SLIDER_DY;
  2307.                 }else if(number==16){
  2308.                     //    OKAY PRESSED.
  2309.                     //    Save palette & quit
  2310.                     changed=1;
  2311.                     break;
  2312.                 }else if(number==17){
  2313.                     //    CANCEL PRESSED
  2314.                     //    Restore old palette & quit
  2315.                     break;
  2316.                 }else if( (number>17) && (number<21) ){
  2317.                     is=number-18;
  2318.                     StartMouseX=MouseInfo.X;
  2319.                     StartSliderX=slider[is].X;
  2320.                 }
  2321.             }
  2322.         }
  2323.         //    Update sliders
  2324.         if( is!=-1){
  2325.             if(!MouseInfo.LeftButton){
  2326.                 is=-1;
  2327.             }else{
  2328.                 x=MouseInfo.X-StartMouseX+StartSliderX;
  2329.                 if(x>SLIDER_RANGE)x=SLIDER_RANGE;
  2330.                 if(x<0)x=0;
  2331.                 if(x!=slider[is].X){
  2332.                     MoveSlider(is, x, ScreenImage);
  2333.                     buttons[18+is].X=RGB_SLIDER_MINX+x;
  2334.                     buttons[18+is].Y=RGB_SLIDER_Y+RGB_SLIDER_DY*is;
  2335.  
  2336.                     color.Red=slider[0].X*255/SLIDER_RANGE;
  2337.                     color.Green=slider[1].X*255/SLIDER_RANGE;
  2338.                     color.Blue=slider[2].X*255/SLIDER_RANGE;
  2339.                     GXSetPaletteRange(&color, SelectedColor+16+GAMEBOY_BASE, 1);
  2340.                     for(j=0; j<16; j++){
  2341.                         if(SourceColor(j)==SelectedColor){
  2342.                             GXSetPaletteRange(&color, j+GAMEBOY_BASE, 1);
  2343.                         }
  2344.                     }
  2345.                     GameBoyPalette2[SelectedColor]=color;
  2346.                 }
  2347.             }
  2348.         }
  2349.         GXDoBlit();
  2350.     }while(1);
  2351.  
  2352.     if(changed){
  2353.         //    Save new palette to prefs
  2354.         memcpy(GameBoyPalette, GameBoyPalette2, 16*sizeof(GXPALETTE));
  2355.         SavePrefs();
  2356.     }else{
  2357.         //    Restore old palette
  2358.         GXSetPaletteRange(OldPalette, GAMEBOY_BASE, 16);
  2359.     }
  2360.     //    Free stuff used
  2361.     KILLMEM(buttons);
  2362.     KILLMEM(OldPalette);
  2363.     KILLMEM(GameBoyPalette2);
  2364.     RestoreScreen();
  2365. }
  2366.  
  2367. void    MoveSlider(int is, int x, GXIMAGE *ToImage)
  2368. {
  2369.     GXBLITLIST    *b;
  2370.     RGBSLIDER    *s;
  2371.     
  2372.     s=&slider[is];
  2373.  
  2374.     if(x>SLIDER_RANGE)x=SLIDER_RANGE;
  2375.     if(x<0)x=0;
  2376.     if(x!=s->X){
  2377.         //    Draw over last place that slider was at
  2378.         //    Could go wrong if slider range is too big
  2379.         b=GXNextBlit();
  2380.         b->Type=BLIT_IMAGE;
  2381.         b->From.X=PaletteSlider.X + s->X + RGB_SLIDER_MINX - RGB_SLIDER_GFX_X;
  2382.         b->From.Y=PaletteSlider.Y + RGB_SLIDER_Y - RGB_SLIDER_GFX_Y;
  2383.         b->From.Width=DownKnob.Width;
  2384.         b->From.Height=DownKnob.Height;
  2385.         b->XTo=s->X+RGB_SLIDER_MINX;
  2386.         b->YTo=RGB_SLIDER_Y+is*RGB_SLIDER_DY;
  2387.         b->FromImage=GadgetsImage;
  2388.         b->ToImage=ToImage;
  2389.  
  2390.         //    Draw new slider
  2391.         b=GXNextBlit();
  2392.         b->Type=BLIT_IMAGE;
  2393.         b->From=DownKnob;
  2394.         b->XTo=x+RGB_SLIDER_MINX;
  2395.         b->YTo=RGB_SLIDER_Y+is*RGB_SLIDER_DY;
  2396.         b->FromImage=GadgetsImage;
  2397.         b->ToImage=ToImage;
  2398.         s->X=x;
  2399.     }
  2400. }
  2401.  
  2402. void    DrawSlider(int is, int x, GXIMAGE *ToImage)
  2403. {
  2404.     GXBLITLIST    *b;
  2405.     RGBSLIDER    *s;
  2406.     long        xplot,yplot;
  2407.     
  2408.     s=&slider[is];
  2409.  
  2410.     if(x>SLIDER_RANGE)x=SLIDER_RANGE;
  2411.     if(x<0)x=0;
  2412.  
  2413.     b=GXNextBlit();
  2414.     b->Type=BLIT_IMAGE;
  2415.     b->From=PaletteSlider;
  2416.     b->XTo=RGB_SLIDER_GFX_X;
  2417.     b->YTo=RGB_SLIDER_GFX_Y+RGB_SLIDER_GFX_DY*is;
  2418.     b->FromImage=GadgetsImage;
  2419.     b->ToImage=ToImage;
  2420.  
  2421.     xplot=RGB_X;
  2422.     yplot=RGB_Y+RGB_DY*is;
  2423.     TXPrintString(    PaletteStrings[is], 
  2424.                     (xplot-TXStringWidth(PaletteStrings[is], BlackFont)/2),
  2425.                     (yplot-TXFONTHeight(BlackFont)/2),
  2426.                     ToImage, BlackFont);
  2427.  
  2428.     b=GXNextBlit();
  2429.     b->Type=BLIT_IMAGE;
  2430.     b->From=DownKnob;
  2431.     b->XTo=x+RGB_SLIDER_MINX;
  2432.     b->YTo=RGB_SLIDER_Y+is*RGB_SLIDER_DY;
  2433.     b->FromImage=GadgetsImage;
  2434.     b->ToImage=ToImage;
  2435.     s->X=x;
  2436. }
  2437.  
  2438. void    DrawPalette(int    j, GXIMAGE *image, int highlight)
  2439. {
  2440.     int            ix,iy,x,y;
  2441.     GXBLITLIST    *b;
  2442.  
  2443.     ix=j%4;
  2444.     iy=j/4;
  2445.     x=COLOR0_X + ix*COLORSEPERATION_X;
  2446.     y=COLOR0_Y + iy*COLORSEPERATION_Y;
  2447.     
  2448.     b=GXNextBlit();
  2449.     b->Type=BLIT_IMAGE;
  2450.     b->XTo=x-3;
  2451.     b->YTo=y-3;
  2452.     if(highlight){
  2453.         b->From=PaletteHighlight;
  2454.     }else{
  2455.         b->From=PaletteNormal;
  2456.     }
  2457.     b->FromImage=GadgetsImage;
  2458.     b->ToImage=image;
  2459.     
  2460.     b=GXNextBlit();
  2461.     b->Type=BLIT_COLORFILL;
  2462.     b->Color=j+16+GAMEBOY_BASE;
  2463.     b->XTo=x;
  2464.     b->YTo=y;
  2465.     b->From.Width=COLOR_WIDTH;
  2466.     b->From.Height=COLOR_HEIGHT;
  2467.     b->ToImage=image;
  2468. }
  2469.  
  2470.     long        NewKeys[8];
  2471.  
  2472.  
  2473. void    KeyOptions(void)
  2474. {
  2475.     GXBLITLIST    *b;
  2476.     GXIMAGE        *ScreenImage;
  2477.     GXMOUSEINFO    MouseInfo;
  2478.     int            x,y,j,moving;
  2479.     GXOBLONG    Buttons[10];
  2480.     int            selection,editing,jj;
  2481.     long        xx,tt,delay;
  2482.     long        key,frame=0;
  2483.     int            number;
  2484.     int            JustPressed;
  2485.     GXOBLONG    area;
  2486.  
  2487.     WaitNoKeys();
  2488.     SaveScreen();
  2489.     ScreenImage=GXStartDrawing(0);
  2490.     for(j=0; j<8; j++)
  2491.         NewKeys[j]=KeyPrefs[j];
  2492.  
  2493.     //    Draw backdrop
  2494.     DrawBackground(ScreenImage, 0);
  2495.     b=GXNextBlit();
  2496.     b->Type=BLIT_IMAGE;
  2497.     b->From=TitleBox;
  2498.     b->XTo=b->YTo=0;
  2499.     b->FromImage=GadgetsImage;
  2500.     b->ToImage=ScreenImage;
  2501.     
  2502.     //    Print title
  2503.     x=TitleBox.Width/2 + TitleBox.X - TXStringWidth(KeyStrings[8], BlackFont)/2;
  2504.     y=TitleBox.Height/2 + TitleBox.Y - TXFONTHeight(BlackFont)/2;
  2505.     TXPrintString(KeyStrings[8], x, y, ScreenImage, BlackFont);
  2506.  
  2507.     //    Set up okay & cancel buttons
  2508.     Buttons[8]=Buttons[9]=ButtonUp;
  2509.     Buttons[8].X=(ScreenWidth-ButtonUp.Width*2)/4;
  2510.     Buttons[9].X=ScreenWidth-Buttons[8].X-ButtonUp.Width;
  2511.     Buttons[8].Y=Buttons[9].Y=ScreenHeight-20;
  2512.     DrawButton(ScreenImage, "Okay", Buttons[8].X, ScreenHeight-20);
  2513.     DrawButton(ScreenImage, "Cancel", Buttons[9].X, ScreenHeight-20);
  2514.  
  2515.     for(j=0; j<NKeyPrefs; j++){
  2516.         y=KEYOPTIONS_Y+KEYOPTIONS_DY*j;    
  2517.         TXPrintString(KeyStrings[j], 
  2518.             (ScreenWidth/2)-TXStringWidth(KeyStrings[j], BlackFont)-10,
  2519.             y, ScreenImage, BlackFont);
  2520.         if(j){
  2521.             TXPrintString(KeyName(NewKeys[j]), ScreenWidth/2+10, y, ScreenImage, BlackFont);
  2522.         }else{
  2523.             TXPrintString(KeyName(NewKeys[j]), ScreenWidth/2+10, y, ScreenImage, RedFont);
  2524.         }
  2525.         Buttons[j].X=10;
  2526.         Buttons[j].Width=ScreenWidth-20;
  2527.         Buttons[j].Y=y;
  2528.         Buttons[j].Height=TXFONTHeight(BlackFont);
  2529.     }    
  2530.  
  2531.     selection=0;
  2532.     editing=0;
  2533.     delay=GXTicksPerSecond()/60;
  2534.     if(!delay)delay=1;
  2535.     do{
  2536.         xx=GXTimer();
  2537.         do{
  2538.             tt=GXTimer()-xx;
  2539.             if(tt<0)break;
  2540.         }while(tt< delay );
  2541.         frame++;
  2542.  
  2543.         GXSystemUpdate();
  2544.         GXReadMouse(&MouseInfo);
  2545.         GXDoBlit();
  2546.         JustPressed=MouseClick();
  2547.         key=GXNextKey();
  2548.         while(GXNextKey())
  2549.             ;
  2550.         if( (number=UpdateButtons(Buttons, 10)) != -1 ){
  2551.             if(JustPressed){
  2552.                 if(number==8){
  2553.                     for(j=0; j<8; j++)
  2554.                         KeyPrefs[j]=NewKeys[j];
  2555.                     SavePrefs();
  2556.                     break;
  2557.                 }else if(number==9){
  2558.                     break;
  2559.                 }else{
  2560.                     ChangeKeySelection(selection, number, ScreenImage);
  2561.                     selection=number;
  2562.                     editing=0;
  2563.                 }
  2564.             }
  2565.         }
  2566.         if(!editing){
  2567.             if( GXKeyDown(KeyPrefs[3]) ){
  2568.                 if( (!moving) || (frame==20) ){
  2569.                     moving=1;
  2570.                     jj=(selection+1)&0x07;
  2571.                     ChangeKeySelection(selection, jj, ScreenImage);
  2572.                     selection=jj;
  2573.                     frame=0;
  2574.                 }
  2575.             }else if( GXKeyDown(KeyPrefs[2]) ){
  2576.                 if( (!moving) || (frame==20) ){
  2577.                     moving=1;
  2578.                     jj=(selection-1)&0x07;
  2579.                     ChangeKeySelection(selection, jj, ScreenImage);
  2580.                     selection=jj;
  2581.                     frame=0;
  2582.                 }
  2583.             }else{
  2584.                 moving=0;
  2585.             }
  2586.         }else{
  2587.             y=KEYOPTIONS_Y+KEYOPTIONS_DY*selection;    
  2588.             xx=GXTimer();
  2589.             xx=xx%GXTicksPerSecond();
  2590.             if( xx < (GXTicksPerSecond()/2) ){
  2591.                 TXPrintString(KeyName(NewKeys[selection]), 
  2592.                     ScreenWidth/2+10, y, ScreenImage, RedFont);
  2593.             }else{
  2594.                 area.X=ScreenWidth/2+10;
  2595.                 area.Y=y;
  2596.                 area.Width=TXStringWidth(KeyName(NewKeys[selection]), RedFont);
  2597.                 area.Height=TXFONTHeight(RedFont);
  2598.                 DrawBackground(ScreenImage, &area);
  2599.             }
  2600.         }
  2601.         if( editing && key && (key!=-1) ){
  2602.             area.X=ScreenWidth/2+10;
  2603.             area.Y=y;
  2604.             area.Width=TXStringWidth(KeyName(NewKeys[selection]), RedFont);
  2605.             area.Height=TXFONTHeight(RedFont);
  2606.             DrawBackground(ScreenImage, &area);
  2607.  
  2608.             NewKeys[selection]=key;
  2609.             editing=0;
  2610.  
  2611.             TXPrintString(KeyName(NewKeys[selection]), 
  2612.                 ScreenWidth/2+10, y, ScreenImage, RedFont);
  2613.         }else if( (key==KEY_RETURN) && (selection!=-1) ){
  2614.             editing=1;
  2615.         }
  2616.     }while(1);
  2617.  
  2618.     RestoreScreen();
  2619. }
  2620.  
  2621. void    DrawButton(GXIMAGE *dest, char *text, long x, long y)
  2622. {
  2623.     GXBLITLIST        *b;
  2624.  
  2625.     b=GXNextBlit();
  2626.     b->Type=BLIT_IMAGE;
  2627.     b->From=ButtonUp;
  2628.     b->XTo=x;
  2629.     b->YTo=y;
  2630.     b->FromImage=GadgetsImage;
  2631.     b->ToImage=dest;
  2632.     TXPrintString(text, 
  2633.         b->XTo+(b->From.Width-TXStringWidth(text,BlackFont))/2,
  2634.         b->YTo+(b->From.Height-TXFONTHeight(BlackFont))/2,
  2635.         dest,
  2636.         BlackFont);
  2637.     
  2638. }
  2639.  
  2640. char    *KeyName(long RawCode)
  2641. {
  2642.     KEYNAMES    *names;
  2643.     int            j;
  2644.  
  2645.  
  2646.     names=KeyNames;
  2647.     for(j=0; j<NKeyNames; j++){
  2648.         if(names->RawCode==RawCode){
  2649.             return names->Name;
  2650.         }
  2651.         names++;
  2652.     }
  2653.     return KeyStrings[9];    //string for unknown key
  2654. }
  2655.  
  2656. void    ChangeKeySelection(int selection, int NewSelection, GXIMAGE *ScreenImage)
  2657. {
  2658.     int    y;
  2659.  
  2660.     if(selection!=-1){
  2661.         y=KEYOPTIONS_Y+KEYOPTIONS_DY*selection;    
  2662.         TXPrintString(KeyName(NewKeys[selection]), 
  2663.             ScreenWidth/2+10, y, ScreenImage, BlackFont);
  2664.     }
  2665.     y=KEYOPTIONS_Y+KEYOPTIONS_DY*NewSelection;    
  2666.     TXPrintString(KeyName(NewKeys[NewSelection]), 
  2667.         ScreenWidth/2+10, y, ScreenImage, RedFont);
  2668.  
  2669. }
  2670.  
  2671. void    KillStringGadget(STRINGGADGET *sg)
  2672. {
  2673.     if(sg){
  2674.         if(sg->String)GXFreeMem(sg->String);
  2675.         GXFreeMem(sg);
  2676.     }
  2677. }
  2678.  
  2679.     int    CursorIsOn=0;
  2680.  
  2681. STRINGGADGET    *MakeStringGadget(char *StartString, GXOBLONG *Area, GXIMAGE *ToImage)
  2682. {
  2683.     STRINGGADGET    *sg;
  2684.  
  2685.     CursorIsOn=0;    
  2686.     sg=(STRINGGADGET *)GXGetMem(sizeof(STRINGGADGET), MEMF_ZERO|MEMF_ABORT);
  2687.     sg->String=(char *)GXGetMem(256*sizeof(char), MEMF_ZERO|MEMF_ABORT);    
  2688.     sg->Area=*Area;
  2689.     ChangeStringGadget(StartString, sg, ToImage);
  2690.     return sg;
  2691. }
  2692.  
  2693. void    ChangeStringGadget(char *str, STRINGGADGET *sg, GXIMAGE *ToImage)
  2694. {
  2695.     sg->CursorPosition=strlen(str);
  2696.     strcpy(sg->String, str);
  2697.     PrintStringGadget(sg, ToImage, 0);
  2698. }
  2699.  
  2700. char    *GetStringGadget(STRINGGADGET *sg)
  2701. {
  2702.     return sg->String;
  2703. }
  2704.  
  2705. void    PrintStringGadget(STRINGGADGET *sg, GXIMAGE *ToImage, int cursoron)
  2706. {
  2707.     char        *from,*to;
  2708.     int            j,x,y,width,width1,width2;
  2709.     GXBLITLIST    *b;
  2710.     static    char    string1[64],string2[64];
  2711.  
  2712.     CursorIsOn=cursoron;
  2713.     from=sg->String;
  2714.     to=string1;
  2715.     for(j=sg->CursorPosition; j; j--){
  2716.         *to++=*from++;
  2717.     }
  2718.     *to++=0;
  2719.     strcpy(string2, from);
  2720.  
  2721.     b=GXNextBlit();
  2722.     b->Type=BLIT_COLORFILL;
  2723.     b->Color=WhiteIndex;
  2724.     b->From=sg->Area;
  2725.     b->XTo=sg->Area.X;
  2726.     b->YTo=sg->Area.Y;
  2727.     b->ToImage=ToImage;
  2728.     width1=TXStringWidth(string1, BlackFont);
  2729.     width2=TXStringWidth(string2, BlackFont);
  2730.     width=width1+width2+BlackFont->Width;
  2731.     
  2732.     x=(sg->Area.Width/2) - (width/2) + sg->Area.X;
  2733.     y=(sg->Area.Height/2) - TXFONTHeight(BlackFont)/2 + sg->Area.Y;
  2734.     TXPrintString(string1, x, y, ToImage, BlackFont);
  2735.     x+=width1;
  2736.     if(cursoron){
  2737.         b=GXNextBlit();
  2738.         b->Type=BLIT_COLORFILL;
  2739.         b->Color=OrangeIndex;
  2740.         b->From.Width=BlackFont->Width;
  2741.         b->From.Height=BlackFont->Height;
  2742.         b->XTo=x;
  2743.         b->YTo=y;
  2744.         b->ToImage=ToImage;
  2745.     }
  2746.     x+=BlackFont->Width;
  2747.     TXPrintString(string2, x, y, ToImage, BlackFont);
  2748. }
  2749.  
  2750. void    UpdateStringGadget(STRINGGADGET *sg, int AsciiKey, GXIMAGE *ToImage, 
  2751.                             int active)
  2752. {
  2753.     int        StringLength,nloop;
  2754.     char    *from,*to;
  2755.     int        DrawCursor;
  2756.     
  2757.     
  2758.     DrawCursor=(GXTimer()%GXTicksPerSecond());
  2759.     DrawCursor=DrawCursor<(GXTicksPerSecond()/2);    
  2760.     if(!active){
  2761.         if(!CursorIsOn){
  2762.             PrintStringGadget(sg, ToImage, 1);    
  2763.         }
  2764.         return;
  2765.     }
  2766.     StringLength=strlen(sg->String);
  2767.     if(AsciiKey==0x1c){
  2768.         //cursor right
  2769.         sg->CursorPosition++;
  2770.         if( sg->CursorPosition > StringLength ){
  2771.             sg->CursorPosition=StringLength;
  2772.         }
  2773.     }else if(AsciiKey==0x1d){
  2774.         //cursor left
  2775.         if(sg->CursorPosition){
  2776.             sg->CursorPosition--;
  2777.         }
  2778.     }else if(AsciiKey==0x7f){
  2779.         //delete
  2780.         if(sg->CursorPosition<StringLength){
  2781.             to=sg->String + sg->CursorPosition;
  2782.             from=to+1;
  2783.             while(*from){
  2784.                 *to++=*from++;
  2785.             }
  2786.             *to=0;
  2787.         }
  2788.     }else if(AsciiKey==0x01){
  2789.         //BackSpace
  2790.         if(sg->CursorPosition){
  2791.             from=sg->String + sg->CursorPosition;
  2792.             to=from-1;
  2793.             while(*from){
  2794.                 *to++=*from++;
  2795.             }
  2796.             *to=0;
  2797.             sg->CursorPosition--;
  2798.         }
  2799.     }else if(     ((AsciiKey>='a')&&(AsciiKey<='z'))||
  2800.                  ((AsciiKey>='0')&&(AsciiKey<='9'))||
  2801.                 (AsciiKey=='.')||
  2802.                 (AsciiKey==' ')     ){
  2803.         if(StringLength>=16){
  2804.             return;
  2805.         }
  2806.         from=sg->String+StringLength;
  2807.         to=from+1;
  2808.         nloop=StringLength-sg->CursorPosition+1;
  2809.         while(nloop){
  2810.             *to--=*from--;
  2811.             nloop--;
  2812.         }
  2813.         *to=AsciiKey;
  2814.         sg->CursorPosition++;
  2815.     }else{
  2816.         if(DrawCursor!=CursorIsOn){
  2817.             PrintStringGadget(sg, ToImage, DrawCursor);
  2818.             return;        
  2819.         }    
  2820.     }
  2821.     PrintStringGadget(sg, ToImage, DrawCursor);    
  2822. }
  2823.  
  2824. int    RawToAscii(int RawKey)
  2825. {
  2826.     struct{
  2827.         UBYTE    AsciiKey;
  2828.         UBYTE    RawKey;
  2829.     }KeyInfo[]={
  2830.                     {'a',KEY_A},
  2831.                     {'b',KEY_B},
  2832.                     {'c',KEY_C},
  2833.                     {'d',KEY_D},
  2834.                     {'e',KEY_E},
  2835.                     {'f',KEY_F},
  2836.                     {'g',KEY_G},
  2837.                     {'h',KEY_H},
  2838.                     {'i',KEY_I},
  2839.                     {'j',KEY_J},
  2840.                     {'k',KEY_K},
  2841.                     {'l',KEY_L},
  2842.                     {'m',KEY_M},
  2843.                     {'n',KEY_N},
  2844.                     {'o',KEY_O},
  2845.                     {'p',KEY_P},
  2846.                     {'q',KEY_Q},
  2847.                     {'r',KEY_R},
  2848.                     {'s',KEY_S},
  2849.                     {'t',KEY_T},
  2850.                     {'u',KEY_U},
  2851.                     {'v',KEY_V},
  2852.                     {'w',KEY_W},
  2853.                     {'x',KEY_X},
  2854.                     {'y',KEY_Y},
  2855.                     {'z',KEY_Z},
  2856.                     {'0',KEY_0},
  2857.                     {'1',KEY_1},
  2858.                     {'2',KEY_2},
  2859.                     {'3',KEY_3},
  2860.                     {'4',KEY_4},
  2861.                     {'5',KEY_5},
  2862.                     {'6',KEY_6},
  2863.                     {'7',KEY_7},
  2864.                     {'8',KEY_8},
  2865.                     {'9',KEY_9},
  2866.                     {'0',KEY_NUMPAD0},
  2867.                     {'1',KEY_NUMPAD1},
  2868.                     {'2',KEY_NUMPAD2},
  2869.                     {'3',KEY_NUMPAD3},
  2870.                     {'4',KEY_NUMPAD4},
  2871.                     {'5',KEY_NUMPAD5},
  2872.                     {'6',KEY_NUMPAD6},
  2873.                     {'7',KEY_NUMPAD7},
  2874.                     {'8',KEY_NUMPAD8},
  2875.                     {'9',KEY_NUMPAD9},
  2876.  
  2877.                     {'.',KEY_FULLSTOP},
  2878.                     {' ',KEY_SPACE},
  2879.                     {'    ',KEY_TAB},
  2880.                     {',',KEY_COMMA},
  2881.                     {0x1c,KEY_CURSORRIGHT},
  2882.                     {0x1d,KEY_CURSORLEFT},
  2883.                     {0x1e,KEY_CURSORUP},
  2884.                     {0x1f,KEY_CURSORDOWN},
  2885.                     {0x7f,KEY_DELETE},
  2886.                     {0x01,KEY_BACKSPACE},
  2887.                     };
  2888.     static UBYTE    *ConversionTable=0;
  2889.     int                j;
  2890.  
  2891.     if(!ConversionTable){
  2892.         ConversionTable=(UBYTE *)GXGetMem(256*sizeof(UBYTE), MEMF_ZERO|MEMF_ABORT);
  2893.         for(j=0; j<ELEMENTS(KeyInfo); j++){
  2894.             ConversionTable[ KeyInfo[j].RawKey]=KeyInfo[j].AsciiKey;
  2895.         }
  2896.     }
  2897.     return ConversionTable[RawKey];
  2898. }
  2899.