wolf3d

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

WL_MAIN.C (31907B)


      1 // WL_MAIN.C
      2 
      3 #include <conio.h>
      4 #include "WL_DEF.H"
      5 #pragma hdrstop
      6 
      7 
      8 /*
      9 =============================================================================
     10 
     11 						   WOLFENSTEIN 3-D
     12 
     13 					  An Id Software production
     14 
     15 						   by John Carmack
     16 
     17 =============================================================================
     18 */
     19 
     20 /*
     21 =============================================================================
     22 
     23 						 LOCAL CONSTANTS
     24 
     25 =============================================================================
     26 */
     27 
     28 
     29 #define FOCALLENGTH     (0x5700l)               // in global coordinates
     30 #define VIEWGLOBAL      0x10000                 // globals visable flush to wall
     31 
     32 #define VIEWWIDTH       256                     // size of view window
     33 #define VIEWHEIGHT      144
     34 
     35 /*
     36 =============================================================================
     37 
     38 						 GLOBAL VARIABLES
     39 
     40 =============================================================================
     41 */
     42 
     43 char            str[80],str2[20];
     44 int				tedlevelnum;
     45 boolean         tedlevel;
     46 boolean         nospr;
     47 boolean         IsA386;
     48 int                     dirangle[9] = {0,ANGLES/8,2*ANGLES/8,3*ANGLES/8,4*ANGLES/8,
     49 	5*ANGLES/8,6*ANGLES/8,7*ANGLES/8,ANGLES};
     50 
     51 //
     52 // proejection variables
     53 //
     54 fixed           focallength;
     55 unsigned        screenofs;
     56 int             viewwidth;
     57 int             viewheight;
     58 int             centerx;
     59 int             shootdelta;                     // pixels away from centerx a target can be
     60 fixed           scale,maxslope;
     61 long            heightnumerator;
     62 int                     minheightdiv;
     63 
     64 
     65 void            Quit (char *error);
     66 
     67 boolean         startgame,loadedgame,virtualreality;
     68 int             mouseadjustment;
     69 
     70 char	configname[13]="CONFIG.";
     71 
     72 
     73 /*
     74 =============================================================================
     75 
     76 						 LOCAL VARIABLES
     77 
     78 =============================================================================
     79 */
     80 
     81 
     82 /*
     83 ====================
     84 =
     85 = ReadConfig
     86 =
     87 ====================
     88 */
     89 
     90 void ReadConfig(void)
     91 {
     92 	int                     file;
     93 	SDMode          sd;
     94 	SMMode          sm;
     95 	SDSMode         sds;
     96 
     97 
     98 	if ( (file = open(configname,O_BINARY | O_RDONLY)) != -1)
     99 	{
    100 	//
    101 	// valid config file
    102 	//
    103 		read(file,Scores,sizeof(HighScore) * MaxScores);
    104 
    105 		read(file,&sd,sizeof(sd));
    106 		read(file,&sm,sizeof(sm));
    107 		read(file,&sds,sizeof(sds));
    108 
    109 		read(file,&mouseenabled,sizeof(mouseenabled));
    110 		read(file,&joystickenabled,sizeof(joystickenabled));
    111 		read(file,&joypadenabled,sizeof(joypadenabled));
    112 		read(file,&joystickprogressive,sizeof(joystickprogressive));
    113 		read(file,&joystickport,sizeof(joystickport));
    114 
    115 		read(file,&dirscan,sizeof(dirscan));
    116 		read(file,&buttonscan,sizeof(buttonscan));
    117 		read(file,&buttonmouse,sizeof(buttonmouse));
    118 		read(file,&buttonjoy,sizeof(buttonjoy));
    119 
    120 		read(file,&viewsize,sizeof(viewsize));
    121 		read(file,&mouseadjustment,sizeof(mouseadjustment));
    122 
    123 		close(file);
    124 
    125 		if (sd == sdm_AdLib && !AdLibPresent && !SoundBlasterPresent)
    126 		{
    127 			sd = sdm_PC;
    128 			sd = smm_Off;
    129 		}
    130 
    131 		if ((sds == sds_SoundBlaster && !SoundBlasterPresent) ||
    132 			(sds == sds_SoundSource && !SoundSourcePresent))
    133 			sds = sds_Off;
    134 
    135 		if (!MousePresent)
    136 			mouseenabled = false;
    137 		if (!JoysPresent[joystickport])
    138 			joystickenabled = false;
    139 
    140 		MainMenu[6].active=1;
    141 		MainItems.curpos=0;
    142 	}
    143 	else
    144 	{
    145 	//
    146 	// no config file, so select by hardware
    147 	//
    148 		if (SoundBlasterPresent || AdLibPresent)
    149 		{
    150 			sd = sdm_AdLib;
    151 			sm = smm_AdLib;
    152 		}
    153 		else
    154 		{
    155 			sd = sdm_PC;
    156 			sm = smm_Off;
    157 		}
    158 
    159 		if (SoundBlasterPresent)
    160 			sds = sds_SoundBlaster;
    161 		else if (SoundSourcePresent)
    162 			sds = sds_SoundSource;
    163 		else
    164 			sds = sds_Off;
    165 
    166 		if (MousePresent)
    167 			mouseenabled = true;
    168 
    169 		joystickenabled = false;
    170 		joypadenabled = false;
    171 		joystickport = 0;
    172 		joystickprogressive = false;
    173 
    174 		viewsize = 15;
    175 		mouseadjustment=5;
    176 	}
    177 
    178 	SD_SetMusicMode (sm);
    179 	SD_SetSoundMode (sd);
    180 	SD_SetDigiDevice (sds);
    181 
    182 }
    183 
    184 
    185 /*
    186 ====================
    187 =
    188 = WriteConfig
    189 =
    190 ====================
    191 */
    192 
    193 void WriteConfig(void)
    194 {
    195 	int                     file;
    196 
    197 	file = open(configname,O_CREAT | O_BINARY | O_WRONLY,
    198 				S_IREAD | S_IWRITE | S_IFREG);
    199 
    200 	if (file != -1)
    201 	{
    202 		write(file,Scores,sizeof(HighScore) * MaxScores);
    203 
    204 		write(file,&SoundMode,sizeof(SoundMode));
    205 		write(file,&MusicMode,sizeof(MusicMode));
    206 		write(file,&DigiMode,sizeof(DigiMode));
    207 
    208 		write(file,&mouseenabled,sizeof(mouseenabled));
    209 		write(file,&joystickenabled,sizeof(joystickenabled));
    210 		write(file,&joypadenabled,sizeof(joypadenabled));
    211 		write(file,&joystickprogressive,sizeof(joystickprogressive));
    212 		write(file,&joystickport,sizeof(joystickport));
    213 
    214 		write(file,&dirscan,sizeof(dirscan));
    215 		write(file,&buttonscan,sizeof(buttonscan));
    216 		write(file,&buttonmouse,sizeof(buttonmouse));
    217 		write(file,&buttonjoy,sizeof(buttonjoy));
    218 
    219 		write(file,&viewsize,sizeof(viewsize));
    220 		write(file,&mouseadjustment,sizeof(mouseadjustment));
    221 
    222 		close(file);
    223 	}
    224 }
    225 
    226 
    227 //===========================================================================
    228 
    229 
    230 /*
    231 ========================
    232 =
    233 = Patch386
    234 =
    235 = Patch ldiv to use 32 bit instructions
    236 =
    237 ========================
    238 */
    239 
    240 char    *JHParmStrings[] = {"no386",nil};
    241 void Patch386 (void)
    242 {
    243 extern void far jabhack2(void);
    244 extern int far  CheckIs386(void);
    245 
    246 	int     i;
    247 
    248 	for (i = 1;i < _argc;i++)
    249 		if (US_CheckParm(_argv[i],JHParmStrings) == 0)
    250 		{
    251 			IsA386 = false;
    252 			return;
    253 		}
    254 
    255 	if (CheckIs386())
    256 	{
    257 		IsA386 = true;
    258 		jabhack2();
    259 	}
    260 	else
    261 		IsA386 = false;
    262 }
    263 
    264 //===========================================================================
    265 
    266 /*
    267 =====================
    268 =
    269 = NewGame
    270 =
    271 = Set up new game to start from the beginning
    272 =
    273 =====================
    274 */
    275 
    276 void NewGame (int difficulty,int episode)
    277 {
    278 	memset (&gamestate,0,sizeof(gamestate));
    279 	gamestate.difficulty = difficulty;
    280 	gamestate.weapon = gamestate.bestweapon
    281 		= gamestate.chosenweapon = wp_pistol;
    282 	gamestate.health = 100;
    283 	gamestate.ammo = STARTAMMO;
    284 	gamestate.lives = 3;
    285 	gamestate.nextextra = EXTRAPOINTS;
    286 	gamestate.episode=episode;
    287 
    288 	startgame = true;
    289 }
    290 
    291 //===========================================================================
    292 
    293 void DiskFlopAnim(int x,int y)
    294 {
    295  static char which=0;
    296  if (!x && !y)
    297    return;
    298  VWB_DrawPic(x,y,C_DISKLOADING1PIC+which);
    299  VW_UpdateScreen();
    300  which^=1;
    301 }
    302 
    303 
    304 long DoChecksum(byte far *source,unsigned size,long checksum)
    305 {
    306  unsigned i;
    307 
    308  for (i=0;i<size-1;i++)
    309    checksum += source[i]^source[i+1];
    310 
    311  return checksum;
    312 }
    313 
    314 
    315 /*
    316 ==================
    317 =
    318 = SaveTheGame
    319 =
    320 ==================
    321 */
    322 
    323 boolean SaveTheGame(int file,int x,int y)
    324 {
    325 	struct diskfree_t dfree;
    326 	long avail,size,checksum;
    327 	objtype *ob,nullobj;
    328 
    329 
    330 	if (_dos_getdiskfree(0,&dfree))
    331 	  Quit("Error in _dos_getdiskfree call");
    332 
    333 	avail = (long)dfree.avail_clusters *
    334 			dfree.bytes_per_sector *
    335 			dfree.sectors_per_cluster;
    336 
    337 	size = 0;
    338 	for (ob = player; ob ; ob=ob->next)
    339 	  size += sizeof(*ob);
    340 	size += sizeof(nullobj);
    341 
    342 	size += sizeof(gamestate) +
    343 			sizeof(LRstruct)*8 +
    344 			sizeof(tilemap) +
    345 			sizeof(actorat) +
    346 			sizeof(laststatobj) +
    347 			sizeof(statobjlist) +
    348 			sizeof(doorposition) +
    349 			sizeof(pwallstate) +
    350 			sizeof(pwallx) +
    351 			sizeof(pwally) +
    352 			sizeof(pwalldir) +
    353 			sizeof(pwallpos);
    354 
    355 	if (avail < size)
    356 	{
    357 	 Message(STR_NOSPACE1"\n"
    358 			 STR_NOSPACE2);
    359 	 return false;
    360 	}
    361 
    362 	checksum = 0;
    363 
    364 
    365 	DiskFlopAnim(x,y);
    366 	CA_FarWrite (file,(void far *)&gamestate,sizeof(gamestate));
    367 	checksum = DoChecksum((byte far *)&gamestate,sizeof(gamestate),checksum);
    368 
    369 	DiskFlopAnim(x,y);
    370 #ifdef SPEAR
    371 	CA_FarWrite (file,(void far *)&LevelRatios[0],sizeof(LRstruct)*20);
    372 	checksum = DoChecksum((byte far *)&LevelRatios[0],sizeof(LRstruct)*20,checksum);
    373 #else
    374 	CA_FarWrite (file,(void far *)&LevelRatios[0],sizeof(LRstruct)*8);
    375 	checksum = DoChecksum((byte far *)&LevelRatios[0],sizeof(LRstruct)*8,checksum);
    376 #endif
    377 
    378 	DiskFlopAnim(x,y);
    379 	CA_FarWrite (file,(void far *)tilemap,sizeof(tilemap));
    380 	checksum = DoChecksum((byte far *)tilemap,sizeof(tilemap),checksum);
    381 	DiskFlopAnim(x,y);
    382 	CA_FarWrite (file,(void far *)actorat,sizeof(actorat));
    383 	checksum = DoChecksum((byte far *)actorat,sizeof(actorat),checksum);
    384 
    385 	CA_FarWrite (file,(void far *)areaconnect,sizeof(areaconnect));
    386 	CA_FarWrite (file,(void far *)areabyplayer,sizeof(areabyplayer));
    387 
    388 	for (ob = player ; ob ; ob=ob->next)
    389 	{
    390 	 DiskFlopAnim(x,y);
    391 	 CA_FarWrite (file,(void far *)ob,sizeof(*ob));
    392 	}
    393 	nullobj.active = ac_badobject;          // end of file marker
    394 	DiskFlopAnim(x,y);
    395 	CA_FarWrite (file,(void far *)&nullobj,sizeof(nullobj));
    396 
    397 
    398 
    399 	DiskFlopAnim(x,y);
    400 	CA_FarWrite (file,(void far *)&laststatobj,sizeof(laststatobj));
    401 	checksum = DoChecksum((byte far *)&laststatobj,sizeof(laststatobj),checksum);
    402 	DiskFlopAnim(x,y);
    403 	CA_FarWrite (file,(void far *)statobjlist,sizeof(statobjlist));
    404 	checksum = DoChecksum((byte far *)statobjlist,sizeof(statobjlist),checksum);
    405 
    406 	DiskFlopAnim(x,y);
    407 	CA_FarWrite (file,(void far *)doorposition,sizeof(doorposition));
    408 	checksum = DoChecksum((byte far *)doorposition,sizeof(doorposition),checksum);
    409 	DiskFlopAnim(x,y);
    410 	CA_FarWrite (file,(void far *)doorobjlist,sizeof(doorobjlist));
    411 	checksum = DoChecksum((byte far *)doorobjlist,sizeof(doorobjlist),checksum);
    412 
    413 	DiskFlopAnim(x,y);
    414 	CA_FarWrite (file,(void far *)&pwallstate,sizeof(pwallstate));
    415 	checksum = DoChecksum((byte far *)&pwallstate,sizeof(pwallstate),checksum);
    416 	CA_FarWrite (file,(void far *)&pwallx,sizeof(pwallx));
    417 	checksum = DoChecksum((byte far *)&pwallx,sizeof(pwallx),checksum);
    418 	CA_FarWrite (file,(void far *)&pwally,sizeof(pwally));
    419 	checksum = DoChecksum((byte far *)&pwally,sizeof(pwally),checksum);
    420 	CA_FarWrite (file,(void far *)&pwalldir,sizeof(pwalldir));
    421 	checksum = DoChecksum((byte far *)&pwalldir,sizeof(pwalldir),checksum);
    422 	CA_FarWrite (file,(void far *)&pwallpos,sizeof(pwallpos));
    423 	checksum = DoChecksum((byte far *)&pwallpos,sizeof(pwallpos),checksum);
    424 
    425 	//
    426 	// WRITE OUT CHECKSUM
    427 	//
    428 	CA_FarWrite (file,(void far *)&checksum,sizeof(checksum));
    429 
    430 	return(true);
    431 }
    432 
    433 //===========================================================================
    434 
    435 /*
    436 ==================
    437 =
    438 = LoadTheGame
    439 =
    440 ==================
    441 */
    442 
    443 boolean LoadTheGame(int file,int x,int y)
    444 {
    445 	long checksum,oldchecksum;
    446 	objtype *ob,nullobj;
    447 
    448 
    449 	checksum = 0;
    450 
    451 	DiskFlopAnim(x,y);
    452 	CA_FarRead (file,(void far *)&gamestate,sizeof(gamestate));
    453 	checksum = DoChecksum((byte far *)&gamestate,sizeof(gamestate),checksum);
    454 
    455 	DiskFlopAnim(x,y);
    456 #ifdef SPEAR
    457 	CA_FarRead (file,(void far *)&LevelRatios[0],sizeof(LRstruct)*20);
    458 	checksum = DoChecksum((byte far *)&LevelRatios[0],sizeof(LRstruct)*20,checksum);
    459 #else
    460 	CA_FarRead (file,(void far *)&LevelRatios[0],sizeof(LRstruct)*8);
    461 	checksum = DoChecksum((byte far *)&LevelRatios[0],sizeof(LRstruct)*8,checksum);
    462 #endif
    463 
    464 	DiskFlopAnim(x,y);
    465 	SetupGameLevel ();
    466 
    467 	DiskFlopAnim(x,y);
    468 	CA_FarRead (file,(void far *)tilemap,sizeof(tilemap));
    469 	checksum = DoChecksum((byte far *)tilemap,sizeof(tilemap),checksum);
    470 	DiskFlopAnim(x,y);
    471 	CA_FarRead (file,(void far *)actorat,sizeof(actorat));
    472 	checksum = DoChecksum((byte far *)actorat,sizeof(actorat),checksum);
    473 
    474 	CA_FarRead (file,(void far *)areaconnect,sizeof(areaconnect));
    475 	CA_FarRead (file,(void far *)areabyplayer,sizeof(areabyplayer));
    476 
    477 
    478 
    479 	InitActorList ();
    480 	DiskFlopAnim(x,y);
    481 	CA_FarRead (file,(void far *)player,sizeof(*player));
    482 
    483 	while (1)
    484 	{
    485 	 DiskFlopAnim(x,y);
    486 		CA_FarRead (file,(void far *)&nullobj,sizeof(nullobj));
    487 		if (nullobj.active == ac_badobject)
    488 			break;
    489 		GetNewActor ();
    490 	 // don't copy over the links
    491 		memcpy (new,&nullobj,sizeof(nullobj)-4);
    492 	}
    493 
    494 
    495 
    496 	DiskFlopAnim(x,y);
    497 	CA_FarRead (file,(void far *)&laststatobj,sizeof(laststatobj));
    498 	checksum = DoChecksum((byte far *)&laststatobj,sizeof(laststatobj),checksum);
    499 	DiskFlopAnim(x,y);
    500 	CA_FarRead (file,(void far *)statobjlist,sizeof(statobjlist));
    501 	checksum = DoChecksum((byte far *)statobjlist,sizeof(statobjlist),checksum);
    502 
    503 	DiskFlopAnim(x,y);
    504 	CA_FarRead (file,(void far *)doorposition,sizeof(doorposition));
    505 	checksum = DoChecksum((byte far *)doorposition,sizeof(doorposition),checksum);
    506 	DiskFlopAnim(x,y);
    507 	CA_FarRead (file,(void far *)doorobjlist,sizeof(doorobjlist));
    508 	checksum = DoChecksum((byte far *)doorobjlist,sizeof(doorobjlist),checksum);
    509 
    510 	DiskFlopAnim(x,y);
    511 	CA_FarRead (file,(void far *)&pwallstate,sizeof(pwallstate));
    512 	checksum = DoChecksum((byte far *)&pwallstate,sizeof(pwallstate),checksum);
    513 	CA_FarRead (file,(void far *)&pwallx,sizeof(pwallx));
    514 	checksum = DoChecksum((byte far *)&pwallx,sizeof(pwallx),checksum);
    515 	CA_FarRead (file,(void far *)&pwally,sizeof(pwally));
    516 	checksum = DoChecksum((byte far *)&pwally,sizeof(pwally),checksum);
    517 	CA_FarRead (file,(void far *)&pwalldir,sizeof(pwalldir));
    518 	checksum = DoChecksum((byte far *)&pwalldir,sizeof(pwalldir),checksum);
    519 	CA_FarRead (file,(void far *)&pwallpos,sizeof(pwallpos));
    520 	checksum = DoChecksum((byte far *)&pwallpos,sizeof(pwallpos),checksum);
    521 
    522 	CA_FarRead (file,(void far *)&oldchecksum,sizeof(oldchecksum));
    523 
    524 	if (oldchecksum != checksum)
    525 	{
    526 	 Message(STR_SAVECHT1"\n"
    527 			 STR_SAVECHT2"\n"
    528 			 STR_SAVECHT3"\n"
    529 			 STR_SAVECHT4);
    530 
    531 	 IN_ClearKeysDown();
    532 	 IN_Ack();
    533 
    534 	 gamestate.score = 0;
    535 	 gamestate.lives = 1;
    536 	 gamestate.weapon =
    537 	   gamestate.chosenweapon =
    538 	   gamestate.bestweapon = wp_pistol;
    539 	 gamestate.ammo = 8;
    540 	}
    541 
    542 	return true;
    543 }
    544 
    545 //===========================================================================
    546 
    547 /*
    548 ==========================
    549 =
    550 = ShutdownId
    551 =
    552 = Shuts down all ID_?? managers
    553 =
    554 ==========================
    555 */
    556 
    557 void ShutdownId (void)
    558 {
    559 	US_Shutdown ();
    560 	SD_Shutdown ();
    561 	PM_Shutdown ();
    562 	IN_Shutdown ();
    563 	VW_Shutdown ();
    564 	CA_Shutdown ();
    565 	MM_Shutdown ();
    566 }
    567 
    568 
    569 //===========================================================================
    570 
    571 /*
    572 ==================
    573 =
    574 = BuildTables
    575 =
    576 = Calculates:
    577 =
    578 = scale                 projection constant
    579 = sintable/costable     overlapping fractional tables
    580 =
    581 ==================
    582 */
    583 
    584 const   float   radtoint = (float)FINEANGLES/2/PI;
    585 
    586 void BuildTables (void)
    587 {
    588   int           i;
    589   float         angle,anglestep;
    590   double        tang;
    591   fixed         value;
    592 
    593 
    594 //
    595 // calculate fine tangents
    596 //
    597 
    598 	for (i=0;i<FINEANGLES/8;i++)
    599 	{
    600 		tang = tan( (i+0.5)/radtoint);
    601 		finetangent[i] = tang*TILEGLOBAL;
    602 		finetangent[FINEANGLES/4-1-i] = 1/tang*TILEGLOBAL;
    603 	}
    604 
    605 //
    606 // costable overlays sintable with a quarter phase shift
    607 // ANGLES is assumed to be divisable by four
    608 //
    609 // The low word of the value is the fraction, the high bit is the sign bit,
    610 // bits 16-30 should be 0
    611 //
    612 
    613   angle = 0;
    614   anglestep = PI/2/ANGLEQUAD;
    615   for (i=0;i<=ANGLEQUAD;i++)
    616   {
    617 	value=GLOBAL1*sin(angle);
    618 	sintable[i]=
    619 	  sintable[i+ANGLES]=
    620 	  sintable[ANGLES/2-i] = value;
    621 	sintable[ANGLES-i]=
    622 	  sintable[ANGLES/2+i] = value | 0x80000000l;
    623 	angle += anglestep;
    624   }
    625 
    626 }
    627 
    628 //===========================================================================
    629 
    630 
    631 /*
    632 ====================
    633 =
    634 = CalcProjection
    635 =
    636 = Uses focallength
    637 =
    638 ====================
    639 */
    640 
    641 void CalcProjection (long focal)
    642 {
    643 	int             i;
    644 	long            intang;
    645 	float   angle;
    646 	double  tang;
    647 	double  planedist;
    648 	double  globinhalf;
    649 	int             halfview;
    650 	double  halfangle,facedist;
    651 
    652 
    653 	focallength = focal;
    654 	facedist = focal+MINDIST;
    655 	halfview = viewwidth/2;                                 // half view in pixels
    656 
    657 //
    658 // calculate scale value for vertical height calculations
    659 // and sprite x calculations
    660 //
    661 	scale = halfview*facedist/(VIEWGLOBAL/2);
    662 
    663 //
    664 // divide heightnumerator by a posts distance to get the posts height for
    665 // the heightbuffer.  The pixel height is height>>2
    666 //
    667 	heightnumerator = (TILEGLOBAL*scale)>>6;
    668 	minheightdiv = heightnumerator/0x7fff +1;
    669 
    670 //
    671 // calculate the angle offset from view angle of each pixel's ray
    672 //
    673 
    674 	for (i=0;i<halfview;i++)
    675 	{
    676 	// start 1/2 pixel over, so viewangle bisects two middle pixels
    677 		tang = (long)i*VIEWGLOBAL/viewwidth/facedist;
    678 		angle = atan(tang);
    679 		intang = angle*radtoint;
    680 		pixelangle[halfview-1-i] = intang;
    681 		pixelangle[halfview+i] = -intang;
    682 	}
    683 
    684 //
    685 // if a point's abs(y/x) is greater than maxslope, the point is outside
    686 // the view area
    687 //
    688 	maxslope = finetangent[pixelangle[0]];
    689 	maxslope >>= 8;
    690 }
    691 
    692 
    693 
    694 //===========================================================================
    695 
    696 /*
    697 ===================
    698 =
    699 = SetupWalls
    700 =
    701 = Map tile values to scaled pics
    702 =
    703 ===================
    704 */
    705 
    706 void SetupWalls (void)
    707 {
    708 	int     i;
    709 
    710 	for (i=1;i<MAXWALLTILES;i++)
    711 	{
    712 		horizwall[i]=(i-1)*2;
    713 		vertwall[i]=(i-1)*2+1;
    714 	}
    715 }
    716 
    717 //===========================================================================
    718 
    719 /*
    720 ==========================
    721 =
    722 = SignonScreen
    723 =
    724 ==========================
    725 */
    726 
    727 void SignonScreen (void)                        // VGA version
    728 {
    729 	unsigned        segstart,seglength;
    730 
    731 	VL_SetVGAPlaneMode ();
    732 	VL_TestPaletteSet ();
    733 	VL_SetPalette (&gamepal);
    734 
    735 	if (!virtualreality)
    736 	{
    737 		VW_SetScreen(0x8000,0);
    738 		VL_MungePic (&introscn,320,200);
    739 		VL_MemToScreen (&introscn,320,200,0,0);
    740 		VW_SetScreen(0,0);
    741 	}
    742 
    743 //
    744 // reclaim the memory from the linked in signon screen
    745 //
    746 	segstart = FP_SEG(&introscn);
    747 	seglength = 64000/16;
    748 	if (FP_OFF(&introscn))
    749 	{
    750 		segstart++;
    751 		seglength--;
    752 	}
    753 	MML_UseSpace (segstart,seglength);
    754 }
    755 
    756 
    757 /*
    758 ==========================
    759 =
    760 = FinishSignon
    761 =
    762 ==========================
    763 */
    764 
    765 void FinishSignon (void)
    766 {
    767 
    768 #ifndef SPEAR
    769 	VW_Bar (0,189,300,11,peekb(0xa000,0));
    770 	WindowX = 0;
    771 	WindowW = 320;
    772 	PrintY = 190;
    773 
    774 	#ifndef JAPAN
    775 	SETFONTCOLOR(14,4);
    776 
    777 	#ifdef SPANISH
    778 	US_CPrint ("Oprima una tecla");
    779 	#else
    780 	US_CPrint ("Press a key");
    781 	#endif
    782 
    783 	#endif
    784 
    785 	if (!NoWait)
    786 		IN_Ack ();
    787 
    788 	#ifndef JAPAN
    789 	VW_Bar (0,189,300,11,peekb(0xa000,0));
    790 
    791 	PrintY = 190;
    792 	SETFONTCOLOR(10,4);
    793 
    794 	#ifdef SPANISH
    795 	US_CPrint ("pensando...");
    796 	#else
    797 	US_CPrint ("Working...");
    798 	#endif
    799 
    800 	#endif
    801 
    802 	SETFONTCOLOR(0,15);
    803 #else
    804 	if (!NoWait)
    805 		VW_WaitVBL(3*70);
    806 #endif
    807 }
    808 
    809 //===========================================================================
    810 
    811 /*
    812 =================
    813 =
    814 = MS_CheckParm
    815 =
    816 =================
    817 */
    818 
    819 boolean MS_CheckParm (char far *check)
    820 {
    821 	int             i;
    822 	char    *parm;
    823 
    824 	for (i = 1;i<_argc;i++)
    825 	{
    826 		parm = _argv[i];
    827 
    828 		while ( !isalpha(*parm) )       // skip - / \ etc.. in front of parm
    829 			if (!*parm++)
    830 				break;                          // hit end of string without an alphanum
    831 
    832 		if ( !_fstricmp(check,parm) )
    833 			return true;
    834 	}
    835 
    836 	return false;
    837 }
    838 
    839 //===========================================================================
    840 
    841 /*
    842 =====================
    843 =
    844 = InitDigiMap
    845 =
    846 =====================
    847 */
    848 
    849 static  int     wolfdigimap[] =
    850 		{
    851 			// These first sounds are in the upload version
    852 #ifndef SPEAR
    853 			HALTSND,                0,
    854 			DOGBARKSND,             1,
    855 			CLOSEDOORSND,           2,
    856 			OPENDOORSND,            3,
    857 			ATKMACHINEGUNSND,       4,
    858 			ATKPISTOLSND,           5,
    859 			ATKGATLINGSND,          6,
    860 			SCHUTZADSND,            7,
    861 			GUTENTAGSND,            8,
    862 			MUTTISND,               9,
    863 			BOSSFIRESND,            10,
    864 			SSFIRESND,              11,
    865 			DEATHSCREAM1SND,        12,
    866 			DEATHSCREAM2SND,        13,
    867 			DEATHSCREAM3SND,        13,
    868 			TAKEDAMAGESND,          14,
    869 			PUSHWALLSND,            15,
    870 
    871 			LEBENSND,               20,
    872 			NAZIFIRESND,            21,
    873 			SLURPIESND,             22,
    874 
    875 			YEAHSND,				32,
    876 
    877 #ifndef UPLOAD
    878 			// These are in all other episodes
    879 			DOGDEATHSND,            16,
    880 			AHHHGSND,               17,
    881 			DIESND,                 18,
    882 			EVASND,                 19,
    883 
    884 			TOT_HUNDSND,            23,
    885 			MEINGOTTSND,            24,
    886 			SCHABBSHASND,           25,
    887 			HITLERHASND,            26,
    888 			SPIONSND,               27,
    889 			NEINSOVASSND,           28,
    890 			DOGATTACKSND,           29,
    891 			LEVELDONESND,           30,
    892 			MECHSTEPSND,			31,
    893 
    894 			SCHEISTSND,				33,
    895 			DEATHSCREAM4SND,		34,		// AIIEEE
    896 			DEATHSCREAM5SND,		35,		// DEE-DEE
    897 			DONNERSND,				36,		// EPISODE 4 BOSS DIE
    898 			EINESND,				37,		// EPISODE 4 BOSS SIGHTING
    899 			ERLAUBENSND,			38,		// EPISODE 6 BOSS SIGHTING
    900 			DEATHSCREAM6SND,		39,		// FART
    901 			DEATHSCREAM7SND,		40,		// GASP
    902 			DEATHSCREAM8SND,		41,		// GUH-BOY!
    903 			DEATHSCREAM9SND,		42,		// AH GEEZ!
    904 			KEINSND,				43,		// EPISODE 5 BOSS SIGHTING
    905 			MEINSND,				44,		// EPISODE 6 BOSS DIE
    906 			ROSESND,				45,		// EPISODE 5 BOSS DIE
    907 
    908 #endif
    909 #else
    910 //
    911 // SPEAR OF DESTINY DIGISOUNDS
    912 //
    913 			HALTSND,                0,
    914 			CLOSEDOORSND,           2,
    915 			OPENDOORSND,            3,
    916 			ATKMACHINEGUNSND,       4,
    917 			ATKPISTOLSND,           5,
    918 			ATKGATLINGSND,          6,
    919 			SCHUTZADSND,            7,
    920 			BOSSFIRESND,            8,
    921 			SSFIRESND,              9,
    922 			DEATHSCREAM1SND,        10,
    923 			DEATHSCREAM2SND,        11,
    924 			TAKEDAMAGESND,          12,
    925 			PUSHWALLSND,            13,
    926 			AHHHGSND,               15,
    927 			LEBENSND,               16,
    928 			NAZIFIRESND,            17,
    929 			SLURPIESND,             18,
    930 			LEVELDONESND,           22,
    931 			DEATHSCREAM4SND,		23,		// AIIEEE
    932 			DEATHSCREAM3SND,        23,		// DOUBLY-MAPPED!!!
    933 			DEATHSCREAM5SND,		24,		// DEE-DEE
    934 			DEATHSCREAM6SND,		25,		// FART
    935 			DEATHSCREAM7SND,		26,		// GASP
    936 			DEATHSCREAM8SND,		27,		// GUH-BOY!
    937 			DEATHSCREAM9SND,		28,		// AH GEEZ!
    938 			GETGATLINGSND,			38,		// Got Gat replacement
    939 
    940 #ifndef SPEARDEMO
    941 			DOGBARKSND,             1,
    942 			DOGDEATHSND,            14,
    943 			SPIONSND,               19,
    944 			NEINSOVASSND,           20,
    945 			DOGATTACKSND,           21,
    946 			TRANSSIGHTSND,			29,		// Trans Sight
    947 			TRANSDEATHSND,			30,		// Trans Death
    948 			WILHELMSIGHTSND,		31,		// Wilhelm Sight
    949 			WILHELMDEATHSND,		32,		// Wilhelm Death
    950 			UBERDEATHSND,			33,		// Uber Death
    951 			KNIGHTSIGHTSND,			34,		// Death Knight Sight
    952 			KNIGHTDEATHSND,			35,		// Death Knight Death
    953 			ANGELSIGHTSND,			36,		// Angel Sight
    954 			ANGELDEATHSND,			37,		// Angel Death
    955 			GETSPEARSND,			39,		// Got Spear replacement
    956 #endif
    957 #endif
    958 			LASTSOUND
    959 		};
    960 
    961 
    962 void InitDigiMap (void)
    963 {
    964 	int                     *map;
    965 
    966 	for (map = wolfdigimap;*map != LASTSOUND;map += 2)
    967 		DigiMap[map[0]] = map[1];
    968 
    969 
    970 }
    971 
    972 
    973 #ifndef SPEAR
    974 CP_iteminfo	MusicItems={CTL_X,CTL_Y,6,0,32};
    975 CP_itemtype far MusicMenu[]=
    976 	{
    977 		{1,"Get Them!",0},
    978 		{1,"Searching",0},
    979 		{1,"P.O.W.",0},
    980 		{1,"Suspense",0},
    981 		{1,"War March",0},
    982 		{1,"Around The Corner!",0},
    983 
    984 		{1,"Nazi Anthem",0},
    985 		{1,"Lurking...",0},
    986 		{1,"Going After Hitler",0},
    987 		{1,"Pounding Headache",0},
    988 		{1,"Into the Dungeons",0},
    989 		{1,"Ultimate Conquest",0},
    990 
    991 		{1,"Kill the S.O.B.",0},
    992 		{1,"The Nazi Rap",0},
    993 		{1,"Twelfth Hour",0},
    994 		{1,"Zero Hour",0},
    995 		{1,"Ultimate Conquest",0},
    996 		{1,"Wolfpack",0}
    997 	};
    998 #else
    999 CP_iteminfo MusicItems={CTL_X,CTL_Y-20,9,0,32};
   1000 CP_itemtype far MusicMenu[]=
   1001    {
   1002 		{1,"Funky Colonel Bill",0},
   1003 		{1,"Death To The Nazis",0},
   1004 		{1,"Tiptoeing Around",0},
   1005 		{1,"Is This THE END?",0},
   1006 		{1,"Evil Incarnate",0},
   1007 		{1,"Jazzin' Them Nazis",0},
   1008 		{1,"Puttin' It To The Enemy",0},
   1009 		{1,"The SS Gonna Get You",0},
   1010 		{1,"Towering Above",0}
   1011 	};
   1012 #endif
   1013 
   1014 #ifndef SPEARDEMO
   1015 void DoJukebox(void)
   1016 {
   1017 	int which,lastsong=-1;
   1018 	unsigned start,songs[]=
   1019 		{
   1020 #ifndef SPEAR
   1021 			GETTHEM_MUS,
   1022 			SEARCHN_MUS,
   1023 			POW_MUS,
   1024 			SUSPENSE_MUS,
   1025 			WARMARCH_MUS,
   1026 			CORNER_MUS,
   1027 
   1028 			NAZI_OMI_MUS,
   1029 			PREGNANT_MUS,
   1030 			GOINGAFT_MUS,
   1031 			HEADACHE_MUS,
   1032 			DUNGEON_MUS,
   1033 			ULTIMATE_MUS,
   1034 
   1035 			INTROCW3_MUS,
   1036 			NAZI_RAP_MUS,
   1037 			TWELFTH_MUS,
   1038 			ZEROHOUR_MUS,
   1039 			ULTIMATE_MUS,
   1040 			PACMAN_MUS
   1041 #else
   1042 			XFUNKIE_MUS,             // 0
   1043 			XDEATH_MUS,              // 2
   1044 			XTIPTOE_MUS,             // 4
   1045 			XTHEEND_MUS,             // 7
   1046 			XEVIL_MUS,               // 17
   1047 			XJAZNAZI_MUS,            // 18
   1048 			XPUTIT_MUS,              // 21
   1049 			XGETYOU_MUS,             // 22
   1050 			XTOWER2_MUS              // 23
   1051 #endif
   1052 		};
   1053 	struct dostime_t time;
   1054 
   1055 
   1056 
   1057 	IN_ClearKeysDown();
   1058 	if (!AdLibPresent && !SoundBlasterPresent)
   1059 		return;
   1060 
   1061 
   1062 	MenuFadeOut();
   1063 
   1064 #ifndef SPEAR
   1065 #ifndef UPLOAD
   1066 	_dos_gettime(&time);
   1067 	start = (time.hsecond%3)*6;
   1068 #else
   1069 	start = 0;
   1070 #endif
   1071 #else
   1072 	start = 0;
   1073 #endif
   1074 
   1075 
   1076 	CA_CacheGrChunk (STARTFONT+1);
   1077 #ifdef SPEAR
   1078 	CacheLump (BACKDROP_LUMP_START,BACKDROP_LUMP_END);
   1079 #else
   1080 	CacheLump (CONTROLS_LUMP_START,CONTROLS_LUMP_END);
   1081 #endif
   1082 	CA_LoadAllSounds ();
   1083 
   1084 	fontnumber=1;
   1085 	ClearMScreen ();
   1086 	VWB_DrawPic(112,184,C_MOUSELBACKPIC);
   1087 	DrawStripes (10);
   1088 	SETFONTCOLOR (TEXTCOLOR,BKGDCOLOR);
   1089 
   1090 #ifndef SPEAR
   1091 	DrawWindow (CTL_X-2,CTL_Y-6,280,13*7,BKGDCOLOR);
   1092 #else
   1093 	DrawWindow (CTL_X-2,CTL_Y-26,280,13*10,BKGDCOLOR);
   1094 #endif
   1095 
   1096 	DrawMenu (&MusicItems,&MusicMenu[start]);
   1097 
   1098 	SETFONTCOLOR (READHCOLOR,BKGDCOLOR);
   1099 	PrintY=15;
   1100 	WindowX = 0;
   1101 	WindowY = 320;
   1102 	US_CPrint ("Robert's Jukebox");
   1103 
   1104 	SETFONTCOLOR (TEXTCOLOR,BKGDCOLOR);
   1105 	VW_UpdateScreen();
   1106 	MenuFadeIn();
   1107 
   1108 	do
   1109 	{
   1110 		which = HandleMenu(&MusicItems,&MusicMenu[start],NULL);
   1111 		if (which>=0)
   1112 		{
   1113 			if (lastsong >= 0)
   1114 				MusicMenu[start+lastsong].active = 1;
   1115 
   1116 			StartCPMusic(songs[start + which]);
   1117 			MusicMenu[start+which].active = 2;
   1118 			DrawMenu (&MusicItems,&MusicMenu[start]);
   1119 			VW_UpdateScreen();
   1120 			lastsong = which;
   1121 		}
   1122 	} while(which>=0);
   1123 
   1124 	MenuFadeOut();
   1125 	IN_ClearKeysDown();
   1126 #ifdef SPEAR
   1127 	UnCacheLump (BACKDROP_LUMP_START,BACKDROP_LUMP_END);
   1128 #else
   1129 	UnCacheLump (CONTROLS_LUMP_START,CONTROLS_LUMP_END);
   1130 #endif
   1131 }
   1132 #endif
   1133 
   1134 
   1135 /*
   1136 ==========================
   1137 =
   1138 = InitGame
   1139 =
   1140 = Load a few things right away
   1141 =
   1142 ==========================
   1143 */
   1144 
   1145 void InitGame (void)
   1146 {
   1147 	int                     i,x,y;
   1148 	unsigned        *blockstart;
   1149 
   1150 	if (MS_CheckParm ("virtual"))
   1151 		virtualreality = true;
   1152 	else
   1153 		virtualreality = false;
   1154 
   1155 	MM_Startup ();                  // so the signon screen can be freed
   1156 
   1157 	SignonScreen ();
   1158 
   1159 	VW_Startup ();
   1160 	IN_Startup ();
   1161 	PM_Startup ();
   1162 	PM_UnlockMainMem ();
   1163 	SD_Startup ();
   1164 	CA_Startup ();
   1165 	US_Startup ();
   1166 
   1167 
   1168 #ifndef SPEAR
   1169 	if (mminfo.mainmem < 235000L)
   1170 #else
   1171 	if (mminfo.mainmem < 257000L && !MS_CheckParm("debugmode"))
   1172 #endif
   1173 	{
   1174 		memptr screen;
   1175 
   1176 		CA_CacheGrChunk (ERRORSCREEN);
   1177 		screen = grsegs[ERRORSCREEN];
   1178 		ShutdownId();
   1179 		movedata ((unsigned)screen,7+7*160,0xb800,0,17*160);
   1180 		gotoxy (1,23);
   1181 		exit(1);
   1182 	}
   1183 
   1184 
   1185 //
   1186 // build some tables
   1187 //
   1188 	InitDigiMap ();
   1189 
   1190 	for (i=0;i<MAPSIZE;i++)
   1191 	{
   1192 		nearmapylookup[i] = &tilemap[0][0]+MAPSIZE*i;
   1193 		farmapylookup[i] = i*64;
   1194 	}
   1195 
   1196 	for (i=0;i<PORTTILESHIGH;i++)
   1197 		uwidthtable[i] = UPDATEWIDE*i;
   1198 
   1199 	blockstart = &blockstarts[0];
   1200 	for (y=0;y<UPDATEHIGH;y++)
   1201 		for (x=0;x<UPDATEWIDE;x++)
   1202 			*blockstart++ = SCREENWIDTH*16*y+x*TILEWIDTH;
   1203 
   1204 	updateptr = &update[0];
   1205 
   1206 	bufferofs = 0;
   1207 	displayofs = 0;
   1208 	ReadConfig ();
   1209 
   1210 
   1211 //
   1212 // HOLDING DOWN 'M' KEY?
   1213 //
   1214 #ifndef SPEARDEMO
   1215 	if (Keyboard[sc_M])
   1216 	  DoJukebox();
   1217 	else
   1218 #endif
   1219 //
   1220 // draw intro screen stuff
   1221 //
   1222 	if (!virtualreality)
   1223 		IntroScreen ();
   1224 
   1225 //
   1226 // load in and lock down some basic chunks
   1227 //
   1228 
   1229 	CA_CacheGrChunk(STARTFONT);
   1230 	MM_SetLock (&grsegs[STARTFONT],true);
   1231 
   1232 	LoadLatchMem ();
   1233 	BuildTables ();          // trig tables
   1234 	SetupWalls ();
   1235 
   1236 #if 0
   1237 {
   1238 int temp,i;
   1239 temp = viewsize;
   1240 	profilehandle = open("SCALERS.TXT", O_CREAT | O_WRONLY | O_TEXT);
   1241 for (i=1;i<20;i++)
   1242 	NewViewSize(i);
   1243 viewsize = temp;
   1244 close(profilehandle);
   1245 }
   1246 #endif
   1247 
   1248 	NewViewSize (viewsize);
   1249 
   1250 
   1251 //
   1252 // initialize variables
   1253 //
   1254 	InitRedShifts ();
   1255 	if (!virtualreality)
   1256 		FinishSignon();
   1257 
   1258 	displayofs = PAGE1START;
   1259 	bufferofs = PAGE2START;
   1260 
   1261 	if (virtualreality)
   1262 	{
   1263 		NoWait = true;
   1264 		geninterrupt(0x60);
   1265 	}
   1266 }
   1267 
   1268 //===========================================================================
   1269 
   1270 /*
   1271 ==========================
   1272 =
   1273 = SetViewSize
   1274 =
   1275 ==========================
   1276 */
   1277 
   1278 boolean SetViewSize (unsigned width, unsigned height)
   1279 {
   1280 	viewwidth = width&~15;                  // must be divisable by 16
   1281 	viewheight = height&~1;                 // must be even
   1282 	centerx = viewwidth/2-1;
   1283 	shootdelta = viewwidth/10;
   1284 	screenofs = ((200-STATUSLINES-viewheight)/2*SCREENWIDTH+(320-viewwidth)/8);
   1285 
   1286 //
   1287 // calculate trace angles and projection constants
   1288 //
   1289 	CalcProjection (FOCALLENGTH);
   1290 
   1291 //
   1292 // build all needed compiled scalers
   1293 //
   1294 //	MM_BombOnError (false);
   1295 	SetupScaling (viewwidth*1.5);
   1296 #if 0
   1297 	MM_BombOnError (true);
   1298 	if (mmerror)
   1299 	{
   1300 		Quit ("Can't build scalers!");
   1301 		mmerror = false;
   1302 		return false;
   1303 	}
   1304 #endif
   1305 	return true;
   1306 }
   1307 
   1308 
   1309 void ShowViewSize (int width)
   1310 {
   1311 	int     oldwidth,oldheight;
   1312 
   1313 	oldwidth = viewwidth;
   1314 	oldheight = viewheight;
   1315 
   1316 	viewwidth = width*16;
   1317 	viewheight = width*16*HEIGHTRATIO;
   1318 	DrawPlayBorder ();
   1319 
   1320 	viewheight = oldheight;
   1321 	viewwidth = oldwidth;
   1322 }
   1323 
   1324 
   1325 void NewViewSize (int width)
   1326 {
   1327 	CA_UpLevel ();
   1328 	MM_SortMem ();
   1329 	viewsize = width;
   1330 	SetViewSize (width*16,width*16*HEIGHTRATIO);
   1331 	CA_DownLevel ();
   1332 }
   1333 
   1334 
   1335 
   1336 //===========================================================================
   1337 
   1338 /*
   1339 ==========================
   1340 =
   1341 = Quit
   1342 =
   1343 ==========================
   1344 */
   1345 
   1346 void Quit (char *error)
   1347 {
   1348 	unsigned        finscreen;
   1349 	memptr	screen;
   1350 
   1351 	if (virtualreality)
   1352 		geninterrupt(0x61);
   1353 
   1354 	ClearMemory ();
   1355 	if (!*error)
   1356 	{
   1357 	 #ifndef JAPAN
   1358 	 CA_CacheGrChunk (ORDERSCREEN);
   1359 	 screen = grsegs[ORDERSCREEN];
   1360 	 #endif
   1361 	 WriteConfig ();
   1362 	}
   1363 	else
   1364 	{
   1365 	 CA_CacheGrChunk (ERRORSCREEN);
   1366 	 screen = grsegs[ERRORSCREEN];
   1367 	}
   1368 
   1369 	ShutdownId ();
   1370 
   1371 	if (error && *error)
   1372 	{
   1373 	  movedata ((unsigned)screen,7,0xb800,0,7*160);
   1374 	  gotoxy (10,4);
   1375 	  puts(error);
   1376 	  gotoxy (1,8);
   1377 	  exit(1);
   1378 	}
   1379 	else
   1380 	if (!error || !(*error))
   1381 	{
   1382 		clrscr();
   1383 		#ifndef JAPAN
   1384 		movedata ((unsigned)screen,7,0xb800,0,4000);
   1385 		gotoxy(1,24);
   1386 		#endif
   1387 //asm	mov	bh,0
   1388 //asm	mov	dh,23	// row
   1389 //asm	mov	dl,0	// collumn
   1390 //asm	mov ah,2
   1391 //asm	int	0x10
   1392 	}
   1393 
   1394 	exit(0);
   1395 }
   1396 
   1397 //===========================================================================
   1398 
   1399 
   1400 
   1401 /*
   1402 =====================
   1403 =
   1404 = DemoLoop
   1405 =
   1406 =====================
   1407 */
   1408 
   1409 static  char *ParmStrings[] = {"baby","easy","normal","hard",""};
   1410 
   1411 void    DemoLoop (void)
   1412 {
   1413 	static int LastDemo;
   1414 	int     i,level;
   1415 	long nsize;
   1416 	memptr	nullblock;
   1417 
   1418 //
   1419 // check for launch from ted
   1420 //
   1421 	if (tedlevel)
   1422 	{
   1423 		NoWait = true;
   1424 		NewGame(1,0);
   1425 
   1426 		for (i = 1;i < _argc;i++)
   1427 		{
   1428 			if ( (level = US_CheckParm(_argv[i],ParmStrings)) != -1)
   1429 			{
   1430 			 gamestate.difficulty=level;
   1431 			 break;
   1432 			}
   1433 		}
   1434 
   1435 #ifndef SPEAR
   1436 		gamestate.episode = tedlevelnum/10;
   1437 		gamestate.mapon = tedlevelnum%10;
   1438 #else
   1439 		gamestate.episode = 0;
   1440 		gamestate.mapon = tedlevelnum;
   1441 #endif
   1442 		GameLoop();
   1443 		Quit (NULL);
   1444 	}
   1445 
   1446 
   1447 //
   1448 // main game cycle
   1449 //
   1450 
   1451 
   1452 //	nsize = (long)40*1024;
   1453 //	MM_GetPtr(&nullblock,nsize);
   1454 
   1455 #ifndef DEMOTEST
   1456 
   1457 	#ifndef UPLOAD
   1458 
   1459 		#ifndef GOODTIMES
   1460 		#ifndef SPEAR
   1461 		#ifndef JAPAN
   1462 		if (!NoWait)
   1463 			NonShareware();
   1464 		#endif
   1465 		#else
   1466 
   1467 			#ifndef GOODTIMES
   1468 			#ifndef SPEARDEMO
   1469 			CopyProtection();
   1470 			#endif
   1471 			#endif
   1472 
   1473 		#endif
   1474 		#endif
   1475 	#endif
   1476 
   1477 	StartCPMusic(INTROSONG);
   1478 
   1479 #ifndef JAPAN
   1480 	if (!NoWait)
   1481 		PG13 ();
   1482 #endif
   1483 
   1484 #endif
   1485 
   1486 	while (1)
   1487 	{
   1488 		while (!NoWait)
   1489 		{
   1490 //
   1491 // title page
   1492 //
   1493 			MM_SortMem ();
   1494 #ifndef DEMOTEST
   1495 
   1496 #ifdef SPEAR
   1497 			CA_CacheGrChunk (TITLEPALETTE);
   1498 
   1499 			CA_CacheGrChunk (TITLE1PIC);
   1500 			VWB_DrawPic (0,0,TITLE1PIC);
   1501 			UNCACHEGRCHUNK (TITLE1PIC);
   1502 
   1503 			CA_CacheGrChunk (TITLE2PIC);
   1504 			VWB_DrawPic (0,80,TITLE2PIC);
   1505 			UNCACHEGRCHUNK (TITLE2PIC);
   1506 			VW_UpdateScreen ();
   1507 			VL_FadeIn(0,255,grsegs[TITLEPALETTE],30);
   1508 
   1509 			UNCACHEGRCHUNK (TITLEPALETTE);
   1510 #else
   1511 			CA_CacheScreen (TITLEPIC);
   1512 			VW_UpdateScreen ();
   1513 			VW_FadeIn();
   1514 #endif
   1515 			if (IN_UserInput(TickBase*15))
   1516 				break;
   1517 			VW_FadeOut();
   1518 //
   1519 // credits page
   1520 //
   1521 			CA_CacheScreen (CREDITSPIC);
   1522 			VW_UpdateScreen();
   1523 			VW_FadeIn ();
   1524 			if (IN_UserInput(TickBase*10))
   1525 				break;
   1526 			VW_FadeOut ();
   1527 //
   1528 // high scores
   1529 //
   1530 			DrawHighScores ();
   1531 			VW_UpdateScreen ();
   1532 			VW_FadeIn ();
   1533 
   1534 			if (IN_UserInput(TickBase*10))
   1535 				break;
   1536 #endif
   1537 //
   1538 // demo
   1539 //
   1540 
   1541 			#ifndef SPEARDEMO
   1542 			PlayDemo (LastDemo++%4);
   1543 			#else
   1544 			PlayDemo (0);
   1545 			#endif
   1546 
   1547 			if (playstate == ex_abort)
   1548 				break;
   1549 			StartCPMusic(INTROSONG);
   1550 		}
   1551 
   1552 		VW_FadeOut ();
   1553 
   1554 #ifndef SPEAR
   1555 		if (Keyboard[sc_Tab] && MS_CheckParm("goobers"))
   1556 #else
   1557 		if (Keyboard[sc_Tab] && MS_CheckParm("debugmode"))
   1558 #endif
   1559 			RecordDemo ();
   1560 		else
   1561 			US_ControlPanel (0);
   1562 
   1563 		if (startgame || loadedgame)
   1564 		{
   1565 			GameLoop ();
   1566 			VW_FadeOut();
   1567 			StartCPMusic(INTROSONG);
   1568 		}
   1569 	}
   1570 }
   1571 
   1572 
   1573 //===========================================================================
   1574 
   1575 
   1576 /*
   1577 ==========================
   1578 =
   1579 = main
   1580 =
   1581 ==========================
   1582 */
   1583 
   1584 char    *nosprtxt[] = {"nospr",nil};
   1585 
   1586 void main (void)
   1587 {
   1588 	int     i;
   1589 
   1590 
   1591 #ifdef BETA
   1592 	//
   1593 	// THIS IS FOR BETA ONLY!
   1594 	//
   1595 	struct dosdate_t d;
   1596 
   1597 	_dos_getdate(&d);
   1598 	if (d.year > YEAR ||
   1599 		(d.month >= MONTH && d.day >= DAY))
   1600 	{
   1601 	 printf("Sorry, BETA-TESTING is over. Thanks for you help.\n");
   1602 	 exit(1);
   1603 	}
   1604 #endif
   1605 
   1606 	CheckForEpisodes();
   1607 
   1608 	Patch386 ();
   1609 
   1610 	InitGame ();
   1611 
   1612 	DemoLoop();
   1613 
   1614 	Quit("Demo loop exited???");
   1615 }
   1616