wolf3d

The original open source release of Wolfenstein 3D
Log | Files | Refs

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 }