wolf3d

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

WL_PLAY.C (24378B)


      1 // WL_PLAY.C
      2 
      3 #include "WL_DEF.H"
      4 #pragma hdrstop
      5 
      6 
      7 /*
      8 =============================================================================
      9 
     10 						 LOCAL CONSTANTS
     11 
     12 =============================================================================
     13 */
     14 
     15 #define sc_Question	0x35
     16 
     17 /*
     18 =============================================================================
     19 
     20 						 GLOBAL VARIABLES
     21 
     22 =============================================================================
     23 */
     24 
     25 boolean		madenoise;					// true when shooting or screaming
     26 
     27 exit_t		playstate;
     28 
     29 int			DebugOk;
     30 
     31 objtype 	objlist[MAXACTORS],*new,*obj,*player,*lastobj,
     32 			*objfreelist,*killerobj;
     33 
     34 unsigned	farmapylookup[MAPSIZE];
     35 byte		*nearmapylookup[MAPSIZE];
     36 
     37 boolean		singlestep,godmode,noclip;
     38 int			extravbls;
     39 
     40 byte		tilemap[MAPSIZE][MAPSIZE];	// wall values only
     41 byte		spotvis[MAPSIZE][MAPSIZE];
     42 objtype		*actorat[MAPSIZE][MAPSIZE];
     43 
     44 //
     45 // replacing refresh manager
     46 //
     47 unsigned	mapwidth,mapheight,tics;
     48 boolean		compatability;
     49 byte		*updateptr;
     50 unsigned	mapwidthtable[64];
     51 unsigned	uwidthtable[UPDATEHIGH];
     52 unsigned	blockstarts[UPDATEWIDE*UPDATEHIGH];
     53 byte		update[UPDATESIZE];
     54 
     55 //
     56 // control info
     57 //
     58 boolean		mouseenabled,joystickenabled,joypadenabled,joystickprogressive;
     59 int			joystickport;
     60 int			dirscan[4] = {sc_UpArrow,sc_RightArrow,sc_DownArrow,sc_LeftArrow};
     61 int			buttonscan[NUMBUTTONS] =
     62 			{sc_Control,sc_Alt,sc_RShift,sc_Space,sc_1,sc_2,sc_3,sc_4};
     63 int			buttonmouse[4]={bt_attack,bt_strafe,bt_use,bt_nobutton};
     64 int			buttonjoy[4]={bt_attack,bt_strafe,bt_use,bt_run};
     65 
     66 int			viewsize;
     67 
     68 boolean		buttonheld[NUMBUTTONS];
     69 
     70 boolean		demorecord,demoplayback;
     71 char		far *demoptr, far *lastdemoptr;
     72 memptr		demobuffer;
     73 
     74 //
     75 // curent user input
     76 //
     77 int			controlx,controly;		// range from -100 to 100 per tic
     78 boolean		buttonstate[NUMBUTTONS];
     79 
     80 
     81 
     82 //===========================================================================
     83 
     84 
     85 void	CenterWindow(word w,word h);
     86 void 	InitObjList (void);
     87 void 	RemoveObj (objtype *gone);
     88 void 	PollControls (void);
     89 void 	StopMusic(void);
     90 void 	StartMusic(void);
     91 void	PlayLoop (void);
     92 
     93 /*
     94 =============================================================================
     95 
     96 						 LOCAL VARIABLES
     97 
     98 =============================================================================
     99 */
    100 
    101 
    102 objtype dummyobj;
    103 
    104 //
    105 // LIST OF SONGS FOR EACH VERSION
    106 //
    107 int songs[]=
    108 {
    109 #ifndef SPEAR
    110  //
    111  // Episode One
    112  //
    113  GETTHEM_MUS,
    114  SEARCHN_MUS,
    115  POW_MUS,
    116  SUSPENSE_MUS,
    117  GETTHEM_MUS,
    118  SEARCHN_MUS,
    119  POW_MUS,
    120  SUSPENSE_MUS,
    121 
    122  WARMARCH_MUS,	// Boss level
    123  CORNER_MUS,	// Secret level
    124 
    125  //
    126  // Episode Two
    127  //
    128  NAZI_OMI_MUS,
    129  PREGNANT_MUS,
    130  GOINGAFT_MUS,
    131  HEADACHE_MUS,
    132  NAZI_OMI_MUS,
    133  PREGNANT_MUS,
    134  HEADACHE_MUS,
    135  GOINGAFT_MUS,
    136 
    137  WARMARCH_MUS,	// Boss level
    138  DUNGEON_MUS,	// Secret level
    139 
    140  //
    141  // Episode Three
    142  //
    143  INTROCW3_MUS,
    144  NAZI_RAP_MUS,
    145  TWELFTH_MUS,
    146  ZEROHOUR_MUS,
    147  INTROCW3_MUS,
    148  NAZI_RAP_MUS,
    149  TWELFTH_MUS,
    150  ZEROHOUR_MUS,
    151 
    152  ULTIMATE_MUS,	// Boss level
    153  PACMAN_MUS,	// Secret level
    154 
    155  //
    156  // Episode Four
    157  //
    158  GETTHEM_MUS,
    159  SEARCHN_MUS,
    160  POW_MUS,
    161  SUSPENSE_MUS,
    162  GETTHEM_MUS,
    163  SEARCHN_MUS,
    164  POW_MUS,
    165  SUSPENSE_MUS,
    166 
    167  WARMARCH_MUS,	// Boss level
    168  CORNER_MUS,	// Secret level
    169 
    170  //
    171  // Episode Five
    172  //
    173  NAZI_OMI_MUS,
    174  PREGNANT_MUS,
    175  GOINGAFT_MUS,
    176  HEADACHE_MUS,
    177  NAZI_OMI_MUS,
    178  PREGNANT_MUS,
    179  HEADACHE_MUS,
    180  GOINGAFT_MUS,
    181 
    182  WARMARCH_MUS,	// Boss level
    183  DUNGEON_MUS,	// Secret level
    184 
    185  //
    186  // Episode Six
    187  //
    188  INTROCW3_MUS,
    189  NAZI_RAP_MUS,
    190  TWELFTH_MUS,
    191  ZEROHOUR_MUS,
    192  INTROCW3_MUS,
    193  NAZI_RAP_MUS,
    194  TWELFTH_MUS,
    195  ZEROHOUR_MUS,
    196 
    197  ULTIMATE_MUS,	// Boss level
    198  FUNKYOU_MUS		// Secret level
    199 #else
    200 
    201  //////////////////////////////////////////////////////////////
    202  //
    203  // SPEAR OF DESTINY TRACKS
    204  //
    205  //////////////////////////////////////////////////////////////
    206  XTIPTOE_MUS,
    207  XFUNKIE_MUS,
    208  XDEATH_MUS,
    209  XGETYOU_MUS,		// DON'T KNOW
    210  ULTIMATE_MUS,	// Trans Gr”sse
    211 
    212  DUNGEON_MUS,
    213  GOINGAFT_MUS,
    214  POW_MUS,
    215  TWELFTH_MUS,
    216  ULTIMATE_MUS,	// Barnacle Wilhelm BOSS
    217 
    218  NAZI_OMI_MUS,
    219  GETTHEM_MUS,
    220  SUSPENSE_MUS,
    221  SEARCHN_MUS,
    222  ZEROHOUR_MUS,
    223  ULTIMATE_MUS,	// Super Mutant BOSS
    224 
    225  XPUTIT_MUS,
    226  ULTIMATE_MUS,	// Death Knight BOSS
    227 
    228  XJAZNAZI_MUS,	// Secret level
    229  XFUNKIE_MUS,	// Secret level (DON'T KNOW)
    230 
    231  XEVIL_MUS		// Angel of Death BOSS
    232 
    233 #endif
    234 };
    235 
    236 
    237 /*
    238 =============================================================================
    239 
    240 						  USER CONTROL
    241 
    242 =============================================================================
    243 */
    244 
    245 
    246 #define BASEMOVE		35
    247 #define RUNMOVE			70
    248 #define BASETURN		35
    249 #define RUNTURN			70
    250 
    251 #define JOYSCALE		2
    252 
    253 /*
    254 ===================
    255 =
    256 = PollKeyboardButtons
    257 =
    258 ===================
    259 */
    260 
    261 void PollKeyboardButtons (void)
    262 {
    263 	int		i;
    264 
    265 	for (i=0;i<NUMBUTTONS;i++)
    266 		if (Keyboard[buttonscan[i]])
    267 			buttonstate[i] = true;
    268 }
    269 
    270 
    271 /*
    272 ===================
    273 =
    274 = PollMouseButtons
    275 =
    276 ===================
    277 */
    278 
    279 void PollMouseButtons (void)
    280 {
    281 	int	buttons;
    282 
    283 	buttons = IN_MouseButtons ();
    284 
    285 	if (buttons&1)
    286 		buttonstate[buttonmouse[0]] = true;
    287 	if (buttons&2)
    288 		buttonstate[buttonmouse[1]] = true;
    289 	if (buttons&4)
    290 		buttonstate[buttonmouse[2]] = true;
    291 }
    292 
    293 
    294 
    295 /*
    296 ===================
    297 =
    298 = PollJoystickButtons
    299 =
    300 ===================
    301 */
    302 
    303 void PollJoystickButtons (void)
    304 {
    305 	int	buttons;
    306 
    307 	buttons = IN_JoyButtons ();
    308 
    309 	if (joystickport && !joypadenabled)
    310 	{
    311 		if (buttons&4)
    312 			buttonstate[buttonjoy[0]] = true;
    313 		if (buttons&8)
    314 			buttonstate[buttonjoy[1]] = true;
    315 	}
    316 	else
    317 	{
    318 		if (buttons&1)
    319 			buttonstate[buttonjoy[0]] = true;
    320 		if (buttons&2)
    321 			buttonstate[buttonjoy[1]] = true;
    322 		if (joypadenabled)
    323 		{
    324 			if (buttons&4)
    325 				buttonstate[buttonjoy[2]] = true;
    326 			if (buttons&8)
    327 				buttonstate[buttonjoy[3]] = true;
    328 		}
    329 	}
    330 }
    331 
    332 
    333 /*
    334 ===================
    335 =
    336 = PollKeyboardMove
    337 =
    338 ===================
    339 */
    340 
    341 void PollKeyboardMove (void)
    342 {
    343 	if (buttonstate[bt_run])
    344 	{
    345 		if (Keyboard[dirscan[di_north]])
    346 			controly -= RUNMOVE*tics;
    347 		if (Keyboard[dirscan[di_south]])
    348 			controly += RUNMOVE*tics;
    349 		if (Keyboard[dirscan[di_west]])
    350 			controlx -= RUNMOVE*tics;
    351 		if (Keyboard[dirscan[di_east]])
    352 			controlx += RUNMOVE*tics;
    353 	}
    354 	else
    355 	{
    356 		if (Keyboard[dirscan[di_north]])
    357 			controly -= BASEMOVE*tics;
    358 		if (Keyboard[dirscan[di_south]])
    359 			controly += BASEMOVE*tics;
    360 		if (Keyboard[dirscan[di_west]])
    361 			controlx -= BASEMOVE*tics;
    362 		if (Keyboard[dirscan[di_east]])
    363 			controlx += BASEMOVE*tics;
    364 	}
    365 }
    366 
    367 
    368 /*
    369 ===================
    370 =
    371 = PollMouseMove
    372 =
    373 ===================
    374 */
    375 
    376 void PollMouseMove (void)
    377 {
    378 	int	mousexmove,mouseymove;
    379 
    380 	Mouse(MDelta);
    381 	mousexmove = _CX;
    382 	mouseymove = _DX;
    383 
    384 	controlx += mousexmove*10/(13-mouseadjustment);
    385 	controly += mouseymove*20/(13-mouseadjustment);
    386 }
    387 
    388 
    389 
    390 /*
    391 ===================
    392 =
    393 = PollJoystickMove
    394 =
    395 ===================
    396 */
    397 
    398 void PollJoystickMove (void)
    399 {
    400 	int	joyx,joyy;
    401 
    402 	INL_GetJoyDelta(joystickport,&joyx,&joyy);
    403 
    404 	if (joystickprogressive)
    405 	{
    406 		if (joyx > 64)
    407 			controlx += (joyx-64)*JOYSCALE*tics;
    408 		else if (joyx < -64)
    409 			controlx -= (-joyx-64)*JOYSCALE*tics;
    410 		if (joyy > 64)
    411 			controlx += (joyy-64)*JOYSCALE*tics;
    412 		else if (joyy < -64)
    413 			controly -= (-joyy-64)*JOYSCALE*tics;
    414 	}
    415 	else if (buttonstate[bt_run])
    416 	{
    417 		if (joyx > 64)
    418 			controlx += RUNMOVE*tics;
    419 		else if (joyx < -64)
    420 			controlx -= RUNMOVE*tics;
    421 		if (joyy > 64)
    422 			controly += RUNMOVE*tics;
    423 		else if (joyy < -64)
    424 			controly -= RUNMOVE*tics;
    425 	}
    426 	else
    427 	{
    428 		if (joyx > 64)
    429 			controlx += BASEMOVE*tics;
    430 		else if (joyx < -64)
    431 			controlx -= BASEMOVE*tics;
    432 		if (joyy > 64)
    433 			controly += BASEMOVE*tics;
    434 		else if (joyy < -64)
    435 			controly -= BASEMOVE*tics;
    436 	}
    437 }
    438 
    439 
    440 /*
    441 ===================
    442 =
    443 = PollControls
    444 =
    445 = Gets user or demo input, call once each frame
    446 =
    447 = controlx		set between -100 and 100 per tic
    448 = controly
    449 = buttonheld[]	the state of the buttons LAST frame
    450 = buttonstate[]	the state of the buttons THIS frame
    451 =
    452 ===================
    453 */
    454 
    455 void PollControls (void)
    456 {
    457 	int		max,min,i;
    458 	byte	buttonbits;
    459 
    460 //
    461 // get timing info for last frame
    462 //
    463 	if (demoplayback)
    464 	{
    465 		while (TimeCount<lasttimecount+DEMOTICS)
    466 		;
    467 		TimeCount = lasttimecount + DEMOTICS;
    468 		lasttimecount += DEMOTICS;
    469 		tics = DEMOTICS;
    470 	}
    471 	else if (demorecord)			// demo recording and playback needs
    472 	{								// to be constant
    473 //
    474 // take DEMOTICS or more tics, and modify Timecount to reflect time taken
    475 //
    476 		while (TimeCount<lasttimecount+DEMOTICS)
    477 		;
    478 		TimeCount = lasttimecount + DEMOTICS;
    479 		lasttimecount += DEMOTICS;
    480 		tics = DEMOTICS;
    481 	}
    482 	else
    483 		CalcTics ();
    484 
    485 	controlx = 0;
    486 	controly = 0;
    487 	memcpy (buttonheld,buttonstate,sizeof(buttonstate));
    488 	memset (buttonstate,0,sizeof(buttonstate));
    489 
    490 	if (demoplayback)
    491 	{
    492 	//
    493 	// read commands from demo buffer
    494 	//
    495 		buttonbits = *demoptr++;
    496 		for (i=0;i<NUMBUTTONS;i++)
    497 		{
    498 			buttonstate[i] = buttonbits&1;
    499 			buttonbits >>= 1;
    500 		}
    501 
    502 		controlx = *demoptr++;
    503 		controly = *demoptr++;
    504 
    505 		if (demoptr == lastdemoptr)
    506 			playstate = ex_completed;		// demo is done
    507 
    508 		controlx *= (int)tics;
    509 		controly *= (int)tics;
    510 
    511 		return;
    512 	}
    513 
    514 
    515 //
    516 // get button states
    517 //
    518 	PollKeyboardButtons ();
    519 
    520 	if (mouseenabled)
    521 		PollMouseButtons ();
    522 
    523 	if (joystickenabled)
    524 		PollJoystickButtons ();
    525 
    526 //
    527 // get movements
    528 //
    529 	PollKeyboardMove ();
    530 
    531 	if (mouseenabled)
    532 		PollMouseMove ();
    533 
    534 	if (joystickenabled)
    535 		PollJoystickMove ();
    536 
    537 //
    538 // bound movement to a maximum
    539 //
    540 	max = 100*tics;
    541 	min = -max;
    542 	if (controlx > max)
    543 		controlx = max;
    544 	else if (controlx < min)
    545 		controlx = min;
    546 
    547 	if (controly > max)
    548 		controly = max;
    549 	else if (controly < min)
    550 		controly = min;
    551 
    552 	if (demorecord)
    553 	{
    554 	//
    555 	// save info out to demo buffer
    556 	//
    557 		controlx /= (int)tics;
    558 		controly /= (int)tics;
    559 
    560 		buttonbits = 0;
    561 
    562 		for (i=NUMBUTTONS-1;i>=0;i--)
    563 		{
    564 			buttonbits <<= 1;
    565 			if (buttonstate[i])
    566 				buttonbits |= 1;
    567 		}
    568 
    569 		*demoptr++ = buttonbits;
    570 		*demoptr++ = controlx;
    571 		*demoptr++ = controly;
    572 
    573 		if (demoptr >= lastdemoptr)
    574 			Quit ("Demo buffer overflowed!");
    575 
    576 		controlx *= (int)tics;
    577 		controly *= (int)tics;
    578 	}
    579 }
    580 
    581 
    582 
    583 //==========================================================================
    584 
    585 
    586 
    587 ///////////////////////////////////////////////////////////////////////////
    588 //
    589 //	CenterWindow() - Generates a window of a given width & height in the
    590 //		middle of the screen
    591 //
    592 ///////////////////////////////////////////////////////////////////////////
    593 
    594 #define MAXX	320
    595 #define MAXY	160
    596 
    597 void	CenterWindow(word w,word h)
    598 {
    599 	FixOfs ();
    600 	US_DrawWindow(((MAXX / 8) - w) / 2,((MAXY / 8) - h) / 2,w,h);
    601 }
    602 
    603 //===========================================================================
    604 
    605 
    606 /*
    607 =====================
    608 =
    609 = CheckKeys
    610 =
    611 =====================
    612 */
    613 
    614 void CheckKeys (void)
    615 {
    616 	int		i;
    617 	byte	scan;
    618 	unsigned	temp;
    619 
    620 
    621 	if (screenfaded || demoplayback)	// don't do anything with a faded screen
    622 		return;
    623 
    624 	scan = LastScan;
    625 
    626 
    627 	#ifdef SPEAR
    628 	//
    629 	// SECRET CHEAT CODE: TAB-G-F10
    630 	//
    631 	if (Keyboard[sc_Tab] &&
    632 		Keyboard[sc_G] &&
    633 		Keyboard[sc_F10])
    634 	{
    635 		WindowH = 160;
    636 		if (godmode)
    637 		{
    638 			Message ("God mode OFF");
    639 			SD_PlaySound (NOBONUSSND);
    640 		}
    641 		else
    642 		{
    643 			Message ("God mode ON");
    644 			SD_PlaySound (ENDBONUS2SND);
    645 		}
    646 
    647 		IN_Ack();
    648 		godmode ^= 1;
    649 		DrawAllPlayBorderSides ();
    650 		IN_ClearKeysDown();
    651 		return;
    652 	}
    653 	#endif
    654 
    655 
    656 	//
    657 	// SECRET CHEAT CODE: 'MLI'
    658 	//
    659 	if (Keyboard[sc_M] &&
    660 		Keyboard[sc_L] &&
    661 		Keyboard[sc_I])
    662 	{
    663 		gamestate.health = 100;
    664 		gamestate.ammo = 99;
    665 		gamestate.keys = 3;
    666 		gamestate.score = 0;
    667 		gamestate.TimeCount += 42000L;
    668 		GiveWeapon (wp_chaingun);
    669 
    670 		DrawWeapon();
    671 		DrawHealth();
    672 		DrawKeys();
    673 		DrawAmmo();
    674 		DrawScore();
    675 
    676 		ClearMemory ();
    677 		CA_CacheGrChunk (STARTFONT+1);
    678 		ClearSplitVWB ();
    679 		VW_ScreenToScreen (displayofs,bufferofs,80,160);
    680 
    681 		Message(STR_CHEATER1"\n"
    682 				STR_CHEATER2"\n\n"
    683 				STR_CHEATER3"\n"
    684 				STR_CHEATER4"\n"
    685 				STR_CHEATER5);
    686 
    687 		UNCACHEGRCHUNK(STARTFONT+1);
    688 		PM_CheckMainMem ();
    689 		IN_ClearKeysDown();
    690 		IN_Ack();
    691 
    692 		DrawAllPlayBorder ();
    693 	}
    694 
    695 	//
    696 	// OPEN UP DEBUG KEYS
    697 	//
    698 #ifndef SPEAR
    699 	if (Keyboard[sc_BackSpace] &&
    700 		Keyboard[sc_LShift] &&
    701 		Keyboard[sc_Alt] &&
    702 		MS_CheckParm("goobers"))
    703 #else
    704 	if (Keyboard[sc_BackSpace] &&
    705 		Keyboard[sc_LShift] &&
    706 		Keyboard[sc_Alt] &&
    707 		MS_CheckParm("debugmode"))
    708 #endif
    709 	{
    710 	 ClearMemory ();
    711 	 CA_CacheGrChunk (STARTFONT+1);
    712 	 ClearSplitVWB ();
    713 	 VW_ScreenToScreen (displayofs,bufferofs,80,160);
    714 
    715 	 Message("Debugging keys are\nnow available!");
    716 	 UNCACHEGRCHUNK(STARTFONT+1);
    717 	 PM_CheckMainMem ();
    718 	 IN_ClearKeysDown();
    719 	 IN_Ack();
    720 
    721 	 DrawAllPlayBorderSides ();
    722 	 DebugOk=1;
    723 	}
    724 
    725 	//
    726 	// TRYING THE KEEN CHEAT CODE!
    727 	//
    728 	if (Keyboard[sc_B] &&
    729 		Keyboard[sc_A] &&
    730 		Keyboard[sc_T])
    731 	{
    732 	 ClearMemory ();
    733 	 CA_CacheGrChunk (STARTFONT+1);
    734 	 ClearSplitVWB ();
    735 	 VW_ScreenToScreen (displayofs,bufferofs,80,160);
    736 
    737 	 Message("Commander Keen is also\n"
    738 			 "available from Apogee, but\n"
    739 			 "then, you already know\n"
    740 			 "that - right, Cheatmeister?!");
    741 
    742 	 UNCACHEGRCHUNK(STARTFONT+1);
    743 	 PM_CheckMainMem ();
    744 	 IN_ClearKeysDown();
    745 	 IN_Ack();
    746 
    747 	 DrawAllPlayBorder ();
    748 	}
    749 
    750 //
    751 // pause key weirdness can't be checked as a scan code
    752 //
    753 	if (Paused)
    754 	{
    755 		bufferofs = displayofs;
    756 		LatchDrawPic (20-4,80-2*8,PAUSEDPIC);
    757 		SD_MusicOff();
    758 		IN_Ack();
    759 		IN_ClearKeysDown ();
    760 		SD_MusicOn();
    761 		Paused = false;
    762 		if (MousePresent)
    763 			Mouse(MDelta);	// Clear accumulated mouse movement
    764 		return;
    765 	}
    766 
    767 
    768 //
    769 // F1-F7/ESC to enter control panel
    770 //
    771 	if (
    772 #ifndef DEBCHECK
    773 		scan == sc_F10 ||
    774 #endif
    775 		scan == sc_F9 ||
    776 		scan == sc_F7 ||
    777 		scan == sc_F8)			// pop up quit dialog
    778 	{
    779 		ClearMemory ();
    780 		ClearSplitVWB ();
    781 		VW_ScreenToScreen (displayofs,bufferofs,80,160);
    782 		US_ControlPanel(scan);
    783 
    784 		 DrawAllPlayBorderSides ();
    785 
    786 		if (scan == sc_F9)
    787 		  StartMusic ();
    788 
    789 		PM_CheckMainMem ();
    790 		SETFONTCOLOR(0,15);
    791 		IN_ClearKeysDown();
    792 		return;
    793 	}
    794 
    795 	if ( (scan >= sc_F1 && scan <= sc_F9) || scan == sc_Escape)
    796 	{
    797 		StopMusic ();
    798 		ClearMemory ();
    799 		VW_FadeOut ();
    800 
    801 		US_ControlPanel(scan);
    802 
    803 		SETFONTCOLOR(0,15);
    804 		IN_ClearKeysDown();
    805 		DrawPlayScreen ();
    806 		if (!startgame && !loadedgame)
    807 		{
    808 			VW_FadeIn ();
    809 			StartMusic ();
    810 		}
    811 		if (loadedgame)
    812 			playstate = ex_abort;
    813 		lasttimecount = TimeCount;
    814 		if (MousePresent)
    815 			Mouse(MDelta);	// Clear accumulated mouse movement
    816 		PM_CheckMainMem ();
    817 		return;
    818 	}
    819 
    820 //
    821 // TAB-? debug keys
    822 //
    823 	if (Keyboard[sc_Tab] && DebugOk)
    824 	{
    825 		CA_CacheGrChunk (STARTFONT);
    826 		fontnumber=0;
    827 		SETFONTCOLOR(0,15);
    828 		DebugKeys();
    829 		if (MousePresent)
    830 			Mouse(MDelta);	// Clear accumulated mouse movement
    831 		lasttimecount = TimeCount;
    832 		return;
    833 	}
    834 
    835 }
    836 
    837 
    838 //===========================================================================
    839 
    840 /*
    841 #############################################################################
    842 
    843 				  The objlist data structure
    844 
    845 #############################################################################
    846 
    847 objlist containt structures for every actor currently playing.  The structure
    848 is accessed as a linked list starting at *player, ending when ob->next ==
    849 NULL.  GetNewObj inserts a new object at the end of the list, meaning that
    850 if an actor spawn another actor, the new one WILL get to think and react the
    851 same frame.  RemoveObj unlinks the given object and returns it to the free
    852 list, but does not damage the objects ->next pointer, so if the current object
    853 removes itself, a linked list following loop can still safely get to the
    854 next element.
    855 
    856 <backwardly linked free list>
    857 
    858 #############################################################################
    859 */
    860 
    861 
    862 /*
    863 =========================
    864 =
    865 = InitActorList
    866 =
    867 = Call to clear out the actor object lists returning them all to the free
    868 = list.  Allocates a special spot for the player.
    869 =
    870 =========================
    871 */
    872 
    873 int	objcount;
    874 
    875 void InitActorList (void)
    876 {
    877 	int	i;
    878 
    879 //
    880 // init the actor lists
    881 //
    882 	for (i=0;i<MAXACTORS;i++)
    883 	{
    884 		objlist[i].prev = &objlist[i+1];
    885 		objlist[i].next = NULL;
    886 	}
    887 
    888 	objlist[MAXACTORS-1].prev = NULL;
    889 
    890 	objfreelist = &objlist[0];
    891 	lastobj = NULL;
    892 
    893 	objcount = 0;
    894 
    895 //
    896 // give the player the first free spots
    897 //
    898 	GetNewActor ();
    899 	player = new;
    900 
    901 }
    902 
    903 //===========================================================================
    904 
    905 /*
    906 =========================
    907 =
    908 = GetNewActor
    909 =
    910 = Sets the global variable new to point to a free spot in objlist.
    911 = The free spot is inserted at the end of the liked list
    912 =
    913 = When the object list is full, the caller can either have it bomb out ot
    914 = return a dummy object pointer that will never get used
    915 =
    916 =========================
    917 */
    918 
    919 void GetNewActor (void)
    920 {
    921 	if (!objfreelist)
    922 		Quit ("GetNewActor: No free spots in objlist!");
    923 
    924 	new = objfreelist;
    925 	objfreelist = new->prev;
    926 	memset (new,0,sizeof(*new));
    927 
    928 	if (lastobj)
    929 		lastobj->next = new;
    930 	new->prev = lastobj;	// new->next is allready NULL from memset
    931 
    932 	new->active = false;
    933 	lastobj = new;
    934 
    935 	objcount++;
    936 }
    937 
    938 //===========================================================================
    939 
    940 /*
    941 =========================
    942 =
    943 = RemoveObj
    944 =
    945 = Add the given object back into the free list, and unlink it from it's
    946 = neighbors
    947 =
    948 =========================
    949 */
    950 
    951 void RemoveObj (objtype *gone)
    952 {
    953 	objtype **spotat;
    954 
    955 	if (gone == player)
    956 		Quit ("RemoveObj: Tried to remove the player!");
    957 
    958 	gone->state = NULL;
    959 
    960 //
    961 // fix the next object's back link
    962 //
    963 	if (gone == lastobj)
    964 		lastobj = (objtype *)gone->prev;
    965 	else
    966 		gone->next->prev = gone->prev;
    967 
    968 //
    969 // fix the previous object's forward link
    970 //
    971 	gone->prev->next = gone->next;
    972 
    973 //
    974 // add it back in to the free list
    975 //
    976 	gone->prev = objfreelist;
    977 	objfreelist = gone;
    978 
    979 	objcount--;
    980 }
    981 
    982 /*
    983 =============================================================================
    984 
    985 						MUSIC STUFF
    986 
    987 =============================================================================
    988 */
    989 
    990 
    991 /*
    992 =================
    993 =
    994 = StopMusic
    995 =
    996 =================
    997 */
    998 
    999 void StopMusic(void)
   1000 {
   1001 	int	i;
   1002 
   1003 	SD_MusicOff();
   1004 	for (i = 0;i < LASTMUSIC;i++)
   1005 		if (audiosegs[STARTMUSIC + i])
   1006 		{
   1007 			MM_SetPurge(&((memptr)audiosegs[STARTMUSIC + i]),3);
   1008 			MM_SetLock(&((memptr)audiosegs[STARTMUSIC + i]),false);
   1009 		}
   1010 }
   1011 
   1012 //==========================================================================
   1013 
   1014 
   1015 /*
   1016 =================
   1017 =
   1018 = StartMusic
   1019 =
   1020 =================
   1021 */
   1022 
   1023 void StartMusic(void)
   1024 {
   1025 	musicnames	chunk;
   1026 
   1027 	SD_MusicOff();
   1028 	chunk = songs[gamestate.mapon+gamestate.episode*10];
   1029 
   1030 //	if ((chunk == -1) || (MusicMode != smm_AdLib))
   1031 //DEBUG control panel		return;
   1032 
   1033 	MM_BombOnError (false);
   1034 	CA_CacheAudioChunk(STARTMUSIC + chunk);
   1035 	MM_BombOnError (true);
   1036 	if (mmerror)
   1037 		mmerror = false;
   1038 	else
   1039 	{
   1040 		MM_SetLock(&((memptr)audiosegs[STARTMUSIC + chunk]),true);
   1041 		SD_StartMusic((MusicGroup far *)audiosegs[STARTMUSIC + chunk]);
   1042 	}
   1043 }
   1044 
   1045 
   1046 /*
   1047 =============================================================================
   1048 
   1049 					PALETTE SHIFTING STUFF
   1050 
   1051 =============================================================================
   1052 */
   1053 
   1054 #define NUMREDSHIFTS	6
   1055 #define REDSTEPS		8
   1056 
   1057 #define NUMWHITESHIFTS	3
   1058 #define WHITESTEPS		20
   1059 #define WHITETICS		6
   1060 
   1061 
   1062 byte	far redshifts[NUMREDSHIFTS][768];
   1063 byte	far whiteshifts[NUMREDSHIFTS][768];
   1064 
   1065 int		damagecount,bonuscount;
   1066 boolean	palshifted;
   1067 
   1068 extern 	byte	far	gamepal;
   1069 
   1070 /*
   1071 =====================
   1072 =
   1073 = InitRedShifts
   1074 =
   1075 =====================
   1076 */
   1077 
   1078 void InitRedShifts (void)
   1079 {
   1080 	byte	far *workptr, far *baseptr;
   1081 	int		i,j,delta;
   1082 
   1083 
   1084 //
   1085 // fade through intermediate frames
   1086 //
   1087 	for (i=1;i<=NUMREDSHIFTS;i++)
   1088 	{
   1089 		workptr = (byte far *)&redshifts[i-1][0];
   1090 		baseptr = &gamepal;
   1091 
   1092 		for (j=0;j<=255;j++)
   1093 		{
   1094 			delta = 64-*baseptr;
   1095 			*workptr++ = *baseptr++ + delta * i / REDSTEPS;
   1096 			delta = -*baseptr;
   1097 			*workptr++ = *baseptr++ + delta * i / REDSTEPS;
   1098 			delta = -*baseptr;
   1099 			*workptr++ = *baseptr++ + delta * i / REDSTEPS;
   1100 		}
   1101 	}
   1102 
   1103 	for (i=1;i<=NUMWHITESHIFTS;i++)
   1104 	{
   1105 		workptr = (byte far *)&whiteshifts[i-1][0];
   1106 		baseptr = &gamepal;
   1107 
   1108 		for (j=0;j<=255;j++)
   1109 		{
   1110 			delta = 64-*baseptr;
   1111 			*workptr++ = *baseptr++ + delta * i / WHITESTEPS;
   1112 			delta = 62-*baseptr;
   1113 			*workptr++ = *baseptr++ + delta * i / WHITESTEPS;
   1114 			delta = 0-*baseptr;
   1115 			*workptr++ = *baseptr++ + delta * i / WHITESTEPS;
   1116 		}
   1117 	}
   1118 }
   1119 
   1120 
   1121 /*
   1122 =====================
   1123 =
   1124 = ClearPaletteShifts
   1125 =
   1126 =====================
   1127 */
   1128 
   1129 void ClearPaletteShifts (void)
   1130 {
   1131 	bonuscount = damagecount = 0;
   1132 }
   1133 
   1134 
   1135 /*
   1136 =====================
   1137 =
   1138 = StartBonusFlash
   1139 =
   1140 =====================
   1141 */
   1142 
   1143 void StartBonusFlash (void)
   1144 {
   1145 	bonuscount = NUMWHITESHIFTS*WHITETICS;		// white shift palette
   1146 }
   1147 
   1148 
   1149 /*
   1150 =====================
   1151 =
   1152 = StartDamageFlash
   1153 =
   1154 =====================
   1155 */
   1156 
   1157 void StartDamageFlash (int damage)
   1158 {
   1159 	damagecount += damage;
   1160 }
   1161 
   1162 
   1163 /*
   1164 =====================
   1165 =
   1166 = UpdatePaletteShifts
   1167 =
   1168 =====================
   1169 */
   1170 
   1171 void UpdatePaletteShifts (void)
   1172 {
   1173 	int	red,white;
   1174 
   1175 	if (bonuscount)
   1176 	{
   1177 		white = bonuscount/WHITETICS +1;
   1178 		if (white>NUMWHITESHIFTS)
   1179 			white = NUMWHITESHIFTS;
   1180 		bonuscount -= tics;
   1181 		if (bonuscount < 0)
   1182 			bonuscount = 0;
   1183 	}
   1184 	else
   1185 		white = 0;
   1186 
   1187 
   1188 	if (damagecount)
   1189 	{
   1190 		red = damagecount/10 +1;
   1191 		if (red>NUMREDSHIFTS)
   1192 			red = NUMREDSHIFTS;
   1193 
   1194 		damagecount -= tics;
   1195 		if (damagecount < 0)
   1196 			damagecount = 0;
   1197 	}
   1198 	else
   1199 		red = 0;
   1200 
   1201 	if (red)
   1202 	{
   1203 		VW_WaitVBL(1);
   1204 		VL_SetPalette (redshifts[red-1]);
   1205 		palshifted = true;
   1206 	}
   1207 	else if (white)
   1208 	{
   1209 		VW_WaitVBL(1);
   1210 		VL_SetPalette (whiteshifts[white-1]);
   1211 		palshifted = true;
   1212 	}
   1213 	else if (palshifted)
   1214 	{
   1215 		VW_WaitVBL(1);
   1216 		VL_SetPalette (&gamepal);		// back to normal
   1217 		palshifted = false;
   1218 	}
   1219 }
   1220 
   1221 
   1222 /*
   1223 =====================
   1224 =
   1225 = FinishPaletteShifts
   1226 =
   1227 = Resets palette to normal if needed
   1228 =
   1229 =====================
   1230 */
   1231 
   1232 void FinishPaletteShifts (void)
   1233 {
   1234 	if (palshifted)
   1235 	{
   1236 		palshifted = 0;
   1237 		VW_WaitVBL(1);
   1238 		VL_SetPalette (&gamepal);
   1239 	}
   1240 }
   1241 
   1242 
   1243 /*
   1244 =============================================================================
   1245 
   1246 						CORE PLAYLOOP
   1247 
   1248 =============================================================================
   1249 */
   1250 
   1251 
   1252 /*
   1253 =====================
   1254 =
   1255 = DoActor
   1256 =
   1257 =====================
   1258 */
   1259 
   1260 void DoActor (objtype *ob)
   1261 {
   1262 	void (*think)(objtype *);
   1263 
   1264 	if (!ob->active && !areabyplayer[ob->areanumber])
   1265 		return;
   1266 
   1267 	if (!(ob->flags&(FL_NONMARK|FL_NEVERMARK)) )
   1268 		actorat[ob->tilex][ob->tiley] = NULL;
   1269 
   1270 //
   1271 // non transitional object
   1272 //
   1273 
   1274 	if (!ob->ticcount)
   1275 	{
   1276 		think =	ob->state->think;
   1277 		if (think)
   1278 		{
   1279 			think (ob);
   1280 			if (!ob->state)
   1281 			{
   1282 				RemoveObj (ob);
   1283 				return;
   1284 			}
   1285 		}
   1286 
   1287 		if (ob->flags&FL_NEVERMARK)
   1288 			return;
   1289 
   1290 		if ( (ob->flags&FL_NONMARK) && actorat[ob->tilex][ob->tiley])
   1291 			return;
   1292 
   1293 		actorat[ob->tilex][ob->tiley] = ob;
   1294 		return;
   1295 	}
   1296 
   1297 //
   1298 // transitional object
   1299 //
   1300 	ob->ticcount-=tics;
   1301 	while ( ob->ticcount <= 0)
   1302 	{
   1303 		think = ob->state->action;			// end of state action
   1304 		if (think)
   1305 		{
   1306 			think (ob);
   1307 			if (!ob->state)
   1308 			{
   1309 				RemoveObj (ob);
   1310 				return;
   1311 			}
   1312 		}
   1313 
   1314 		ob->state = ob->state->next;
   1315 
   1316 		if (!ob->state)
   1317 		{
   1318 			RemoveObj (ob);
   1319 			return;
   1320 		}
   1321 
   1322 		if (!ob->state->tictime)
   1323 		{
   1324 			ob->ticcount = 0;
   1325 			goto think;
   1326 		}
   1327 
   1328 		ob->ticcount += ob->state->tictime;
   1329 	}
   1330 
   1331 think:
   1332 	//
   1333 	// think
   1334 	//
   1335 	think =	ob->state->think;
   1336 	if (think)
   1337 	{
   1338 		think (ob);
   1339 		if (!ob->state)
   1340 		{
   1341 			RemoveObj (ob);
   1342 			return;
   1343 		}
   1344 	}
   1345 
   1346 	if (ob->flags&FL_NEVERMARK)
   1347 		return;
   1348 
   1349 	if ( (ob->flags&FL_NONMARK) && actorat[ob->tilex][ob->tiley])
   1350 		return;
   1351 
   1352 	actorat[ob->tilex][ob->tiley] = ob;
   1353 }
   1354 
   1355 //==========================================================================
   1356 
   1357 
   1358 /*
   1359 ===================
   1360 =
   1361 = PlayLoop
   1362 =
   1363 ===================
   1364 */
   1365 long funnyticount;
   1366 
   1367 
   1368 void PlayLoop (void)
   1369 {
   1370 	int		give;
   1371 	int	helmetangle;
   1372 
   1373 	playstate = TimeCount = lasttimecount = 0;
   1374 	frameon = 0;
   1375 	running = false;
   1376 	anglefrac = 0;
   1377 	facecount = 0;
   1378 	funnyticount = 0;
   1379 	memset (buttonstate,0,sizeof(buttonstate));
   1380 	ClearPaletteShifts ();
   1381 
   1382 	if (MousePresent)
   1383 		Mouse(MDelta);	// Clear accumulated mouse movement
   1384 
   1385 	if (demoplayback)
   1386 		IN_StartAck ();
   1387 
   1388 	do
   1389 	{
   1390 		if (virtualreality)
   1391 		{
   1392 			helmetangle = peek (0x40,0xf0);
   1393 			player->angle += helmetangle;
   1394 			if (player->angle >= ANGLES)
   1395 				player->angle -= ANGLES;
   1396 		}
   1397 
   1398 
   1399 		PollControls();
   1400 
   1401 //
   1402 // actor thinking
   1403 //
   1404 		madenoise = false;
   1405 
   1406 		MoveDoors ();
   1407 		MovePWalls ();
   1408 
   1409 		for (obj = player;obj;obj = obj->next)
   1410 			DoActor (obj);
   1411 
   1412 		UpdatePaletteShifts ();
   1413 
   1414 		ThreeDRefresh ();
   1415 
   1416 		//
   1417 		// MAKE FUNNY FACE IF BJ DOESN'T MOVE FOR AWHILE
   1418 		//
   1419 		#ifdef SPEAR
   1420 		funnyticount += tics;
   1421 		if (funnyticount > 30l*70)
   1422 		{
   1423 			funnyticount = 0;
   1424 			StatusDrawPic (17,4,BJWAITING1PIC+(US_RndT()&1));
   1425 			facecount = 0;
   1426 		}
   1427 		#endif
   1428 
   1429 		gamestate.TimeCount+=tics;
   1430 
   1431 		SD_Poll ();
   1432 		UpdateSoundLoc();	// JAB
   1433 
   1434 		if (screenfaded)
   1435 			VW_FadeIn ();
   1436 
   1437 		CheckKeys();
   1438 
   1439 //
   1440 // debug aids
   1441 //
   1442 		if (singlestep)
   1443 		{
   1444 			VW_WaitVBL(14);
   1445 			lasttimecount = TimeCount;
   1446 		}
   1447 		if (extravbls)
   1448 			VW_WaitVBL(extravbls);
   1449 
   1450 		if (demoplayback)
   1451 		{
   1452 			if (IN_CheckAck ())
   1453 			{
   1454 				IN_ClearKeysDown ();
   1455 				playstate = ex_abort;
   1456 			}
   1457 		}
   1458 
   1459 
   1460 		if (virtualreality)
   1461 		{
   1462 			player->angle -= helmetangle;
   1463 			if (player->angle < 0)
   1464 				player->angle += ANGLES;
   1465 		}
   1466 
   1467 	}while (!playstate && !startgame);
   1468 
   1469 	if (playstate != ex_died)
   1470 		FinishPaletteShifts ();
   1471 }
   1472