ID_US_1.C (15192B)
1 // 2 // ID Engine 3 // ID_US_1.c - User Manager - General routines 4 // v1.1d1 5 // By Jason Blochowiak 6 // Hacked up for Catacomb 3D 7 // 8 9 // 10 // This module handles dealing with user input & feedback 11 // 12 // Depends on: Input Mgr, View Mgr, some variables from the Sound, Caching, 13 // and Refresh Mgrs, Memory Mgr for background save/restore 14 // 15 // Globals: 16 // ingame - Flag set by game indicating if a game is in progress 17 // abortgame - Flag set if the current game should be aborted (if a load 18 // game fails) 19 // loadedgame - Flag set if a game was loaded 20 // abortprogram - Normally nil, this points to a terminal error message 21 // if the program needs to abort 22 // restartgame - Normally set to gd_Continue, this is set to one of the 23 // difficulty levels if a new game should be started 24 // PrintX, PrintY - Where the User Mgr will print (global coords) 25 // WindowX,WindowY,WindowW,WindowH - The dimensions of the current 26 // window 27 // 28 29 #include "ID_HEADS.H" 30 31 #pragma hdrstop 32 33 #pragma warn -pia 34 35 36 // Global variables 37 char *abortprogram; 38 boolean NoWait; 39 word PrintX,PrintY; 40 word WindowX,WindowY,WindowW,WindowH; 41 42 // Internal variables 43 #define ConfigVersion 1 44 45 static char *ParmStrings[] = {"TEDLEVEL","NOWAIT"}, 46 *ParmStrings2[] = {"COMP","NOCOMP"}; 47 static boolean US_Started; 48 49 boolean Button0,Button1, 50 CursorBad; 51 int CursorX,CursorY; 52 53 void (*USL_MeasureString)(char far *,word *,word *) = VW_MeasurePropString, 54 (*USL_DrawString)(char far *) = VWB_DrawPropString; 55 56 SaveGame Games[MaxSaveGames]; 57 HighScore Scores[MaxScores] = 58 { 59 {"id software-'92",10000,1}, 60 {"Adrian Carmack",10000,1}, 61 {"John Carmack",10000,1}, 62 {"Kevin Cloud",10000,1}, 63 {"Tom Hall",10000,1}, 64 {"John Romero",10000,1}, 65 {"Jay Wilbur",10000,1}, 66 }; 67 68 // Internal routines 69 70 // Public routines 71 72 /////////////////////////////////////////////////////////////////////////// 73 // 74 // USL_HardError() - Handles the Abort/Retry/Fail sort of errors passed 75 // from DOS. 76 // 77 /////////////////////////////////////////////////////////////////////////// 78 #pragma warn -par 79 #pragma warn -rch 80 int 81 USL_HardError(word errval,int ax,int bp,int si) 82 { 83 #define IGNORE 0 84 #define RETRY 1 85 #define ABORT 2 86 extern void ShutdownId(void); 87 88 static char buf[32]; 89 static WindowRec wr; 90 int di; 91 char c,*s,*t; 92 93 94 di = _DI; 95 96 if (ax < 0) 97 s = "Device Error"; 98 else 99 { 100 if ((di & 0x00ff) == 0) 101 s = "Drive ~ is Write Protected"; 102 else 103 s = "Error on Drive ~"; 104 for (t = buf;*s;s++,t++) // Can't use sprintf() 105 if ((*t = *s) == '~') 106 *t = (ax & 0x00ff) + 'A'; 107 *t = '\0'; 108 s = buf; 109 } 110 111 c = peekb(0x40,0x49); // Get the current screen mode 112 if ((c < 4) || (c == 7)) 113 goto oh_kill_me; 114 115 // DEBUG - handle screen cleanup 116 117 US_SaveWindow(&wr); 118 US_CenterWindow(30,3); 119 US_CPrint(s); 120 US_CPrint("(R)etry or (A)bort?"); 121 VW_UpdateScreen(); 122 IN_ClearKeysDown(); 123 124 asm sti // Let the keyboard interrupts come through 125 126 while (true) 127 { 128 switch (IN_WaitForASCII()) 129 { 130 case key_Escape: 131 case 'a': 132 case 'A': 133 goto oh_kill_me; 134 break; 135 case key_Return: 136 case key_Space: 137 case 'r': 138 case 'R': 139 US_ClearWindow(); 140 VW_UpdateScreen(); 141 US_RestoreWindow(&wr); 142 return(RETRY); 143 break; 144 } 145 } 146 147 oh_kill_me: 148 abortprogram = s; 149 ShutdownId(); 150 fprintf(stderr,"Terminal Error: %s\n",s); 151 if (tedlevel) 152 fprintf(stderr,"You launched from TED. I suggest that you reboot...\n"); 153 154 return(ABORT); 155 #undef IGNORE 156 #undef RETRY 157 #undef ABORT 158 } 159 #pragma warn +par 160 #pragma warn +rch 161 162 163 /////////////////////////////////////////////////////////////////////////// 164 // 165 // US_Startup() - Starts the User Mgr 166 // 167 /////////////////////////////////////////////////////////////////////////// 168 void 169 US_Startup(void) 170 { 171 int i,n; 172 173 if (US_Started) 174 return; 175 176 harderr(USL_HardError); // Install the fatal error handler 177 178 US_InitRndT(true); // Initialize the random number generator 179 180 for (i = 1;i < _argc;i++) 181 { 182 switch (US_CheckParm(_argv[i],ParmStrings2)) 183 { 184 case 0: 185 compatability = true; 186 break; 187 case 1: 188 compatability = false; 189 break; 190 } 191 } 192 193 // Check for TED launching here 194 for (i = 1;i < _argc;i++) 195 { 196 n = US_CheckParm(_argv[i],ParmStrings); 197 switch(n) 198 { 199 case 0: 200 tedlevelnum = atoi(_argv[i + 1]); 201 if (tedlevelnum >= 0) 202 tedlevel = true; 203 break; 204 205 case 1: 206 NoWait = true; 207 break; 208 } 209 } 210 211 US_Started = true; 212 } 213 214 215 /////////////////////////////////////////////////////////////////////////// 216 // 217 // US_Shutdown() - Shuts down the User Mgr 218 // 219 /////////////////////////////////////////////////////////////////////////// 220 void 221 US_Shutdown(void) 222 { 223 if (!US_Started) 224 return; 225 226 US_Started = false; 227 } 228 229 /////////////////////////////////////////////////////////////////////////// 230 // 231 // US_CheckParm() - checks to see if a string matches one of a set of 232 // strings. The check is case insensitive. The routine returns the 233 // index of the string that matched, or -1 if no matches were found 234 // 235 /////////////////////////////////////////////////////////////////////////// 236 int 237 US_CheckParm(char *parm,char **strings) 238 { 239 char cp,cs, 240 *p,*s; 241 int i; 242 243 while (!isalpha(*parm)) // Skip non-alphas 244 parm++; 245 246 for (i = 0;*strings && **strings;i++) 247 { 248 for (s = *strings++,p = parm,cs = cp = 0;cs == cp;) 249 { 250 cs = *s++; 251 if (!cs) 252 return(i); 253 cp = *p++; 254 255 if (isupper(cs)) 256 cs = tolower(cs); 257 if (isupper(cp)) 258 cp = tolower(cp); 259 } 260 } 261 return(-1); 262 } 263 264 265 // Window/Printing routines 266 267 /////////////////////////////////////////////////////////////////////////// 268 // 269 // US_SetPrintRoutines() - Sets the routines used to measure and print 270 // from within the User Mgr. Primarily provided to allow switching 271 // between masked and non-masked fonts 272 // 273 /////////////////////////////////////////////////////////////////////////// 274 void 275 US_SetPrintRoutines(void (*measure)(char far *,word *,word *),void (*print)(char far *)) 276 { 277 USL_MeasureString = measure; 278 USL_DrawString = print; 279 } 280 281 /////////////////////////////////////////////////////////////////////////// 282 // 283 // US_Print() - Prints a string in the current window. Newlines are 284 // supported. 285 // 286 /////////////////////////////////////////////////////////////////////////// 287 void 288 US_Print(char far *s) 289 { 290 char c,far *se; 291 word w,h; 292 293 while (*s) 294 { 295 se = s; 296 while ((c = *se) && (c != '\n')) 297 se++; 298 *se = '\0'; 299 300 USL_MeasureString(s,&w,&h); 301 px = PrintX; 302 py = PrintY; 303 USL_DrawString(s); 304 305 s = se; 306 if (c) 307 { 308 *se = c; 309 s++; 310 311 PrintX = WindowX; 312 PrintY += h; 313 } 314 else 315 PrintX += w; 316 } 317 } 318 319 /////////////////////////////////////////////////////////////////////////// 320 // 321 // US_PrintUnsigned() - Prints an unsigned long 322 // 323 /////////////////////////////////////////////////////////////////////////// 324 void 325 US_PrintUnsigned(longword n) 326 { 327 char buffer[32]; 328 329 US_Print(ultoa(n,buffer,10)); 330 } 331 332 /////////////////////////////////////////////////////////////////////////// 333 // 334 // US_PrintSigned() - Prints a signed long 335 // 336 /////////////////////////////////////////////////////////////////////////// 337 void 338 US_PrintSigned(long n) 339 { 340 char buffer[32]; 341 342 US_Print(ltoa(n,buffer,10)); 343 } 344 345 /////////////////////////////////////////////////////////////////////////// 346 // 347 // USL_PrintInCenter() - Prints a string in the center of the given rect 348 // 349 /////////////////////////////////////////////////////////////////////////// 350 void 351 USL_PrintInCenter(char far *s,Rect r) 352 { 353 word w,h, 354 rw,rh; 355 356 USL_MeasureString(s,&w,&h); 357 rw = r.lr.x - r.ul.x; 358 rh = r.lr.y - r.ul.y; 359 360 px = r.ul.x + ((rw - w) / 2); 361 py = r.ul.y + ((rh - h) / 2); 362 USL_DrawString(s); 363 } 364 365 /////////////////////////////////////////////////////////////////////////// 366 // 367 // US_PrintCentered() - Prints a string centered in the current window. 368 // 369 /////////////////////////////////////////////////////////////////////////// 370 void 371 US_PrintCentered(char far *s) 372 { 373 Rect r; 374 375 r.ul.x = WindowX; 376 r.ul.y = WindowY; 377 r.lr.x = r.ul.x + WindowW; 378 r.lr.y = r.ul.y + WindowH; 379 380 USL_PrintInCenter(s,r); 381 } 382 383 /////////////////////////////////////////////////////////////////////////// 384 // 385 // US_CPrintLine() - Prints a string centered on the current line and 386 // advances to the next line. Newlines are not supported. 387 // 388 /////////////////////////////////////////////////////////////////////////// 389 void 390 US_CPrintLine(char far *s) 391 { 392 word w,h; 393 394 USL_MeasureString(s,&w,&h); 395 396 if (w > WindowW) 397 Quit("US_CPrintLine() - String exceeds width"); 398 px = WindowX + ((WindowW - w) / 2); 399 py = PrintY; 400 USL_DrawString(s); 401 PrintY += h; 402 } 403 404 /////////////////////////////////////////////////////////////////////////// 405 // 406 // US_CPrint() - Prints a string in the current window. Newlines are 407 // supported. 408 // 409 /////////////////////////////////////////////////////////////////////////// 410 void 411 US_CPrint(char far *s) 412 { 413 char c,far *se; 414 415 while (*s) 416 { 417 se = s; 418 while ((c = *se) && (c != '\n')) 419 se++; 420 *se = '\0'; 421 422 US_CPrintLine(s); 423 424 s = se; 425 if (c) 426 { 427 *se = c; 428 s++; 429 } 430 } 431 } 432 433 /////////////////////////////////////////////////////////////////////////// 434 // 435 // US_ClearWindow() - Clears the current window to white and homes the 436 // cursor 437 // 438 /////////////////////////////////////////////////////////////////////////// 439 void 440 US_ClearWindow(void) 441 { 442 VWB_Bar(WindowX,WindowY,WindowW,WindowH,WHITE); 443 PrintX = WindowX; 444 PrintY = WindowY; 445 } 446 447 /////////////////////////////////////////////////////////////////////////// 448 // 449 // US_DrawWindow() - Draws a frame and sets the current window parms 450 // 451 /////////////////////////////////////////////////////////////////////////// 452 void 453 US_DrawWindow(word x,word y,word w,word h) 454 { 455 word i, 456 sx,sy,sw,sh; 457 458 WindowX = x * 8; 459 WindowY = y * 8; 460 WindowW = w * 8; 461 WindowH = h * 8; 462 463 PrintX = WindowX; 464 PrintY = WindowY; 465 466 sx = (x - 1) * 8; 467 sy = (y - 1) * 8; 468 sw = (w + 1) * 8; 469 sh = (h + 1) * 8; 470 471 US_ClearWindow(); 472 473 VWB_DrawTile8(sx,sy,0),VWB_DrawTile8(sx,sy + sh,5); 474 for (i = sx + 8;i <= sx + sw - 8;i += 8) 475 VWB_DrawTile8(i,sy,1),VWB_DrawTile8(i,sy + sh,6); 476 VWB_DrawTile8(i,sy,2),VWB_DrawTile8(i,sy + sh,7); 477 478 for (i = sy + 8;i <= sy + sh - 8;i += 8) 479 VWB_DrawTile8(sx,i,3),VWB_DrawTile8(sx + sw,i,4); 480 } 481 482 /////////////////////////////////////////////////////////////////////////// 483 // 484 // US_CenterWindow() - Generates a window of a given width & height in the 485 // middle of the screen 486 // 487 /////////////////////////////////////////////////////////////////////////// 488 void 489 US_CenterWindow(word w,word h) 490 { 491 US_DrawWindow(((MaxX / 8) - w) / 2,((MaxY / 8) - h) / 2,w,h); 492 } 493 494 /////////////////////////////////////////////////////////////////////////// 495 // 496 // US_SaveWindow() - Saves the current window parms into a record for 497 // later restoration 498 // 499 /////////////////////////////////////////////////////////////////////////// 500 void 501 US_SaveWindow(WindowRec *win) 502 { 503 win->x = WindowX; 504 win->y = WindowY; 505 win->w = WindowW; 506 win->h = WindowH; 507 508 win->px = PrintX; 509 win->py = PrintY; 510 } 511 512 /////////////////////////////////////////////////////////////////////////// 513 // 514 // US_RestoreWindow() - Sets the current window parms to those held in the 515 // record 516 // 517 /////////////////////////////////////////////////////////////////////////// 518 void 519 US_RestoreWindow(WindowRec *win) 520 { 521 WindowX = win->x; 522 WindowY = win->y; 523 WindowW = win->w; 524 WindowH = win->h; 525 526 PrintX = win->px; 527 PrintY = win->py; 528 } 529 530 // Input routines 531 532 /////////////////////////////////////////////////////////////////////////// 533 // 534 // USL_XORICursor() - XORs the I-bar text cursor. Used by US_LineInput() 535 // 536 /////////////////////////////////////////////////////////////////////////// 537 static void 538 USL_XORICursor(int x,int y,char *s,word cursor) 539 { 540 static boolean status; // VGA doesn't XOR... 541 char buf[MaxString]; 542 int temp; 543 word w,h; 544 545 strcpy(buf,s); 546 buf[cursor] = '\0'; 547 USL_MeasureString(buf,&w,&h); 548 549 px = x + w - 1; 550 py = y; 551 if (status^=1) 552 USL_DrawString("\x80"); 553 else 554 { 555 temp = fontcolor; 556 fontcolor = backcolor; 557 USL_DrawString("\x80"); 558 fontcolor = temp; 559 } 560 561 } 562 563 /////////////////////////////////////////////////////////////////////////// 564 // 565 // US_LineInput() - Gets a line of user input at (x,y), the string defaults 566 // to whatever is pointed at by def. Input is restricted to maxchars 567 // chars or maxwidth pixels wide. If the user hits escape (and escok is 568 // true), nothing is copied into buf, and false is returned. If the 569 // user hits return, the current string is copied into buf, and true is 570 // returned 571 // 572 /////////////////////////////////////////////////////////////////////////// 573 boolean 574 US_LineInput(int x,int y,char *buf,char *def,boolean escok, 575 int maxchars,int maxwidth) 576 { 577 boolean redraw, 578 cursorvis,cursormoved, 579 done,result; 580 ScanCode sc; 581 char c, 582 s[MaxString],olds[MaxString]; 583 word i, 584 cursor, 585 w,h, 586 len,temp; 587 longword lasttime; 588 589 if (def) 590 strcpy(s,def); 591 else 592 *s = '\0'; 593 *olds = '\0'; 594 cursor = strlen(s); 595 cursormoved = redraw = true; 596 597 cursorvis = done = false; 598 lasttime = TimeCount; 599 LastASCII = key_None; 600 LastScan = sc_None; 601 602 while (!done) 603 { 604 if (cursorvis) 605 USL_XORICursor(x,y,s,cursor); 606 607 asm pushf 608 asm cli 609 610 sc = LastScan; 611 LastScan = sc_None; 612 c = LastASCII; 613 LastASCII = key_None; 614 615 asm popf 616 617 switch (sc) 618 { 619 case sc_LeftArrow: 620 if (cursor) 621 cursor--; 622 c = key_None; 623 cursormoved = true; 624 break; 625 case sc_RightArrow: 626 if (s[cursor]) 627 cursor++; 628 c = key_None; 629 cursormoved = true; 630 break; 631 case sc_Home: 632 cursor = 0; 633 c = key_None; 634 cursormoved = true; 635 break; 636 case sc_End: 637 cursor = strlen(s); 638 c = key_None; 639 cursormoved = true; 640 break; 641 642 case sc_Return: 643 strcpy(buf,s); 644 done = true; 645 result = true; 646 c = key_None; 647 break; 648 case sc_Escape: 649 if (escok) 650 { 651 done = true; 652 result = false; 653 } 654 c = key_None; 655 break; 656 657 case sc_BackSpace: 658 if (cursor) 659 { 660 strcpy(s + cursor - 1,s + cursor); 661 cursor--; 662 redraw = true; 663 } 664 c = key_None; 665 cursormoved = true; 666 break; 667 case sc_Delete: 668 if (s[cursor]) 669 { 670 strcpy(s + cursor,s + cursor + 1); 671 redraw = true; 672 } 673 c = key_None; 674 cursormoved = true; 675 break; 676 677 case 0x4c: // Keypad 5 678 case sc_UpArrow: 679 case sc_DownArrow: 680 case sc_PgUp: 681 case sc_PgDn: 682 case sc_Insert: 683 c = key_None; 684 break; 685 } 686 687 if (c) 688 { 689 len = strlen(s); 690 USL_MeasureString(s,&w,&h); 691 692 if 693 ( 694 isprint(c) 695 && (len < MaxString - 1) 696 && ((!maxchars) || (len < maxchars)) 697 && ((!maxwidth) || (w < maxwidth)) 698 ) 699 { 700 for (i = len + 1;i > cursor;i--) 701 s[i] = s[i - 1]; 702 s[cursor++] = c; 703 redraw = true; 704 } 705 } 706 707 if (redraw) 708 { 709 px = x; 710 py = y; 711 temp = fontcolor; 712 fontcolor = backcolor; 713 USL_DrawString(olds); 714 fontcolor = temp; 715 strcpy(olds,s); 716 717 px = x; 718 py = y; 719 USL_DrawString(s); 720 721 redraw = false; 722 } 723 724 if (cursormoved) 725 { 726 cursorvis = false; 727 lasttime = TimeCount - TickBase; 728 729 cursormoved = false; 730 } 731 if (TimeCount - lasttime > TickBase / 2) 732 { 733 lasttime = TimeCount; 734 735 cursorvis ^= true; 736 } 737 if (cursorvis) 738 USL_XORICursor(x,y,s,cursor); 739 740 VW_UpdateScreen(); 741 } 742 743 if (cursorvis) 744 USL_XORICursor(x,y,s,cursor); 745 if (!result) 746 { 747 px = x; 748 py = y; 749 USL_DrawString(olds); 750 } 751 VW_UpdateScreen(); 752 753 IN_ClearKeysDown(); 754 return(result); 755 }