wolf3d/WL_MAIN.C

1617 lines
33 KiB
C
Raw Permalink Normal View History

1995-07-21 00:00:00 +00:00
// WL_MAIN.C
#include <conio.h>
#include "WL_DEF.H"
#pragma hdrstop
/*
=============================================================================
WOLFENSTEIN 3-D
An Id Software production
by John Carmack
=============================================================================
*/
/*
=============================================================================
LOCAL CONSTANTS
=============================================================================
*/
#define FOCALLENGTH (0x5700l) // in global coordinates
#define VIEWGLOBAL 0x10000 // globals visable flush to wall
#define VIEWWIDTH 256 // size of view window
#define VIEWHEIGHT 144
/*
=============================================================================
GLOBAL VARIABLES
=============================================================================
*/
char str[80],str2[20];
int tedlevelnum;
boolean tedlevel;
boolean nospr;
boolean IsA386;
int dirangle[9] = {0,ANGLES/8,2*ANGLES/8,3*ANGLES/8,4*ANGLES/8,
5*ANGLES/8,6*ANGLES/8,7*ANGLES/8,ANGLES};
//
// proejection variables
//
fixed focallength;
unsigned screenofs;
int viewwidth;
int viewheight;
int centerx;
int shootdelta; // pixels away from centerx a target can be
fixed scale,maxslope;
long heightnumerator;
int minheightdiv;
void Quit (char *error);
boolean startgame,loadedgame,virtualreality;
int mouseadjustment;
char configname[13]="CONFIG.";
/*
=============================================================================
LOCAL VARIABLES
=============================================================================
*/
/*
====================
=
= ReadConfig
=
====================
*/
void ReadConfig(void)
{
int file;
SDMode sd;
SMMode sm;
SDSMode sds;
if ( (file = open(configname,O_BINARY | O_RDONLY)) != -1)
{
//
// valid config file
//
read(file,Scores,sizeof(HighScore) * MaxScores);
read(file,&sd,sizeof(sd));
read(file,&sm,sizeof(sm));
read(file,&sds,sizeof(sds));
read(file,&mouseenabled,sizeof(mouseenabled));
read(file,&joystickenabled,sizeof(joystickenabled));
read(file,&joypadenabled,sizeof(joypadenabled));
read(file,&joystickprogressive,sizeof(joystickprogressive));
read(file,&joystickport,sizeof(joystickport));
read(file,&dirscan,sizeof(dirscan));
read(file,&buttonscan,sizeof(buttonscan));
read(file,&buttonmouse,sizeof(buttonmouse));
read(file,&buttonjoy,sizeof(buttonjoy));
read(file,&viewsize,sizeof(viewsize));
read(file,&mouseadjustment,sizeof(mouseadjustment));
close(file);
if (sd == sdm_AdLib && !AdLibPresent && !SoundBlasterPresent)
{
sd = sdm_PC;
sd = smm_Off;
}
if ((sds == sds_SoundBlaster && !SoundBlasterPresent) ||
(sds == sds_SoundSource && !SoundSourcePresent))
sds = sds_Off;
if (!MousePresent)
mouseenabled = false;
if (!JoysPresent[joystickport])
joystickenabled = false;
MainMenu[6].active=1;
MainItems.curpos=0;
}
else
{
//
// no config file, so select by hardware
//
if (SoundBlasterPresent || AdLibPresent)
{
sd = sdm_AdLib;
sm = smm_AdLib;
}
else
{
sd = sdm_PC;
sm = smm_Off;
}
if (SoundBlasterPresent)
sds = sds_SoundBlaster;
else if (SoundSourcePresent)
sds = sds_SoundSource;
else
sds = sds_Off;
if (MousePresent)
mouseenabled = true;
joystickenabled = false;
joypadenabled = false;
joystickport = 0;
joystickprogressive = false;
viewsize = 15;
mouseadjustment=5;
}
SD_SetMusicMode (sm);
SD_SetSoundMode (sd);
SD_SetDigiDevice (sds);
}
/*
====================
=
= WriteConfig
=
====================
*/
void WriteConfig(void)
{
int file;
file = open(configname,O_CREAT | O_BINARY | O_WRONLY,
S_IREAD | S_IWRITE | S_IFREG);
if (file != -1)
{
write(file,Scores,sizeof(HighScore) * MaxScores);
write(file,&SoundMode,sizeof(SoundMode));
write(file,&MusicMode,sizeof(MusicMode));
write(file,&DigiMode,sizeof(DigiMode));
write(file,&mouseenabled,sizeof(mouseenabled));
write(file,&joystickenabled,sizeof(joystickenabled));
write(file,&joypadenabled,sizeof(joypadenabled));
write(file,&joystickprogressive,sizeof(joystickprogressive));
write(file,&joystickport,sizeof(joystickport));
write(file,&dirscan,sizeof(dirscan));
write(file,&buttonscan,sizeof(buttonscan));
write(file,&buttonmouse,sizeof(buttonmouse));
write(file,&buttonjoy,sizeof(buttonjoy));
write(file,&viewsize,sizeof(viewsize));
write(file,&mouseadjustment,sizeof(mouseadjustment));
close(file);
}
}
//===========================================================================
/*
========================
=
= Patch386
=
= Patch ldiv to use 32 bit instructions
=
========================
*/
char *JHParmStrings[] = {"no386",nil};
void Patch386 (void)
{
extern void far jabhack2(void);
extern int far CheckIs386(void);
int i;
for (i = 1;i < _argc;i++)
if (US_CheckParm(_argv[i],JHParmStrings) == 0)
{
IsA386 = false;
return;
}
if (CheckIs386())
{
IsA386 = true;
jabhack2();
}
else
IsA386 = false;
}
//===========================================================================
/*
=====================
=
= NewGame
=
= Set up new game to start from the beginning
=
=====================
*/
void NewGame (int difficulty,int episode)
{
memset (&gamestate,0,sizeof(gamestate));
gamestate.difficulty = difficulty;
gamestate.weapon = gamestate.bestweapon
= gamestate.chosenweapon = wp_pistol;
gamestate.health = 100;
gamestate.ammo = STARTAMMO;
gamestate.lives = 3;
gamestate.nextextra = EXTRAPOINTS;
gamestate.episode=episode;
startgame = true;
}
//===========================================================================
void DiskFlopAnim(int x,int y)
{
static char which=0;
if (!x && !y)
return;
VWB_DrawPic(x,y,C_DISKLOADING1PIC+which);
VW_UpdateScreen();
which^=1;
}
long DoChecksum(byte far *source,unsigned size,long checksum)
{
unsigned i;
for (i=0;i<size-1;i++)
checksum += source[i]^source[i+1];
return checksum;
}
/*
==================
=
= SaveTheGame
=
==================
*/
boolean SaveTheGame(int file,int x,int y)
{
struct diskfree_t dfree;
long avail,size,checksum;
objtype *ob,nullobj;
if (_dos_getdiskfree(0,&dfree))
Quit("Error in _dos_getdiskfree call");
avail = (long)dfree.avail_clusters *
dfree.bytes_per_sector *
dfree.sectors_per_cluster;
size = 0;
for (ob = player; ob ; ob=ob->next)
size += sizeof(*ob);
size += sizeof(nullobj);
size += sizeof(gamestate) +
sizeof(LRstruct)*8 +
sizeof(tilemap) +
sizeof(actorat) +
sizeof(laststatobj) +
sizeof(statobjlist) +
sizeof(doorposition) +
sizeof(pwallstate) +
sizeof(pwallx) +
sizeof(pwally) +
sizeof(pwalldir) +
sizeof(pwallpos);
if (avail < size)
{
Message(STR_NOSPACE1"\n"
STR_NOSPACE2);
return false;
}
checksum = 0;
DiskFlopAnim(x,y);
CA_FarWrite (file,(void far *)&gamestate,sizeof(gamestate));
checksum = DoChecksum((byte far *)&gamestate,sizeof(gamestate),checksum);
DiskFlopAnim(x,y);
#ifdef SPEAR
CA_FarWrite (file,(void far *)&LevelRatios[0],sizeof(LRstruct)*20);
checksum = DoChecksum((byte far *)&LevelRatios[0],sizeof(LRstruct)*20,checksum);
#else
CA_FarWrite (file,(void far *)&LevelRatios[0],sizeof(LRstruct)*8);
checksum = DoChecksum((byte far *)&LevelRatios[0],sizeof(LRstruct)*8,checksum);
#endif
DiskFlopAnim(x,y);
CA_FarWrite (file,(void far *)tilemap,sizeof(tilemap));
checksum = DoChecksum((byte far *)tilemap,sizeof(tilemap),checksum);
DiskFlopAnim(x,y);
CA_FarWrite (file,(void far *)actorat,sizeof(actorat));
checksum = DoChecksum((byte far *)actorat,sizeof(actorat),checksum);
CA_FarWrite (file,(void far *)areaconnect,sizeof(areaconnect));
CA_FarWrite (file,(void far *)areabyplayer,sizeof(areabyplayer));
for (ob = player ; ob ; ob=ob->next)
{
DiskFlopAnim(x,y);
CA_FarWrite (file,(void far *)ob,sizeof(*ob));
}
nullobj.active = ac_badobject; // end of file marker
DiskFlopAnim(x,y);
CA_FarWrite (file,(void far *)&nullobj,sizeof(nullobj));
DiskFlopAnim(x,y);
CA_FarWrite (file,(void far *)&laststatobj,sizeof(laststatobj));
checksum = DoChecksum((byte far *)&laststatobj,sizeof(laststatobj),checksum);
DiskFlopAnim(x,y);
CA_FarWrite (file,(void far *)statobjlist,sizeof(statobjlist));
checksum = DoChecksum((byte far *)statobjlist,sizeof(statobjlist),checksum);
DiskFlopAnim(x,y);
CA_FarWrite (file,(void far *)doorposition,sizeof(doorposition));
checksum = DoChecksum((byte far *)doorposition,sizeof(doorposition),checksum);
DiskFlopAnim(x,y);
CA_FarWrite (file,(void far *)doorobjlist,sizeof(doorobjlist));
checksum = DoChecksum((byte far *)doorobjlist,sizeof(doorobjlist),checksum);
DiskFlopAnim(x,y);
CA_FarWrite (file,(void far *)&pwallstate,sizeof(pwallstate));
checksum = DoChecksum((byte far *)&pwallstate,sizeof(pwallstate),checksum);
CA_FarWrite (file,(void far *)&pwallx,sizeof(pwallx));
checksum = DoChecksum((byte far *)&pwallx,sizeof(pwallx),checksum);
CA_FarWrite (file,(void far *)&pwally,sizeof(pwally));
checksum = DoChecksum((byte far *)&pwally,sizeof(pwally),checksum);
CA_FarWrite (file,(void far *)&pwalldir,sizeof(pwalldir));
checksum = DoChecksum((byte far *)&pwalldir,sizeof(pwalldir),checksum);
CA_FarWrite (file,(void far *)&pwallpos,sizeof(pwallpos));
checksum = DoChecksum((byte far *)&pwallpos,sizeof(pwallpos),checksum);
//
// WRITE OUT CHECKSUM
//
CA_FarWrite (file,(void far *)&checksum,sizeof(checksum));
return(true);
}
//===========================================================================
/*
==================
=
= LoadTheGame
=
==================
*/
boolean LoadTheGame(int file,int x,int y)
{
long checksum,oldchecksum;
objtype *ob,nullobj;
checksum = 0;
DiskFlopAnim(x,y);
CA_FarRead (file,(void far *)&gamestate,sizeof(gamestate));
checksum = DoChecksum((byte far *)&gamestate,sizeof(gamestate),checksum);
DiskFlopAnim(x,y);
#ifdef SPEAR
CA_FarRead (file,(void far *)&LevelRatios[0],sizeof(LRstruct)*20);
checksum = DoChecksum((byte far *)&LevelRatios[0],sizeof(LRstruct)*20,checksum);
#else
CA_FarRead (file,(void far *)&LevelRatios[0],sizeof(LRstruct)*8);
checksum = DoChecksum((byte far *)&LevelRatios[0],sizeof(LRstruct)*8,checksum);
#endif
DiskFlopAnim(x,y);
SetupGameLevel ();
DiskFlopAnim(x,y);
CA_FarRead (file,(void far *)tilemap,sizeof(tilemap));
checksum = DoChecksum((byte far *)tilemap,sizeof(tilemap),checksum);
DiskFlopAnim(x,y);
CA_FarRead (file,(void far *)actorat,sizeof(actorat));
checksum = DoChecksum((byte far *)actorat,sizeof(actorat),checksum);
CA_FarRead (file,(void far *)areaconnect,sizeof(areaconnect));
CA_FarRead (file,(void far *)areabyplayer,sizeof(areabyplayer));
InitActorList ();
DiskFlopAnim(x,y);
CA_FarRead (file,(void far *)player,sizeof(*player));
while (1)
{
DiskFlopAnim(x,y);
CA_FarRead (file,(void far *)&nullobj,sizeof(nullobj));
if (nullobj.active == ac_badobject)
break;
GetNewActor ();
// don't copy over the links
memcpy (new,&nullobj,sizeof(nullobj)-4);
}
DiskFlopAnim(x,y);
CA_FarRead (file,(void far *)&laststatobj,sizeof(laststatobj));
checksum = DoChecksum((byte far *)&laststatobj,sizeof(laststatobj),checksum);
DiskFlopAnim(x,y);
CA_FarRead (file,(void far *)statobjlist,sizeof(statobjlist));
checksum = DoChecksum((byte far *)statobjlist,sizeof(statobjlist),checksum);
DiskFlopAnim(x,y);
CA_FarRead (file,(void far *)doorposition,sizeof(doorposition));
checksum = DoChecksum((byte far *)doorposition,sizeof(doorposition),checksum);
DiskFlopAnim(x,y);
CA_FarRead (file,(void far *)doorobjlist,sizeof(doorobjlist));
checksum = DoChecksum((byte far *)doorobjlist,sizeof(doorobjlist),checksum);
DiskFlopAnim(x,y);
CA_FarRead (file,(void far *)&pwallstate,sizeof(pwallstate));
checksum = DoChecksum((byte far *)&pwallstate,sizeof(pwallstate),checksum);
CA_FarRead (file,(void far *)&pwallx,sizeof(pwallx));
checksum = DoChecksum((byte far *)&pwallx,sizeof(pwallx),checksum);
CA_FarRead (file,(void far *)&pwally,sizeof(pwally));
checksum = DoChecksum((byte far *)&pwally,sizeof(pwally),checksum);
CA_FarRead (file,(void far *)&pwalldir,sizeof(pwalldir));
checksum = DoChecksum((byte far *)&pwalldir,sizeof(pwalldir),checksum);
CA_FarRead (file,(void far *)&pwallpos,sizeof(pwallpos));
checksum = DoChecksum((byte far *)&pwallpos,sizeof(pwallpos),checksum);
CA_FarRead (file,(void far *)&oldchecksum,sizeof(oldchecksum));
if (oldchecksum != checksum)
{
Message(STR_SAVECHT1"\n"
STR_SAVECHT2"\n"
STR_SAVECHT3"\n"
STR_SAVECHT4);
IN_ClearKeysDown();
IN_Ack();
gamestate.score = 0;
gamestate.lives = 1;
gamestate.weapon =
gamestate.chosenweapon =
gamestate.bestweapon = wp_pistol;
gamestate.ammo = 8;
}
return true;
}
//===========================================================================
/*
==========================
=
= ShutdownId
=
= Shuts down all ID_?? managers
=
==========================
*/
void ShutdownId (void)
{
US_Shutdown ();
SD_Shutdown ();
PM_Shutdown ();
IN_Shutdown ();
VW_Shutdown ();
CA_Shutdown ();
MM_Shutdown ();
}
//===========================================================================
/*
==================
=
= BuildTables
=
= Calculates:
=
= scale projection constant
= sintable/costable overlapping fractional tables
=
==================
*/
const float radtoint = (float)FINEANGLES/2/PI;
void BuildTables (void)
{
int i;
float angle,anglestep;
double tang;
fixed value;
//
// calculate fine tangents
//
for (i=0;i<FINEANGLES/8;i++)
{
tang = tan( (i+0.5)/radtoint);
finetangent[i] = tang*TILEGLOBAL;
finetangent[FINEANGLES/4-1-i] = 1/tang*TILEGLOBAL;
}
//
// costable overlays sintable with a quarter phase shift
// ANGLES is assumed to be divisable by four
//
// The low word of the value is the fraction, the high bit is the sign bit,
// bits 16-30 should be 0
//
angle = 0;
anglestep = PI/2/ANGLEQUAD;
for (i=0;i<=ANGLEQUAD;i++)
{
value=GLOBAL1*sin(angle);
sintable[i]=
sintable[i+ANGLES]=
sintable[ANGLES/2-i] = value;
sintable[ANGLES-i]=
sintable[ANGLES/2+i] = value | 0x80000000l;
angle += anglestep;
}
}
//===========================================================================
/*
====================
=
= CalcProjection
=
= Uses focallength
=
====================
*/
void CalcProjection (long focal)
{
int i;
long intang;
float angle;
double tang;
double planedist;
double globinhalf;
int halfview;
double halfangle,facedist;
focallength = focal;
facedist = focal+MINDIST;
halfview = viewwidth/2; // half view in pixels
//
// calculate scale value for vertical height calculations
// and sprite x calculations
//
scale = halfview*facedist/(VIEWGLOBAL/2);
//
// divide heightnumerator by a posts distance to get the posts height for
// the heightbuffer. The pixel height is height>>2
//
heightnumerator = (TILEGLOBAL*scale)>>6;
minheightdiv = heightnumerator/0x7fff +1;
//
// calculate the angle offset from view angle of each pixel's ray
//
for (i=0;i<halfview;i++)
{
// start 1/2 pixel over, so viewangle bisects two middle pixels
tang = (long)i*VIEWGLOBAL/viewwidth/facedist;
angle = atan(tang);
intang = angle*radtoint;
pixelangle[halfview-1-i] = intang;
pixelangle[halfview+i] = -intang;
}
//
// if a point's abs(y/x) is greater than maxslope, the point is outside
// the view area
//
maxslope = finetangent[pixelangle[0]];
maxslope >>= 8;
}
//===========================================================================
/*
===================
=
= SetupWalls
=
= Map tile values to scaled pics
=
===================
*/
void SetupWalls (void)
{
int i;
for (i=1;i<MAXWALLTILES;i++)
{
horizwall[i]=(i-1)*2;
vertwall[i]=(i-1)*2+1;
}
}
//===========================================================================
/*
==========================
=
= SignonScreen
=
==========================
*/
void SignonScreen (void) // VGA version
{
unsigned segstart,seglength;
VL_SetVGAPlaneMode ();
VL_TestPaletteSet ();
VL_SetPalette (&gamepal);
if (!virtualreality)
{
VW_SetScreen(0x8000,0);
VL_MungePic (&introscn,320,200);
VL_MemToScreen (&introscn,320,200,0,0);
VW_SetScreen(0,0);
}
//
// reclaim the memory from the linked in signon screen
//
segstart = FP_SEG(&introscn);
seglength = 64000/16;
if (FP_OFF(&introscn))
{
segstart++;
seglength--;
}
MML_UseSpace (segstart,seglength);
}
/*
==========================
=
= FinishSignon
=
==========================
*/
void FinishSignon (void)
{
#ifndef SPEAR
VW_Bar (0,189,300,11,peekb(0xa000,0));
WindowX = 0;
WindowW = 320;
PrintY = 190;
#ifndef JAPAN
SETFONTCOLOR(14,4);
#ifdef SPANISH
US_CPrint ("Oprima una tecla");
#else
US_CPrint ("Press a key");
#endif
#endif
if (!NoWait)
IN_Ack ();
#ifndef JAPAN
VW_Bar (0,189,300,11,peekb(0xa000,0));
PrintY = 190;
SETFONTCOLOR(10,4);
#ifdef SPANISH
US_CPrint ("pensando...");
#else
US_CPrint ("Working...");
#endif
#endif
SETFONTCOLOR(0,15);
#else
if (!NoWait)
VW_WaitVBL(3*70);
#endif
}
//===========================================================================
/*
=================
=
= MS_CheckParm
=
=================
*/
boolean MS_CheckParm (char far *check)
{
int i;
char *parm;
for (i = 1;i<_argc;i++)
{
parm = _argv[i];
while ( !isalpha(*parm) ) // skip - / \ etc.. in front of parm
if (!*parm++)
break; // hit end of string without an alphanum
if ( !_fstricmp(check,parm) )
return true;
}
return false;
}
//===========================================================================
/*
=====================
=
= InitDigiMap
=
=====================
*/
static int wolfdigimap[] =
{
// These first sounds are in the upload version
#ifndef SPEAR
HALTSND, 0,
DOGBARKSND, 1,
CLOSEDOORSND, 2,
OPENDOORSND, 3,
ATKMACHINEGUNSND, 4,
ATKPISTOLSND, 5,
ATKGATLINGSND, 6,
SCHUTZADSND, 7,
GUTENTAGSND, 8,
MUTTISND, 9,
BOSSFIRESND, 10,
SSFIRESND, 11,
DEATHSCREAM1SND, 12,
DEATHSCREAM2SND, 13,
DEATHSCREAM3SND, 13,
TAKEDAMAGESND, 14,
PUSHWALLSND, 15,
LEBENSND, 20,
NAZIFIRESND, 21,
SLURPIESND, 22,
YEAHSND, 32,
#ifndef UPLOAD
// These are in all other episodes
DOGDEATHSND, 16,
AHHHGSND, 17,
DIESND, 18,
EVASND, 19,
TOT_HUNDSND, 23,
MEINGOTTSND, 24,
SCHABBSHASND, 25,
HITLERHASND, 26,
SPIONSND, 27,
NEINSOVASSND, 28,
DOGATTACKSND, 29,
LEVELDONESND, 30,
MECHSTEPSND, 31,
SCHEISTSND, 33,
DEATHSCREAM4SND, 34, // AIIEEE
DEATHSCREAM5SND, 35, // DEE-DEE
DONNERSND, 36, // EPISODE 4 BOSS DIE
EINESND, 37, // EPISODE 4 BOSS SIGHTING
ERLAUBENSND, 38, // EPISODE 6 BOSS SIGHTING
DEATHSCREAM6SND, 39, // FART
DEATHSCREAM7SND, 40, // GASP
DEATHSCREAM8SND, 41, // GUH-BOY!
DEATHSCREAM9SND, 42, // AH GEEZ!
KEINSND, 43, // EPISODE 5 BOSS SIGHTING
MEINSND, 44, // EPISODE 6 BOSS DIE
ROSESND, 45, // EPISODE 5 BOSS DIE
#endif
#else
//
// SPEAR OF DESTINY DIGISOUNDS
//
HALTSND, 0,
CLOSEDOORSND, 2,
OPENDOORSND, 3,
ATKMACHINEGUNSND, 4,
ATKPISTOLSND, 5,
ATKGATLINGSND, 6,
SCHUTZADSND, 7,
BOSSFIRESND, 8,
SSFIRESND, 9,
DEATHSCREAM1SND, 10,
DEATHSCREAM2SND, 11,
TAKEDAMAGESND, 12,
PUSHWALLSND, 13,
AHHHGSND, 15,
LEBENSND, 16,
NAZIFIRESND, 17,
SLURPIESND, 18,
LEVELDONESND, 22,
DEATHSCREAM4SND, 23, // AIIEEE
DEATHSCREAM3SND, 23, // DOUBLY-MAPPED!!!
DEATHSCREAM5SND, 24, // DEE-DEE
DEATHSCREAM6SND, 25, // FART
DEATHSCREAM7SND, 26, // GASP
DEATHSCREAM8SND, 27, // GUH-BOY!
DEATHSCREAM9SND, 28, // AH GEEZ!
GETGATLINGSND, 38, // Got Gat replacement
#ifndef SPEARDEMO
DOGBARKSND, 1,
DOGDEATHSND, 14,
SPIONSND, 19,
NEINSOVASSND, 20,
DOGATTACKSND, 21,
TRANSSIGHTSND, 29, // Trans Sight
TRANSDEATHSND, 30, // Trans Death
WILHELMSIGHTSND, 31, // Wilhelm Sight
WILHELMDEATHSND, 32, // Wilhelm Death
UBERDEATHSND, 33, // Uber Death
KNIGHTSIGHTSND, 34, // Death Knight Sight
KNIGHTDEATHSND, 35, // Death Knight Death
ANGELSIGHTSND, 36, // Angel Sight
ANGELDEATHSND, 37, // Angel Death
GETSPEARSND, 39, // Got Spear replacement
#endif
#endif
LASTSOUND
};
void InitDigiMap (void)
{
int *map;
for (map = wolfdigimap;*map != LASTSOUND;map += 2)
DigiMap[map[0]] = map[1];
}
#ifndef SPEAR
CP_iteminfo MusicItems={CTL_X,CTL_Y,6,0,32};
CP_itemtype far MusicMenu[]=
{
{1,"Get Them!",0},
{1,"Searching",0},
{1,"P.O.W.",0},
{1,"Suspense",0},
{1,"War March",0},
{1,"Around The Corner!",0},
{1,"Nazi Anthem",0},
{1,"Lurking...",0},
{1,"Going After Hitler",0},
{1,"Pounding Headache",0},
{1,"Into the Dungeons",0},
{1,"Ultimate Conquest",0},
{1,"Kill the S.O.B.",0},
{1,"The Nazi Rap",0},
{1,"Twelfth Hour",0},
{1,"Zero Hour",0},
{1,"Ultimate Conquest",0},
{1,"Wolfpack",0}
};
#else
CP_iteminfo MusicItems={CTL_X,CTL_Y-20,9,0,32};
CP_itemtype far MusicMenu[]=
{
{1,"Funky Colonel Bill",0},
{1,"Death To The Nazis",0},
{1,"Tiptoeing Around",0},
{1,"Is This THE END?",0},
{1,"Evil Incarnate",0},
{1,"Jazzin' Them Nazis",0},
{1,"Puttin' It To The Enemy",0},
{1,"The SS Gonna Get You",0},
{1,"Towering Above",0}
};
#endif
#ifndef SPEARDEMO
void DoJukebox(void)
{
int which,lastsong=-1;
unsigned start,songs[]=
{
#ifndef SPEAR
GETTHEM_MUS,
SEARCHN_MUS,
POW_MUS,
SUSPENSE_MUS,
WARMARCH_MUS,
CORNER_MUS,
NAZI_OMI_MUS,
PREGNANT_MUS,
GOINGAFT_MUS,
HEADACHE_MUS,
DUNGEON_MUS,
ULTIMATE_MUS,
INTROCW3_MUS,
NAZI_RAP_MUS,
TWELFTH_MUS,
ZEROHOUR_MUS,
ULTIMATE_MUS,
PACMAN_MUS
#else
XFUNKIE_MUS, // 0
XDEATH_MUS, // 2
XTIPTOE_MUS, // 4
XTHEEND_MUS, // 7
XEVIL_MUS, // 17
XJAZNAZI_MUS, // 18
XPUTIT_MUS, // 21
XGETYOU_MUS, // 22
XTOWER2_MUS // 23
#endif
};
struct dostime_t time;
IN_ClearKeysDown();
if (!AdLibPresent && !SoundBlasterPresent)
return;
MenuFadeOut();
#ifndef SPEAR
#ifndef UPLOAD
_dos_gettime(&time);
start = (time.hsecond%3)*6;
#else
start = 0;
#endif
#else
start = 0;
#endif
CA_CacheGrChunk (STARTFONT+1);
#ifdef SPEAR
CacheLump (BACKDROP_LUMP_START,BACKDROP_LUMP_END);
#else
CacheLump (CONTROLS_LUMP_START,CONTROLS_LUMP_END);
#endif
CA_LoadAllSounds ();
fontnumber=1;
ClearMScreen ();
VWB_DrawPic(112,184,C_MOUSELBACKPIC);
DrawStripes (10);
SETFONTCOLOR (TEXTCOLOR,BKGDCOLOR);
#ifndef SPEAR
DrawWindow (CTL_X-2,CTL_Y-6,280,13*7,BKGDCOLOR);
#else
DrawWindow (CTL_X-2,CTL_Y-26,280,13*10,BKGDCOLOR);
#endif
DrawMenu (&MusicItems,&MusicMenu[start]);
SETFONTCOLOR (READHCOLOR,BKGDCOLOR);
PrintY=15;
WindowX = 0;
WindowY = 320;
US_CPrint ("Robert's Jukebox");
SETFONTCOLOR (TEXTCOLOR,BKGDCOLOR);
VW_UpdateScreen();
MenuFadeIn();
do
{
which = HandleMenu(&MusicItems,&MusicMenu[start],NULL);
if (which>=0)
{
if (lastsong >= 0)
MusicMenu[start+lastsong].active = 1;
StartCPMusic(songs[start + which]);
MusicMenu[start+which].active = 2;
DrawMenu (&MusicItems,&MusicMenu[start]);
VW_UpdateScreen();
lastsong = which;
}
} while(which>=0);
MenuFadeOut();
IN_ClearKeysDown();
#ifdef SPEAR
UnCacheLump (BACKDROP_LUMP_START,BACKDROP_LUMP_END);
#else
UnCacheLump (CONTROLS_LUMP_START,CONTROLS_LUMP_END);
#endif
}
#endif
/*
==========================
=
= InitGame
=
= Load a few things right away
=
==========================
*/
void InitGame (void)
{
int i,x,y;
unsigned *blockstart;
if (MS_CheckParm ("virtual"))
virtualreality = true;
else
virtualreality = false;
MM_Startup (); // so the signon screen can be freed
SignonScreen ();
VW_Startup ();
IN_Startup ();
PM_Startup ();
PM_UnlockMainMem ();
SD_Startup ();
CA_Startup ();
US_Startup ();
#ifndef SPEAR
if (mminfo.mainmem < 235000L)
#else
if (mminfo.mainmem < 257000L && !MS_CheckParm("debugmode"))
#endif
{
memptr screen;
CA_CacheGrChunk (ERRORSCREEN);
screen = grsegs[ERRORSCREEN];
ShutdownId();
movedata ((unsigned)screen,7+7*160,0xb800,0,17*160);
gotoxy (1,23);
exit(1);
}
//
// build some tables
//
InitDigiMap ();
for (i=0;i<MAPSIZE;i++)
{
nearmapylookup[i] = &tilemap[0][0]+MAPSIZE*i;
farmapylookup[i] = i*64;
}
for (i=0;i<PORTTILESHIGH;i++)
uwidthtable[i] = UPDATEWIDE*i;
blockstart = &blockstarts[0];
for (y=0;y<UPDATEHIGH;y++)
for (x=0;x<UPDATEWIDE;x++)
*blockstart++ = SCREENWIDTH*16*y+x*TILEWIDTH;
updateptr = &update[0];
bufferofs = 0;
displayofs = 0;
ReadConfig ();
//
// HOLDING DOWN 'M' KEY?
//
#ifndef SPEARDEMO
if (Keyboard[sc_M])
DoJukebox();
else
#endif
//
// draw intro screen stuff
//
if (!virtualreality)
IntroScreen ();
//
// load in and lock down some basic chunks
//
CA_CacheGrChunk(STARTFONT);
MM_SetLock (&grsegs[STARTFONT],true);
LoadLatchMem ();
BuildTables (); // trig tables
SetupWalls ();
#if 0
{
int temp,i;
temp = viewsize;
profilehandle = open("SCALERS.TXT", O_CREAT | O_WRONLY | O_TEXT);
for (i=1;i<20;i++)
NewViewSize(i);
viewsize = temp;
close(profilehandle);
}
#endif
NewViewSize (viewsize);
//
// initialize variables
//
InitRedShifts ();
if (!virtualreality)
FinishSignon();
displayofs = PAGE1START;
bufferofs = PAGE2START;
if (virtualreality)
{
NoWait = true;
geninterrupt(0x60);
}
}
//===========================================================================
/*
==========================
=
= SetViewSize
=
==========================
*/
boolean SetViewSize (unsigned width, unsigned height)
{
viewwidth = width&~15; // must be divisable by 16
viewheight = height&~1; // must be even
centerx = viewwidth/2-1;
shootdelta = viewwidth/10;
screenofs = ((200-STATUSLINES-viewheight)/2*SCREENWIDTH+(320-viewwidth)/8);
//
// calculate trace angles and projection constants
//
CalcProjection (FOCALLENGTH);
//
// build all needed compiled scalers
//
// MM_BombOnError (false);
SetupScaling (viewwidth*1.5);
#if 0
MM_BombOnError (true);
if (mmerror)
{
Quit ("Can't build scalers!");
mmerror = false;
return false;
}
#endif
return true;
}
void ShowViewSize (int width)
{
int oldwidth,oldheight;
oldwidth = viewwidth;
oldheight = viewheight;
viewwidth = width*16;
viewheight = width*16*HEIGHTRATIO;
DrawPlayBorder ();
viewheight = oldheight;
viewwidth = oldwidth;
}
void NewViewSize (int width)
{
CA_UpLevel ();
MM_SortMem ();
viewsize = width;
SetViewSize (width*16,width*16*HEIGHTRATIO);
CA_DownLevel ();
}
//===========================================================================
/*
==========================
=
= Quit
=
==========================
*/
void Quit (char *error)
{
unsigned finscreen;
memptr screen;
if (virtualreality)
geninterrupt(0x61);
ClearMemory ();
if (!*error)
{
#ifndef JAPAN
CA_CacheGrChunk (ORDERSCREEN);
screen = grsegs[ORDERSCREEN];
#endif
WriteConfig ();
}
else
{
CA_CacheGrChunk (ERRORSCREEN);
screen = grsegs[ERRORSCREEN];
}
ShutdownId ();
if (error && *error)
{
movedata ((unsigned)screen,7,0xb800,0,7*160);
gotoxy (10,4);
puts(error);
gotoxy (1,8);
exit(1);
}
else
if (!error || !(*error))
{
clrscr();
#ifndef JAPAN
movedata ((unsigned)screen,7,0xb800,0,4000);
gotoxy(1,24);
#endif
//asm mov bh,0
//asm mov dh,23 // row
//asm mov dl,0 // collumn
//asm mov ah,2
//asm int 0x10
}
exit(0);
}
//===========================================================================
/*
=====================
=
= DemoLoop
=
=====================
*/
static char *ParmStrings[] = {"baby","easy","normal","hard",""};
void DemoLoop (void)
{
static int LastDemo;
int i,level;
long nsize;
memptr nullblock;
//
// check for launch from ted
//
if (tedlevel)
{
NoWait = true;
NewGame(1,0);
for (i = 1;i < _argc;i++)
{
if ( (level = US_CheckParm(_argv[i],ParmStrings)) != -1)
{
gamestate.difficulty=level;
break;
}
}
#ifndef SPEAR
gamestate.episode = tedlevelnum/10;
gamestate.mapon = tedlevelnum%10;
#else
gamestate.episode = 0;
gamestate.mapon = tedlevelnum;
#endif
GameLoop();
Quit (NULL);
}
//
// main game cycle
//
// nsize = (long)40*1024;
// MM_GetPtr(&nullblock,nsize);
#ifndef DEMOTEST
#ifndef UPLOAD
#ifndef GOODTIMES
#ifndef SPEAR
#ifndef JAPAN
if (!NoWait)
NonShareware();
#endif
#else
#ifndef GOODTIMES
#ifndef SPEARDEMO
CopyProtection();
#endif
#endif
#endif
#endif
#endif
StartCPMusic(INTROSONG);
#ifndef JAPAN
if (!NoWait)
PG13 ();
#endif
#endif
while (1)
{
while (!NoWait)
{
//
// title page
//
MM_SortMem ();
#ifndef DEMOTEST
#ifdef SPEAR
CA_CacheGrChunk (TITLEPALETTE);
CA_CacheGrChunk (TITLE1PIC);
VWB_DrawPic (0,0,TITLE1PIC);
UNCACHEGRCHUNK (TITLE1PIC);
CA_CacheGrChunk (TITLE2PIC);
VWB_DrawPic (0,80,TITLE2PIC);
UNCACHEGRCHUNK (TITLE2PIC);
VW_UpdateScreen ();
VL_FadeIn(0,255,grsegs[TITLEPALETTE],30);
UNCACHEGRCHUNK (TITLEPALETTE);
#else
CA_CacheScreen (TITLEPIC);
VW_UpdateScreen ();
VW_FadeIn();
#endif
if (IN_UserInput(TickBase*15))
break;
VW_FadeOut();
//
// credits page
//
CA_CacheScreen (CREDITSPIC);
VW_UpdateScreen();
VW_FadeIn ();
if (IN_UserInput(TickBase*10))
break;
VW_FadeOut ();
//
// high scores
//
DrawHighScores ();
VW_UpdateScreen ();
VW_FadeIn ();
if (IN_UserInput(TickBase*10))
break;
#endif
//
// demo
//
#ifndef SPEARDEMO
PlayDemo (LastDemo++%4);
#else
PlayDemo (0);
#endif
if (playstate == ex_abort)
break;
StartCPMusic(INTROSONG);
}
VW_FadeOut ();
#ifndef SPEAR
if (Keyboard[sc_Tab] && MS_CheckParm("goobers"))
#else
if (Keyboard[sc_Tab] && MS_CheckParm("debugmode"))
#endif
RecordDemo ();
else
US_ControlPanel (0);
if (startgame || loadedgame)
{
GameLoop ();
VW_FadeOut();
StartCPMusic(INTROSONG);
}
}
}
//===========================================================================
/*
==========================
=
= main
=
==========================
*/
char *nosprtxt[] = {"nospr",nil};
void main (void)
{
int i;
#ifdef BETA
//
// THIS IS FOR BETA ONLY!
//
struct dosdate_t d;
_dos_getdate(&d);
if (d.year > YEAR ||
(d.month >= MONTH && d.day >= DAY))
{
printf("Sorry, BETA-TESTING is over. Thanks for you help.\n");
exit(1);
}
#endif
CheckForEpisodes();
Patch386 ();
InitGame ();
DemoLoop();
Quit("Demo loop exited???");
}