]> 4ch.mooo.com Git - 16.git/blob - 16/cawat/ID_US_1.C
789229cc6ca49baa37d31db175e2c0dc252794ce
[16.git] / 16 / cawat / ID_US_1.C
1 /* Catacomb Armageddon Source Code\r
2  * Copyright (C) 1993-2014 Flat Rock Software\r
3  *\r
4  * This program is free software; you can redistribute it and/or modify\r
5  * it under the terms of the GNU General Public License as published by\r
6  * the Free Software Foundation; either version 2 of the License, or\r
7  * (at your option) any later version.\r
8  *\r
9  * This program is distributed in the hope that it will be useful,\r
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
12  * GNU General Public License for more details.\r
13  *\r
14  * You should have received a copy of the GNU General Public License along\r
15  * with this program; if not, write to the Free Software Foundation, Inc.,\r
16  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\r
17  */\r
18 \r
19 //\r
20 //      ID Engine\r
21 //      ID_US_1.c - User Manager - General routines\r
22 //      v1.1d1\r
23 //      By Jason Blochowiak\r
24 //      Hacked up for Catacomb 3D\r
25 //\r
26 \r
27 //\r
28 //      This module handles dealing with user input & feedback\r
29 //\r
30 //      Depends on: Input Mgr, View Mgr, some variables from the Sound, Caching,\r
31 //              and Refresh Mgrs, Memory Mgr for background save/restore\r
32 //\r
33 //      Globals:\r
34 //              ingame - Flag set by game indicating if a game is in progress\r
35 //      abortgame - Flag set if the current game should be aborted (if a load\r
36 //                      game fails)\r
37 //              loadedgame - Flag set if a game was loaded\r
38 //              abortprogram - Normally nil, this points to a terminal error message\r
39 //                      if the program needs to abort\r
40 //              restartgame - Normally set to gd_Continue, this is set to one of the\r
41 //                      difficulty levels if a new game should be started\r
42 //              PrintX, PrintY - Where the User Mgr will print (global coords)\r
43 //              WindowX,WindowY,WindowW,WindowH - The dimensions of the current\r
44 //                      window\r
45 //\r
46 \r
47 #include "ID_HEADS.H"\r
48 \r
49 #pragma hdrstop\r
50 \r
51 #pragma warn    -pia\r
52 \r
53 \r
54 //      Special imports\r
55 extern  boolean         showscorebox;\r
56 #ifdef  KEEN\r
57 extern  boolean         oldshooting;\r
58 extern  ScanCode        firescan;\r
59 #else\r
60                 ScanCode        firescan;\r
61 #endif\r
62 \r
63 //      Global variables\r
64                 char            *abortprogram;\r
65                 boolean         NoWait,\r
66                                         HighScoresDirty;\r
67                 word            PrintX,PrintY;\r
68                 word            WindowX,WindowY,WindowW,WindowH;\r
69 \r
70                 word    MaxX=320,MaxY=200;      // MDM (GAMERS EDGE)\r
71 \r
72 //      Internal variables\r
73 #define ConfigVersion   1\r
74 \r
75 static  char            *ParmStrings[] = {"TEDLEVEL","NOWAIT"},\r
76                                         *ParmStrings2[] = {"COMP","NOCOMP"};\r
77 static  boolean         US_Started;\r
78 \r
79                 boolean         Button0,Button1,\r
80                                         CursorBad;\r
81                 int                     CursorX,CursorY;\r
82 \r
83                 void            (*USL_MeasureString)(char far *,word *,word *) = VW_MeasurePropString,\r
84                                         (*USL_DrawString)(char far *) = VWB_DrawPropString;\r
85 \r
86                 boolean         (*USL_SaveGame)(int),(*USL_LoadGame)(int);\r
87                 void            (*USL_ResetGame)(void);\r
88                 SaveGame        Games[MaxSaveGames];\r
89                 HighScore       Scores[MaxScores] =\r
90                                         {\r
91                                                 {"Sir Lancelot",500,3},\r
92                                                 {"",0},\r
93                                                 {"",0},\r
94                                                 {"",0},\r
95                                                 {"",0},\r
96                                                 {"",0},\r
97                                                 {"",0},\r
98                                         };\r
99 \r
100 //      Internal routines\r
101 \r
102 //      Public routines\r
103 \r
104 ///////////////////////////////////////////////////////////////////////////\r
105 //\r
106 //      USL_HardError() - Handles the Abort/Retry/Fail sort of errors passed\r
107 //                      from DOS.\r
108 //\r
109 ///////////////////////////////////////////////////////////////////////////\r
110 #pragma warn    -par\r
111 #pragma warn    -rch\r
112 int\r
113 USL_HardError(word errval,int ax,int bp,int si)\r
114 {\r
115 #define IGNORE  0\r
116 #define RETRY   1\r
117 #define ABORT   2\r
118 extern  void    ShutdownId(void);\r
119 \r
120 static  char            buf[32];\r
121 static  WindowRec       wr;\r
122                 int                     di;\r
123                 char            c,*s,*t;\r
124 \r
125 \r
126         di = _DI;\r
127 \r
128         if (ax < 0)\r
129                 s = "Device Error";\r
130         else\r
131         {\r
132                 if ((di & 0x00ff) == 0)\r
133                         s = "Drive ~ is Write Protected";\r
134                 else\r
135                         s = "Error on Drive ~";\r
136                 for (t = buf;*s;s++,t++)        // Can't use sprintf()\r
137                         if ((*t = *s) == '~')\r
138                                 *t = (ax & 0x00ff) + 'A';\r
139                 *t = '\0';\r
140                 s = buf;\r
141         }\r
142 \r
143         c = peekb(0x40,0x49);   // Get the current screen mode\r
144         if ((c < 4) || (c == 7))\r
145                 goto oh_kill_me;\r
146 \r
147         // DEBUG - handle screen cleanup\r
148 \r
149         US_SaveWindow(&wr);\r
150         US_CenterWindow(30,3);\r
151         US_CPrint(s);\r
152         US_CPrint("(R)etry or (A)bort?");\r
153         VW_UpdateScreen();\r
154         IN_ClearKeysDown();\r
155 \r
156 asm     sti     // Let the keyboard interrupts come through\r
157 \r
158         while (true)\r
159         {\r
160                 switch (IN_WaitForASCII())\r
161                 {\r
162                 case key_Escape:\r
163                 case 'a':\r
164                 case 'A':\r
165                         goto oh_kill_me;\r
166                         break;\r
167                 case key_Return:\r
168                 case key_Space:\r
169                 case 'r':\r
170                 case 'R':\r
171                         US_ClearWindow();\r
172                         VW_UpdateScreen();\r
173                         US_RestoreWindow(&wr);\r
174                         return(RETRY);\r
175                         break;\r
176                 }\r
177         }\r
178 \r
179 oh_kill_me:\r
180         abortprogram = s;\r
181         ShutdownId();\r
182         fprintf(stderr,"Terminal Error: %s\n",s);\r
183         if (tedlevel)\r
184                 fprintf(stderr,"You launched from TED. I suggest that you reboot...\n");\r
185 \r
186         return(ABORT);\r
187 #undef  IGNORE\r
188 #undef  RETRY\r
189 #undef  ABORT\r
190 }\r
191 #pragma warn    +par\r
192 #pragma warn    +rch\r
193 \r
194 ///////////////////////////////////////////////////////////////////////////\r
195 //\r
196 //      USL_GiveSaveName() - Returns a pointer to a static buffer that contains\r
197 //              the filename to use for the specified save game\r
198 //\r
199 ///////////////////////////////////////////////////////////////////////////\r
200 char *\r
201 USL_GiveSaveName(word game)\r
202 {\r
203 static  char    name[] = "SAVEGAMx."EXT;\r
204 \r
205         name[7] = '0' + game;\r
206         return(name);\r
207 }\r
208 \r
209 ///////////////////////////////////////////////////////////////////////////\r
210 //\r
211 //      US_SetLoadSaveHooks() - Sets the routines that the User Mgr calls after\r
212 //              reading or writing the save game headers\r
213 //\r
214 ///////////////////////////////////////////////////////////////////////////\r
215 void\r
216 US_SetLoadSaveHooks(boolean (*load)(int),boolean (*save)(int),void (*reset)(void))\r
217 {\r
218         USL_LoadGame = load;\r
219         USL_SaveGame = save;\r
220         USL_ResetGame = reset;\r
221 }\r
222 \r
223 ///////////////////////////////////////////////////////////////////////////\r
224 //\r
225 //      USL_ReadConfig() - Reads the configuration file, if present, and sets\r
226 //              things up accordingly. If it's not present, uses defaults. This file\r
227 //              includes the high scores.\r
228 //\r
229 ///////////////////////////////////////////////////////////////////////////\r
230 static void\r
231 USL_ReadConfig(void)\r
232 {\r
233         boolean         gotit;\r
234         char            sig[sizeof(EXT)];\r
235         word            version;\r
236         int                     file;\r
237         SDMode          sd;\r
238         SMMode          sm;\r
239         ControlType     ctl;\r
240 \r
241         if ((file = open("CONFIG."EXT,O_BINARY | O_RDONLY)) != -1)\r
242         {\r
243                 read(file,sig,sizeof(EXT));\r
244                 read(file,&version,sizeof(version));\r
245                 if (strcmp(sig,EXT) || (version != ConfigVersion))\r
246                 {\r
247                         close(file);\r
248                         goto rcfailed;\r
249                 }\r
250                 read(file,Scores,sizeof(HighScore) * MaxScores);\r
251                 read(file,&sd,sizeof(sd));\r
252                 read(file,&sm,sizeof(sm));\r
253                 read(file,&ctl,sizeof(ctl));\r
254                 read(file,&(KbdDefs[0]),sizeof(KbdDefs[0]));\r
255                 read(file,&showscorebox,sizeof(showscorebox));\r
256                 read(file,&compatability,sizeof(compatability));\r
257 #ifdef KEEN\r
258                 read(file,&oldshooting,sizeof(oldshooting));\r
259                 read(file,&firescan,sizeof(firescan));\r
260 #endif\r
261                 close(file);\r
262 \r
263                 HighScoresDirty = false;\r
264                 gotit = true;\r
265         }\r
266         else\r
267         {\r
268 rcfailed:\r
269                 sd = sdm_Off;\r
270                 sm = smm_Off;\r
271                 ctl = ctrl_Keyboard;\r
272                 showscorebox = true;\r
273 #ifdef KEEN\r
274                 oldshooting = false;\r
275 #endif\r
276 \r
277                 gotit = false;\r
278                 HighScoresDirty = true;\r
279         }\r
280 \r
281         SD_Default(gotit,sd,sm);\r
282         IN_Default(gotit,ctl);\r
283 }\r
284 \r
285 ///////////////////////////////////////////////////////////////////////////\r
286 //\r
287 //      USL_WriteConfig() - Writes out the current configuration, including the\r
288 //              high scores.\r
289 //\r
290 ///////////////////////////////////////////////////////////////////////////\r
291 static void\r
292 USL_WriteConfig(void)\r
293 {\r
294         word    version;\r
295         int             file;\r
296 \r
297         version = ConfigVersion;\r
298         file = open("CONFIG."EXT,O_CREAT | O_BINARY | O_WRONLY,\r
299                                 S_IREAD | S_IWRITE | S_IFREG);\r
300         if (file != -1)\r
301         {\r
302                 write(file,EXT,sizeof(EXT));\r
303                 write(file,&version,sizeof(version));\r
304                 write(file,Scores,sizeof(HighScore) * MaxScores);\r
305                 write(file,&SoundMode,sizeof(SoundMode));\r
306                 write(file,&MusicMode,sizeof(MusicMode));\r
307                 if      // Hack\r
308                 (\r
309                         (Controls[0] == ctrl_Joystick1)\r
310                 ||      (Controls[0] == ctrl_Joystick2)\r
311                 )\r
312                         Controls[0] = ctrl_Keyboard;\r
313                 write(file,&(Controls[0]),sizeof(Controls[0]));\r
314                 write(file,&(KbdDefs[0]),sizeof(KbdDefs[0]));\r
315                 write(file,&showscorebox,sizeof(showscorebox));\r
316                 write(file,&compatability,sizeof(compatability));\r
317 #ifdef KEEN\r
318                 write(file,&oldshooting,sizeof(oldshooting));\r
319                 write(file,&firescan,sizeof(firescan));\r
320 #endif\r
321                 close(file);\r
322         }\r
323 }\r
324 \r
325 ///////////////////////////////////////////////////////////////////////////\r
326 //\r
327 //      USL_CheckSavedGames() - Checks to see which saved games are present\r
328 //              & valid\r
329 //\r
330 ///////////////////////////////////////////////////////////////////////////\r
331 static void\r
332 USL_CheckSavedGames(void)\r
333 {\r
334         boolean         ok;\r
335         char            *filename;\r
336         word            i;\r
337         int                     file;\r
338         SaveGame        *game;\r
339 \r
340         USL_SaveGame = 0;\r
341         USL_LoadGame = 0;\r
342 \r
343         for (i = 0,game = Games;i < MaxSaveGames;i++,game++)\r
344         {\r
345                 filename = USL_GiveSaveName(i);\r
346                 ok = false;\r
347                 if ((file = open(filename,O_BINARY | O_RDONLY)) != -1)\r
348                 {\r
349                         if\r
350                         (\r
351                                 (read(file,game,sizeof(*game)) == sizeof(*game))\r
352                         &&      (!strcmp(game->signature,EXT))\r
353                         &&      (game->oldtest == &PrintX)\r
354                         )\r
355                                 ok = true;\r
356 \r
357                         close(file);\r
358                 }\r
359 \r
360                 if (ok)\r
361                         game->present = true;\r
362                 else\r
363                 {\r
364                         strcpy(game->signature,EXT);\r
365                         game->present = false;\r
366                         strcpy(game->name,"Empty");\r
367                 }\r
368         }\r
369 }\r
370 \r
371 ///////////////////////////////////////////////////////////////////////////\r
372 //\r
373 //      US_Startup() - Starts the User Mgr\r
374 //\r
375 ///////////////////////////////////////////////////////////////////////////\r
376 void\r
377 US_Startup(void)\r
378 {\r
379         int     i;\r
380 \r
381         if (US_Started)\r
382                 return;\r
383 \r
384         harderr(USL_HardError); // Install the fatal error handler\r
385 \r
386         US_InitRndT(true);              // Initialize the random number generator\r
387 \r
388         USL_ReadConfig();               // Read config file\r
389 \r
390         for (i = 1;i < _argc;i++)\r
391         {\r
392                 switch (US_CheckParm(_argv[i],ParmStrings2))\r
393                 {\r
394                 case 0:\r
395                         if (grmode == EGAGR)\r
396                                 compatability = true;\r
397                         break;\r
398                 case 1:\r
399                         compatability = false;\r
400                         break;\r
401                 }\r
402         }\r
403 \r
404         US_Started = true;\r
405 }\r
406 \r
407 ///////////////////////////////////////////////////////////////////////////\r
408 //\r
409 //      US_Setup() - Does the disk access part of the User Mgr's startup\r
410 //\r
411 ///////////////////////////////////////////////////////////////////////////\r
412 void\r
413 US_Setup(void)\r
414 {\r
415         USL_CheckSavedGames();  // Check which saved games are present\r
416 }\r
417 \r
418 ///////////////////////////////////////////////////////////////////////////\r
419 //\r
420 //      US_Shutdown() - Shuts down the User Mgr\r
421 //\r
422 ///////////////////////////////////////////////////////////////////////////\r
423 void\r
424 US_Shutdown(void)\r
425 {\r
426         if (!US_Started)\r
427                 return;\r
428 \r
429         if (!abortprogram)\r
430                 USL_WriteConfig();\r
431 \r
432         US_Started = false;\r
433 }\r
434 \r
435 ///////////////////////////////////////////////////////////////////////////\r
436 //\r
437 //      US_CheckParm() - checks to see if a string matches one of a set of\r
438 //              strings. The check is case insensitive. The routine returns the\r
439 //              index of the string that matched, or -1 if no matches were found\r
440 //\r
441 ///////////////////////////////////////////////////////////////////////////\r
442 int\r
443 US_CheckParm(char *parm,char **strings)\r
444 {\r
445         char    cp,cs,\r
446                         *p,*s;\r
447         int             i;\r
448 \r
449         while (!isalpha(*parm)) // Skip non-alphas\r
450                 parm++;\r
451 \r
452         for (i = 0;*strings && **strings;i++)\r
453         {\r
454                 for (s = *strings++,p = parm,cs = cp = 0;cs == cp;)\r
455                 {\r
456                         cs = *s++;\r
457                         if (!cs)\r
458                                 return(i);\r
459                         cp = *p++;\r
460 \r
461                         if (isupper(cs))\r
462                                 cs = tolower(cs);\r
463                         if (isupper(cp))\r
464                                 cp = tolower(cp);\r
465                 }\r
466         }\r
467         return(-1);\r
468 }\r
469 \r
470 #if 0\r
471 ///////////////////////////////////////////////////////////////////////////\r
472 //\r
473 //      USL_ScreenDraw() - Draws a chunk of the text screen (called only by\r
474 //              US_TextScreen())\r
475 //\r
476 ///////////////////////////////////////////////////////////////////////////\r
477 static void\r
478 USL_ScreenDraw(word x,word y,char *s,byte attr)\r
479 {\r
480         byte    far *screen,far *oscreen;\r
481 \r
482         screen = MK_FP(0xb800,(x * 2) + (y * 80 * 2));\r
483         oscreen = (&introscn + 7) + ((x - 1) * 2) + (y * 80 * 2) + 1;\r
484         while (*s)\r
485         {\r
486                 *screen++ = *s++;\r
487                 if (attr != 0xff)\r
488                 {\r
489                         *screen++ = (attr & 0x8f) | (*oscreen & 0x70);\r
490                         oscreen += 2;\r
491                 }\r
492                 else\r
493                         screen++;\r
494         }\r
495 }\r
496 #endif\r
497 \r
498 ///////////////////////////////////////////////////////////////////////////\r
499 //\r
500 //      USL_ClearTextScreen() - Makes sure the screen is in text mode, clears it,\r
501 //              and moves the cursor to the leftmost column of the bottom line\r
502 //\r
503 ///////////////////////////////////////////////////////////////////////////\r
504 static void\r
505 USL_ClearTextScreen(void)\r
506 {\r
507         // Set to 80x25 color text mode\r
508         _AL = 3;                                // Mode 3\r
509         _AH = 0x00;\r
510         geninterrupt(0x10);\r
511 \r
512         // Use BIOS to move the cursor to the bottom of the screen\r
513         _AH = 0x0f;\r
514         geninterrupt(0x10);             // Get current video mode into _BH\r
515         _DL = 0;                                // Lefthand side of the screen\r
516         _DH = 24;                               // Bottom row\r
517         _AH = 0x02;\r
518         geninterrupt(0x10);\r
519 }\r
520 \r
521 #if 0\r
522 ///////////////////////////////////////////////////////////////////////////\r
523 //\r
524 //      US_TextScreen() - Puts up the startup text screen\r
525 //      Note: These are the only User Manager functions that can be safely called\r
526 //              before the User Mgr has been started up\r
527 //\r
528 ///////////////////////////////////////////////////////////////////////////\r
529 void\r
530 US_TextScreen(void)\r
531 {\r
532         word    i,n;\r
533 \r
534         USL_ClearTextScreen();\r
535 \r
536         _fmemcpy(MK_FP(0xb800,0),7 + &introscn,80 * 25 * 2);\r
537 \r
538         // Check for TED launching here\r
539         for (i = 1;i < _argc;i++)\r
540         {\r
541                 n = US_CheckParm(_argv[i],ParmStrings);\r
542                 if (n == 0)\r
543                 {\r
544                         tedlevelnum = atoi(_argv[i + 1]);\r
545                         if (tedlevelnum >= 0)\r
546                         {\r
547                                 tedlevel = true;\r
548                                 return;\r
549                         }\r
550                         else\r
551                                 break;\r
552                 }\r
553                 else if (n == 1)\r
554                 {\r
555                         NoWait = true;\r
556                         return;\r
557                 }\r
558         }\r
559 }\r
560 \r
561 ///////////////////////////////////////////////////////////////////////////\r
562 //\r
563 //      USL_Show() - Changes the appearance of one of the fields on the text\r
564 //              screen. Possibly adds a checkmark in front of it and highlights it\r
565 //\r
566 ///////////////////////////////////////////////////////////////////////////\r
567 static void\r
568 USL_Show(word x,word y,word w,boolean show,boolean hilight)\r
569 {\r
570         byte    far *screen,far *oscreen;\r
571 \r
572         screen = MK_FP(0xb800,((x - 1) * 2) + (y * 80 * 2));\r
573         oscreen = (&introscn + 7) + ((x - 1) * 2) + (y * 80 * 2) - 1;\r
574         *screen++ = show? 251 : ' ';    // Checkmark char or space\r
575 //      *screen = 0x48;\r
576 //      *screen = (*oscreen & 0xf0) | 8;\r
577         oscreen += 2;\r
578         if (show && hilight)\r
579         {\r
580                 for (w++;w--;screen += 2,oscreen += 2)\r
581                         *screen = (*oscreen & 0xf0) | 0x0f;\r
582         }\r
583 }\r
584 \r
585 ///////////////////////////////////////////////////////////////////////////\r
586 //\r
587 //      USL_ShowMem() - Right justifies a longword in one of the memory fields on\r
588 //              the text screen\r
589 //\r
590 ///////////////////////////////////////////////////////////////////////////\r
591 static void\r
592 USL_ShowMem(word x,word y,long mem)\r
593 {\r
594         char    buf[16];\r
595         word    i;\r
596 \r
597         for (i = strlen(ltoa(mem,buf,10));i < 5;i++)\r
598                 USL_ScreenDraw(x++,y," ",0xff);\r
599         USL_ScreenDraw(x,y,buf,0xff);\r
600 }\r
601 \r
602 ///////////////////////////////////////////////////////////////////////////\r
603 //\r
604 //      US_UpdateTextScreen() - Called after the ID libraries are started up.\r
605 //              Displays what hardware is present.\r
606 //\r
607 ///////////////////////////////////////////////////////////////////////////\r
608 void\r
609 US_UpdateTextScreen(void)\r
610 {\r
611         boolean         b;\r
612         longword        totalmem;\r
613 \r
614         // Show video card info\r
615         b = (grmode == CGAGR);\r
616         USL_Show(21,7,4,(videocard >= CGAcard) && (videocard <= VGAcard),b);\r
617         b = (grmode == EGAGR);\r
618         USL_Show(21,8,4,(videocard >= EGAcard) && (videocard <= VGAcard),b);\r
619         b = (grmode == VGAGR);\r
620         USL_Show(21,9,4,videocard == VGAcard,b);\r
621         if (compatability)\r
622                 USL_ScreenDraw(5,10,"SVGA Compatibility Mode Enabled.",0x4f);\r
623 \r
624         // Show input device info\r
625         USL_Show(60,7,8,true,true);\r
626         USL_Show(60,8,11,JoysPresent[0],true);\r
627         USL_Show(60,9,11,JoysPresent[1],true);\r
628         USL_Show(60,10,5,MousePresent,true);\r
629 \r
630         // Show sound hardware info\r
631         USL_Show(21,14,11,true,SoundMode == sdm_PC);\r
632         b = (SoundMode == sdm_AdLib) || (MusicMode == smm_AdLib);\r
633         USL_Show(21,15,14,AdLibPresent,b);\r
634         if (b && AdLibPresent)  // Hack because of two lines\r
635         {\r
636                 byte    far *screen,far *oscreen;\r
637                 word    x,y,w;\r
638 \r
639                 x = 21;\r
640                 y = 16;\r
641                 w = 14;\r
642                 screen = MK_FP(0xb800,(x * 2) + (y * 80 * 2) - 1);\r
643                 oscreen = (&introscn + 7) + (x * 2) + (y * 80 * 2) - 1;\r
644                 oscreen += 2;\r
645                 for (w++;w--;screen += 2,oscreen += 2)\r
646                         *screen = (*oscreen & 0xf0) | 0x0f;\r
647         }\r
648 \r
649         // Show memory available/used\r
650         USL_ShowMem(63,15,mminfo.mainmem / 1024);\r
651         USL_Show(53,15,23,true,true);\r
652         USL_ShowMem(63,16,mminfo.EMSmem / 1024);\r
653         USL_Show(53,16,23,mminfo.EMSmem? true : false,true);\r
654         USL_ShowMem(63,17,mminfo.XMSmem / 1024);\r
655         USL_Show(53,17,23,mminfo.XMSmem? true : false,true);\r
656         totalmem = mminfo.mainmem + mminfo.EMSmem + mminfo.XMSmem;\r
657         USL_ShowMem(63,18,totalmem / 1024);\r
658         USL_Show(53,18,23,true,true);   // DEBUG\r
659         USL_ScreenDraw(52,18," ",0xff);\r
660 \r
661         // Change Initializing... to Loading...\r
662         USL_ScreenDraw(27,22,"  Loading...   ",0x9c);\r
663 }\r
664 \r
665 ///////////////////////////////////////////////////////////////////////////\r
666 //\r
667 //      US_FinishTextScreen() - After the main program has finished its initial\r
668 //              loading, this routine waits for a keypress and then clears the screen\r
669 //\r
670 ///////////////////////////////////////////////////////////////////////////\r
671 void\r
672 US_FinishTextScreen(void)\r
673 {\r
674 static  byte    colors[] = {4,6,13,15,15,15,15,15,15};\r
675                 boolean up;\r
676                 int             i,c;\r
677 \r
678         // Change Loading... to Press a Key\r
679 \r
680         if (!(tedlevel || NoWait))\r
681         {\r
682                 IN_ClearKeysDown();\r
683                 for (i = 0,up = true;!IN_UserInput(4,true);)\r
684                 {\r
685                         c = colors[i];\r
686                         if (up)\r
687                         {\r
688                                 if (++i == 9)\r
689                                         i = 8,up = false;\r
690                         }\r
691                         else\r
692                         {\r
693                                 if (--i < 0)\r
694                                         i = 1,up = true;\r
695                         }\r
696 \r
697                         USL_ScreenDraw(29,22," Ready - Press a Key     ",0x00 + c);\r
698                 }\r
699         }\r
700         else\r
701                 USL_ScreenDraw(29,22," Ready - Press a Key     ",0x9a);\r
702         IN_ClearKeysDown();\r
703 \r
704         USL_ClearTextScreen();\r
705 }\r
706 #endif\r
707 \r
708 //      Window/Printing routines\r
709 \r
710 ///////////////////////////////////////////////////////////////////////////\r
711 //\r
712 //      US_SetPrintRoutines() - Sets the routines used to measure and print\r
713 //              from within the User Mgr. Primarily provided to allow switching\r
714 //              between masked and non-masked fonts\r
715 //\r
716 ///////////////////////////////////////////////////////////////////////////\r
717 void\r
718 US_SetPrintRoutines(void (*measure)(char far *,word *,word *),void (*print)(char far *))\r
719 {\r
720         USL_MeasureString = measure;\r
721         USL_DrawString = print;\r
722 }\r
723 \r
724 ///////////////////////////////////////////////////////////////////////////\r
725 //\r
726 //      US_Print() - Prints a string in the current window. Newlines are\r
727 //              supported.\r
728 //\r
729 ///////////////////////////////////////////////////////////////////////////\r
730 void\r
731 US_Print(char *s)\r
732 {\r
733         char    c,*se;\r
734         word    w,h;\r
735 \r
736         while (*s)\r
737         {\r
738                 se = s;\r
739                 while ((c = *se) && (c != '\n'))\r
740                         se++;\r
741                 *se = '\0';\r
742 \r
743                 USL_MeasureString(s,&w,&h);\r
744                 px = PrintX;\r
745                 py = PrintY;\r
746                 USL_DrawString(s);\r
747 \r
748                 s = se;\r
749                 if (c)\r
750                 {\r
751                         *se = c;\r
752                         s++;\r
753 \r
754                         PrintX = WindowX;\r
755                         PrintY += h;\r
756                 }\r
757                 else\r
758                         PrintX += w;\r
759         }\r
760 }\r
761 \r
762 // MDM - (GAMERS EDGE)  begin\r
763 \r
764 ///////////////////////////////////////////////////////////////////////////\r
765 //\r
766 // US_Printxy()\r
767 //\r
768 void US_Printxy(word x, word y, char *text)\r
769 {\r
770         word orgx, orgy;\r
771 \r
772         orgx = PrintX;\r
773         orgy = PrintY;\r
774 \r
775 //      PrintX = WindowX+x;\r
776 //      PrintY = WindowY+y;\r
777         PrintX = x;\r
778         PrintY = y;\r
779         US_Print(text);\r
780 \r
781         PrintX = orgx;\r
782         PrintY = orgy;\r
783 }\r
784 \r
785 // MDM - (GAMERS EDGE)  end\r
786 \r
787 ///////////////////////////////////////////////////////////////////////////\r
788 //\r
789 //      US_PrintUnsigned() - Prints an unsigned long\r
790 //\r
791 ///////////////////////////////////////////////////////////////////////////\r
792 void\r
793 US_PrintUnsigned(longword n)\r
794 {\r
795         char    buffer[32];\r
796 \r
797         US_Print(ultoa(n,buffer,10));\r
798 }\r
799 \r
800 ///////////////////////////////////////////////////////////////////////////\r
801 //\r
802 //      US_PrintSigned() - Prints a signed long\r
803 //\r
804 ///////////////////////////////////////////////////////////////////////////\r
805 void\r
806 US_PrintSigned(long n)\r
807 {\r
808         char    buffer[32];\r
809 \r
810         US_Print(ltoa(n,buffer,10));\r
811 }\r
812 \r
813 ///////////////////////////////////////////////////////////////////////////\r
814 //\r
815 //      USL_PrintInCenter() - Prints a string in the center of the given rect\r
816 //\r
817 ///////////////////////////////////////////////////////////////////////////\r
818 void\r
819 USL_PrintInCenter(char *s,Rect r)\r
820 {\r
821         word    w,h,\r
822                         rw,rh;\r
823 \r
824         USL_MeasureString(s,&w,&h);\r
825         rw = r.lr.x - r.ul.x;\r
826         rh = r.lr.y - r.ul.y;\r
827 \r
828         px = r.ul.x + ((rw - w) / 2);\r
829         py = r.ul.y + ((rh - h) / 2);\r
830         USL_DrawString(s);\r
831 }\r
832 \r
833 ///////////////////////////////////////////////////////////////////////////\r
834 //\r
835 //      US_PrintCentered() - Prints a string centered in the current window.\r
836 //\r
837 ///////////////////////////////////////////////////////////////////////////\r
838 void\r
839 US_PrintCentered(char *s)\r
840 {\r
841         Rect    r;\r
842 \r
843         r.ul.x = WindowX;\r
844         r.ul.y = WindowY;\r
845         r.lr.x = r.ul.x + WindowW;\r
846         r.lr.y = r.ul.y + WindowH;\r
847 \r
848         USL_PrintInCenter(s,r);\r
849 }\r
850 \r
851 ///////////////////////////////////////////////////////////////////////////\r
852 //\r
853 //      US_CPrintLine() - Prints a string centered on the current line and\r
854 //              advances to the next line. Newlines are not supported.\r
855 //\r
856 ///////////////////////////////////////////////////////////////////////////\r
857 void\r
858 US_CPrintLine(char *s)\r
859 {\r
860         word    w,h;\r
861 \r
862         USL_MeasureString(s,&w,&h);\r
863 \r
864         if (w > WindowW)\r
865                 Quit("US_CPrintLine() - String exceeds width");\r
866         px = WindowX + ((WindowW - w) / 2);\r
867         py = PrintY;\r
868         USL_DrawString(s);\r
869         PrintY += h;\r
870 }\r
871 \r
872 ///////////////////////////////////////////////////////////////////////////\r
873 //\r
874 //      US_CPrint() - Prints a string in the current window. Newlines are\r
875 //              supported.\r
876 //\r
877 ///////////////////////////////////////////////////////////////////////////\r
878 void\r
879 US_CPrint(char *s)\r
880 {\r
881         char    c,*se;\r
882 \r
883         while (*s)\r
884         {\r
885                 se = s;\r
886                 while ((c = *se) && (c != '\n'))\r
887                         se++;\r
888                 *se = '\0';\r
889 \r
890                 US_CPrintLine(s);\r
891 \r
892                 s = se;\r
893                 if (c)\r
894                 {\r
895                         *se = c;\r
896                         s++;\r
897                 }\r
898         }\r
899 }\r
900 \r
901 ///////////////////////////////////////////////////////////////////////////\r
902 //\r
903 //      US_ClearWindow() - Clears the current window to white and homes the\r
904 //              cursor\r
905 //\r
906 ///////////////////////////////////////////////////////////////////////////\r
907 void\r
908 US_ClearWindow(void)\r
909 {\r
910         VWB_Bar(WindowX,WindowY,WindowW,WindowH,LT_GREY);\r
911         PrintX = WindowX;\r
912         PrintY = WindowY;\r
913 }\r
914 \r
915 ///////////////////////////////////////////////////////////////////////////\r
916 //\r
917 //      US_DrawWindow() - Draws a frame and sets the current window parms\r
918 //\r
919 ///////////////////////////////////////////////////////////////////////////\r
920 void\r
921 US_DrawWindow(word x,word y,word w,word h)\r
922 {\r
923         word    i,\r
924                         sx,sy,sw,sh;\r
925 \r
926         WindowX = x * 8;\r
927         WindowY = y * 8;\r
928         WindowW = w * 8;\r
929         WindowH = h * 8;\r
930 \r
931         PrintX = WindowX;\r
932         PrintY = WindowY;\r
933 \r
934         sx = (x - 1) * 8;\r
935         sy = (y - 1) * 8;\r
936         sw = (w + 1) * 8;\r
937         sh = (h + 1) * 8;\r
938 \r
939         US_ClearWindow();\r
940 \r
941         VWB_DrawTile8M(sx,sy,0),VWB_DrawTile8M(sx,sy + sh,6);\r
942         for (i = sx + 8;i <= sx + sw - 8;i += 8)\r
943                 VWB_DrawTile8M(i,sy,1),VWB_DrawTile8M(i,sy + sh,7);\r
944         VWB_DrawTile8M(i,sy,2),VWB_DrawTile8M(i,sy + sh,8);\r
945 \r
946         for (i = sy + 8;i <= sy + sh - 8;i += 8)\r
947                 VWB_DrawTile8M(sx,i,3),VWB_DrawTile8M(sx + sw,i,5);\r
948 }\r
949 \r
950 ///////////////////////////////////////////////////////////////////////////\r
951 //\r
952 //      US_CenterWindow() - Generates a window of a given width & height in the\r
953 //              middle of the screen\r
954 //\r
955 ///////////////////////////////////////////////////////////////////////////\r
956 void\r
957 US_CenterWindow(word w,word h)\r
958 {\r
959         US_DrawWindow(((MaxX / 8) - w) / 2,((MaxY / 8) - h) / 2,w,h);\r
960 }\r
961 \r
962 ///////////////////////////////////////////////////////////////////////////\r
963 //\r
964 //      US_CenterSaveWindow() - Generates a window of a given width & height in\r
965 //              the middle of the screen, saving the background\r
966 //\r
967 ///////////////////////////////////////////////////////////////////////////\r
968 void\r
969 US_CenterSaveWindow(word w,word h,memptr *save)\r
970 {\r
971         word    x,y,\r
972                         screen;\r
973 \r
974         x = ((MaxX / 8) - w) / 2;\r
975         y = ((MaxY / 8) - h) / 2;\r
976         MM_GetPtr(save,(w * h) * CHARWIDTH);\r
977         screen = bufferofs + panadjust + ylookup[y] + (x * CHARWIDTH);\r
978         VW_ScreenToMem(screen,*save,w * CHARWIDTH,h);\r
979         US_DrawWindow(((MaxX / 8) - w) / 2,((MaxY / 8) - h) / 2,w,h);\r
980 }\r
981 \r
982 ///////////////////////////////////////////////////////////////////////////\r
983 //\r
984 //      US_RestoreSaveWindow() - Restores the background of the size of the\r
985 //              current window from the memory specified by save\r
986 //\r
987 ///////////////////////////////////////////////////////////////////////////\r
988 void\r
989 US_RestoreSaveWindow(memptr *save)\r
990 {\r
991         word    screen;\r
992 \r
993         screen = bufferofs + panadjust + ylookup[WindowY] + (WindowX * CHARWIDTH);\r
994         VW_MemToScreen(*save,screen,WindowW * CHARWIDTH,WindowH);\r
995         MM_FreePtr(save);\r
996 }\r
997 \r
998 ///////////////////////////////////////////////////////////////////////////\r
999 //\r
1000 //      US_SaveWindow() - Saves the current window parms into a record for\r
1001 //              later restoration\r
1002 //\r
1003 ///////////////////////////////////////////////////////////////////////////\r
1004 void\r
1005 US_SaveWindow(WindowRec *win)\r
1006 {\r
1007         win->x = WindowX;\r
1008         win->y = WindowY;\r
1009         win->w = WindowW;\r
1010         win->h = WindowH;\r
1011 \r
1012         win->px = PrintX;\r
1013         win->py = PrintY;\r
1014 }\r
1015 \r
1016 ///////////////////////////////////////////////////////////////////////////\r
1017 //\r
1018 //      US_RestoreWindow() - Sets the current window parms to those held in the\r
1019 //              record\r
1020 //\r
1021 ///////////////////////////////////////////////////////////////////////////\r
1022 void\r
1023 US_RestoreWindow(WindowRec *win)\r
1024 {\r
1025         WindowX = win->x;\r
1026         WindowY = win->y;\r
1027         WindowW = win->w;\r
1028         WindowH = win->h;\r
1029 \r
1030         PrintX = win->px;\r
1031         PrintY = win->py;\r
1032 }\r
1033 \r
1034 //      Cursor routines\r
1035 \r
1036 #if 0\r
1037 ///////////////////////////////////////////////////////////////////////////\r
1038 //\r
1039 //      US_StartCursor() - Sets up the cursor for User Mgr use\r
1040 //\r
1041 ///////////////////////////////////////////////////////////////////////////\r
1042 void\r
1043 US_StartCursor(void)\r
1044 {\r
1045         CursorInfo      info;\r
1046 \r
1047         VW_SetCursor(CURSORARROWSPR);\r
1048         CursorX = MaxX / 2;\r
1049         CursorY = MaxY / 2;\r
1050         VW_MoveCursor(CursorX,CursorY);\r
1051         VW_ShowCursor();\r
1052 \r
1053         IN_ReadCursor(&info);   // Dispose of any accumulated movement\r
1054 }\r
1055 \r
1056 ///////////////////////////////////////////////////////////////////////////\r
1057 //\r
1058 //      US_ShutCursor() - Cleans up after US_StartCursor()\r
1059 //\r
1060 ///////////////////////////////////////////////////////////////////////////\r
1061 void\r
1062 US_ShutCursor(void)\r
1063 {\r
1064         VW_HideCursor();\r
1065 }\r
1066 \r
1067 ///////////////////////////////////////////////////////////////////////////\r
1068 //\r
1069 //      US_UpdateCursor() - Gets the new cursor position & button states from\r
1070 //              the Input Mgr and tells the View Mgr where the cursor is\r
1071 //\r
1072 ///////////////////////////////////////////////////////////////////////////\r
1073 boolean\r
1074 US_UpdateCursor(void)\r
1075 {\r
1076         CursorInfo      info;\r
1077 \r
1078         IN_ReadCursor(&info);\r
1079         if (info.x || info.y || CursorBad)\r
1080         {\r
1081                 CursorX += info.x;\r
1082                 if (CursorX >= MaxX)\r
1083                         CursorX = MaxX - 1;\r
1084                 else if (CursorX < 0)\r
1085                         CursorX = 0;\r
1086 \r
1087                 CursorY += info.y;\r
1088                 if (CursorY >= MaxY)\r
1089                         CursorY = MaxY - 1;\r
1090                 else if (CursorY < 0)\r
1091                         CursorY = 0;\r
1092 \r
1093                 VW_MoveCursor(CursorX,CursorY);\r
1094                 CursorBad = false;\r
1095         }\r
1096         Button0 = info.button0;\r
1097         Button1 = info.button1;\r
1098         return(Button0 || Button1);\r
1099 }\r
1100 #endif\r
1101 \r
1102 //      Input routines\r
1103 \r
1104 ///////////////////////////////////////////////////////////////////////////\r
1105 //\r
1106 //      USL_XORICursor() - XORs the I-bar text cursor. Used by US_LineInput()\r
1107 //\r
1108 ///////////////////////////////////////////////////////////////////////////\r
1109 static void\r
1110 USL_XORICursor(int x,int y,char *s,word cursor)\r
1111 {\r
1112         char    buf[MaxString];\r
1113         word    w,h;\r
1114 \r
1115         strcpy(buf,s);\r
1116         buf[cursor] = '\0';\r
1117         USL_MeasureString(buf,&w,&h);\r
1118 \r
1119         px = x + w - 1;\r
1120         py = y;\r
1121         USL_DrawString("\x80");\r
1122 }\r
1123 \r
1124 ///////////////////////////////////////////////////////////////////////////\r
1125 //\r
1126 //      US_LineInput() - Gets a line of user input at (x,y), the string defaults\r
1127 //              to whatever is pointed at by def. Input is restricted to maxchars\r
1128 //              chars or maxwidth pixels wide. If the user hits escape (and escok is\r
1129 //              true), nothing is copied into buf, and false is returned. If the\r
1130 //              user hits return, the current string is copied into buf, and true is\r
1131 //              returned\r
1132 //\r
1133 ///////////////////////////////////////////////////////////////////////////\r
1134 boolean\r
1135 US_LineInput(int x,int y,char *buf,char *def,boolean escok,\r
1136                                 int maxchars,int maxwidth)\r
1137 {\r
1138         boolean         redraw,\r
1139                                 cursorvis,cursormoved,\r
1140                                 done,result;\r
1141         ScanCode        sc;\r
1142         char            c,\r
1143                                 s[MaxString],olds[MaxString];\r
1144         word            i,\r
1145                                 cursor,\r
1146                                 w,h,\r
1147                                 len;\r
1148         longword        lasttime;\r
1149 \r
1150         VW_HideCursor();\r
1151 \r
1152         if (def)\r
1153                 strcpy(s,def);\r
1154         else\r
1155                 *s = '\0';\r
1156         *olds = '\0';\r
1157         cursor = strlen(s);\r
1158         cursormoved = redraw = true;\r
1159 \r
1160         cursorvis = done = false;\r
1161         lasttime = TimeCount;\r
1162         LastASCII = key_None;\r
1163         LastScan = sc_None;\r
1164 \r
1165         while (!done)\r
1166         {\r
1167                 if (cursorvis)\r
1168                         USL_XORICursor(x,y,s,cursor);\r
1169 \r
1170         asm     pushf\r
1171         asm     cli\r
1172 \r
1173                 sc = LastScan;\r
1174                 LastScan = sc_None;\r
1175                 c = LastASCII;\r
1176                 LastASCII = key_None;\r
1177 \r
1178         asm     popf\r
1179 \r
1180                 switch (sc)\r
1181                 {\r
1182                 case sc_LeftArrow:\r
1183                         if (cursor)\r
1184                                 cursor--;\r
1185                         c = key_None;\r
1186                         cursormoved = true;\r
1187                         break;\r
1188                 case sc_RightArrow:\r
1189                         if (s[cursor])\r
1190                                 cursor++;\r
1191                         c = key_None;\r
1192                         cursormoved = true;\r
1193                         break;\r
1194                 case sc_Home:\r
1195                         cursor = 0;\r
1196                         c = key_None;\r
1197                         cursormoved = true;\r
1198                         break;\r
1199                 case sc_End:\r
1200                         cursor = strlen(s);\r
1201                         c = key_None;\r
1202                         cursormoved = true;\r
1203                         break;\r
1204 \r
1205                 case sc_Return:\r
1206                         strcpy(buf,s);\r
1207                         done = true;\r
1208                         result = true;\r
1209                         c = key_None;\r
1210                         break;\r
1211                 case sc_Escape:\r
1212                         if (escok)\r
1213                         {\r
1214                                 done = true;\r
1215                                 result = false;\r
1216                         }\r
1217                         c = key_None;\r
1218                         break;\r
1219 \r
1220                 case sc_BackSpace:\r
1221                         if (cursor)\r
1222                         {\r
1223                                 strcpy(s + cursor - 1,s + cursor);\r
1224                                 cursor--;\r
1225                                 redraw = true;\r
1226                         }\r
1227                         c = key_None;\r
1228                         cursormoved = true;\r
1229                         break;\r
1230                 case sc_Delete:\r
1231                         if (s[cursor])\r
1232                         {\r
1233                                 strcpy(s + cursor,s + cursor + 1);\r
1234                                 redraw = true;\r
1235                         }\r
1236                         c = key_None;\r
1237                         cursormoved = true;\r
1238                         break;\r
1239 \r
1240                 case 0x4c:      // Keypad 5\r
1241                 case sc_UpArrow:\r
1242                 case sc_DownArrow:\r
1243                 case sc_PgUp:\r
1244                 case sc_PgDn:\r
1245                 case sc_Insert:\r
1246                         c = key_None;\r
1247                         break;\r
1248                 }\r
1249 \r
1250                 if (c)\r
1251                 {\r
1252                         len = strlen(s);\r
1253                         USL_MeasureString(s,&w,&h);\r
1254 \r
1255                         if\r
1256                         (\r
1257                                 isprint(c)\r
1258                         &&      (len < MaxString - 1)\r
1259                         &&      ((!maxchars) || (len < maxchars))\r
1260                         &&      ((!maxwidth) || (w < maxwidth))\r
1261                         )\r
1262                         {\r
1263                                 for (i = len + 1;i > cursor;i--)\r
1264                                         s[i] = s[i - 1];\r
1265                                 s[cursor++] = c;\r
1266                                 redraw = true;\r
1267                         }\r
1268                 }\r
1269 \r
1270                 if (redraw)\r
1271                 {\r
1272                         px = x;\r
1273                         py = y;\r
1274                         USL_DrawString(olds);\r
1275                         strcpy(olds,s);\r
1276 \r
1277                         px = x;\r
1278                         py = y;\r
1279                         USL_DrawString(s);\r
1280 \r
1281                         redraw = false;\r
1282                 }\r
1283 \r
1284                 if (cursormoved)\r
1285                 {\r
1286                         cursorvis = false;\r
1287                         lasttime = TimeCount - TickBase;\r
1288 \r
1289                         cursormoved = false;\r
1290                 }\r
1291                 if (TimeCount - lasttime > TickBase / 2)\r
1292                 {\r
1293                         lasttime = TimeCount;\r
1294 \r
1295                         cursorvis ^= true;\r
1296                 }\r
1297                 if (cursorvis)\r
1298                         USL_XORICursor(x,y,s,cursor);\r
1299 \r
1300                 VW_UpdateScreen();\r
1301         }\r
1302 \r
1303         if (cursorvis)\r
1304                 USL_XORICursor(x,y,s,cursor);\r
1305         if (!result)\r
1306         {\r
1307                 px = x;\r
1308                 py = y;\r
1309                 USL_DrawString(olds);\r
1310         }\r
1311         VW_ShowCursor();\r
1312         VW_UpdateScreen();\r
1313 \r
1314         IN_ClearKeysDown();\r
1315         return(result);\r
1316 }\r
1317 \r