]> 4ch.mooo.com Git - 16.git/blobdiff - 16/keen456/KEEN4-6/ID_US_2.C
extrcted keen code remake
[16.git] / 16 / keen456 / KEEN4-6 / ID_US_2.C
diff --git a/16/keen456/KEEN4-6/ID_US_2.C b/16/keen456/KEEN4-6/ID_US_2.C
new file mode 100755 (executable)
index 0000000..e194861
--- /dev/null
@@ -0,0 +1,2260 @@
+/* Reconstructed Commander Keen 4-6 Source Code\r
+ * Copyright (C) 2021 K1n9_Duk3\r
+ *\r
+ * This file is primarily based on:\r
+ * Catacomb 3-D Source Code\r
+ * Copyright (C) 1993-2014 Flat Rock Software\r
+ *\r
+ * This program is free software; you can redistribute it and/or modify\r
+ * it under the terms of the GNU General Public License as published by\r
+ * the Free Software Foundation; either version 2 of the License, or\r
+ * (at your option) any later version.\r
+ *\r
+ * This program is distributed in the hope that it will be useful,\r
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+ * GNU General Public License for more details.\r
+ *\r
+ * You should have received a copy of the GNU General Public License along\r
+ * with this program; if not, write to the Free Software Foundation, Inc.,\r
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\r
+ */\r
+\r
+//\r
+//      ID Engine\r
+//      ID_US.c - User Manager - User interface\r
+//      v1.1d1\r
+//      By Jason Blochowiak\r
+//      Hacked up for Catacomb 3D\r
+//\r
+\r
+#include "ID_HEADS.H"\r
+#pragma hdrstop\r
+\r
+#pragma warn    -pia\r
+\r
+//      Special imports\r
+extern  boolean         showscorebox;\r
+#ifdef  KEEN\r
+extern boolean         jerk;\r
+extern  boolean         oldshooting;\r
+extern  ScanCode        firescan;\r
+void   USL_CheckSavedGames(void);\r
+#else\r
+               ScanCode        firescan;\r
+#endif\r
+\r
+//      Global variables\r
+               boolean         ingame,abortgame,loadedgame;\r
+               GameDiff        restartgame = gd_Continue;\r
+\r
+//      Internal variables\r
+static  boolean         GameIsDirty,\r
+                                       QuitToDos,\r
+                                       CtlPanelDone;\r
+\r
+#ifdef KEEN6\r
+       int             listindex = -1;\r
+       boolean         checkpassed;\r
+#endif\r
+\r
+//      Forward reference prototypes\r
+static void     USL_SetupCard(void);\r
+\r
+//      Control panel data\r
+\r
+#define CtlPanelSX      74\r
+#define CtlPanelSY      48\r
+#define CtlPanelEX      234\r
+#define CtlPanelEY      150\r
+#define CtlPanelW       (CtlPanelEX - CtlPanelSX)\r
+#define CtlPanelH       (CtlPanelEY - CtlPanelSY)\r
+\r
+#ifdef KEEN\r
+\r
+#define TileBase        92\r
+\r
+#if GRMODE == CGAGR\r
+\r
+#define BackColor               0\r
+#define HiliteColor             (BackColor ^ 3)\r
+#define NohiliteColor   (BackColor ^ 2)\r
+\r
+#else\r
+\r
+#define BackColor               8\r
+#define HiliteColor             (BackColor ^ 10)\r
+#define NohiliteColor   (BackColor ^ 2)\r
+\r
+#endif // if GRMODE == CGAGR ... else ...\r
+\r
+#else  // ifdef KEEN\r
+\r
+#define TileBase        92\r
+\r
+// DEBUG - CGA\r
+#define BackColor               0\r
+#define HiliteColor             (BackColor ^ 12)\r
+#define NohiliteColor   (BackColor ^ 4)\r
+\r
+#endif\r
+\r
+typedef enum\r
+               {\r
+                       uc_None,\r
+                       uc_Return,\r
+                       uc_Abort,\r
+                       uc_Quit,\r
+                       uc_Loaded,\r
+                       uc_SEasy,\r
+                       uc_SNormal,\r
+                       uc_SHard,\r
+               } UComm;\r
+typedef enum\r
+               {\r
+                       uii_Bad,\r
+                       uii_Button,uii_RadioButton,uii_Folder\r
+               } UIType;\r
+typedef enum\r
+               {\r
+                       ui_Normal = 0,\r
+                       ui_Pushed = 1,\r
+                       ui_Selected = 2,\r
+                       ui_Disabled = 4,\r
+                       ui_Separated = 8\r
+               } UIFlags;\r
+#define UISelectFlags (ui_Pushed | ui_Selected | ui_Disabled)\r
+\r
+typedef enum\r
+               {\r
+                       uic_SetupCard,uic_DrawCard,uic_TouchupCard,\r
+                       uic_DrawIcon,uic_Draw,uic_Hit\r
+               } UserCall;\r
+\r
+typedef struct  UserItem\r
+               {\r
+                               UIType                  type;\r
+                               UIFlags                 flags;\r
+                               ScanCode                hotkey;\r
+                               char                    *text;\r
+                               UComm                   comm;\r
+                               void                    far *child;     // Should be (UserItemGroup *)\r
+\r
+                               word                    x,y;\r
+               } UserItem;\r
+typedef struct  UserItemGroup\r
+               {\r
+                               word                    x,y;\r
+                               graphicnums             title;\r
+                               ScanCode                hotkey;\r
+                               UserItem                far *items;\r
+                               boolean                 (*custom)(UserCall,struct UserItem far *);      // Custom routine\r
+\r
+                               word                    cursor;\r
+               struct  UserItemGroup   far *parent;\r
+               } UserItemGroup;\r
+\r
+static  char            *BottomS1,*BottomS2,*BottomS3;\r
+static  UComm           Communication;\r
+static  ScanCode        *KeyMaps[] =\r
+                                       {\r
+                                               &KbdDefs[0].button0,\r
+                                               &KbdDefs[0].button1,\r
+                                               &firescan,\r
+                                               &KbdDefs[0].upleft,\r
+                                               &KbdDefs[0].up,\r
+                                               &KbdDefs[0].upright,\r
+                                               &KbdDefs[0].right,\r
+                                               &KbdDefs[0].downright,\r
+                                               &KbdDefs[0].down,\r
+                                               &KbdDefs[0].downleft,\r
+                                               &KbdDefs[0].left\r
+                                       };\r
+\r
+// Custom routine prototypes\r
+static  boolean USL_ConfigCustom(UserCall call,struct UserItem far *item),\r
+                               USL_KeyCustom(UserCall call,struct UserItem far *item),\r
+                               USL_KeySCustom(UserCall call,struct UserItem far *item),\r
+                               USL_Joy1Custom(UserCall call,struct UserItem far *item),\r
+                               USL_Joy2Custom(UserCall call,struct UserItem far *item),\r
+                               USL_JoyGCustom(UserCall call,struct UserItem far *item),\r
+                               USL_LoadCustom(UserCall call,struct UserItem far *item),\r
+                               USL_SaveCustom(UserCall call,struct UserItem far *item),\r
+                               USL_ScoreCustom(UserCall call,struct UserItem far *item),\r
+                               USL_CompCustom(UserCall call,struct UserItem far *item),\r
+                               USL_SmoothCustom(UserCall call,struct UserItem far *item),\r
+#ifdef KEEN\r
+                               USL_TwoCustom(UserCall call,struct UserItem far *item),\r
+#endif\r
+                               USL_PongCustom(UserCall call,struct UserItem far *item);\r
+\r
+#define DefButton(key,text)                             uii_Button,ui_Normal,key,text\r
+#define DefRButton(key,text)                    uii_RadioButton,ui_Normal,key,text\r
+#define DefFolder(key,text,child)               uii_Folder,ui_Normal,key,text,uc_None,child\r
+#define CustomGroup(title,key,custom)   0,0,title,key,0,custom\r
+       UserItem far holder[] =\r
+       {\r
+               {DefButton(sc_None,"DEBUG")},\r
+               {uii_Bad}\r
+       };\r
+       UserItemGroup   far holdergroup = {0,0,CP_MAINMENUPIC,sc_None,holder};\r
+\r
+       // Sound menu\r
+       UserItem far soundi[] =\r
+       {\r
+               {DefRButton(sc_N,"NO SOUND EFFECTS")},\r
+               {DefRButton(sc_P,"PC SPEAKER")},\r
+               {DefRButton(sc_A,"ADLIB/SOUNDBLASTER")},\r
+               {DefRButton(sc_Q,"QUIET ADLIB/SOUNDBLASTER")},\r
+               {uii_Bad}\r
+       };\r
+       UserItemGroup   far soundgroup = {8,0,CP_SOUNDMENUPIC,sc_None,soundi};\r
+\r
+       // Music menu\r
+       UserItem far musici[] =\r
+       {\r
+               {DefRButton(sc_N,"NO MUSIC")},\r
+               {DefRButton(sc_A,"ADLIB/SOUNDBLASTER")},\r
+               {uii_Bad}\r
+       };\r
+       UserItemGroup   far musicgroup = {8,0,CP_MUSICMENUPIC,sc_None,musici};\r
+\r
+       // New game menu\r
+       UserItem far newgamei[] =\r
+       {\r
+               {DefButton(sc_E,"BEGIN EASY GAME"),uc_SEasy},\r
+               {DefButton(sc_N,"BEGIN NORMAL GAME"),uc_SNormal},\r
+               {DefButton(sc_H,"BEGIN HARD GAME"),uc_SHard},\r
+               {uii_Bad}\r
+       };\r
+       UserItemGroup   far newgamegroup = {8,0,CP_NEWGAMEMENUPIC,sc_None,newgamei,0,1};\r
+\r
+       // Load/Save game menu\r
+       UserItem far loadsavegamei[] =\r
+       {\r
+#ifdef CAT3D\r
+               {uii_Button,ui_Normal,sc_None},\r
+               {uii_Button,ui_Normal,sc_None},\r
+               {uii_Button,ui_Normal,sc_None},\r
+               {uii_Button,ui_Normal,sc_None},\r
+               {uii_Button,ui_Normal,sc_None},\r
+               {uii_Button,ui_Normal,sc_None},\r
+#else\r
+               {uii_Button,ui_Normal,sc_1},\r
+               {uii_Button,ui_Normal,sc_2},\r
+               {uii_Button,ui_Normal,sc_3},\r
+               {uii_Button,ui_Normal,sc_4},\r
+               {uii_Button,ui_Normal,sc_5},\r
+               {uii_Button,ui_Normal,sc_6},\r
+#endif\r
+               {uii_Bad}\r
+       };\r
+       UserItemGroup   far loadgamegroup = {4,3,CP_LOADMENUPIC,sc_None,loadsavegamei,USL_LoadCustom};\r
+       UserItemGroup   far savegamegroup = {4,3,CP_SAVEMENUPIC,sc_None,loadsavegamei,USL_SaveCustom};\r
+\r
+       // Options menu\r
+       UserItemGroup   far scoregroup = {0,0,0,sc_None,0,USL_ScoreCustom};\r
+#ifdef KEEN\r
+       UserItemGroup   far twogroup = {0,0,0,sc_None,0,USL_TwoCustom};\r
+#endif\r
+#if GRMODE != CGAGR\r
+       UserItemGroup   far smoothgroup = {0,0,0,sc_None,0,USL_SmoothCustom};\r
+       UserItemGroup   far compgroup = {0,0,0,sc_None,0,USL_CompCustom};\r
+#endif\r
+\r
+       UserItem far optionsi[] =\r
+       {\r
+               {DefFolder(sc_S,"",&scoregroup)},\r
+#ifdef KEEN\r
+               {DefFolder(sc_T,"",&twogroup)},\r
+#endif\r
+#if GRMODE != CGAGR\r
+               {DefFolder(sc_M,"",&smoothgroup)},\r
+               {DefFolder(sc_C,"",&compgroup)},\r
+#endif\r
+               {uii_Bad}\r
+       };\r
+       UserItemGroup   far optionsgroup = {8,0,CP_OPTIONSMENUPIC,sc_None,optionsi};\r
+\r
+       // Keyboard menu\r
+       UserItem far keyi[] =\r
+       {\r
+               {DefButton(sc_None,"UP & LEFT")},\r
+               {DefButton(sc_None,"UP")},\r
+               {DefButton(sc_None,"UP & RIGHT")},\r
+               {DefButton(sc_None,"RIGHT")},\r
+               {DefButton(sc_None,"DOWN & RIGHT")},\r
+               {DefButton(sc_None,"DOWN")},\r
+               {DefButton(sc_None,"DOWN & LEFT")},\r
+               {DefButton(sc_None,"LEFT")},\r
+               {uii_Bad}\r
+       };\r
+       UserItemGroup   far keygroup = {0,0,CP_KEYMOVEMENTPIC,sc_None,keyi,USL_KeyCustom};\r
+       UserItem far keybi[] =\r
+       {\r
+#ifdef  KEEN\r
+               {DefButton(sc_J,"JUMP")},\r
+               {DefButton(sc_P,"POGO")},\r
+               {DefButton(sc_F,"FIRE")},\r
+#endif\r
+#ifdef  CAT3D\r
+               {DefButton(sc_J,"FIRE")},\r
+               {DefButton(sc_P,"STRAFE")},\r
+#endif\r
+#ifdef  CPD\r
+               {DefButton(sc_J,"SHOOT")},\r
+               {DefButton(sc_P,"BOMB")},\r
+#endif\r
+               {uii_Bad}\r
+       };\r
+       UserItemGroup   far keybgroup = {0,0,CP_KEYBUTTONPIC,sc_None,keybi,USL_KeyCustom};\r
+       UserItem far keysi[] =\r
+       {\r
+               {DefFolder(sc_M,"MOVEMENT",&keygroup)},\r
+               {DefFolder(sc_B,"BUTTONS",&keybgroup)},\r
+               {uii_Bad}\r
+       };\r
+       UserItemGroup   far keysgroup = {8,0,CP_KEYBOARDMENUPIC,sc_None,keysi,USL_KeySCustom};\r
+\r
+       // Joystick #1 & #2\r
+       UserItemGroup   far joy1group = {CustomGroup(CP_JOYSTICKMENUPIC,sc_None,USL_Joy1Custom)};\r
+       UserItemGroup   far joy2group = {CustomGroup(CP_JOYSTICKMENUPIC,sc_None,USL_Joy2Custom)};\r
+       UserItemGroup   far gravisgroup = {CustomGroup(CP_JOYSTICKMENUPIC,sc_None,USL_JoyGCustom)};\r
+\r
+       // Config menu\r
+       UserItem far configi[] =\r
+       {\r
+               {DefFolder(sc_S,"SOUND",&soundgroup)},\r
+               {DefFolder(sc_M,"MUSIC",&musicgroup)},\r
+#ifndef CAT3D\r
+               {DefFolder(sc_O,"OPTIONS",&optionsgroup)},\r
+#endif\r
+               {uii_Folder,ui_Separated,sc_K,"USE KEYBOARD",uc_None,&keysgroup},\r
+               {DefFolder(sc_1,"USE JOYSTICK #1",&joy1group)},\r
+               {DefFolder(sc_2,"USE JOYSTICK #2",&joy2group)},\r
+               {DefFolder(sc_G,"",&gravisgroup)},\r
+               {uii_Bad}\r
+       };\r
+#ifdef CAT3D\r
+       UserItemGroup   far configgroup = {8,0,CP_CONFIGMENUPIC,sc_None,configi,USL_ConfigCustom};\r
+#else\r
+       UserItemGroup   far configgroup = {0,0,CP_CONFIGMENUPIC,sc_None,configi,USL_ConfigCustom};\r
+#endif\r
+\r
+       // Main menu\r
+       UserItemGroup   far ponggroup = {0,0,0,sc_None,0,USL_PongCustom};\r
+       UserItem far rooti[] =\r
+       {\r
+               {DefFolder(sc_N,"NEW GAME",&newgamegroup)},\r
+               {DefFolder(sc_L,"LOAD GAME",&loadgamegroup)},\r
+               {DefFolder(sc_S,"SAVE GAME",&savegamegroup)},\r
+               {DefFolder(sc_C,"CONFIGURE",&configgroup)},\r
+               {DefButton(sc_R,nil),uc_Return},        // Return to Game/Demo\r
+               {DefButton(sc_E,"END GAME"),uc_Abort},\r
+#ifdef KEEN\r
+               {DefFolder(sc_P,"PADDLE WAR",&ponggroup)},\r
+#elif defined CAT3D\r
+               {DefFolder(sc_B,"SKULL 'N' BONES",&ponggroup)},\r
+#endif\r
+               {DefButton(sc_Q,"QUIT"),uc_Quit},\r
+               {uii_Bad}\r
+       };\r
+       UserItemGroup   far rootgroup = {32,4,CP_MAINMENUPIC,sc_None,rooti};\r
+#undef  DefButton\r
+#undef  DefFolder\r
+\r
+#define MaxCards        7\r
+       word                    cstackptr;\r
+       UserItemGroup   far *cardstack[MaxCards],\r
+                                       far *topcard;\r
+\r
+//      Card stack code\r
+static void\r
+USL_SetupStack(void)\r
+{\r
+       cstackptr = 0;\r
+       cardstack[0] = topcard = &rootgroup;\r
+}\r
+\r
+static void\r
+USL_PopCard(void)\r
+{\r
+       if (!cstackptr)\r
+               return;\r
+\r
+       topcard = cardstack[--cstackptr];\r
+}\r
+\r
+static void\r
+USL_PushCard(UserItemGroup far *card)\r
+{\r
+       if (cstackptr == MaxCards - 1)\r
+               return;\r
+\r
+       topcard = cardstack[++cstackptr] = card;\r
+}\r
+\r
+static void\r
+USL_DrawItemIcon(UserItem far *item)\r
+{\r
+       word    flags,tile;\r
+\r
+       if (topcard->custom && topcard->custom(uic_DrawIcon,item))\r
+               return;\r
+\r
+       flags = item->flags;\r
+       if (flags & ui_Disabled)\r
+               tile = TileBase + ((flags & ui_Selected)? 5 : 4);\r
+       else if ((item->type == uii_RadioButton) && (!(flags & ui_Pushed)))\r
+               tile = TileBase + ((flags & ui_Selected)? 3 : 2);\r
+       else\r
+               tile = TileBase + ((flags & ui_Selected)? 1 : 0);\r
+       VWB_DrawTile8(item->x,item->y,tile);\r
+}\r
+\r
+static void\r
+USL_DrawItem(UserItem far *item)\r
+{\r
+       if (topcard->custom && topcard->custom(uic_Draw,item))\r
+               return;\r
+\r
+       VWB_Bar(CtlPanelSX + 1,item->y,\r
+                       CtlPanelEX - CtlPanelSX - 1,8,BackColor);       // Clear out background\r
+       USL_DrawItemIcon(item);\r
+       if ((item->flags & ui_Selected) && !(item->flags & ui_Disabled))\r
+               fontcolor = HiliteColor;\r
+       else\r
+               fontcolor = NohiliteColor;\r
+       px = item->x + 8;\r
+       py = item->y + 1;\r
+       USL_DrawString(item->text);\r
+       fontcolor = F_BLACK;\r
+}\r
+\r
+#ifdef KEEN\r
+#if GRMODE == CGAGR\r
+#define MyLine(y)       VWB_Hlin(CtlPanelSX + 3,CtlPanelEX - 3,y,3);\r
+#else\r
+#define MyLine(y)       VWB_Hlin(CtlPanelSX + 3,CtlPanelEX - 3,y,10);\r
+#endif\r
+#else\r
+#define MyLine(y)       VWB_Hlin(CtlPanelSX + 3,CtlPanelEX - 3,y,12);\r
+#endif\r
+\r
+static void\r
+USL_DrawBottom(void)\r
+{\r
+       word    w,h;\r
+\r
+       fontcolor = NohiliteColor;\r
+\r
+       px = CtlPanelSX + 4;\r
+       py = CtlPanelEY - 15;\r
+       USL_DrawString(BottomS1);\r
+\r
+       USL_MeasureString(BottomS2,&w,&h);\r
+       px = CtlPanelEX - 4 - w;\r
+       USL_DrawString(BottomS2);\r
+\r
+       USL_MeasureString(BottomS3,&w,&h);\r
+       px = CtlPanelSX + ((CtlPanelEX - CtlPanelSX - w) / 2);\r
+       py += h + 1;\r
+       USL_DrawString(BottomS3);\r
+\r
+       fontcolor = F_WHITE;\r
+       MyLine(CtlPanelEY - 17);\r
+}\r
+\r
+static void\r
+USL_DrawCtlPanelContents(void)\r
+{\r
+       int                             x,y;\r
+       UserItem                far *item;\r
+\r
+       if (topcard->custom && topcard->custom(uic_DrawCard,nil))\r
+               return;\r
+\r
+       if (topcard->title)\r
+       {\r
+               // Draw the title\r
+               MyLine(CtlPanelSY + 7);\r
+               VWB_DrawPic(CtlPanelSX + 6,CtlPanelSY,topcard->title);\r
+       }\r
+\r
+       USL_DrawBottom();\r
+\r
+       if (!topcard->items)\r
+               return;\r
+\r
+       x = topcard->x + CtlPanelSX;\r
+       if (x % 8)\r
+               x += 8 - (x % 8);\r
+       y = topcard->y + CtlPanelSY + 12;\r
+       for (item = topcard->items;item->type != uii_Bad;item++)\r
+       {\r
+               if (item->flags & ui_Separated)\r
+                       y += 8;\r
+\r
+               item->x = x;\r
+               item->y = y;\r
+               USL_DrawItem(item);\r
+               y += 8;\r
+       }\r
+       if (topcard->custom)\r
+               topcard->custom(uic_TouchupCard,nil);\r
+}\r
+\r
+static void\r
+USL_DrawCtlPanel(void)\r
+{\r
+       if (topcard->items || topcard->title)\r
+       {\r
+               // Draw the backdrop\r
+               VWB_DrawPic(0,0,CP_MENUSCREENPIC);\r
+\r
+               // Draw the contents\r
+               USL_DrawCtlPanelContents();\r
+       }\r
+\r
+       // Refresh the screen\r
+       VW_UpdateScreen();\r
+}\r
+\r
+static void\r
+USL_DialogSetup(word w,word h,word *x,word *y)\r
+{\r
+       VWB_DrawMPic(CtlPanelSX,CtlPanelSY,CP_MENUMASKPICM);\r
+\r
+       *x = CtlPanelSX + ((CtlPanelW - w) / 2);\r
+       *y = CtlPanelSY + ((CtlPanelH - h) / 2);\r
+       VWB_Bar(*x,*y,w + 1,h + 1,BackColor);\r
+       VWB_Hlin(*x - 1,*x + w + 1,*y - 1,NohiliteColor);\r
+       VWB_Hlin(*x - 1,*x + w + 1,*y + h + 1,NohiliteColor);\r
+       VWB_Vlin(*y - 1,*y + h + 1,*x - 1,NohiliteColor);\r
+       VWB_Vlin(*y - 1,*y + h + 1,*x + w + 1,NohiliteColor);\r
+}\r
+\r
+static void\r
+USL_ShowLoadSave(char *s,char *name)\r
+{\r
+       word    x,y,\r
+                       w,h,\r
+                       tw,sw;\r
+       char    msg[MaxGameName + 4];\r
+\r
+       strcpy(msg,"'");\r
+       strcat(msg,name);\r
+       strcat(msg,"'");\r
+       USL_MeasureString(s,&sw,&h);\r
+       USL_MeasureString(msg,&w,&h);\r
+       tw = ((sw > w)? sw : w) + 6;\r
+       USL_DialogSetup(tw,(h * 2) + 2,&x,&y);\r
+       py = y + 2;\r
+       px = x + ((tw - sw) / 2);\r
+       USL_DrawString(s);\r
+       py += h;\r
+       px = x + ((tw - w) / 2);\r
+       USL_DrawString(msg);\r
+\r
+       VW_UpdateScreen();\r
+#ifdef CAT3D\r
+       IN_UserInput(100, true);\r
+#endif\r
+}\r
+\r
+static boolean\r
+USL_CtlDialog(char *s1,char *s2,char *s3)\r
+{\r
+       word            w,h,sh,\r
+                               w1,w2,w3,\r
+                               x,y;\r
+       ScanCode        c;\r
+       CursorInfo      cursorinfo;\r
+\r
+       USL_MeasureString(s1,&w1,&h);\r
+       USL_MeasureString(s2,&w2,&h);\r
+       if (s3)\r
+               USL_MeasureString(s3,&w3,&h);\r
+       else\r
+               w3 = 0;\r
+       w = (w1 > w2)? ((w1 > w3)? w1 : w3) : ((w2 > w3)? w2 : w3);\r
+       w += 7;\r
+       sh = h;\r
+       h *= s3? 5 : 4;\r
+\r
+       USL_DialogSetup(w,h,&x,&y);\r
+\r
+       fontcolor = HiliteColor;\r
+       px = x + ((w - w1) / 2);\r
+       py = y + sh + 1;\r
+       USL_DrawString(s1);\r
+       py += (sh * 2) - 1;\r
+\r
+       VWB_Hlin(x + 3,x + w - 3,py,NohiliteColor);\r
+       py += 2;\r
+\r
+       fontcolor = NohiliteColor;\r
+       px = x + ((w - w2) / 2);\r
+       USL_DrawString(s2);\r
+       py += sh;\r
+\r
+       if (s3)\r
+       {\r
+               px = x + ((w - w3) / 2);\r
+               USL_DrawString(s3);\r
+       }\r
+\r
+       VW_UpdateScreen();\r
+\r
+       IN_ClearKeysDown();\r
+       do\r
+       {\r
+               IN_ReadCursor(&cursorinfo);\r
+               if (cursorinfo.button0)\r
+                       c = sc_Y;\r
+               else if (cursorinfo.button1)\r
+                       c = sc_Escape;\r
+               else\r
+                       c = LastScan;\r
+       } while (c == sc_None);\r
+       do\r
+       {\r
+               IN_ReadCursor(&cursorinfo);\r
+       } while (cursorinfo.button0 || cursorinfo.button1);\r
+\r
+       IN_ClearKeysDown();\r
+       USL_DrawCtlPanel();\r
+       return(c == sc_Y);\r
+}\r
+\r
+static boolean\r
+USL_ConfirmComm(UComm comm)\r
+{\r
+       boolean confirm,dialog;\r
+       char    *s1,*s2,*s3;\r
+\r
+       if (!comm)\r
+               Quit("USL_ConfirmComm() - empty comm");\r
+\r
+       confirm = true;\r
+       dialog = false;\r
+       s3 = "ESC TO BACK OUT";\r
+       switch (comm)\r
+       {\r
+       case uc_Abort:\r
+               s1 = "REALLY END CURRENT GAME?";\r
+               s2 = "PRESS Y TO END IT";\r
+               if (ingame && GameIsDirty)\r
+                       dialog = true;\r
+               break;\r
+       case uc_Quit:\r
+               s1 = "REALLY QUIT?";\r
+               s2 = "PRESS Y TO QUIT";\r
+               dialog = true;\r
+               break;\r
+       case uc_Loaded:\r
+               s1 = "YOU'RE IN A GAME";\r
+               s2 = "PRESS Y TO LOAD GAME";\r
+               if (ingame && GameIsDirty)\r
+                       dialog = true;\r
+               break;\r
+       case uc_SEasy:\r
+       case uc_SNormal:\r
+       case uc_SHard:\r
+               s1 = "YOU'RE IN A GAME";\r
+               s2 = "PRESS Y FOR NEW GAME";\r
+               if (ingame && GameIsDirty)\r
+                       dialog = true;\r
+               break;\r
+       }\r
+\r
+       confirm = dialog? USL_CtlDialog(s1,s2,s3) : true;\r
+       if (confirm)\r
+       {\r
+               Communication = comm;\r
+               CtlPanelDone = true;\r
+       }\r
+       return(confirm);\r
+}\r
+\r
+///////////////////////////////////////////////////////////////////////////\r
+//\r
+//      USL_HandleError() - Handles telling the user that there's been an error\r
+//\r
+///////////////////////////////////////////////////////////////////////////\r
+static void\r
+USL_HandleError(int num)\r
+{\r
+       char    buf[64];\r
+\r
+       strcpy(buf,"Error: ");\r
+       if (num < 0)\r
+               strcat(buf,"Unknown");\r
+       else if (num == ENOMEM)\r
+               strcat(buf,"Disk is Full");\r
+       else if (num == EINVFMT)\r
+               strcat(buf,"File is Incomplete");\r
+       else\r
+               strcat(buf,sys_errlist[num]);\r
+\r
+       VW_HideCursor();\r
+\r
+       USL_CtlDialog(buf,"PRESS ANY KEY",nil);\r
+       VW_UpdateScreen();\r
+\r
+       IN_ClearKeysDown();\r
+       IN_Ack();\r
+\r
+       VW_ShowCursor();\r
+       VW_UpdateScreen();\r
+}\r
+\r
+//      Custom routines\r
+#if 0\r
+static boolean\r
+USL_GenericCustom(UserCall call,UserItem far *item)\r
+{\r
+       boolean result;\r
+\r
+       result = false;\r
+       switch (call)\r
+       {\r
+       }\r
+       return(result);\r
+}\r
+#endif\r
+\r
+static void\r
+USL_SetOptionsText(void)\r
+{\r
+       optionsi[0].text = showscorebox? "SCORE BOX (ON)" : "SCORE BOX (OFF)";\r
+       optionsi[1].text = oldshooting? "TWO-BUTTON FIRING (ON)" : "TWO-BUTTON FIRING (OFF)";\r
+#if GRMODE != CGAGR\r
+       optionsi[2].text = jerk? "FIX JERKY MOTION (ON)" : "FIX JERKY MOTION (OFF)";\r
+       optionsi[3].text = compatability? "SVGA COMPATIBILITY (ON)" : "SVGA COMPATIBILITY (OFF)";\r
+#endif\r
+\r
+       keybi[2].flags &= ~ui_Disabled;\r
+       if (oldshooting)\r
+               keybi[2].flags |= ui_Disabled;\r
+\r
+       // gravis option is only enabled when a joystick is selected\r
+       configi[6].flags |= ui_Disabled;\r
+       if (Controls[0] == ctrl_Joystick1 || Controls[0] == ctrl_Joystick2)\r
+               configi[6].flags &= ~ui_Disabled;\r
+\r
+       configi[6].text = GravisGamepad? "USE GRAVIS GAMEPAD (ON)" : "USE GRAVIS GAMEPAD (OFF)";\r
+}\r
+\r
+#pragma argsused\r
+static boolean\r
+USL_ScoreCustom(UserCall call,UserItem far *item)\r
+{\r
+       if (call != uic_SetupCard)\r
+               return(false);\r
+\r
+       showscorebox ^= true;\r
+       USL_CtlDialog(showscorebox? "Score box now on" : "Score box now off",\r
+                                       "Press any key",nil);\r
+       USL_SetOptionsText();\r
+       return(true);\r
+}\r
+\r
+#pragma argsused\r
+static boolean\r
+USL_SmoothCustom(UserCall call,UserItem far *item)\r
+{\r
+       if (call != uic_SetupCard)\r
+               return(false);\r
+\r
+       jerk ^= true;\r
+       USL_CtlDialog(jerk? "Jerky motion fix enabled" : "Jerky motion fix disabled",\r
+                                       "Press any key",nil);\r
+       USL_SetOptionsText();\r
+       return(true);\r
+}\r
+\r
+#pragma argsused\r
+static boolean\r
+USL_CompCustom(UserCall call,UserItem far *item)\r
+{\r
+       if (call != uic_SetupCard)\r
+               return(false);\r
+\r
+       compatability ^= true;\r
+       USL_CtlDialog(compatability? "SVGA compatibility now on" : "SVGA compatibility now off",\r
+                                       "Press any key",nil);\r
+       USL_SetOptionsText();\r
+       return(true);\r
+}\r
+\r
+#ifdef  KEEN\r
+#pragma argsused\r
+static boolean\r
+USL_TwoCustom(UserCall call,UserItem far *item)\r
+{\r
+       if (call != uic_SetupCard)\r
+               return(false);\r
+\r
+       oldshooting ^= true;\r
+       USL_CtlDialog(oldshooting? "Two-button firing now on" : "Two-button firing now off",\r
+                                       "Press any key",nil);\r
+       USL_SetOptionsText();\r
+       return(true);\r
+}\r
+#endif\r
+\r
+static boolean\r
+USL_ConfigCustom(UserCall call,UserItem far *item)\r
+{\r
+static  char    *CtlNames[] = {"KEYBOARD","KEYBOARD","JOYSTICK #1","JOYSTICK #2","MOUSE"};\r
+               char    *s;\r
+               word    w,h,\r
+                               tw;\r
+\r
+       if (call == uic_TouchupCard)\r
+       {\r
+               s = "CONTROL: ";\r
+               USL_MeasureString(s,&w,&h);\r
+               tw = w;\r
+               USL_MeasureString(CtlNames[Controls[0]],&w,&h);\r
+               tw += w;\r
+               py = CtlPanelEY - 18 - h;\r
+               px = CtlPanelSX + ((CtlPanelW - tw) / 2);\r
+               fontcolor = NohiliteColor;\r
+               USL_DrawString(s);\r
+               USL_DrawString(CtlNames[Controls[0]]);\r
+       }\r
+       item++; // Shut the compiler up\r
+       return(false);\r
+}\r
+\r
+static void\r
+USL_CKSetKey(UserItem far *item,word i)\r
+{\r
+       boolean         on;\r
+       word            j;\r
+       ScanCode        scan;\r
+       longword        time;\r
+       CursorInfo      cursorinfo;\r
+\r
+       on = false;\r
+       time = 0;\r
+       LastScan = sc_None;\r
+       fontcolor = HiliteColor;\r
+       do\r
+       {\r
+               if (TimeCount >= time)\r
+               {\r
+                       on ^= true;\r
+                       VWB_Bar(item->x + 90,item->y,40,8,fontcolor ^ BackColor);\r
+                       VWB_Bar(item->x + 90 + 1,item->y + 1,40 - 2,8 - 2,BackColor);\r
+                       if (on)\r
+                               VWB_DrawTile8(item->x + 90 + 16,item->y,TileBase + 8);\r
+                       VW_UpdateScreen();\r
+\r
+                       time = TimeCount + (TickBase / 2);\r
+               }\r
+\r
+               IN_ReadCursor(&cursorinfo);\r
+               while (cursorinfo.button0 || cursorinfo.button1)\r
+               {\r
+                       IN_ReadCursor(&cursorinfo);\r
+                       LastScan = sc_Escape;\r
+               }\r
+\r
+       asm     pushf\r
+       asm     cli\r
+               if (LastScan == sc_LShift)\r
+                       LastScan = sc_None;\r
+       asm     popf\r
+       } while (!(scan = LastScan));\r
+\r
+       if (scan != sc_Escape)\r
+       {\r
+               for (j = 0,on = false;j < 11;j++)\r
+               {\r
+                       if (j == i)\r
+                               continue;\r
+                       if (*(KeyMaps[j]) == scan)\r
+                       {\r
+                               on = true;\r
+                               break;\r
+                       }\r
+               }\r
+               if (on)\r
+#ifdef KEEN\r
+                       USL_CtlDialog("Key already used","Press any key",nil);\r
+#else\r
+                       USL_CtlDialog("Key already used","Press a key",nil);\r
+#endif\r
+               else\r
+                       *(KeyMaps[i]) = scan;\r
+       }\r
+       IN_ClearKeysDown();\r
+}\r
+\r
+#pragma argsused\r
+static boolean\r
+USL_KeySCustom(UserCall call,UserItem far *item)\r
+{\r
+       if (call == uic_SetupCard)\r
+       {\r
+               Controls[0] = ctrl_Keyboard;\r
+               GravisGamepad = false;\r
+               USL_SetOptionsText();\r
+       }\r
+       return(false);\r
+}\r
+\r
+#pragma argsused\r
+static boolean\r
+USL_KeyCustom(UserCall call,UserItem far *item)\r
+{\r
+       boolean result;\r
+       word    i;\r
+\r
+       result = false;\r
+       i = (topcard == &keygroup)? (3 + (item - keyi)) : (item - keybi);\r
+       switch (call)\r
+       {\r
+       case uic_SetupCard:\r
+               Controls[0] = ctrl_Keyboard;\r
+               break;\r
+       case uic_Draw:\r
+               VWB_Bar(CtlPanelSX + 1,item->y,\r
+                               CtlPanelEX - CtlPanelSX - 1,8,BackColor);       // Clear out background\r
+               USL_DrawItemIcon(item);\r
+               fontcolor = (item->flags & ui_Selected)? HiliteColor : NohiliteColor;\r
+               px = item->x + 8;\r
+               py = item->y + 1;\r
+               USL_DrawString(item->text);\r
+               VWB_Bar(item->x + 90,item->y,40,8,fontcolor ^ BackColor);\r
+               VWB_Bar(item->x + 90 + 1,item->y + 1,40 - 2,8 - 2,BackColor);\r
+               px = item->x + 90 + 6;\r
+               py = item->y + 1;\r
+               USL_DrawString(IN_GetScanName(*KeyMaps[i]));\r
+               result = true;\r
+               break;\r
+       case uic_Hit:\r
+               USL_KeyCustom(uic_Draw,item);\r
+               USL_CKSetKey(item,i);\r
+               USL_DrawCtlPanel();\r
+               result = true;\r
+               break;\r
+       }\r
+       return(result);\r
+}\r
+\r
+static void\r
+USL_CJDraw(char *s1,char *s2)\r
+{\r
+       word    w,h;\r
+\r
+       USL_MeasureString(s1,&w,&h);\r
+       px = CtlPanelSX + ((CtlPanelW - w) / 2);\r
+       py = CtlPanelEY - 34;\r
+       VWB_Bar(CtlPanelSX + 1,py,CtlPanelW - 2,h * 2,BackColor);\r
+       fontcolor = HiliteColor;\r
+       USL_DrawString(s1);\r
+       py += h;\r
+       USL_MeasureString(s2,&w,&h);\r
+       px = CtlPanelSX + ((CtlPanelW - w) / 2);\r
+       USL_DrawString(s2);\r
+}\r
+\r
+static boolean\r
+USL_CJGet(word joy,word button,word x,word y,word *xaxis,word *yaxis)\r
+{\r
+       boolean         on;\r
+       longword        time;\r
+\r
+       while (IN_GetJoyButtonsDB(joy))\r
+               if (LastScan == sc_Escape)\r
+                       return(false);\r
+\r
+       on = false;\r
+       time = 0;\r
+       while (!(IN_GetJoyButtonsDB(joy) & (1 << button)))\r
+       {\r
+               if (TimeCount >= time)\r
+               {\r
+                       on ^= true;\r
+                       time = TimeCount + (TickBase / 2);\r
+                       VWB_DrawTile8(x,y,TileBase + on);\r
+                       VW_UpdateScreen();\r
+               }\r
+\r
+               if (LastScan == sc_Escape)\r
+                       return(false);\r
+       }\r
+       IN_GetJoyAbs(joy,xaxis,yaxis);\r
+       return(true);\r
+}\r
+\r
+static boolean\r
+USL_ConfigJoystick(word joy)\r
+{\r
+       word    x,y,\r
+                       minx,miny,\r
+                       maxx,maxy;\r
+\r
+       BottomS1 = BottomS2 = "";\r
+#ifdef KEEN\r
+       BottomS3 = "ESC to back out";\r
+#else\r
+       BottomS3 = "Esc to back out";\r
+#endif\r
+       USL_DrawCtlPanel();\r
+       x = CtlPanelSX + 60;\r
+       y = CtlPanelSY + 19;\r
+       VWB_DrawPic(x,y,CP_JOYSTICKPIC);\r
+\r
+       USL_CJDraw("Move Joystick to upper left","and press button #1");\r
+       VWB_DrawTile8(x + 24,y + 8,TileBase + 6);\r
+       VWB_DrawTile8(x + 8,y + 8,TileBase + 1);\r
+       VWB_DrawTile8(x + 8,y + 24,TileBase + 0);\r
+       VW_UpdateScreen();\r
+       if (!USL_CJGet(joy,0,x + 8,y + 8,&minx,&miny))\r
+               return(false);\r
+\r
+       USL_CJDraw("Move Joystick to lower right","and press button #2");\r
+       VWB_DrawTile8(x + 24,y + 8,TileBase - 25);\r
+       VWB_DrawTile8(x + 40,y + 24,TileBase + 7);\r
+       VWB_DrawTile8(x + 8,y + 8,TileBase + 0);\r
+       VWB_DrawTile8(x + 8,y + 24,TileBase + 1);\r
+       VW_UpdateScreen();\r
+       if (!USL_CJGet(joy,1,x + 8,y + 24,&maxx,&maxy))\r
+               return(false);\r
+\r
+       while (IN_GetJoyButtonsDB(joy))\r
+               ;\r
+\r
+#ifdef KEEN\r
+       if (minx != maxx && miny != maxy)\r
+       {\r
+               IN_SetupJoy(joy,minx,maxx,miny,maxy);\r
+               return(true);\r
+       }\r
+       return(false);\r
+#else\r
+       IN_SetupJoy(joy,minx,maxx,miny,maxy);\r
+       return(true);\r
+#endif\r
+}\r
+\r
+#pragma argsused\r
+static boolean\r
+USL_Joy1Custom(UserCall call,UserItem far *item)\r
+{\r
+       if (call == uic_SetupCard)\r
+       {\r
+               if (USL_ConfigJoystick(0))\r
+               {\r
+                       Controls[0] = ctrl_Joystick1;\r
+                       USL_CtlDialog("USING JOYSTICK #1","PRESS ANY KEY",nil);\r
+                       USL_SetOptionsText();\r
+               }\r
+               return(true);\r
+       }\r
+       else\r
+               return(false);\r
+}\r
+\r
+#pragma argsused\r
+static boolean\r
+USL_Joy2Custom(UserCall call,UserItem far *item)\r
+{\r
+       if (call == uic_SetupCard)\r
+       {\r
+               if (USL_ConfigJoystick(1))\r
+               {\r
+                       Controls[0] = ctrl_Joystick2;\r
+                       USL_CtlDialog("USING JOYSTICK #2","PRESS ANY KEY",nil);\r
+                       USL_SetOptionsText();\r
+               }\r
+               return(true);\r
+       }\r
+       else\r
+               return(false);\r
+}\r
+\r
+static void\r
+USL_CGDraw(char *s1, char *s2, int buttonsDone)\r
+{\r
+       static char *GButtonNames[4] = {"Red","Blue","Yellow","Green"};\r
+       static char *GActionNames[4] = {"Jump","Pogo","Fire","Status"};\r
+\r
+       int     i, n;\r
+       char    *actionstr;\r
+       word    w, h;\r
+\r
+       VWB_Bar(CtlPanelSX+1, CtlPanelSY+16, CtlPanelW-2, 68, BackColor);\r
+       px = CtlPanelSX+8;\r
+       py = CtlPanelSY+16;\r
+       USL_DrawString("Make sure that the button");\r
+       px = CtlPanelSX+8;\r
+       py = CtlPanelSY+24;\r
+       USL_DrawString("switch is set for 4 buttons");\r
+\r
+       for (i=0; i<4; i++)\r
+       {\r
+               px = CtlPanelSX+8;\r
+               py = i*8 + CtlPanelSY+40;\r
+               USL_DrawString(GButtonNames[i]);\r
+               USL_DrawString(":");\r
+               actionstr = "?";\r
+               for (n=0;n<buttonsDone;n++)\r
+               {\r
+                       if (GravisMap[n] == i)\r
+                               actionstr = GActionNames[n];\r
+               }\r
+               px = CtlPanelSX+56;\r
+               USL_DrawString(actionstr);\r
+       }\r
+\r
+       USL_MeasureString(s1, &w, &h);\r
+       px = w;\r
+       USL_MeasureString(s2, &w, &h);\r
+       px = (CtlPanelW-px-w)/2 + CtlPanelSX;\r
+       py = CtlPanelSY+76;\r
+       USL_DrawString(s1);\r
+       USL_DrawString(s2);\r
+       VW_UpdateScreen();\r
+}\r
+\r
+static boolean\r
+USL_CGGet(int buttonsDone, char *action)\r
+{\r
+       word    buttons, i, n;\r
+\r
+       USL_CGDraw("PRESS BUTTON FOR ", action, buttonsDone);\r
+\r
+redo:\r
+       do\r
+       {\r
+               if (LastScan == sc_Escape)\r
+               {\r
+                       Keyboard[sc_Escape] = false;\r
+                       if (LastScan == sc_Escape)\r
+                               LastScan = sc_None;\r
+                       return false;\r
+               }\r
+\r
+               buttons = IN_GetJoyButtonsDB(2);\r
+               if (!buttons)\r
+                       continue;\r
+\r
+               for(i=n=0; i<4; i++)\r
+               {\r
+                       if (buttons & (1 << i))\r
+                               n += i+1;\r
+               }\r
+\r
+               if (!n || n >= 5)\r
+                       continue;\r
+\r
+               n--;\r
+               for (i=0; i<buttonsDone; i++)\r
+               {\r
+                       if (GravisMap[i] == n)\r
+                               goto redo;\r
+               }\r
+\r
+               GravisMap[buttonsDone] = n;\r
+               return true;\r
+       } while (true);\r
+}\r
+\r
+#pragma argsused\r
+static boolean\r
+USL_JoyGCustom(UserCall call,UserItem far *item)\r
+{\r
+       if (call == uic_SetupCard)\r
+       {\r
+               if (GravisGamepad)\r
+               {\r
+                       GravisGamepad = false;\r
+               }\r
+               else\r
+               {\r
+                       BottomS1 = BottomS2 = "";\r
+                       BottomS3 = "ESC to back out";\r
+                       USL_DrawCtlPanel();\r
+                       fontcolor = HiliteColor;\r
+                       px = CtlPanelSX + 8;\r
+                       py = CtlPanelSX + 8;\r
+                       fontcolor = HiliteColor;        // redundant...\r
+                       IN_ClearKeysDown();\r
+                       if (  USL_CGGet(0, "JUMP")\r
+                               && USL_CGGet(1, "POGO")\r
+                               && USL_CGGet(2, "FIRE")\r
+                               && USL_CGGet(3, "STATUS") )\r
+                       {\r
+                               GravisGamepad = true;\r
+                               USL_CGDraw("PRESS ANY KEY", "", 4);\r
+                               IN_Ack();\r
+                       }\r
+                       else\r
+                       {\r
+                               GravisGamepad = false;\r
+                       }\r
+               }\r
+               USL_SetOptionsText();\r
+               return true;\r
+       }\r
+       return false;\r
+}\r
+\r
+static void\r
+USL_DrawFileIcon(UserItem far *item)\r
+{\r
+       word    color;\r
+\r
+       item->y = topcard->y + CtlPanelSY + 12;\r
+       item->y += (item - loadsavegamei) * 11;\r
+\r
+       fontcolor = (item->flags & ui_Selected)? HiliteColor : NohiliteColor;\r
+       color = fontcolor ^ BackColor;  // Blech!\r
+       VWB_Hlin(item->x,item->x + (CtlPanelW - 12),item->y,color);\r
+       VWB_Hlin(item->x,item->x + (CtlPanelW - 12),item->y + 9,color);\r
+       VWB_Vlin(item->y,item->y + 9,item->x,color);\r
+       VWB_Vlin(item->y,item->y + 9,item->x + (CtlPanelW - 12),color);\r
+}\r
+\r
+static void\r
+USL_DoLoadGame(UserItem far *item)\r
+{\r
+       char            *filename;\r
+       word            n,\r
+                               err;\r
+       int                     file;\r
+       SaveGame        *game;\r
+\r
+       if (!USL_ConfirmComm(uc_Loaded))\r
+               return;\r
+\r
+       n = item - loadsavegamei;\r
+       game = &Games[n];\r
+\r
+       USL_ShowLoadSave("Loading",game->name);\r
+\r
+       err = 0;\r
+       filename = USL_GiveSaveName(n);\r
+       if ((file = open(filename,O_BINARY | O_RDONLY)) != -1)\r
+       {\r
+               if (read(file,game,sizeof(*game)) == sizeof(*game))\r
+               {\r
+                       if (USL_LoadGame)\r
+                               if (!USL_LoadGame(file))\r
+                                       USL_HandleError(err = errno);\r
+               }\r
+               else\r
+                       USL_HandleError(err = errno);\r
+               close(file);\r
+       }\r
+       else\r
+               USL_HandleError(err = errno);\r
+       if (err)\r
+       {\r
+               abortgame = true;\r
+               Communication = uc_None;\r
+               CtlPanelDone = false;\r
+       }\r
+       else\r
+               loadedgame = true;\r
+       game->present = true;\r
+\r
+       if (loadedgame)\r
+               Paused = true;\r
+\r
+       USL_DrawCtlPanel();\r
+}\r
+\r
+static boolean\r
+USL_LoadCustom(UserCall call,UserItem far *item)\r
+{\r
+       boolean result;\r
+       word    i;\r
+\r
+       result = false;\r
+       switch (call)\r
+       {\r
+       case uic_SetupCard:\r
+#ifdef KEEN\r
+               if (getenv("UID"))\r
+                       USL_CheckSavedGames();\r
+#endif\r
+               for (i = 0;i < MaxSaveGames;i++)\r
+               {\r
+                       if (Games[i].present)\r
+                               loadsavegamei[i].flags &= ~ui_Disabled;\r
+                       else\r
+                               loadsavegamei[i].flags |= ui_Disabled;\r
+               }\r
+               break;\r
+       case uic_DrawIcon:\r
+               USL_DrawFileIcon(item);\r
+               result = true;\r
+               break;\r
+       case uic_Draw:\r
+               USL_DrawFileIcon(item);\r
+               VWB_Bar(item->x + 1,item->y + 2,CtlPanelW - 12 - 2,7,BackColor);\r
+\r
+               i = item - loadsavegamei;\r
+               if (Games[i].present)\r
+                       px = item->x + 2;\r
+               else\r
+                       px = item->x + 60;\r
+               py = item->y + 2;\r
+               USL_DrawString(Games[i].present? Games[i].name : "Empty");\r
+               result = true;\r
+               break;\r
+       case uic_Hit:\r
+               USL_DoLoadGame(item);\r
+               result = true;\r
+               break;\r
+       }\r
+       return(result);\r
+}\r
+\r
+static void\r
+USL_DoSaveGame(UserItem far *item)\r
+{\r
+       boolean         ok;\r
+       char            *filename;\r
+       word            n,err;\r
+       int         file;\r
+       SaveGame        *game;\r
+\r
+       BottomS1 = "Type name";\r
+       BottomS2 = "Enter accepts";\r
+       USL_DrawCtlPanel();\r
+\r
+       n = item - loadsavegamei;\r
+       game = &Games[n];\r
+       fontcolor = HiliteColor;\r
+       VWB_Bar(item->x + 1,item->y + 2,CtlPanelW - 12 - 2,7,BackColor);\r
+       game->oldtest = &PrintX;\r
+       ok = US_LineInput(item->x + 2,item->y + 2,\r
+                                               game->name,game->present? game->name : nil,\r
+                                               true,MaxGameName,\r
+                                               CtlPanelW - 22);\r
+       if (!strlen(game->name))\r
+               strcpy(game->name,"Untitled");\r
+       if (ok)\r
+       {\r
+               USL_ShowLoadSave("Saving",game->name);\r
+\r
+               filename = USL_GiveSaveName(n);\r
+               err = 0;\r
+               file = open(filename,O_CREAT | O_BINARY | O_WRONLY,\r
+                                       S_IREAD | S_IWRITE | S_IFREG);\r
+               if (file != -1)\r
+               {\r
+                       if (write(file,game,sizeof(*game)) == sizeof(*game))\r
+                       {\r
+                               if (USL_SaveGame)\r
+                                       ok = USL_SaveGame(file);\r
+                               if (!ok)\r
+                                       USL_HandleError(err = errno);\r
+                       }\r
+                       else\r
+                               USL_HandleError(err = ((errno == ENOENT)? ENOMEM : errno));\r
+                       close(file);\r
+               }\r
+               else\r
+                       USL_HandleError(err = ((errno == ENOENT)? ENOMEM : errno));\r
+               if (err)\r
+               {\r
+                       remove(filename);\r
+                       ok = false;\r
+               }\r
+\r
+       }\r
+\r
+       if (!game->present)\r
+               game->present = ok;\r
+\r
+       if (ok)\r
+               GameIsDirty = false;\r
+       USL_SetupCard();\r
+}\r
+\r
+static boolean\r
+USL_SaveCustom(UserCall call,UserItem far *item)\r
+{\r
+       word    i;\r
+\r
+       switch (call)\r
+       {\r
+       case uic_SetupCard:\r
+#ifdef KEEN\r
+               if (getenv("UID"))\r
+                       USL_CheckSavedGames();\r
+#endif\r
+               for (i = 0;i < MaxSaveGames;i++)\r
+                       loadsavegamei[i].flags &= ~ui_Disabled;\r
+               return(false);\r
+       case uic_Hit:\r
+               USL_DoSaveGame(item);\r
+               return(true);\r
+//              break;\r
+       }\r
+       return(USL_LoadCustom(call,item));\r
+}\r
+\r
+#define PaddleMinX      (CtlPanelSX + 4)\r
+#define PaddleMaxX      (CtlPanelEX - 15)\r
+#define BallMinX        (CtlPanelSX + 4)\r
+#define BallMinY        (CtlPanelSY + 12 + 2)\r
+#define BallMaxX        (CtlPanelEX - 6)\r
+#define BallMaxY        (CtlPanelEY - 13)\r
+#define CPaddleY        (BallMinY + 4)\r
+#define KPaddleY        (BallMaxY - 2)\r
+void\r
+USL_DrawPongScore(word k,word c)\r
+{\r
+       fontcolor = HiliteColor;\r
+       PrintY = py = CtlPanelSY + 4;\r
+       px = CtlPanelSX + 6;\r
+       VWB_Bar(px,py,42,6,BackColor);\r
+       USL_DrawString("KEEN:");\r
+       PrintX = px;\r
+       US_PrintUnsigned(k);\r
+       px = CtlPanelSX + 108;\r
+       VWB_Bar(px,py,50,6,BackColor);\r
+       USL_DrawString("COMP:");\r
+       PrintX = px;\r
+       US_PrintUnsigned(c);\r
+}\r
+\r
+void\r
+USL_PlayPong(void)\r
+{\r
+       boolean         ball,killball,revdir,done,lastscore;\r
+       word            cycle,\r
+                               x,y,\r
+                               kx,cx,\r
+                               rx,\r
+                               bx,by,\r
+                               oldkx,oldcx,oldbx,oldby,\r
+                               kscore,cscore,\r
+                               speedup;\r
+       int                     bdx,bdy;\r
+       longword        balltime,lasttime,waittime;\r
+       CursorInfo      cursorinfo;\r
+\r
+       kx = cx = PaddleMinX + ((PaddleMaxX - PaddleMinX) / 2);\r
+       bx = by = bdx = bdy = 0;\r
+       oldbx = oldcx = oldkx = PaddleMinX;\r
+       oldby = BallMinY;\r
+       kscore = cscore = 0;\r
+       USL_DrawPongScore(0,0);\r
+       cycle = 0;\r
+       revdir = false;\r
+       killball = true;\r
+       done = false;\r
+       lastscore = false;\r
+       lasttime = TimeCount;\r
+       do\r
+       {\r
+               while ((waittime = TimeCount - lasttime) == 0)\r
+                       ;\r
+\r
+               lasttime = TimeCount;\r
+               if (waittime > 4)\r
+                       waittime = 4;\r
+\r
+               while (waittime-- && !done && LastScan != sc_Escape)\r
+               {\r
+                       IN_ReadCursor(&cursorinfo);\r
+                       if (((cursorinfo.x < 0) || IN_KeyDown(sc_LeftArrow)) && (kx > PaddleMinX))\r
+                               kx -= 2;\r
+                       else if (((cursorinfo.x > 0) || IN_KeyDown(sc_RightArrow)) && (kx < PaddleMaxX))\r
+                               kx += 2;\r
+\r
+                       if (killball)\r
+                       {\r
+                               ball = false;\r
+                               balltime = TickBase;\r
+                               speedup = 10;\r
+                               killball = false;\r
+                               VWB_Bar(oldbx,oldby,5,5,BackColor);\r
+                       }\r
+\r
+                       if (ball && (cycle++ % 3))\r
+                       {\r
+                               x = (bx >> 2);\r
+                               if (!(x & 1))\r
+                                       x += (US_RndT() & 1);\r
+\r
+                               if ((cx + 6 < x) && (cx < PaddleMaxX))\r
+                                       cx += 1;\r
+                               else if ((cx + 6 > x) && (cx > PaddleMinX))\r
+                                       cx -= 1;\r
+                       }\r
+\r
+                       if (!ball && !--balltime)\r
+                       {\r
+                               ball = true;\r
+                               bdx = 1 - (US_RndT() % 3);\r
+                               bdy = 3;\r
+                               if (lastscore)\r
+                                       bdy = -bdy;\r
+                               bx = (BallMinX + ((BallMaxX - BallMinX) / 2)) << 2;\r
+                               by = (BallMinY + ((BallMaxY - BallMinY) / 2)) << 2;\r
+                       }\r
+\r
+                       if (ball)\r
+                       {\r
+                               if\r
+                               (\r
+                                       (((bx + bdx) >> 2) > BallMaxX)\r
+                               ||      (((bx + bdx) >> 2) < BallMinX)\r
+                               )\r
+                               {\r
+                                       SD_PlaySound(BALLBOUNCESND);\r
+                                       bdx = -bdx;\r
+                               }\r
+                               bx += bdx;\r
+\r
+                               if (((by + bdy) >> 2) > BallMaxY)\r
+                               {\r
+                                       killball = true;\r
+                                       lastscore = false;\r
+                                       cscore++;\r
+                                       SD_PlaySound(COMPSCOREDSND);\r
+                                       USL_DrawPongScore(kscore,cscore);\r
+                                       if (cscore == 21)\r
+                                       {\r
+                                               USL_CtlDialog("You lost!","Press any key",nil);\r
+                                               done = true;\r
+                                               continue;\r
+                                       }\r
+                               }\r
+                               else if (((by + bdy) >> 2) < BallMinY)\r
+                               {\r
+                                       killball = true;\r
+                                       lastscore = true;\r
+                                       kscore++;\r
+                                       SD_PlaySound(KEENSCOREDSND);\r
+                                       USL_DrawPongScore(kscore,cscore);\r
+                                       if (kscore == 21)\r
+                                       {\r
+                                               USL_CtlDialog("You won!","Press any key",nil);\r
+                                               done = true;\r
+                                               continue;\r
+                                       }\r
+                               }\r
+                               by += bdy;\r
+\r
+                               x = bx >> 2;\r
+                               y = by >> 2;\r
+                               if (!killball)\r
+                               {\r
+                                       if\r
+                                       (\r
+                                               (bdy < 0)\r
+                                       &&      ((y >= CPaddleY) && (y < CPaddleY + 3))\r
+                                       &&      ((x >= (cx - 5)) && (x < (cx + 11)))\r
+                                       )\r
+                                       {\r
+                                               rx = cx;\r
+                                               revdir = true;\r
+                                               SD_PlaySound(COMPPADDLESND);\r
+                                       }\r
+                                       else if\r
+                                       (\r
+                                               (bdy > 0)\r
+                                       &&      ((y >= (KPaddleY - 3)) && (y < KPaddleY))\r
+                                       &&      ((x >= (kx - 5)) && (x < (kx + 11)))\r
+                                       )\r
+                                       {\r
+                                               if (((bdy >> 2) < 3) && !(--speedup))\r
+                                               {\r
+                                                       bdy++;\r
+                                                       speedup = 10;\r
+                                               }\r
+                                               rx = kx;\r
+                                               revdir = true;\r
+                                               SD_PlaySound(KEENPADDLESND);\r
+                                       }\r
+                                       if (revdir)\r
+                                       {\r
+                                               bdy = -bdy;\r
+                                               bdx = ((x + 5 - rx) >> 1) - (1 << 2);\r
+                                               if (!bdx)\r
+                                                       bdx--;\r
+                                               revdir = false;\r
+                                       }\r
+                               }\r
+                       }\r
+               }\r
+\r
+               if (ball)\r
+               {\r
+                       VWB_Bar(oldbx,oldby,5,5,BackColor);\r
+                       oldbx = x;\r
+                       oldby = y;\r
+#if GRMODE == CGAGR\r
+                       {\r
+                               static int ballsprites[4] = {BALLSPR, BALL1PIXELTOTHERIGHTSPR, BALL2PIXELSTOTHERIGHTSPR, BALL3PIXELSTOTHERIGHTSPR};\r
+                               VWB_DrawSprite(x,y,ballsprites[x & 3]);\r
+                       }\r
+#else\r
+                       VWB_DrawSprite(x,y,(x & 1)? BALL1PIXELTOTHERIGHTSPR : BALLSPR);\r
+#endif\r
+               }\r
+               VWB_Bar(oldcx-3,CPaddleY,16,3,BackColor);\r
+               oldcx = cx;\r
+               VWB_DrawSprite(cx,CPaddleY,PADDLESPR);\r
+               VWB_Bar(oldkx-3,KPaddleY,16,3,BackColor);\r
+               oldkx = kx;\r
+               VWB_DrawSprite(kx,KPaddleY,PADDLESPR);\r
+\r
+               VW_UpdateScreen();\r
+       } while ((LastScan != sc_Escape) && !done);\r
+       IN_ClearKeysDown();\r
+}\r
+\r
+#pragma argsused\r
+static boolean\r
+USL_PongCustom(UserCall call,struct UserItem far *item)\r
+{\r
+       if (call != uic_SetupCard)\r
+               return(false);\r
+\r
+       VWB_DrawPic(0,0,CP_MENUSCREENPIC);\r
+       VWB_DrawPic(CtlPanelSX + 56,CtlPanelSY,CP_PADDLEWARPIC);\r
+       VWB_Hlin(CtlPanelSX + 3,CtlPanelEX - 3,CtlPanelSY + 12,HiliteColor ^ BackColor);\r
+       VWB_Hlin(CtlPanelSX + 3,CtlPanelEX - 3,CtlPanelEY - 7,HiliteColor ^ BackColor);\r
+       USL_PlayPong();\r
+\r
+       return(true);\r
+}\r
+\r
+//      Flag management stuff\r
+static void\r
+USL_ClearFlags(UserItemGroup far *node)\r
+{\r
+       UserItem        far *i;\r
+\r
+       if (!node->items)\r
+               return;\r
+\r
+       for (i = node->items;i->type != uii_Bad;i++)\r
+       {\r
+               i->flags &= ~UISelectFlags;\r
+               if (i->child)\r
+                       USL_ClearFlags((UserItemGroup far *)i->child);\r
+       }\r
+}\r
+\r
+static int\r
+USL_FindPushedItem(UserItemGroup far *group)\r
+{\r
+       word            i;\r
+       UserItem        far *item;\r
+\r
+       for (item = group->items,i = 0;item->type != uii_Bad;item++,i++)\r
+               if (item->flags & ui_Pushed)\r
+                       return(i);\r
+       return(-1);\r
+}\r
+\r
+static void\r
+USL_SelectItem(UserItemGroup far *group,word index,boolean draw)\r
+{\r
+       UserItem        far *item;\r
+\r
+       if (index != group->cursor)\r
+       {\r
+               item = &group->items[group->cursor];\r
+               item->flags &= ~ui_Selected;\r
+               if (draw)\r
+                       USL_DrawItem(item);\r
+       }\r
+\r
+       group->cursor = index;\r
+       item = &group->items[group->cursor];\r
+       group->items[group->cursor].flags |= ui_Selected;\r
+       if (draw)\r
+               USL_DrawItem(item);\r
+}\r
+\r
+static void\r
+USL_PushItem(UserItemGroup far *group,word index,boolean draw)\r
+{\r
+       word            i;\r
+       UserItem        far *item;\r
+\r
+       USL_SelectItem(group,index,draw);\r
+       for (item = group->items,i = 0;item->type != uii_Bad;item++,i++)\r
+       {\r
+               if (item->type != uii_RadioButton)\r
+                       continue;\r
+\r
+               if (i == index)\r
+               {\r
+                       item->flags |= ui_Pushed;\r
+                       if (draw)\r
+                               USL_DrawItem(item);\r
+               }\r
+               else if (item->flags & ui_Pushed)\r
+               {\r
+                       item->flags &= ~ui_Pushed;\r
+                       if (draw)\r
+                               USL_DrawItem(item);\r
+               }\r
+       }\r
+}\r
+\r
+static void\r
+USL_NextItem(void)\r
+{\r
+       if (topcard->items[topcard->cursor + 1].type == uii_Bad)\r
+               return;\r
+       USL_SelectItem(topcard,topcard->cursor + 1,true);\r
+}\r
+\r
+static void\r
+USL_PrevItem(void)\r
+{\r
+       if (!topcard->cursor)\r
+               return;\r
+       USL_SelectItem(topcard,topcard->cursor - 1,true);\r
+}\r
+\r
+static void\r
+USL_SetupCard(void)\r
+{\r
+       BottomS1 = "Arrows move";\r
+       BottomS2 = "Enter selects";\r
+       BottomS3 = cstackptr? "ESC to back out" : "ESC to quit";\r
+\r
+       USL_SelectItem(topcard,topcard->cursor,false);\r
+       USL_DrawCtlPanel();     // Contents?\r
+}\r
+\r
+static void\r
+USL_DownLevel(UserItemGroup far *group)\r
+{\r
+       if (!group)\r
+               Quit("USL_DownLevel() - nil card");\r
+       USL_PushCard(group);\r
+       if (group->custom && group->custom(uic_SetupCard,nil))\r
+               USL_PopCard();\r
+       USL_SetupCard();\r
+}\r
+\r
+static void\r
+USL_UpLevel(void)\r
+{\r
+       if (!cstackptr)\r
+       {\r
+               USL_ConfirmComm(uc_Quit);\r
+               return;\r
+       }\r
+\r
+       if (topcard->items)\r
+               topcard->items[topcard->cursor].flags &= ~ui_Selected;\r
+       USL_PopCard();\r
+       USL_SetupCard();\r
+}\r
+\r
+static void\r
+USL_DoItem(void)\r
+{\r
+       // DEBUG - finish this routine\r
+       UserItem                far *item;\r
+\r
+       item = &topcard->items[topcard->cursor];\r
+       if (item->flags & ui_Disabled)\r
+               SD_PlaySound(NOWAYSND);\r
+       else\r
+       {\r
+               switch (item->type)\r
+               {\r
+               case uii_Button:\r
+                       if (!(topcard->custom && topcard->custom(uic_Hit,item)))\r
+                               USL_ConfirmComm(item->comm);\r
+                       break;\r
+               case uii_RadioButton:\r
+                       USL_PushItem(topcard,topcard->cursor,true);\r
+                       break;\r
+               case uii_Folder:\r
+                       USL_DownLevel(item->child);\r
+                       break;\r
+               }\r
+       }\r
+}\r
+\r
+static void\r
+USL_SetControlValues(void)\r
+{\r
+       int sndindex;\r
+\r
+       sndindex = SoundMode;\r
+       if (sndindex == sdm_AdLib && QuietFX)\r
+               sndindex++;\r
+\r
+       USL_PushItem(&soundgroup,sndindex,false);\r
+       USL_PushItem(&musicgroup,MusicMode,false);\r
+       if (!AdLibPresent)\r
+       {\r
+               soundi[2].flags |= ui_Disabled; // AdLib sound effects\r
+               soundi[3].flags |= ui_Disabled; // Quiet AdLib sound effects\r
+               musici[1].flags |= ui_Disabled; // AdLib music\r
+       }\r
+\r
+#ifdef CAT3D\r
+       if (!JoysPresent[0])\r
+               configi[3].flags |= ui_Disabled;\r
+       if (!JoysPresent[1])\r
+               configi[4].flags |= ui_Disabled;\r
+#else\r
+       if (!JoysPresent[0])\r
+               configi[4].flags |= ui_Disabled;\r
+       if (!JoysPresent[1])\r
+               configi[5].flags |= ui_Disabled;\r
+       if (!JoysPresent[0] && !JoysPresent[1])\r
+               configi[6].flags |= ui_Disabled;\r
+#endif\r
+\r
+       rooti[4].text = ingame? "RETURN TO GAME" : "RETURN TO DEMO";\r
+       if (!ingame)\r
+       {\r
+               rooti[2].flags |= ui_Disabled;  // Save Game\r
+               rooti[5].flags |= ui_Disabled;  // End Game\r
+       }\r
+       rootgroup.cursor = ingame? 4 : 0;\r
+       USL_SetOptionsText();\r
+       // DEBUG - write the rest of this\r
+}\r
+\r
+///////////////////////////////////////////////////////////////////////////\r
+//\r
+//      USL_SetUpCtlPanel() - Sets the states of the UserItems to reflect the\r
+//              values of all the appropriate variables\r
+//\r
+///////////////////////////////////////////////////////////////////////////\r
+static void\r
+USL_SetUpCtlPanel(void)\r
+{\r
+       int     i;\r
+\r
+       // Cache in all of the stuff for the control panel\r
+       CA_UpLevel();\r
+       for (i = CONTROLS_LUMP_START;i <= CONTROLS_LUMP_END;i++)\r
+               CA_MarkGrChunk(i);\r
+       for (i = PADDLE_LUMP_START;i <= PADDLE_LUMP_END;i++)\r
+               CA_MarkGrChunk(i);\r
+       CA_MarkGrChunk(STARTFONT+1);            // Little font\r
+       CA_MarkGrChunk(CP_MENUMASKPICM);        // Mask for dialogs\r
+       CA_CacheMarks("Control Panel");\r
+       CA_LoadAllSounds();\r
+\r
+       // Do some other setup\r
+       fontnumber = 1;\r
+       US_SetPrintRoutines(VW_MeasurePropString,VWB_DrawPropString);\r
+       fontcolor = F_BLACK;\r
+#ifdef CAT3D\r
+       VW_Bar (0,0,320,200,3); // CAT3D patch\r
+#else\r
+       VW_ClearVideo(3);\r
+#endif\r
+       RF_FixOfs();\r
+       VW_InitDoubleBuffer();\r
+\r
+       Communication = uc_None;\r
+       USL_ClearFlags(&rootgroup);\r
+       USL_SetControlValues();\r
+       USL_SetupStack();\r
+       USL_SetupCard();\r
+\r
+       if (ingame)\r
+               GameIsDirty = true;\r
+\r
+       IN_ClearKeysDown();\r
+}\r
+\r
+static void\r
+USL_HandleComm(UComm comm)\r
+{\r
+       switch (comm)\r
+       {\r
+       case uc_Loaded:\r
+       case uc_Return:\r
+               break;\r
+       case uc_Abort:\r
+               abortgame = true;\r
+               break;\r
+       case uc_Quit:\r
+               QuitToDos = true;\r
+               break;\r
+       case uc_SEasy:\r
+               restartgame = gd_Easy;\r
+               break;\r
+       case uc_SNormal:\r
+               restartgame = gd_Normal;\r
+               break;\r
+       case uc_SHard:\r
+               restartgame = gd_Hard;\r
+               break;\r
+\r
+       default:\r
+               Quit("USL_HandleComm() - unknown");\r
+               break;\r
+       }\r
+}\r
+\r
+static void\r
+USL_GetControlValues(void)\r
+{\r
+       int     i;\r
+\r
+       // DEBUG - write the rest of this\r
+       i = USL_FindPushedItem(&soundgroup);\r
+       if (i == 3)\r
+       {\r
+               QuietFX = true;\r
+               i--;\r
+       }\r
+       else\r
+       {\r
+               QuietFX = false;\r
+       }\r
+       if (i != SoundMode)\r
+               SD_SetSoundMode(i);\r
+\r
+       i = USL_FindPushedItem(&musicgroup);\r
+       if (i != MusicMode)\r
+               SD_SetMusicMode(i);\r
+}\r
+\r
+///////////////////////////////////////////////////////////////////////////\r
+//\r
+//      USL_TearDownCtlPanel() - Given the state of the control panel, sets the\r
+//              modes and values as appropriate\r
+//\r
+///////////////////////////////////////////////////////////////////////////\r
+static void\r
+USL_TearDownCtlPanel(void)\r
+{\r
+       USL_GetControlValues();\r
+       if (Communication)\r
+               USL_HandleComm(Communication);\r
+\r
+       fontnumber = 0; // Normal font\r
+       fontcolor = F_BLACK;\r
+       if (restartgame && USL_ResetGame)\r
+               USL_ResetGame();\r
+       else if (QuitToDos)\r
+       {\r
+               if (tedlevel)\r
+                       TEDDeath();\r
+               else\r
+               {\r
+                       US_CenterWindow(20,3);\r
+                       fontcolor = F_SECONDCOLOR;\r
+                       US_PrintCentered("Quitting...");\r
+                       fontcolor = F_BLACK;\r
+                       VW_UpdateScreen();\r
+                       Quit(nil);\r
+               }\r
+       }\r
+\r
+       IN_ClearKeysDown();\r
+       SD_WaitSoundDone();\r
+#ifdef CAT3D\r
+       VW_Bar (0,0,320,200,3); // CAT3D patch\r
+#else\r
+       VW_ClearVideo(3);\r
+#endif\r
+       CA_DownLevel();\r
+       CA_LoadAllSounds();\r
+}\r
+\r
+///////////////////////////////////////////////////////////////////////////\r
+//\r
+//      US_ControlPanel() - This is the main routine for the control panel\r
+//\r
+///////////////////////////////////////////////////////////////////////////\r
+#define MoveMin 40\r
+void\r
+US_ControlPanel(void)\r
+{\r
+extern void HelpScreens(void);\r
+\r
+       boolean         resetitem,on;\r
+       word            i;\r
+       int                     ydelta;\r
+       longword        flashtime;\r
+       UserItem        far *item;\r
+       CursorInfo      cursorinfo;\r
+\r
+#if 0\r
+       // DEBUG!!!\r
+       {\r
+               USL_SetUpCtlPanel();\r
+               Communication = uc_Loaded;\r
+               CtlPanelDone = true;\r
+               loadedgame = true;\r
+               USL_TearDownCtlPanel();\r
+               return;\r
+       }\r
+#endif\r
+\r
+       if ((LastScan < sc_F1) || (LastScan > sc_F10))\r
+               IN_ClearKeysDown();\r
+\r
+       USL_SetUpCtlPanel();\r
+       USL_DrawCtlPanel();\r
+\r
+       ydelta = 0;\r
+       for (CtlPanelDone = false,resetitem = on = true;!CtlPanelDone;)\r
+       {\r
+               item = &(topcard->items[topcard->cursor]);\r
+\r
+               if (resetitem)\r
+               {\r
+                       flashtime = TimeCount + (TickBase / 2);\r
+                       resetitem = false;\r
+               }\r
+\r
+               if (TimeCount >= flashtime)\r
+               {\r
+                       on ^= true;\r
+                       resetitem = true;\r
+                       if (!on)\r
+                               item->flags &= ~ui_Selected;\r
+                       USL_DrawItemIcon(item);\r
+                       item->flags |= ui_Selected;\r
+               }\r
+\r
+               VW_UpdateScreen();\r
+\r
+               if (LastScan)\r
+               {\r
+                       switch (LastScan)\r
+                       {\r
+                       case sc_UpArrow:\r
+                               USL_PrevItem();\r
+                               resetitem = true;\r
+                               break;\r
+                       case sc_DownArrow:\r
+                               USL_NextItem();\r
+                               resetitem = true;\r
+                               break;\r
+                       case sc_Return:\r
+                               USL_DoItem();\r
+                               resetitem = true;\r
+                               break;\r
+                       case sc_Escape:\r
+                               USL_UpLevel();\r
+                               resetitem = true;\r
+                               break;\r
+#ifndef KEEN6\r
+                       case sc_F1:\r
+                               HelpScreens();\r
+                               USL_DrawCtlPanel();\r
+                               resetitem = true;\r
+                               break;\r
+#endif\r
+                       }\r
+\r
+                       if\r
+                       (\r
+                               (!resetitem)\r
+                       &&      (\r
+                                       (LastScan == KbdDefs[0].button0)\r
+                               ||      (LastScan == KbdDefs[0].button1)\r
+                               )\r
+                       )\r
+                       {\r
+                               USL_DoItem();\r
+                               resetitem = true;\r
+                       }\r
+\r
+                       if (!resetitem)\r
+                       {\r
+                               for (item = topcard->items,i = 0;item->type != uii_Bad;item++,i++)\r
+                               {\r
+                                       if (item->hotkey == LastScan)\r
+                                       {\r
+                                               USL_SelectItem(topcard,i,true);\r
+                                               resetitem = true;\r
+                                               break;\r
+                                       }\r
+                               }\r
+                       }\r
+\r
+                       IN_ClearKeysDown();\r
+               }\r
+               else\r
+               {\r
+                       IN_ReadCursor(&cursorinfo);\r
+                       ydelta += cursorinfo.y;\r
+                       if (cursorinfo.button0)\r
+                       {\r
+                               do\r
+                               {\r
+                                       IN_ReadCursor(&cursorinfo);\r
+                               } while (cursorinfo.button0);\r
+                               USL_DoItem();\r
+                               resetitem = true;\r
+                       }\r
+                       else if (cursorinfo.button1)\r
+                       {\r
+                               do\r
+                               {\r
+                                       IN_ReadCursor(&cursorinfo);\r
+                               } while (cursorinfo.button1);\r
+                               USL_UpLevel();\r
+                               resetitem = true;\r
+                       }\r
+                       else if (ydelta < -MoveMin)\r
+                       {\r
+                               ydelta += MoveMin;\r
+                               USL_PrevItem();\r
+                               resetitem = true;\r
+                       }\r
+                       else if (ydelta > MoveMin)\r
+                       {\r
+                               ydelta -= MoveMin;\r
+                               USL_NextItem();\r
+                               resetitem = true;\r
+                       }\r
+               }\r
+       }\r
+\r
+       USL_TearDownCtlPanel();\r
+}\r
+\r
+#ifdef KEEN6\r
+\r
+boolean US_ManualCheck(void)\r
+{\r
+       typedef struct {\r
+               char far *name;\r
+               int shapenum;\r
+               int x, y;\r
+       } creatureinfo;\r
+\r
+       static creatureinfo list[] = {\r
+               {"BIP",       BIPSHIPRSPR,        -2,  0},\r
+               {"BABOBBA",   BABOBBAR1SPR,        0,  0},\r
+               {"BLORB",     BLORB1SPR,          -2,  0},\r
+               {"GIK",       GIKWALKR1SPR,       -1,  0},\r
+               {"CEILICK",   CEILICK1SPR,         0,  0},\r
+               {"BLOOGLET",  RBLOOGLETWALKR1SPR, -2,  0},\r
+               {"BLOOGUARD", BLOOGUARDWALKL1SPR, -3, -1},\r
+               {"FLECT",     FLECTSTANDSPR,      -1,  0},\r
+               {"BOBBA",     BOBBAR1SPR,         -2,  0},\r
+               {"NOSPIKE",   NOSPIKESTANDSPR,    -2,  0},\r
+               {"ORBATRIX",  ORBATRIXR1SPR,      -2,  1},\r
+               {"FLEEX",     FLEEXWALKR1SPR,     -2,  0}\r
+       };\r
+\r
+       boolean correct;\r
+       char far *name;\r
+       char c;\r
+       char *ptr;\r
+       unsigned spriteheight, spritewidth;\r
+       int x, y;\r
+       int editwidth;\r
+       creatureinfo info;\r
+       char strbuf[16];\r
+\r
+       if (checkpassed)\r
+               return true;\r
+\r
+       correct = false;\r
+       if (listindex == -1)\r
+       {\r
+               _AH = 0x2C;     // get time\r
+               geninterrupt(0x21);\r
+               x = _CH;        // store hours\r
+               _AH = 0x2A;     // get date\r
+               geninterrupt(0x21);\r
+               y = _DL;        // store day\r
+\r
+               listindex = (x + y) % (int)(sizeof(list)/sizeof(creatureinfo));\r
+       }\r
+\r
+       CA_UpLevel();\r
+       info = list[listindex];\r
+       name = info.name;\r
+       CA_ClearMarks();\r
+       CA_MarkGrChunk(info.shapenum);\r
+       CA_CacheMarks(NULL);\r
+\r
+       VWB_Bar(0, 0, 320, 200, BackColor);\r
+       spritewidth = spritetable[info.shapenum - STARTSPRITES].width;\r
+       spriteheight = spritetable[info.shapenum - STARTSPRITES].height;\r
+       US_CenterWindow(30, (spriteheight+41)/8 + 1);\r
+       PrintY = WindowY + 2;\r
+       US_CPrint("What is the name of this creature?");\r
+\r
+       x = WindowX + (WindowW-spritewidth)/2 + info.x*8;\r
+       y = WindowY + 15;\r
+       if (info.shapenum == CEILICK1SPR)\r
+       {\r
+               y++;\r
+       }\r
+       else\r
+       {\r
+               y += info.y * 8;\r
+       }\r
+       VWB_DrawSprite(x, y, info.shapenum);\r
+\r
+       y = WindowY + WindowH - 16;\r
+       editwidth = 100;\r
+       x = WindowX + (WindowW - 100) / 2;\r
+       VWB_Bar(x, y, editwidth, 14, BLACK);\r
+       VWB_Bar(x+1, y+1, editwidth-2, 12, WHITE);\r
+       x += 2;\r
+       y += 2;\r
+       editwidth -= 8;\r
+       VW_UpdateScreen();\r
+\r
+       if (US_LineInput(x, y, strbuf, NULL, true, sizeof(strbuf), editwidth))\r
+       {\r
+               ptr = strbuf;\r
+               correct = true;\r
+               while (*name)\r
+               {\r
+                       c = *ptr;\r
+                       if ((islower(c)? _toupper(c) : c) != *name)\r
+                       {\r
+                               correct = false;\r
+                       }\r
+\r
+                       ptr++;\r
+                       name++;\r
+               }\r
+               if (*ptr)\r
+               {\r
+                       correct = false;\r
+               }\r
+\r
+               if (!correct)\r
+               {\r
+                       VWB_Bar(0, 0, 320, 200, BackColor);\r
+                       US_CenterWindow(35, 5);\r
+                       PrintY += 11;\r
+                       US_CPrint("Sorry, that's not quite right.");\r
+                       US_CPrint("Please check your manual and try again.");\r
+                       VW_UpdateScreen();\r
+                       IN_Ack();\r
+               }\r
+       }\r
+\r
+       VWB_Bar(0, 0, 320, 200, BackColor);\r
+       CA_DownLevel();\r
+       checkpassed = correct;\r
+       return correct;\r
+}\r
+\r
+#endif
\ No newline at end of file