+/* Catacomb Armageddon 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_1.c - User Manager - General routines\r
+// v1.1d1\r
+// By Jason Blochowiak\r
+// Hacked up for Catacomb 3D\r
+//\r
+\r
+//\r
+// This module handles dealing with user input & feedback\r
+//\r
+// Depends on: Input Mgr, View Mgr, some variables from the Sound, Caching,\r
+// and Refresh Mgrs, Memory Mgr for background save/restore\r
+//\r
+// Globals:\r
+// ingame - Flag set by game indicating if a game is in progress\r
+// abortgame - Flag set if the current game should be aborted (if a load\r
+// game fails)\r
+// loadedgame - Flag set if a game was loaded\r
+// abortprogram - Normally nil, this points to a terminal error message\r
+// if the program needs to abort\r
+// restartgame - Normally set to gd_Continue, this is set to one of the\r
+// difficulty levels if a new game should be started\r
+// PrintX, PrintY - Where the User Mgr will print (global coords)\r
+// WindowX,WindowY,WindowW,WindowH - The dimensions of the current\r
+// window\r
+//\r
+\r
+#include "ID_HEADS.H"\r
+\r
+#pragma hdrstop\r
+\r
+#pragma warn -pia\r
+\r
+\r
+// Special imports\r
+extern boolean showscorebox;\r
+#ifdef KEEN\r
+extern boolean oldshooting;\r
+extern ScanCode firescan;\r
+#else\r
+ ScanCode firescan;\r
+#endif\r
+\r
+// Global variables\r
+ char *abortprogram;\r
+ boolean NoWait,\r
+ HighScoresDirty;\r
+ word PrintX,PrintY;\r
+ word WindowX,WindowY,WindowW,WindowH;\r
+\r
+ word MaxX=320,MaxY=200; // MDM (GAMERS EDGE)\r
+\r
+// Internal variables\r
+#define ConfigVersion 1\r
+\r
+static char *ParmStrings[] = {"TEDLEVEL","NOWAIT"},\r
+ *ParmStrings2[] = {"COMP","NOCOMP"};\r
+static boolean US_Started;\r
+\r
+ boolean Button0,Button1,\r
+ CursorBad;\r
+ int CursorX,CursorY;\r
+\r
+ void (*USL_MeasureString)(char far *,word *,word *) = VW_MeasurePropString,\r
+ (*USL_DrawString)(char far *) = VWB_DrawPropString;\r
+\r
+ boolean (*USL_SaveGame)(int),(*USL_LoadGame)(int);\r
+ void (*USL_ResetGame)(void);\r
+ SaveGame Games[MaxSaveGames];\r
+ HighScore Scores[MaxScores] =\r
+ {\r
+ {"Sir Lancelot",500,3},\r
+ {"",0},\r
+ {"",0},\r
+ {"",0},\r
+ {"",0},\r
+ {"",0},\r
+ {"",0},\r
+ };\r
+\r
+// Internal routines\r
+\r
+// Public routines\r
+\r
+///////////////////////////////////////////////////////////////////////////\r
+//\r
+// USL_HardError() - Handles the Abort/Retry/Fail sort of errors passed\r
+// from DOS.\r
+//\r
+///////////////////////////////////////////////////////////////////////////\r
+#pragma warn -par\r
+#pragma warn -rch\r
+int\r
+USL_HardError(word errval,int ax,int bp,int si)\r
+{\r
+#define IGNORE 0\r
+#define RETRY 1\r
+#define ABORT 2\r
+extern void ShutdownId(void);\r
+\r
+static char buf[32];\r
+static WindowRec wr;\r
+ int di;\r
+ char c,*s,*t;\r
+\r
+\r
+ di = _DI;\r
+\r
+ if (ax < 0)\r
+ s = "Device Error";\r
+ else\r
+ {\r
+ if ((di & 0x00ff) == 0)\r
+ s = "Drive ~ is Write Protected";\r
+ else\r
+ s = "Error on Drive ~";\r
+ for (t = buf;*s;s++,t++) // Can't use sprintf()\r
+ if ((*t = *s) == '~')\r
+ *t = (ax & 0x00ff) + 'A';\r
+ *t = '\0';\r
+ s = buf;\r
+ }\r
+\r
+ c = peekb(0x40,0x49); // Get the current screen mode\r
+ if ((c < 4) || (c == 7))\r
+ goto oh_kill_me;\r
+\r
+ // DEBUG - handle screen cleanup\r
+\r
+ US_SaveWindow(&wr);\r
+ US_CenterWindow(30,3);\r
+ US_CPrint(s);\r
+ US_CPrint("(R)etry or (A)bort?");\r
+ VW_UpdateScreen();\r
+ IN_ClearKeysDown();\r
+\r
+asm sti // Let the keyboard interrupts come through\r
+\r
+ while (true)\r
+ {\r
+ switch (IN_WaitForASCII())\r
+ {\r
+ case key_Escape:\r
+ case 'a':\r
+ case 'A':\r
+ goto oh_kill_me;\r
+ break;\r
+ case key_Return:\r
+ case key_Space:\r
+ case 'r':\r
+ case 'R':\r
+ US_ClearWindow();\r
+ VW_UpdateScreen();\r
+ US_RestoreWindow(&wr);\r
+ return(RETRY);\r
+ break;\r
+ }\r
+ }\r
+\r
+oh_kill_me:\r
+ abortprogram = s;\r
+ ShutdownId();\r
+ fprintf(stderr,"Terminal Error: %s\n",s);\r
+ if (tedlevel)\r
+ fprintf(stderr,"You launched from TED. I suggest that you reboot...\n");\r
+\r
+ return(ABORT);\r
+#undef IGNORE\r
+#undef RETRY\r
+#undef ABORT\r
+}\r
+#pragma warn +par\r
+#pragma warn +rch\r
+\r
+///////////////////////////////////////////////////////////////////////////\r
+//\r
+// USL_GiveSaveName() - Returns a pointer to a static buffer that contains\r
+// the filename to use for the specified save game\r
+//\r
+///////////////////////////////////////////////////////////////////////////\r
+char *\r
+USL_GiveSaveName(word game)\r
+{\r
+static char name[] = "SAVEGAMx."EXT;\r
+\r
+ name[7] = '0' + game;\r
+ return(name);\r
+}\r
+\r
+///////////////////////////////////////////////////////////////////////////\r
+//\r
+// US_SetLoadSaveHooks() - Sets the routines that the User Mgr calls after\r
+// reading or writing the save game headers\r
+//\r
+///////////////////////////////////////////////////////////////////////////\r
+void\r
+US_SetLoadSaveHooks(boolean (*load)(int),boolean (*save)(int),void (*reset)(void))\r
+{\r
+ USL_LoadGame = load;\r
+ USL_SaveGame = save;\r
+ USL_ResetGame = reset;\r
+}\r
+\r
+///////////////////////////////////////////////////////////////////////////\r
+//\r
+// USL_ReadConfig() - Reads the configuration file, if present, and sets\r
+// things up accordingly. If it's not present, uses defaults. This file\r
+// includes the high scores.\r
+//\r
+///////////////////////////////////////////////////////////////////////////\r
+static void\r
+USL_ReadConfig(void)\r
+{\r
+ boolean gotit;\r
+ char sig[sizeof(EXT)];\r
+ word version;\r
+ int file;\r
+ SDMode sd;\r
+ SMMode sm;\r
+ ControlType ctl;\r
+\r
+ if ((file = open("CONFIG."EXT,O_BINARY | O_RDONLY)) != -1)\r
+ {\r
+ read(file,sig,sizeof(EXT));\r
+ read(file,&version,sizeof(version));\r
+ if (strcmp(sig,EXT) || (version != ConfigVersion))\r
+ {\r
+ close(file);\r
+ goto rcfailed;\r
+ }\r
+ read(file,Scores,sizeof(HighScore) * MaxScores);\r
+ read(file,&sd,sizeof(sd));\r
+ read(file,&sm,sizeof(sm));\r
+ read(file,&ctl,sizeof(ctl));\r
+ read(file,&(KbdDefs[0]),sizeof(KbdDefs[0]));\r
+ read(file,&showscorebox,sizeof(showscorebox));\r
+ read(file,&compatability,sizeof(compatability));\r
+#ifdef KEEN\r
+ read(file,&oldshooting,sizeof(oldshooting));\r
+ read(file,&firescan,sizeof(firescan));\r
+#endif\r
+ close(file);\r
+\r
+ HighScoresDirty = false;\r
+ gotit = true;\r
+ }\r
+ else\r
+ {\r
+rcfailed:\r
+ sd = sdm_Off;\r
+ sm = smm_Off;\r
+ ctl = ctrl_Keyboard;\r
+ showscorebox = true;\r
+#ifdef KEEN\r
+ oldshooting = false;\r
+#endif\r
+\r
+ gotit = false;\r
+ HighScoresDirty = true;\r
+ }\r
+\r
+ SD_Default(gotit,sd,sm);\r
+ IN_Default(gotit,ctl);\r
+}\r
+\r
+///////////////////////////////////////////////////////////////////////////\r
+//\r
+// USL_WriteConfig() - Writes out the current configuration, including the\r
+// high scores.\r
+//\r
+///////////////////////////////////////////////////////////////////////////\r
+static void\r
+USL_WriteConfig(void)\r
+{\r
+ word version;\r
+ int file;\r
+\r
+ version = ConfigVersion;\r
+ file = open("CONFIG."EXT,O_CREAT | O_BINARY | O_WRONLY,\r
+ S_IREAD | S_IWRITE | S_IFREG);\r
+ if (file != -1)\r
+ {\r
+ write(file,EXT,sizeof(EXT));\r
+ write(file,&version,sizeof(version));\r
+ write(file,Scores,sizeof(HighScore) * MaxScores);\r
+ write(file,&SoundMode,sizeof(SoundMode));\r
+ write(file,&MusicMode,sizeof(MusicMode));\r
+ if // Hack\r
+ (\r
+ (Controls[0] == ctrl_Joystick1)\r
+ || (Controls[0] == ctrl_Joystick2)\r
+ )\r
+ Controls[0] = ctrl_Keyboard;\r
+ write(file,&(Controls[0]),sizeof(Controls[0]));\r
+ write(file,&(KbdDefs[0]),sizeof(KbdDefs[0]));\r
+ write(file,&showscorebox,sizeof(showscorebox));\r
+ write(file,&compatability,sizeof(compatability));\r
+#ifdef KEEN\r
+ write(file,&oldshooting,sizeof(oldshooting));\r
+ write(file,&firescan,sizeof(firescan));\r
+#endif\r
+ close(file);\r
+ }\r
+}\r
+\r
+///////////////////////////////////////////////////////////////////////////\r
+//\r
+// USL_CheckSavedGames() - Checks to see which saved games are present\r
+// & valid\r
+//\r
+///////////////////////////////////////////////////////////////////////////\r
+static void\r
+USL_CheckSavedGames(void)\r
+{\r
+ boolean ok;\r
+ char *filename;\r
+ word i;\r
+ int file;\r
+ SaveGame *game;\r
+\r
+ USL_SaveGame = 0;\r
+ USL_LoadGame = 0;\r
+\r
+ for (i = 0,game = Games;i < MaxSaveGames;i++,game++)\r
+ {\r
+ filename = USL_GiveSaveName(i);\r
+ ok = false;\r
+ if ((file = open(filename,O_BINARY | O_RDONLY)) != -1)\r
+ {\r
+ if\r
+ (\r
+ (read(file,game,sizeof(*game)) == sizeof(*game))\r
+ && (!strcmp(game->signature,EXT))\r
+ && (game->oldtest == &PrintX)\r
+ )\r
+ ok = true;\r
+\r
+ close(file);\r
+ }\r
+\r
+ if (ok)\r
+ game->present = true;\r
+ else\r
+ {\r
+ strcpy(game->signature,EXT);\r
+ game->present = false;\r
+ strcpy(game->name,"Empty");\r
+ }\r
+ }\r
+}\r
+\r
+///////////////////////////////////////////////////////////////////////////\r
+//\r
+// US_Startup() - Starts the User Mgr\r
+//\r
+///////////////////////////////////////////////////////////////////////////\r
+void\r
+US_Startup(void)\r
+{\r
+ int i;\r
+\r
+ if (US_Started)\r
+ return;\r
+\r
+ harderr(USL_HardError); // Install the fatal error handler\r
+\r
+ US_InitRndT(true); // Initialize the random number generator\r
+\r
+ USL_ReadConfig(); // Read config file\r
+\r
+ for (i = 1;i < _argc;i++)\r
+ {\r
+ switch (US_CheckParm(_argv[i],ParmStrings2))\r
+ {\r
+ case 0:\r
+ if (grmode == EGAGR)\r
+ compatability = true;\r
+ break;\r
+ case 1:\r
+ compatability = false;\r
+ break;\r
+ }\r
+ }\r
+\r
+ US_Started = true;\r
+}\r
+\r
+///////////////////////////////////////////////////////////////////////////\r
+//\r
+// US_Setup() - Does the disk access part of the User Mgr's startup\r
+//\r
+///////////////////////////////////////////////////////////////////////////\r
+void\r
+US_Setup(void)\r
+{\r
+ USL_CheckSavedGames(); // Check which saved games are present\r
+}\r
+\r
+///////////////////////////////////////////////////////////////////////////\r
+//\r
+// US_Shutdown() - Shuts down the User Mgr\r
+//\r
+///////////////////////////////////////////////////////////////////////////\r
+void\r
+US_Shutdown(void)\r
+{\r
+ if (!US_Started)\r
+ return;\r
+\r
+ if (!abortprogram)\r
+ USL_WriteConfig();\r
+\r
+ US_Started = false;\r
+}\r
+\r
+///////////////////////////////////////////////////////////////////////////\r
+//\r
+// US_CheckParm() - checks to see if a string matches one of a set of\r
+// strings. The check is case insensitive. The routine returns the\r
+// index of the string that matched, or -1 if no matches were found\r
+//\r
+///////////////////////////////////////////////////////////////////////////\r
+int\r
+US_CheckParm(char *parm,char **strings)\r
+{\r
+ char cp,cs,\r
+ *p,*s;\r
+ int i;\r
+\r
+ while (!isalpha(*parm)) // Skip non-alphas\r
+ parm++;\r
+\r
+ for (i = 0;*strings && **strings;i++)\r
+ {\r
+ for (s = *strings++,p = parm,cs = cp = 0;cs == cp;)\r
+ {\r
+ cs = *s++;\r
+ if (!cs)\r
+ return(i);\r
+ cp = *p++;\r
+\r
+ if (isupper(cs))\r
+ cs = tolower(cs);\r
+ if (isupper(cp))\r
+ cp = tolower(cp);\r
+ }\r
+ }\r
+ return(-1);\r
+}\r
+\r
+#if 0\r
+///////////////////////////////////////////////////////////////////////////\r
+//\r
+// USL_ScreenDraw() - Draws a chunk of the text screen (called only by\r
+// US_TextScreen())\r
+//\r
+///////////////////////////////////////////////////////////////////////////\r
+static void\r
+USL_ScreenDraw(word x,word y,char *s,byte attr)\r
+{\r
+ byte far *screen,far *oscreen;\r
+\r
+ screen = MK_FP(0xb800,(x * 2) + (y * 80 * 2));\r
+ oscreen = (&introscn + 7) + ((x - 1) * 2) + (y * 80 * 2) + 1;\r
+ while (*s)\r
+ {\r
+ *screen++ = *s++;\r
+ if (attr != 0xff)\r
+ {\r
+ *screen++ = (attr & 0x8f) | (*oscreen & 0x70);\r
+ oscreen += 2;\r
+ }\r
+ else\r
+ screen++;\r
+ }\r
+}\r
+#endif\r
+\r
+///////////////////////////////////////////////////////////////////////////\r
+//\r
+// USL_ClearTextScreen() - Makes sure the screen is in text mode, clears it,\r
+// and moves the cursor to the leftmost column of the bottom line\r
+//\r
+///////////////////////////////////////////////////////////////////////////\r
+static void\r
+USL_ClearTextScreen(void)\r
+{\r
+ // Set to 80x25 color text mode\r
+ _AL = 3; // Mode 3\r
+ _AH = 0x00;\r
+ geninterrupt(0x10);\r
+\r
+ // Use BIOS to move the cursor to the bottom of the screen\r
+ _AH = 0x0f;\r
+ geninterrupt(0x10); // Get current video mode into _BH\r
+ _DL = 0; // Lefthand side of the screen\r
+ _DH = 24; // Bottom row\r
+ _AH = 0x02;\r
+ geninterrupt(0x10);\r
+}\r
+\r
+#if 0\r
+///////////////////////////////////////////////////////////////////////////\r
+//\r
+// US_TextScreen() - Puts up the startup text screen\r
+// Note: These are the only User Manager functions that can be safely called\r
+// before the User Mgr has been started up\r
+//\r
+///////////////////////////////////////////////////////////////////////////\r
+void\r
+US_TextScreen(void)\r
+{\r
+ word i,n;\r
+\r
+ USL_ClearTextScreen();\r
+\r
+ _fmemcpy(MK_FP(0xb800,0),7 + &introscn,80 * 25 * 2);\r
+\r
+ // Check for TED launching here\r
+ for (i = 1;i < _argc;i++)\r
+ {\r
+ n = US_CheckParm(_argv[i],ParmStrings);\r
+ if (n == 0)\r
+ {\r
+ tedlevelnum = atoi(_argv[i + 1]);\r
+ if (tedlevelnum >= 0)\r
+ {\r
+ tedlevel = true;\r
+ return;\r
+ }\r
+ else\r
+ break;\r
+ }\r
+ else if (n == 1)\r
+ {\r
+ NoWait = true;\r
+ return;\r
+ }\r
+ }\r
+}\r
+\r
+///////////////////////////////////////////////////////////////////////////\r
+//\r
+// USL_Show() - Changes the appearance of one of the fields on the text\r
+// screen. Possibly adds a checkmark in front of it and highlights it\r
+//\r
+///////////////////////////////////////////////////////////////////////////\r
+static void\r
+USL_Show(word x,word y,word w,boolean show,boolean hilight)\r
+{\r
+ byte far *screen,far *oscreen;\r
+\r
+ screen = MK_FP(0xb800,((x - 1) * 2) + (y * 80 * 2));\r
+ oscreen = (&introscn + 7) + ((x - 1) * 2) + (y * 80 * 2) - 1;\r
+ *screen++ = show? 251 : ' '; // Checkmark char or space\r
+// *screen = 0x48;\r
+// *screen = (*oscreen & 0xf0) | 8;\r
+ oscreen += 2;\r
+ if (show && hilight)\r
+ {\r
+ for (w++;w--;screen += 2,oscreen += 2)\r
+ *screen = (*oscreen & 0xf0) | 0x0f;\r
+ }\r
+}\r
+\r
+///////////////////////////////////////////////////////////////////////////\r
+//\r
+// USL_ShowMem() - Right justifies a longword in one of the memory fields on\r
+// the text screen\r
+//\r
+///////////////////////////////////////////////////////////////////////////\r
+static void\r
+USL_ShowMem(word x,word y,long mem)\r
+{\r
+ char buf[16];\r
+ word i;\r
+\r
+ for (i = strlen(ltoa(mem,buf,10));i < 5;i++)\r
+ USL_ScreenDraw(x++,y," ",0xff);\r
+ USL_ScreenDraw(x,y,buf,0xff);\r
+}\r
+\r
+///////////////////////////////////////////////////////////////////////////\r
+//\r
+// US_UpdateTextScreen() - Called after the ID libraries are started up.\r
+// Displays what hardware is present.\r
+//\r
+///////////////////////////////////////////////////////////////////////////\r
+void\r
+US_UpdateTextScreen(void)\r
+{\r
+ boolean b;\r
+ longword totalmem;\r
+\r
+ // Show video card info\r
+ b = (grmode == CGAGR);\r
+ USL_Show(21,7,4,(videocard >= CGAcard) && (videocard <= VGAcard),b);\r
+ b = (grmode == EGAGR);\r
+ USL_Show(21,8,4,(videocard >= EGAcard) && (videocard <= VGAcard),b);\r
+ b = (grmode == VGAGR);\r
+ USL_Show(21,9,4,videocard == VGAcard,b);\r
+ if (compatability)\r
+ USL_ScreenDraw(5,10,"SVGA Compatibility Mode Enabled.",0x4f);\r
+\r
+ // Show input device info\r
+ USL_Show(60,7,8,true,true);\r
+ USL_Show(60,8,11,JoysPresent[0],true);\r
+ USL_Show(60,9,11,JoysPresent[1],true);\r
+ USL_Show(60,10,5,MousePresent,true);\r
+\r
+ // Show sound hardware info\r
+ USL_Show(21,14,11,true,SoundMode == sdm_PC);\r
+ b = (SoundMode == sdm_AdLib) || (MusicMode == smm_AdLib);\r
+ USL_Show(21,15,14,AdLibPresent,b);\r
+ if (b && AdLibPresent) // Hack because of two lines\r
+ {\r
+ byte far *screen,far *oscreen;\r
+ word x,y,w;\r
+\r
+ x = 21;\r
+ y = 16;\r
+ w = 14;\r
+ screen = MK_FP(0xb800,(x * 2) + (y * 80 * 2) - 1);\r
+ oscreen = (&introscn + 7) + (x * 2) + (y * 80 * 2) - 1;\r
+ oscreen += 2;\r
+ for (w++;w--;screen += 2,oscreen += 2)\r
+ *screen = (*oscreen & 0xf0) | 0x0f;\r
+ }\r
+\r
+ // Show memory available/used\r
+ USL_ShowMem(63,15,mminfo.mainmem / 1024);\r
+ USL_Show(53,15,23,true,true);\r
+ USL_ShowMem(63,16,mminfo.EMSmem / 1024);\r
+ USL_Show(53,16,23,mminfo.EMSmem? true : false,true);\r
+ USL_ShowMem(63,17,mminfo.XMSmem / 1024);\r
+ USL_Show(53,17,23,mminfo.XMSmem? true : false,true);\r
+ totalmem = mminfo.mainmem + mminfo.EMSmem + mminfo.XMSmem;\r
+ USL_ShowMem(63,18,totalmem / 1024);\r
+ USL_Show(53,18,23,true,true); // DEBUG\r
+ USL_ScreenDraw(52,18," ",0xff);\r
+\r
+ // Change Initializing... to Loading...\r
+ USL_ScreenDraw(27,22," Loading... ",0x9c);\r
+}\r
+\r
+///////////////////////////////////////////////////////////////////////////\r
+//\r
+// US_FinishTextScreen() - After the main program has finished its initial\r
+// loading, this routine waits for a keypress and then clears the screen\r
+//\r
+///////////////////////////////////////////////////////////////////////////\r
+void\r
+US_FinishTextScreen(void)\r
+{\r
+static byte colors[] = {4,6,13,15,15,15,15,15,15};\r
+ boolean up;\r
+ int i,c;\r
+\r
+ // Change Loading... to Press a Key\r
+\r
+ if (!(tedlevel || NoWait))\r
+ {\r
+ IN_ClearKeysDown();\r
+ for (i = 0,up = true;!IN_UserInput(4,true);)\r
+ {\r
+ c = colors[i];\r
+ if (up)\r
+ {\r
+ if (++i == 9)\r
+ i = 8,up = false;\r
+ }\r
+ else\r
+ {\r
+ if (--i < 0)\r
+ i = 1,up = true;\r
+ }\r
+\r
+ USL_ScreenDraw(29,22," Ready - Press a Key ",0x00 + c);\r
+ }\r
+ }\r
+ else\r
+ USL_ScreenDraw(29,22," Ready - Press a Key ",0x9a);\r
+ IN_ClearKeysDown();\r
+\r
+ USL_ClearTextScreen();\r
+}\r
+#endif\r
+\r
+// Window/Printing routines\r
+\r
+///////////////////////////////////////////////////////////////////////////\r
+//\r
+// US_SetPrintRoutines() - Sets the routines used to measure and print\r
+// from within the User Mgr. Primarily provided to allow switching\r
+// between masked and non-masked fonts\r
+//\r
+///////////////////////////////////////////////////////////////////////////\r
+void\r
+US_SetPrintRoutines(void (*measure)(char far *,word *,word *),void (*print)(char far *))\r
+{\r
+ USL_MeasureString = measure;\r
+ USL_DrawString = print;\r
+}\r
+\r
+///////////////////////////////////////////////////////////////////////////\r
+//\r
+// US_Print() - Prints a string in the current window. Newlines are\r
+// supported.\r
+//\r
+///////////////////////////////////////////////////////////////////////////\r
+void\r
+US_Print(char *s)\r
+{\r
+ char c,*se;\r
+ word w,h;\r
+\r
+ while (*s)\r
+ {\r
+ se = s;\r
+ while ((c = *se) && (c != '\n'))\r
+ se++;\r
+ *se = '\0';\r
+\r
+ USL_MeasureString(s,&w,&h);\r
+ px = PrintX;\r
+ py = PrintY;\r
+ USL_DrawString(s);\r
+\r
+ s = se;\r
+ if (c)\r
+ {\r
+ *se = c;\r
+ s++;\r
+\r
+ PrintX = WindowX;\r
+ PrintY += h;\r
+ }\r
+ else\r
+ PrintX += w;\r
+ }\r
+}\r
+\r
+// MDM - (GAMERS EDGE) begin\r
+\r
+///////////////////////////////////////////////////////////////////////////\r
+//\r
+// US_Printxy()\r
+//\r
+void US_Printxy(word x, word y, char *text)\r
+{\r
+ word orgx, orgy;\r
+\r
+ orgx = PrintX;\r
+ orgy = PrintY;\r
+\r
+// PrintX = WindowX+x;\r
+// PrintY = WindowY+y;\r
+ PrintX = x;\r
+ PrintY = y;\r
+ US_Print(text);\r
+\r
+ PrintX = orgx;\r
+ PrintY = orgy;\r
+}\r
+\r
+// MDM - (GAMERS EDGE) end\r
+\r
+///////////////////////////////////////////////////////////////////////////\r
+//\r
+// US_PrintUnsigned() - Prints an unsigned long\r
+//\r
+///////////////////////////////////////////////////////////////////////////\r
+void\r
+US_PrintUnsigned(longword n)\r
+{\r
+ char buffer[32];\r
+\r
+ US_Print(ultoa(n,buffer,10));\r
+}\r
+\r
+///////////////////////////////////////////////////////////////////////////\r
+//\r
+// US_PrintSigned() - Prints a signed long\r
+//\r
+///////////////////////////////////////////////////////////////////////////\r
+void\r
+US_PrintSigned(long n)\r
+{\r
+ char buffer[32];\r
+\r
+ US_Print(ltoa(n,buffer,10));\r
+}\r
+\r
+///////////////////////////////////////////////////////////////////////////\r
+//\r
+// USL_PrintInCenter() - Prints a string in the center of the given rect\r
+//\r
+///////////////////////////////////////////////////////////////////////////\r
+void\r
+USL_PrintInCenter(char *s,Rect r)\r
+{\r
+ word w,h,\r
+ rw,rh;\r
+\r
+ USL_MeasureString(s,&w,&h);\r
+ rw = r.lr.x - r.ul.x;\r
+ rh = r.lr.y - r.ul.y;\r
+\r
+ px = r.ul.x + ((rw - w) / 2);\r
+ py = r.ul.y + ((rh - h) / 2);\r
+ USL_DrawString(s);\r
+}\r
+\r
+///////////////////////////////////////////////////////////////////////////\r
+//\r
+// US_PrintCentered() - Prints a string centered in the current window.\r
+//\r
+///////////////////////////////////////////////////////////////////////////\r
+void\r
+US_PrintCentered(char *s)\r
+{\r
+ Rect r;\r
+\r
+ r.ul.x = WindowX;\r
+ r.ul.y = WindowY;\r
+ r.lr.x = r.ul.x + WindowW;\r
+ r.lr.y = r.ul.y + WindowH;\r
+\r
+ USL_PrintInCenter(s,r);\r
+}\r
+\r
+///////////////////////////////////////////////////////////////////////////\r
+//\r
+// US_CPrintLine() - Prints a string centered on the current line and\r
+// advances to the next line. Newlines are not supported.\r
+//\r
+///////////////////////////////////////////////////////////////////////////\r
+void\r
+US_CPrintLine(char *s)\r
+{\r
+ word w,h;\r
+\r
+ USL_MeasureString(s,&w,&h);\r
+\r
+ if (w > WindowW)\r
+ Quit("US_CPrintLine() - String exceeds width");\r
+ px = WindowX + ((WindowW - w) / 2);\r
+ py = PrintY;\r
+ USL_DrawString(s);\r
+ PrintY += h;\r
+}\r
+\r
+///////////////////////////////////////////////////////////////////////////\r
+//\r
+// US_CPrint() - Prints a string in the current window. Newlines are\r
+// supported.\r
+//\r
+///////////////////////////////////////////////////////////////////////////\r
+void\r
+US_CPrint(char *s)\r
+{\r
+ char c,*se;\r
+\r
+ while (*s)\r
+ {\r
+ se = s;\r
+ while ((c = *se) && (c != '\n'))\r
+ se++;\r
+ *se = '\0';\r
+\r
+ US_CPrintLine(s);\r
+\r
+ s = se;\r
+ if (c)\r
+ {\r
+ *se = c;\r
+ s++;\r
+ }\r
+ }\r
+}\r
+\r
+///////////////////////////////////////////////////////////////////////////\r
+//\r
+// US_ClearWindow() - Clears the current window to white and homes the\r
+// cursor\r
+//\r
+///////////////////////////////////////////////////////////////////////////\r
+void\r
+US_ClearWindow(void)\r
+{\r
+ VWB_Bar(WindowX,WindowY,WindowW,WindowH,LT_GREY);\r
+ PrintX = WindowX;\r
+ PrintY = WindowY;\r
+}\r
+\r
+///////////////////////////////////////////////////////////////////////////\r
+//\r
+// US_DrawWindow() - Draws a frame and sets the current window parms\r
+//\r
+///////////////////////////////////////////////////////////////////////////\r
+void\r
+US_DrawWindow(word x,word y,word w,word h)\r
+{\r
+ word i,\r
+ sx,sy,sw,sh;\r
+\r
+ WindowX = x * 8;\r
+ WindowY = y * 8;\r
+ WindowW = w * 8;\r
+ WindowH = h * 8;\r
+\r
+ PrintX = WindowX;\r
+ PrintY = WindowY;\r
+\r
+ sx = (x - 1) * 8;\r
+ sy = (y - 1) * 8;\r
+ sw = (w + 1) * 8;\r
+ sh = (h + 1) * 8;\r
+\r
+ US_ClearWindow();\r
+\r
+ VWB_DrawTile8M(sx,sy,0),VWB_DrawTile8M(sx,sy + sh,6);\r
+ for (i = sx + 8;i <= sx + sw - 8;i += 8)\r
+ VWB_DrawTile8M(i,sy,1),VWB_DrawTile8M(i,sy + sh,7);\r
+ VWB_DrawTile8M(i,sy,2),VWB_DrawTile8M(i,sy + sh,8);\r
+\r
+ for (i = sy + 8;i <= sy + sh - 8;i += 8)\r
+ VWB_DrawTile8M(sx,i,3),VWB_DrawTile8M(sx + sw,i,5);\r
+}\r
+\r
+///////////////////////////////////////////////////////////////////////////\r
+//\r
+// US_CenterWindow() - Generates a window of a given width & height in the\r
+// middle of the screen\r
+//\r
+///////////////////////////////////////////////////////////////////////////\r
+void\r
+US_CenterWindow(word w,word h)\r
+{\r
+ US_DrawWindow(((MaxX / 8) - w) / 2,((MaxY / 8) - h) / 2,w,h);\r
+}\r
+\r
+///////////////////////////////////////////////////////////////////////////\r
+//\r
+// US_CenterSaveWindow() - Generates a window of a given width & height in\r
+// the middle of the screen, saving the background\r
+//\r
+///////////////////////////////////////////////////////////////////////////\r
+void\r
+US_CenterSaveWindow(word w,word h,memptr *save)\r
+{\r
+ word x,y,\r
+ screen;\r
+\r
+ x = ((MaxX / 8) - w) / 2;\r
+ y = ((MaxY / 8) - h) / 2;\r
+ MM_GetPtr(save,(w * h) * CHARWIDTH);\r
+ screen = bufferofs + panadjust + ylookup[y] + (x * CHARWIDTH);\r
+ VW_ScreenToMem(screen,*save,w * CHARWIDTH,h);\r
+ US_DrawWindow(((MaxX / 8) - w) / 2,((MaxY / 8) - h) / 2,w,h);\r
+}\r
+\r
+///////////////////////////////////////////////////////////////////////////\r
+//\r
+// US_RestoreSaveWindow() - Restores the background of the size of the\r
+// current window from the memory specified by save\r
+//\r
+///////////////////////////////////////////////////////////////////////////\r
+void\r
+US_RestoreSaveWindow(memptr *save)\r
+{\r
+ word screen;\r
+\r
+ screen = bufferofs + panadjust + ylookup[WindowY] + (WindowX * CHARWIDTH);\r
+ VW_MemToScreen(*save,screen,WindowW * CHARWIDTH,WindowH);\r
+ MM_FreePtr(save);\r
+}\r
+\r
+///////////////////////////////////////////////////////////////////////////\r
+//\r
+// US_SaveWindow() - Saves the current window parms into a record for\r
+// later restoration\r
+//\r
+///////////////////////////////////////////////////////////////////////////\r
+void\r
+US_SaveWindow(WindowRec *win)\r
+{\r
+ win->x = WindowX;\r
+ win->y = WindowY;\r
+ win->w = WindowW;\r
+ win->h = WindowH;\r
+\r
+ win->px = PrintX;\r
+ win->py = PrintY;\r
+}\r
+\r
+///////////////////////////////////////////////////////////////////////////\r
+//\r
+// US_RestoreWindow() - Sets the current window parms to those held in the\r
+// record\r
+//\r
+///////////////////////////////////////////////////////////////////////////\r
+void\r
+US_RestoreWindow(WindowRec *win)\r
+{\r
+ WindowX = win->x;\r
+ WindowY = win->y;\r
+ WindowW = win->w;\r
+ WindowH = win->h;\r
+\r
+ PrintX = win->px;\r
+ PrintY = win->py;\r
+}\r
+\r
+// Cursor routines\r
+\r
+#if 0\r
+///////////////////////////////////////////////////////////////////////////\r
+//\r
+// US_StartCursor() - Sets up the cursor for User Mgr use\r
+//\r
+///////////////////////////////////////////////////////////////////////////\r
+void\r
+US_StartCursor(void)\r
+{\r
+ CursorInfo info;\r
+\r
+ VW_SetCursor(CURSORARROWSPR);\r
+ CursorX = MaxX / 2;\r
+ CursorY = MaxY / 2;\r
+ VW_MoveCursor(CursorX,CursorY);\r
+ VW_ShowCursor();\r
+\r
+ IN_ReadCursor(&info); // Dispose of any accumulated movement\r
+}\r
+\r
+///////////////////////////////////////////////////////////////////////////\r
+//\r
+// US_ShutCursor() - Cleans up after US_StartCursor()\r
+//\r
+///////////////////////////////////////////////////////////////////////////\r
+void\r
+US_ShutCursor(void)\r
+{\r
+ VW_HideCursor();\r
+}\r
+\r
+///////////////////////////////////////////////////////////////////////////\r
+//\r
+// US_UpdateCursor() - Gets the new cursor position & button states from\r
+// the Input Mgr and tells the View Mgr where the cursor is\r
+//\r
+///////////////////////////////////////////////////////////////////////////\r
+boolean\r
+US_UpdateCursor(void)\r
+{\r
+ CursorInfo info;\r
+\r
+ IN_ReadCursor(&info);\r
+ if (info.x || info.y || CursorBad)\r
+ {\r
+ CursorX += info.x;\r
+ if (CursorX >= MaxX)\r
+ CursorX = MaxX - 1;\r
+ else if (CursorX < 0)\r
+ CursorX = 0;\r
+\r
+ CursorY += info.y;\r
+ if (CursorY >= MaxY)\r
+ CursorY = MaxY - 1;\r
+ else if (CursorY < 0)\r
+ CursorY = 0;\r
+\r
+ VW_MoveCursor(CursorX,CursorY);\r
+ CursorBad = false;\r
+ }\r
+ Button0 = info.button0;\r
+ Button1 = info.button1;\r
+ return(Button0 || Button1);\r
+}\r
+#endif\r
+\r
+// Input routines\r
+\r
+///////////////////////////////////////////////////////////////////////////\r
+//\r
+// USL_XORICursor() - XORs the I-bar text cursor. Used by US_LineInput()\r
+//\r
+///////////////////////////////////////////////////////////////////////////\r
+static void\r
+USL_XORICursor(int x,int y,char *s,word cursor)\r
+{\r
+ char buf[MaxString];\r
+ word w,h;\r
+\r
+ strcpy(buf,s);\r
+ buf[cursor] = '\0';\r
+ USL_MeasureString(buf,&w,&h);\r
+\r
+ px = x + w - 1;\r
+ py = y;\r
+ USL_DrawString("\x80");\r
+}\r
+\r
+///////////////////////////////////////////////////////////////////////////\r
+//\r
+// US_LineInput() - Gets a line of user input at (x,y), the string defaults\r
+// to whatever is pointed at by def. Input is restricted to maxchars\r
+// chars or maxwidth pixels wide. If the user hits escape (and escok is\r
+// true), nothing is copied into buf, and false is returned. If the\r
+// user hits return, the current string is copied into buf, and true is\r
+// returned\r
+//\r
+///////////////////////////////////////////////////////////////////////////\r
+boolean\r
+US_LineInput(int x,int y,char *buf,char *def,boolean escok,\r
+ int maxchars,int maxwidth)\r
+{\r
+ boolean redraw,\r
+ cursorvis,cursormoved,\r
+ done,result;\r
+ ScanCode sc;\r
+ char c,\r
+ s[MaxString],olds[MaxString];\r
+ word i,\r
+ cursor,\r
+ w,h,\r
+ len;\r
+ longword lasttime;\r
+\r
+ VW_HideCursor();\r
+\r
+ if (def)\r
+ strcpy(s,def);\r
+ else\r
+ *s = '\0';\r
+ *olds = '\0';\r
+ cursor = strlen(s);\r
+ cursormoved = redraw = true;\r
+\r
+ cursorvis = done = false;\r
+ lasttime = TimeCount;\r
+ LastASCII = key_None;\r
+ LastScan = sc_None;\r
+\r
+ while (!done)\r
+ {\r
+ if (cursorvis)\r
+ USL_XORICursor(x,y,s,cursor);\r
+\r
+ asm pushf\r
+ asm cli\r
+\r
+ sc = LastScan;\r
+ LastScan = sc_None;\r
+ c = LastASCII;\r
+ LastASCII = key_None;\r
+\r
+ asm popf\r
+\r
+ switch (sc)\r
+ {\r
+ case sc_LeftArrow:\r
+ if (cursor)\r
+ cursor--;\r
+ c = key_None;\r
+ cursormoved = true;\r
+ break;\r
+ case sc_RightArrow:\r
+ if (s[cursor])\r
+ cursor++;\r
+ c = key_None;\r
+ cursormoved = true;\r
+ break;\r
+ case sc_Home:\r
+ cursor = 0;\r
+ c = key_None;\r
+ cursormoved = true;\r
+ break;\r
+ case sc_End:\r
+ cursor = strlen(s);\r
+ c = key_None;\r
+ cursormoved = true;\r
+ break;\r
+\r
+ case sc_Return:\r
+ strcpy(buf,s);\r
+ done = true;\r
+ result = true;\r
+ c = key_None;\r
+ break;\r
+ case sc_Escape:\r
+ if (escok)\r
+ {\r
+ done = true;\r
+ result = false;\r
+ }\r
+ c = key_None;\r
+ break;\r
+\r
+ case sc_BackSpace:\r
+ if (cursor)\r
+ {\r
+ strcpy(s + cursor - 1,s + cursor);\r
+ cursor--;\r
+ redraw = true;\r
+ }\r
+ c = key_None;\r
+ cursormoved = true;\r
+ break;\r
+ case sc_Delete:\r
+ if (s[cursor])\r
+ {\r
+ strcpy(s + cursor,s + cursor + 1);\r
+ redraw = true;\r
+ }\r
+ c = key_None;\r
+ cursormoved = true;\r
+ break;\r
+\r
+ case 0x4c: // Keypad 5\r
+ case sc_UpArrow:\r
+ case sc_DownArrow:\r
+ case sc_PgUp:\r
+ case sc_PgDn:\r
+ case sc_Insert:\r
+ c = key_None;\r
+ break;\r
+ }\r
+\r
+ if (c)\r
+ {\r
+ len = strlen(s);\r
+ USL_MeasureString(s,&w,&h);\r
+\r
+ if\r
+ (\r
+ isprint(c)\r
+ && (len < MaxString - 1)\r
+ && ((!maxchars) || (len < maxchars))\r
+ && ((!maxwidth) || (w < maxwidth))\r
+ )\r
+ {\r
+ for (i = len + 1;i > cursor;i--)\r
+ s[i] = s[i - 1];\r
+ s[cursor++] = c;\r
+ redraw = true;\r
+ }\r
+ }\r
+\r
+ if (redraw)\r
+ {\r
+ px = x;\r
+ py = y;\r
+ USL_DrawString(olds);\r
+ strcpy(olds,s);\r
+\r
+ px = x;\r
+ py = y;\r
+ USL_DrawString(s);\r
+\r
+ redraw = false;\r
+ }\r
+\r
+ if (cursormoved)\r
+ {\r
+ cursorvis = false;\r
+ lasttime = TimeCount - TickBase;\r
+\r
+ cursormoved = false;\r
+ }\r
+ if (TimeCount - lasttime > TickBase / 2)\r
+ {\r
+ lasttime = TimeCount;\r
+\r
+ cursorvis ^= true;\r
+ }\r
+ if (cursorvis)\r
+ USL_XORICursor(x,y,s,cursor);\r
+\r
+ VW_UpdateScreen();\r
+ }\r
+\r
+ if (cursorvis)\r
+ USL_XORICursor(x,y,s,cursor);\r
+ if (!result)\r
+ {\r
+ px = x;\r
+ py = y;\r
+ USL_DrawString(olds);\r
+ }\r
+ VW_ShowCursor();\r
+ VW_UpdateScreen();\r
+\r
+ IN_ClearKeysDown();\r
+ return(result);\r
+}\r
+\r