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