mirror of
https://github.com/libretro/libretro-wolfenstein3d.git
synced 2024-11-27 02:30:31 +00:00
1928 lines
51 KiB
C++
1928 lines
51 KiB
C++
// WL_MAIN.C
|
|
|
|
#ifdef _WIN32
|
|
#include <io.h>
|
|
#else
|
|
#include <unistd.h>
|
|
#endif
|
|
|
|
#include "wl_def.h"
|
|
#pragma hdrstop
|
|
|
|
|
|
|
|
|
|
/*
|
|
=============================================================================
|
|
|
|
WOLFENSTEIN 3-D
|
|
|
|
An Id Software production
|
|
|
|
by John Carmack
|
|
|
|
=============================================================================
|
|
*/
|
|
|
|
extern byte signon[];
|
|
|
|
/*
|
|
=============================================================================
|
|
|
|
LOCAL CONSTANTS
|
|
|
|
=============================================================================
|
|
*/
|
|
|
|
|
|
#define FOCALLENGTH (0x5700l) // in global coordinates
|
|
//#define FOCALLENGTH (0x0200l) // 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];
|
|
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 viewscreenx, viewscreeny;
|
|
int viewwidth;
|
|
int viewheight;
|
|
short centerx;
|
|
int shootdelta; // pixels away from centerx a target can be
|
|
fixed scale;
|
|
int32_t heightnumerator;
|
|
|
|
|
|
void Quit (const char *error,...);
|
|
|
|
boolean startgame;
|
|
boolean loadedgame;
|
|
int mouseadjustment;
|
|
|
|
char configdir[256] = "";
|
|
char configname[13] = "config.";
|
|
|
|
//
|
|
// Command line parameter variables
|
|
//
|
|
boolean param_debugmode = false;
|
|
boolean param_nowait = false;
|
|
int param_difficulty = 1; // default is "normal"
|
|
int param_tedlevel = -1; // default is not to start a level
|
|
int param_joystickindex = 0;
|
|
|
|
|
|
int param_joystickhat = -1;
|
|
int param_samplerate = 44100;
|
|
int param_audiobuffer = 2048 / (44100 / param_samplerate);
|
|
|
|
int param_mission = 0;
|
|
boolean param_goodtimes = false;
|
|
boolean param_ignorenumchunks = false;
|
|
|
|
/*
|
|
=============================================================================
|
|
|
|
LOCAL VARIABLES
|
|
|
|
=============================================================================
|
|
*/
|
|
|
|
|
|
/*
|
|
====================
|
|
=
|
|
= ReadConfig
|
|
=
|
|
====================
|
|
*/
|
|
|
|
void ReadConfig(void)
|
|
{
|
|
SDMode sd;
|
|
SMMode sm;
|
|
SDSMode sds;
|
|
|
|
char configpath[300];
|
|
|
|
|
|
if(configdir[0])
|
|
snprintf(configpath, sizeof(configpath), "%s/%s", configdir, configname);
|
|
else
|
|
strcpy(configpath, configname);
|
|
|
|
const int file = open(configpath, O_RDONLY | O_BINARY);
|
|
if (file != -1)
|
|
{
|
|
//
|
|
// valid config file
|
|
//
|
|
word tmp;
|
|
read(file,&tmp,sizeof(tmp));
|
|
if(tmp!=0xfefa)
|
|
{
|
|
close(file);
|
|
goto noconfig;
|
|
}
|
|
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));
|
|
boolean dummyJoypadEnabled;
|
|
read(file,&dummyJoypadEnabled,sizeof(dummyJoypadEnabled));
|
|
boolean dummyJoystickProgressive;
|
|
read(file,&dummyJoystickProgressive,sizeof(dummyJoystickProgressive));
|
|
int dummyJoystickPort = 0;
|
|
read(file,&dummyJoystickPort,sizeof(dummyJoystickPort));
|
|
|
|
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 || sm == smm_AdLib) && !AdLibPresent
|
|
&& !SoundBlasterPresent)
|
|
{
|
|
sd = sdm_PC;
|
|
sm = smm_Off;
|
|
}
|
|
|
|
if ((sds == sds_SoundBlaster && !SoundBlasterPresent))
|
|
sds = sds_Off;
|
|
|
|
// make sure values are correct
|
|
|
|
if(mouseenabled) mouseenabled=true;
|
|
if(joystickenabled) joystickenabled=true;
|
|
|
|
if (!MousePresent)
|
|
mouseenabled = false;
|
|
if (!IN_JoyPresent())
|
|
joystickenabled = false;
|
|
|
|
if(mouseadjustment<0) mouseadjustment=0;
|
|
else if(mouseadjustment>9) mouseadjustment=9;
|
|
|
|
if(viewsize<4) viewsize=4;
|
|
else if(viewsize>21) viewsize=21;
|
|
|
|
MainMenu[6].active=1;
|
|
MainItems.curpos=0;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// no config file, so select by hardware
|
|
//
|
|
noconfig:
|
|
if (SoundBlasterPresent || AdLibPresent)
|
|
{
|
|
sd = sdm_AdLib;
|
|
sm = smm_AdLib;
|
|
}
|
|
else
|
|
{
|
|
sd = sdm_PC;
|
|
sm = smm_Off;
|
|
}
|
|
|
|
if (SoundBlasterPresent)
|
|
sds = sds_SoundBlaster;
|
|
else
|
|
sds = sds_Off;
|
|
|
|
if (MousePresent)
|
|
mouseenabled = true;
|
|
|
|
if (IN_JoyPresent())
|
|
joystickenabled = true;
|
|
|
|
viewsize = 19; // start with a good size
|
|
mouseadjustment=5;
|
|
}
|
|
|
|
SD_SetMusicMode (sm);
|
|
SD_SetSoundMode (sd);
|
|
SD_SetDigiDevice (sds);
|
|
}
|
|
|
|
/*
|
|
====================
|
|
=
|
|
= WriteConfig
|
|
=
|
|
====================
|
|
*/
|
|
|
|
void WriteConfig(void)
|
|
{
|
|
char configpath[300];
|
|
|
|
if(configdir[0])
|
|
snprintf(configpath, sizeof(configpath), "%s/%s", configdir, configname);
|
|
else
|
|
strcpy(configpath, configname);
|
|
|
|
const int file = open(configpath, O_CREAT | O_WRONLY | O_BINARY, 0644);
|
|
if (file != -1)
|
|
{
|
|
word tmp=0xfefa;
|
|
write(file,&tmp,sizeof(tmp));
|
|
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));
|
|
boolean dummyJoypadEnabled = false;
|
|
write(file,&dummyJoypadEnabled,sizeof(dummyJoypadEnabled));
|
|
boolean dummyJoystickProgressive = false;
|
|
write(file,&dummyJoystickProgressive,sizeof(dummyJoystickProgressive));
|
|
int dummyJoystickPort = 0;
|
|
write(file,&dummyJoystickPort,sizeof(dummyJoystickPort));
|
|
|
|
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);
|
|
}
|
|
|
|
}
|
|
|
|
|
|
//===========================================================================
|
|
|
|
/*
|
|
=====================
|
|
=
|
|
= 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 int8_t which=0;
|
|
if (!x && !y)
|
|
return;
|
|
VWB_DrawPic(x,y,C_DISKLOADING1PIC+which);
|
|
VW_UpdateScreen();
|
|
which^=1;
|
|
}
|
|
|
|
|
|
int32_t DoChecksum(byte *source,unsigned size,int32_t checksum)
|
|
{
|
|
unsigned i;
|
|
|
|
for (i=0;i<size-1;i++)
|
|
checksum += source[i]^source[i+1];
|
|
|
|
return checksum;
|
|
}
|
|
|
|
|
|
/*
|
|
==================
|
|
=
|
|
= SaveTheGame
|
|
=
|
|
==================
|
|
*/
|
|
|
|
extern statetype s_grdstand;
|
|
extern statetype s_player;
|
|
|
|
boolean SaveTheGame(FILE *file,int x,int y)
|
|
{
|
|
// struct diskfree_t dfree;
|
|
// int32_t avail,size,checksum;
|
|
int checksum;
|
|
objtype *ob;
|
|
objtype nullobj;
|
|
statobj_t nullstat;
|
|
|
|
/* if (_dos_getdiskfree(0,&dfree))
|
|
Quit("Error in _dos_getdiskfree call");
|
|
|
|
avail = (int32_t)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)*LRpack +
|
|
sizeof(tilemap) +
|
|
sizeof(actorat) +
|
|
sizeof(laststatobj) +
|
|
sizeof(statobjlist) +
|
|
sizeof(doorposition) +
|
|
sizeof(pwallstate) +
|
|
sizeof(pwalltile) +
|
|
sizeof(pwallx) +
|
|
sizeof(pwally) +
|
|
sizeof(pwalldir) +
|
|
sizeof(pwallpos);
|
|
|
|
if (avail < size)
|
|
{
|
|
Message(STR_NOSPACE1"\n"STR_NOSPACE2);
|
|
return false;
|
|
}*/
|
|
|
|
checksum = 0;
|
|
|
|
DiskFlopAnim(x,y);
|
|
fwrite(&gamestate,sizeof(gamestate),1,file);
|
|
checksum = DoChecksum((byte *)&gamestate,sizeof(gamestate),checksum);
|
|
|
|
DiskFlopAnim(x,y);
|
|
fwrite(&LevelRatios[0],sizeof(LRstruct)*LRpack,1,file);
|
|
checksum = DoChecksum((byte *)&LevelRatios[0],sizeof(LRstruct)*LRpack,checksum);
|
|
|
|
DiskFlopAnim(x,y);
|
|
fwrite(tilemap,sizeof(tilemap),1,file);
|
|
checksum = DoChecksum((byte *)tilemap,sizeof(tilemap),checksum);
|
|
DiskFlopAnim(x,y);
|
|
|
|
int i;
|
|
for(i=0;i<MAPSIZE;i++)
|
|
{
|
|
for(int j=0;j<MAPSIZE;j++)
|
|
{
|
|
word actnum;
|
|
objtype *objptr=actorat[i][j];
|
|
if(ISPOINTER(objptr))
|
|
actnum=0x8000 | (word)(objptr-objlist);
|
|
else
|
|
actnum=(word)(uintptr_t)objptr;
|
|
fwrite(&actnum,sizeof(actnum),1,file);
|
|
checksum = DoChecksum((byte *)&actnum,sizeof(actnum),checksum);
|
|
}
|
|
}
|
|
|
|
fwrite (areaconnect,sizeof(areaconnect),1,file);
|
|
fwrite (areabyplayer,sizeof(areabyplayer),1,file);
|
|
|
|
// player object needs special treatment as it's in WL_AGENT.CPP and not in
|
|
// WL_ACT2.CPP which could cause problems for the relative addressing
|
|
|
|
ob = player;
|
|
DiskFlopAnim(x,y);
|
|
memcpy(&nullobj,ob,sizeof(nullobj));
|
|
nullobj.state=(statetype *) ((uintptr_t)nullobj.state-(uintptr_t)&s_player);
|
|
fwrite(&nullobj,sizeof(nullobj),1,file);
|
|
ob = ob->next;
|
|
|
|
DiskFlopAnim(x,y);
|
|
for (; ob ; ob=ob->next)
|
|
{
|
|
memcpy(&nullobj,ob,sizeof(nullobj));
|
|
nullobj.state=(statetype *) ((uintptr_t)nullobj.state-(uintptr_t)&s_grdstand);
|
|
fwrite(&nullobj,sizeof(nullobj),1,file);
|
|
}
|
|
nullobj.active = ac_badobject; // end of file marker
|
|
DiskFlopAnim(x,y);
|
|
fwrite(&nullobj,sizeof(nullobj),1,file);
|
|
|
|
DiskFlopAnim(x,y);
|
|
word laststatobjnum=(word) (laststatobj-statobjlist);
|
|
fwrite(&laststatobjnum,sizeof(laststatobjnum),1,file);
|
|
checksum = DoChecksum((byte *)&laststatobjnum,sizeof(laststatobjnum),checksum);
|
|
|
|
DiskFlopAnim(x,y);
|
|
for(i=0;i<MAXSTATS;i++)
|
|
{
|
|
memcpy(&nullstat,statobjlist+i,sizeof(nullstat));
|
|
nullstat.visspot=(byte *) ((uintptr_t) nullstat.visspot-(uintptr_t)spotvis);
|
|
fwrite(&nullstat,sizeof(nullstat),1,file);
|
|
checksum = DoChecksum((byte *)&nullstat,sizeof(nullstat),checksum);
|
|
}
|
|
|
|
DiskFlopAnim(x,y);
|
|
fwrite (doorposition,sizeof(doorposition),1,file);
|
|
checksum = DoChecksum((byte *)doorposition,sizeof(doorposition),checksum);
|
|
DiskFlopAnim(x,y);
|
|
fwrite (doorobjlist,sizeof(doorobjlist),1,file);
|
|
checksum = DoChecksum((byte *)doorobjlist,sizeof(doorobjlist),checksum);
|
|
|
|
DiskFlopAnim(x,y);
|
|
fwrite (&pwallstate,sizeof(pwallstate),1,file);
|
|
checksum = DoChecksum((byte *)&pwallstate,sizeof(pwallstate),checksum);
|
|
fwrite (&pwalltile,sizeof(pwalltile),1,file);
|
|
checksum = DoChecksum((byte *)&pwalltile,sizeof(pwalltile),checksum);
|
|
fwrite (&pwallx,sizeof(pwallx),1,file);
|
|
checksum = DoChecksum((byte *)&pwallx,sizeof(pwallx),checksum);
|
|
fwrite (&pwally,sizeof(pwally),1,file);
|
|
checksum = DoChecksum((byte *)&pwally,sizeof(pwally),checksum);
|
|
fwrite (&pwalldir,sizeof(pwalldir),1,file);
|
|
checksum = DoChecksum((byte *)&pwalldir,sizeof(pwalldir),checksum);
|
|
fwrite (&pwallpos,sizeof(pwallpos),1,file);
|
|
checksum = DoChecksum((byte *)&pwallpos,sizeof(pwallpos),checksum);
|
|
|
|
//
|
|
// WRITE OUT CHECKSUM
|
|
//
|
|
fwrite (&checksum,sizeof(checksum),1,file);
|
|
|
|
fwrite (&lastgamemusicoffset,sizeof(lastgamemusicoffset),1,file);
|
|
|
|
return(true);
|
|
}
|
|
|
|
//===========================================================================
|
|
|
|
/*
|
|
==================
|
|
=
|
|
= LoadTheGame
|
|
=
|
|
==================
|
|
*/
|
|
|
|
boolean LoadTheGame(FILE *file,int x,int y)
|
|
{
|
|
int32_t checksum,oldchecksum;
|
|
objtype nullobj;
|
|
statobj_t nullstat;
|
|
|
|
checksum = 0;
|
|
|
|
DiskFlopAnim(x,y);
|
|
fread (&gamestate,sizeof(gamestate),1,file);
|
|
checksum = DoChecksum((byte *)&gamestate,sizeof(gamestate),checksum);
|
|
|
|
DiskFlopAnim(x,y);
|
|
fread (&LevelRatios[0],sizeof(LRstruct)*LRpack,1,file);
|
|
checksum = DoChecksum((byte *)&LevelRatios[0],sizeof(LRstruct)*LRpack,checksum);
|
|
|
|
DiskFlopAnim(x,y);
|
|
SetupGameLevel ();
|
|
|
|
DiskFlopAnim(x,y);
|
|
fread (tilemap,sizeof(tilemap),1,file);
|
|
checksum = DoChecksum((byte *)tilemap,sizeof(tilemap),checksum);
|
|
|
|
DiskFlopAnim(x,y);
|
|
|
|
int actnum=0, i;
|
|
for(i=0;i<MAPSIZE;i++)
|
|
{
|
|
for(int j=0;j<MAPSIZE;j++)
|
|
{
|
|
fread (&actnum,sizeof(word),1,file);
|
|
checksum = DoChecksum((byte *) &actnum,sizeof(word),checksum);
|
|
if(actnum&0x8000)
|
|
actorat[i][j]=objlist+(actnum&0x7fff);
|
|
else
|
|
actorat[i][j]=(objtype *)(uintptr_t) actnum;
|
|
}
|
|
}
|
|
|
|
fread (areaconnect,sizeof(areaconnect),1,file);
|
|
fread (areabyplayer,sizeof(areabyplayer),1,file);
|
|
|
|
InitActorList ();
|
|
DiskFlopAnim(x,y);
|
|
fread (player,sizeof(*player),1,file);
|
|
player->state=(statetype *) ((uintptr_t)player->state+(uintptr_t)&s_player);
|
|
|
|
//Load all actors ?
|
|
while (1)
|
|
{
|
|
DiskFlopAnim(x,y);
|
|
fread (&nullobj,sizeof(nullobj),1,file);
|
|
if (nullobj.active == ac_badobject)
|
|
break;
|
|
GetNewActor ();
|
|
nullobj.state=(statetype *) ((uintptr_t)nullobj.state+(uintptr_t)&s_grdstand);
|
|
// don't copy over the links
|
|
memcpy (newobj,&nullobj,sizeof(nullobj)-8);
|
|
}
|
|
|
|
DiskFlopAnim(x,y);
|
|
word laststatobjnum;
|
|
fread (&laststatobjnum,sizeof(laststatobjnum),1,file);
|
|
laststatobj=statobjlist+laststatobjnum;
|
|
checksum = DoChecksum((byte *)&laststatobjnum,sizeof(laststatobjnum),checksum);
|
|
|
|
DiskFlopAnim(x,y);
|
|
for(i=0;i<MAXSTATS;i++)
|
|
{
|
|
fread(&nullstat,sizeof(nullstat),1,file);
|
|
checksum = DoChecksum((byte *)&nullstat,sizeof(nullstat),checksum);
|
|
nullstat.visspot=(byte *) ((uintptr_t)nullstat.visspot+(uintptr_t)spotvis);
|
|
memcpy(statobjlist+i,&nullstat,sizeof(nullstat));
|
|
}
|
|
|
|
DiskFlopAnim(x,y);
|
|
fread (doorposition,sizeof(doorposition),1,file);
|
|
checksum = DoChecksum((byte *)doorposition,sizeof(doorposition),checksum);
|
|
DiskFlopAnim(x,y);
|
|
fread (doorobjlist,sizeof(doorobjlist),1,file);
|
|
checksum = DoChecksum((byte *)doorobjlist,sizeof(doorobjlist),checksum);
|
|
|
|
DiskFlopAnim(x,y);
|
|
fread (&pwallstate,sizeof(pwallstate),1,file);
|
|
checksum = DoChecksum((byte *)&pwallstate,sizeof(pwallstate),checksum);
|
|
fread (&pwalltile,sizeof(pwalltile),1,file);
|
|
checksum = DoChecksum((byte *)&pwalltile,sizeof(pwalltile),checksum);
|
|
fread (&pwallx,sizeof(pwallx),1,file);
|
|
checksum = DoChecksum((byte *)&pwallx,sizeof(pwallx),checksum);
|
|
fread (&pwally,sizeof(pwally),1,file);
|
|
checksum = DoChecksum((byte *)&pwally,sizeof(pwally),checksum);
|
|
fread (&pwalldir,sizeof(pwalldir),1,file);
|
|
checksum = DoChecksum((byte *)&pwalldir,sizeof(pwalldir),checksum);
|
|
fread (&pwallpos,sizeof(pwallpos),1,file);
|
|
checksum = DoChecksum((byte *)&pwallpos,sizeof(pwallpos),checksum);
|
|
|
|
if (gamestate.secretcount) // assign valid floorcodes under moved pushwalls
|
|
{
|
|
word *map, *obj; word tile, sprite;
|
|
map = mapsegs[0]; obj = mapsegs[1];
|
|
for (y=0;y<mapheight;y++)
|
|
for (x=0;x<mapwidth;x++)
|
|
{
|
|
tile = *map++; sprite = *obj++;
|
|
if (sprite == PUSHABLETILE && !tilemap[x][y]
|
|
&& (tile < AREATILE || tile >= (AREATILE+NUMMAPS)))
|
|
{
|
|
if (*map >= AREATILE)
|
|
tile = *map;
|
|
if (*(map-1-mapwidth) >= AREATILE)
|
|
tile = *(map-1-mapwidth);
|
|
if (*(map-1+mapwidth) >= AREATILE)
|
|
tile = *(map-1+mapwidth);
|
|
if ( *(map-2) >= AREATILE)
|
|
tile = *(map-2);
|
|
|
|
*(map-1) = tile; *(obj-1) = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
Thrust(0,0); // set player->areanumber to the floortile you're standing on
|
|
|
|
fread (&oldchecksum,sizeof(oldchecksum),1,file);
|
|
|
|
fread (&lastgamemusicoffset,sizeof(lastgamemusicoffset),1,file);
|
|
if(lastgamemusicoffset<0) lastgamemusicoffset=0;
|
|
|
|
|
|
if (oldchecksum != checksum)
|
|
{
|
|
Message(STR_SAVECHT1"\n"
|
|
STR_SAVECHT2"\n"
|
|
STR_SAVECHT3"\n"
|
|
STR_SAVECHT4);
|
|
|
|
IN_ClearKeysDown();
|
|
IN_Ack();
|
|
|
|
gamestate.oldscore = 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 (); // This line is completely useless...
|
|
SD_Shutdown ();
|
|
PM_Shutdown ();
|
|
IN_Shutdown ();
|
|
VW_Shutdown ();
|
|
CA_Shutdown ();
|
|
}
|
|
|
|
|
|
//===========================================================================
|
|
|
|
/*
|
|
==================
|
|
=
|
|
= BuildTables
|
|
=
|
|
= Calculates:
|
|
=
|
|
= scale projection constant
|
|
= sintable/costable overlapping fractional tables
|
|
=
|
|
==================
|
|
*/
|
|
|
|
const float radtoint = (float)(FINEANGLES/2/PI);
|
|
|
|
void BuildTables (void)
|
|
{
|
|
//
|
|
// calculate fine tangents
|
|
//
|
|
|
|
int i;
|
|
for(i=0;i<FINEANGLES/8;i++)
|
|
{
|
|
double tang=tan((i+0.5)/radtoint);
|
|
finetangent[i]=(int32_t)(tang*GLOBAL1);
|
|
finetangent[FINEANGLES/4-1-i]=(int32_t)((1/tang)*GLOBAL1);
|
|
}
|
|
|
|
//
|
|
// costable overlays sintable with a quarter phase shift
|
|
// ANGLES is assumed to be divisable by four
|
|
//
|
|
|
|
float angle=0;
|
|
float anglestep=(float)(PI/2/ANGLEQUAD);
|
|
for(i=0; i<ANGLEQUAD; i++)
|
|
{
|
|
fixed value=(int32_t)(GLOBAL1*sin(angle));
|
|
sintable[i]=sintable[i+ANGLES]=sintable[ANGLES/2-i]=value;
|
|
sintable[ANGLES-i]=sintable[ANGLES/2+i]=-value;
|
|
angle+=anglestep;
|
|
}
|
|
sintable[ANGLEQUAD] = 65536;
|
|
sintable[3*ANGLEQUAD] = -65536;
|
|
|
|
}
|
|
|
|
//===========================================================================
|
|
|
|
|
|
/*
|
|
====================
|
|
=
|
|
= CalcProjection
|
|
=
|
|
= Uses focallength
|
|
=
|
|
====================
|
|
*/
|
|
|
|
void CalcProjection (int32_t focal)
|
|
{
|
|
int i;
|
|
int intang;
|
|
float angle;
|
|
double tang;
|
|
int halfview;
|
|
double 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 = (fixed) (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;
|
|
|
|
//
|
|
// 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 = (int32_t)i*VIEWGLOBAL/viewwidth/facedist;
|
|
angle = (float) atan(tang);
|
|
intang = (int) (angle*radtoint);
|
|
pixelangle[halfview-1-i] = intang;
|
|
pixelangle[halfview+i] = -intang;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
//===========================================================================
|
|
|
|
/*
|
|
===================
|
|
=
|
|
= SetupWalls
|
|
=
|
|
= Map tile values to scaled pics
|
|
=
|
|
===================
|
|
*/
|
|
|
|
void SetupWalls (void)
|
|
{
|
|
int i;
|
|
|
|
horizwall[0]=0;
|
|
vertwall[0]=0;
|
|
|
|
for (i=1;i<MAXWALLTILES;i++)
|
|
{
|
|
horizwall[i]=(i-1)*2;
|
|
vertwall[i]=(i-1)*2+1;
|
|
}
|
|
}
|
|
|
|
//===========================================================================
|
|
|
|
/*
|
|
==========================
|
|
=
|
|
= SignonScreen
|
|
=
|
|
==========================
|
|
*/
|
|
|
|
void SignonScreen (void) // VGA version
|
|
{
|
|
VL_SetVGAPlaneMode ();
|
|
|
|
VL_MungePic (signon,320,200);
|
|
VL_MemToScreen (signon,320,200,0,0);
|
|
}
|
|
|
|
|
|
/*
|
|
==========================
|
|
=
|
|
= FinishSignon
|
|
=
|
|
==========================
|
|
*/
|
|
|
|
void FinishSignon (void)
|
|
{
|
|
#ifndef SPEAR
|
|
VW_Bar (0,189,300,11,VL_GetPixel(0,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
|
|
|
|
VH_UpdateScreen();
|
|
|
|
if (!param_nowait)
|
|
IN_Ack ();
|
|
|
|
#ifndef JAPAN
|
|
VW_Bar (0,189,300,11,VL_GetPixel(0,0));
|
|
|
|
PrintY = 190;
|
|
SETFONTCOLOR(10,4);
|
|
|
|
#ifdef SPANISH
|
|
US_CPrint ("pensando...");
|
|
#else
|
|
US_CPrint ("Working...");
|
|
#endif
|
|
|
|
VH_UpdateScreen();
|
|
#endif
|
|
|
|
SETFONTCOLOR(0,15);
|
|
#else
|
|
VH_UpdateScreen();
|
|
|
|
if (!param_nowait)
|
|
VW_WaitVBL(3*70);
|
|
#endif
|
|
}
|
|
|
|
//===========================================================================
|
|
|
|
/*
|
|
=====================
|
|
=
|
|
= InitDigiMap
|
|
=
|
|
=====================
|
|
*/
|
|
|
|
// channel mapping:
|
|
// -1: any non reserved channel
|
|
// 0: player weapons
|
|
// 1: boss weapons
|
|
|
|
static int wolfdigimap[] =
|
|
{
|
|
// These first sounds are in the upload version
|
|
#ifndef SPEAR
|
|
HALTSND, 0, -1,
|
|
DOGBARKSND, 1, -1,
|
|
CLOSEDOORSND, 2, -1,
|
|
OPENDOORSND, 3, -1,
|
|
ATKMACHINEGUNSND, 4, 0,
|
|
ATKPISTOLSND, 5, 0,
|
|
ATKGATLINGSND, 6, 0,
|
|
SCHUTZADSND, 7, -1,
|
|
GUTENTAGSND, 8, -1,
|
|
MUTTISND, 9, -1,
|
|
BOSSFIRESND, 10, 1,
|
|
SSFIRESND, 11, -1,
|
|
DEATHSCREAM1SND, 12, -1,
|
|
DEATHSCREAM2SND, 13, -1,
|
|
DEATHSCREAM3SND, 13, -1,
|
|
TAKEDAMAGESND, 14, -1,
|
|
PUSHWALLSND, 15, -1,
|
|
|
|
LEBENSND, 20, -1,
|
|
NAZIFIRESND, 21, -1,
|
|
SLURPIESND, 22, -1,
|
|
|
|
YEAHSND, 32, -1,
|
|
|
|
#ifndef UPLOAD
|
|
// These are in all other episodes
|
|
DOGDEATHSND, 16, -1,
|
|
AHHHGSND, 17, -1,
|
|
DIESND, 18, -1,
|
|
EVASND, 19, -1,
|
|
|
|
TOT_HUNDSND, 23, -1,
|
|
MEINGOTTSND, 24, -1,
|
|
SCHABBSHASND, 25, -1,
|
|
HITLERHASND, 26, -1,
|
|
SPIONSND, 27, -1,
|
|
NEINSOVASSND, 28, -1,
|
|
DOGATTACKSND, 29, -1,
|
|
LEVELDONESND, 30, -1,
|
|
MECHSTEPSND, 31, -1,
|
|
|
|
SCHEISTSND, 33, -1,
|
|
DEATHSCREAM4SND, 34, -1, // AIIEEE
|
|
DEATHSCREAM5SND, 35, -1, // DEE-DEE
|
|
DONNERSND, 36, -1, // EPISODE 4 BOSS DIE
|
|
EINESND, 37, -1, // EPISODE 4 BOSS SIGHTING
|
|
ERLAUBENSND, 38, -1, // EPISODE 6 BOSS SIGHTING
|
|
DEATHSCREAM6SND, 39, -1, // FART
|
|
DEATHSCREAM7SND, 40, -1, // GASP
|
|
DEATHSCREAM8SND, 41, -1, // GUH-BOY!
|
|
DEATHSCREAM9SND, 42, -1, // AH GEEZ!
|
|
KEINSND, 43, -1, // EPISODE 5 BOSS SIGHTING
|
|
MEINSND, 44, -1, // EPISODE 6 BOSS DIE
|
|
ROSESND, 45, -1, // EPISODE 5 BOSS DIE
|
|
|
|
#endif
|
|
#else
|
|
//
|
|
// SPEAR OF DESTINY DIGISOUNDS
|
|
//
|
|
HALTSND, 0, -1,
|
|
CLOSEDOORSND, 2, -1,
|
|
OPENDOORSND, 3, -1,
|
|
ATKMACHINEGUNSND, 4, 0,
|
|
ATKPISTOLSND, 5, 0,
|
|
ATKGATLINGSND, 6, 0,
|
|
SCHUTZADSND, 7, -1,
|
|
BOSSFIRESND, 8, 1,
|
|
SSFIRESND, 9, -1,
|
|
DEATHSCREAM1SND, 10, -1,
|
|
DEATHSCREAM2SND, 11, -1,
|
|
TAKEDAMAGESND, 12, -1,
|
|
PUSHWALLSND, 13, -1,
|
|
AHHHGSND, 15, -1,
|
|
LEBENSND, 16, -1,
|
|
NAZIFIRESND, 17, -1,
|
|
SLURPIESND, 18, -1,
|
|
LEVELDONESND, 22, -1,
|
|
DEATHSCREAM4SND, 23, -1, // AIIEEE
|
|
DEATHSCREAM3SND, 23, -1, // DOUBLY-MAPPED!!!
|
|
DEATHSCREAM5SND, 24, -1, // DEE-DEE
|
|
DEATHSCREAM6SND, 25, -1, // FART
|
|
DEATHSCREAM7SND, 26, -1, // GASP
|
|
DEATHSCREAM8SND, 27, -1, // GUH-BOY!
|
|
DEATHSCREAM9SND, 28, -1, // AH GEEZ!
|
|
GETGATLINGSND, 38, -1, // Got Gat replacement
|
|
|
|
#ifndef SPEARDEMO
|
|
DOGBARKSND, 1, -1,
|
|
DOGDEATHSND, 14, -1,
|
|
SPIONSND, 19, -1,
|
|
NEINSOVASSND, 20, -1,
|
|
DOGATTACKSND, 21, -1,
|
|
TRANSSIGHTSND, 29, -1, // Trans Sight
|
|
TRANSDEATHSND, 30, -1, // Trans Death
|
|
WILHELMSIGHTSND, 31, -1, // Wilhelm Sight
|
|
WILHELMDEATHSND, 32, -1, // Wilhelm Death
|
|
UBERDEATHSND, 33, -1, // Uber Death
|
|
KNIGHTSIGHTSND, 34, -1, // Death Knight Sight
|
|
KNIGHTDEATHSND, 35, -1, // Death Knight Death
|
|
ANGELSIGHTSND, 36, -1, // Angel Sight
|
|
ANGELDEATHSND, 37, -1, // Angel Death
|
|
GETSPEARSND, 39, -1, // Got Spear replacement
|
|
#endif
|
|
#endif
|
|
LASTSOUND
|
|
};
|
|
|
|
|
|
void InitDigiMap (void)
|
|
{
|
|
int *map;
|
|
|
|
for (map = wolfdigimap; *map != LASTSOUND; map += 3)
|
|
{
|
|
DigiMap[map[0]] = map[1];
|
|
DigiChannel[map[1]] = map[2];
|
|
SD_PrepareSound(map[1]);
|
|
}
|
|
}
|
|
|
|
#ifndef SPEAR
|
|
CP_iteminfo MusicItems={CTL_X,CTL_Y,6,0,32};
|
|
CP_itemtype 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 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;
|
|
unsigned 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
|
|
};
|
|
|
|
IN_ClearKeysDown();
|
|
if (!AdLibPresent && !SoundBlasterPresent)
|
|
return;
|
|
|
|
MenuFadeOut();
|
|
|
|
#ifndef SPEAR
|
|
#ifndef UPLOAD
|
|
start = ((SDL_GetTicks()/10)%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
|
|
=
|
|
==========================
|
|
*/
|
|
|
|
static void InitGame()
|
|
{
|
|
#ifndef SPEARDEMO
|
|
boolean didjukebox=false;
|
|
#endif
|
|
|
|
// initialize SDL
|
|
#if defined _WIN32
|
|
putenv("SDL_VIDEODRIVER=directx");
|
|
#endif
|
|
if(SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_JOYSTICK) < 0)
|
|
{
|
|
printf("Unable to init SDL: %s\n", SDL_GetError());
|
|
exit(1);
|
|
}
|
|
atexit(SDL_Quit);
|
|
|
|
int numJoysticks = SDL_NumJoysticks();
|
|
if(param_joystickindex && (param_joystickindex < -1 || param_joystickindex >= numJoysticks))
|
|
{
|
|
if(!numJoysticks)
|
|
printf("No joysticks are available to SDL!\n");
|
|
else
|
|
printf("The joystick index must be between -1 and %i!\n", numJoysticks - 1);
|
|
exit(1);
|
|
}
|
|
|
|
SignonScreen ();
|
|
|
|
#if defined _WIN32
|
|
if(!fullscreen)
|
|
{
|
|
struct SDL_SysWMinfo wmInfo;
|
|
SDL_VERSION(&wmInfo.version);
|
|
|
|
if(SDL_GetWMInfo(&wmInfo) != -1)
|
|
{
|
|
HWND hwndSDL = wmInfo.window;
|
|
DWORD style = GetWindowLong(hwndSDL, GWL_STYLE) & ~WS_SYSMENU;
|
|
SetWindowLong(hwndSDL, GWL_STYLE, style);
|
|
SetWindowPos(hwndSDL, NULL, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
VH_Startup ();
|
|
IN_Startup ();
|
|
PM_Startup ();
|
|
SD_Startup ();
|
|
CA_Startup ();
|
|
US_Startup ();
|
|
|
|
// TODO: Will any memory checking be needed someday??
|
|
#ifdef NOTYET
|
|
#ifndef SPEAR
|
|
if (mminfo.mainmem < 235000L)
|
|
#else
|
|
if (mminfo.mainmem < 257000L && !MS_CheckParm("debugmode"))
|
|
#endif
|
|
{
|
|
byte *screen;
|
|
|
|
CA_CacheGrChunk (ERRORSCREEN);
|
|
screen = grsegs[ERRORSCREEN];
|
|
ShutdownId();
|
|
/* memcpy((byte *)0xb8000,screen+7+7*160,17*160);
|
|
gotoxy (1,23);*/
|
|
exit(1);
|
|
}
|
|
#endif
|
|
|
|
|
|
//
|
|
// build some tables
|
|
//
|
|
InitDigiMap ();
|
|
|
|
ReadConfig ();
|
|
|
|
SetupSaveGames();
|
|
|
|
//
|
|
// HOLDING DOWN 'M' KEY?
|
|
//
|
|
#ifndef SPEARDEMO
|
|
if (Keyboard[sc_M])
|
|
{
|
|
DoJukebox();
|
|
didjukebox=true;
|
|
}
|
|
else
|
|
#endif
|
|
|
|
//
|
|
// draw intro screen stuff
|
|
//
|
|
IntroScreen ();
|
|
|
|
|
|
//
|
|
// load in and lock down some basic chunks
|
|
//
|
|
|
|
CA_CacheGrChunk(STARTFONT);
|
|
CA_CacheGrChunk(STATUSBARPIC);
|
|
|
|
LoadLatchMem ();
|
|
BuildTables (); // trig tables
|
|
SetupWalls ();
|
|
|
|
NewViewSize (viewsize);
|
|
|
|
//
|
|
// initialize variables
|
|
//
|
|
InitRedShifts ();
|
|
#ifndef SPEARDEMO
|
|
if(!didjukebox)
|
|
#endif
|
|
FinishSignon();
|
|
|
|
#ifdef NOTYET
|
|
vdisp = (byte *) (0xa0000+PAGE1START);
|
|
vbuf = (byte *) (0xa0000+PAGE2START);
|
|
#endif
|
|
}
|
|
|
|
//===========================================================================
|
|
|
|
/*
|
|
==========================
|
|
=
|
|
= 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;
|
|
if((unsigned) viewheight == screenHeight)
|
|
viewscreenx = viewscreeny = screenofs = 0;
|
|
else
|
|
{
|
|
viewscreenx = (screenWidth-viewwidth) / 2;
|
|
viewscreeny = (screenHeight-scaleFactor*STATUSLINES-viewheight)/2;
|
|
screenofs = viewscreeny*screenWidth+viewscreenx;
|
|
}
|
|
|
|
//
|
|
// calculate trace angles and projection constants
|
|
//
|
|
CalcProjection (FOCALLENGTH);
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
void ShowViewSize (int width)
|
|
{
|
|
int oldwidth,oldheight;
|
|
|
|
oldwidth = viewwidth;
|
|
oldheight = viewheight;
|
|
|
|
if(width == 21)
|
|
{
|
|
viewwidth = screenWidth;
|
|
viewheight = screenHeight;
|
|
VWB_BarScaledCoord (0, 0, screenWidth, screenHeight, 0);
|
|
}
|
|
else if(width == 20)
|
|
{
|
|
viewwidth = screenWidth;
|
|
viewheight = screenHeight - scaleFactor*STATUSLINES;
|
|
DrawPlayBorder ();
|
|
}
|
|
else
|
|
{
|
|
viewwidth = width*16*screenWidth/320;
|
|
viewheight = (int) (width*16*HEIGHTRATIO*screenHeight/200);
|
|
DrawPlayBorder ();
|
|
}
|
|
|
|
viewwidth = oldwidth;
|
|
viewheight = oldheight;
|
|
}
|
|
|
|
|
|
void NewViewSize (int width)
|
|
{
|
|
viewsize = width;
|
|
if(viewsize == 21)
|
|
SetViewSize(screenWidth, screenHeight);
|
|
else if(viewsize == 20)
|
|
SetViewSize(screenWidth, screenHeight - scaleFactor * STATUSLINES);
|
|
else
|
|
SetViewSize(width*16*screenWidth/320, (unsigned) (width*16*HEIGHTRATIO*screenHeight/200));
|
|
}
|
|
|
|
|
|
|
|
//===========================================================================
|
|
|
|
/*
|
|
==========================
|
|
=
|
|
= Quit
|
|
=
|
|
==========================
|
|
*/
|
|
|
|
void Quit (const char *errorStr, ...)
|
|
{
|
|
#ifdef NOTYET
|
|
byte *screen;
|
|
#endif
|
|
char error[256];
|
|
if(errorStr != NULL)
|
|
{
|
|
va_list vlist;
|
|
va_start(vlist, errorStr);
|
|
vsprintf(error, errorStr, vlist);
|
|
va_end(vlist);
|
|
}
|
|
else error[0] = 0;
|
|
|
|
if (!pictable) // don't try to display the red box before it's loaded
|
|
{
|
|
ShutdownId();
|
|
if (error && *error)
|
|
{
|
|
#ifdef NOTYET
|
|
SetTextCursor(0,0);
|
|
#endif
|
|
puts(error);
|
|
#ifdef NOTYET
|
|
SetTextCursor(0,2);
|
|
#endif
|
|
VW_WaitVBL(100);
|
|
}
|
|
exit(1);
|
|
}
|
|
|
|
if (!error || !*error)
|
|
{
|
|
#ifdef NOTYET
|
|
#ifndef JAPAN
|
|
CA_CacheGrChunk (ORDERSCREEN);
|
|
screen = grsegs[ORDERSCREEN];
|
|
#endif
|
|
#endif
|
|
WriteConfig ();
|
|
}
|
|
#ifdef NOTYET
|
|
else
|
|
{
|
|
CA_CacheGrChunk (ERRORSCREEN);
|
|
screen = grsegs[ERRORSCREEN];
|
|
}
|
|
#endif
|
|
|
|
ShutdownId ();
|
|
|
|
if (error && *error)
|
|
{
|
|
#ifdef NOTYET
|
|
memcpy((byte *)0xb8000,screen+7,7*160);
|
|
SetTextCursor(9,3);
|
|
#endif
|
|
puts(error);
|
|
#ifdef NOTYET
|
|
SetTextCursor(0,7);
|
|
#endif
|
|
VW_WaitVBL(200);
|
|
exit(1);
|
|
}
|
|
else
|
|
if (!error || !(*error))
|
|
{
|
|
#ifdef NOTYET
|
|
#ifndef JAPAN
|
|
memcpy((byte *)0xb8000,screen+7,24*160); // 24 for SPEAR/UPLOAD compatibility
|
|
#endif
|
|
SetTextCursor(0,23);
|
|
#endif
|
|
}
|
|
|
|
exit(0);
|
|
}
|
|
|
|
//===========================================================================
|
|
|
|
|
|
|
|
/*
|
|
=====================
|
|
=
|
|
= DemoLoop
|
|
=
|
|
=====================
|
|
*/
|
|
|
|
|
|
static void DemoLoop()
|
|
{
|
|
int LastDemo = 0;
|
|
|
|
//
|
|
// check for launch from ted
|
|
//
|
|
if (param_tedlevel != -1)
|
|
{
|
|
param_nowait = true;
|
|
EnableEndGameMenuItem();
|
|
NewGame(param_difficulty,0);
|
|
|
|
#ifndef SPEAR
|
|
gamestate.episode = param_tedlevel/10;
|
|
gamestate.mapon = param_tedlevel%10;
|
|
#else
|
|
gamestate.episode = 0;
|
|
gamestate.mapon = param_tedlevel;
|
|
#endif
|
|
GameLoop();
|
|
Quit (NULL);
|
|
}
|
|
|
|
|
|
//
|
|
// main game cycle
|
|
//
|
|
|
|
#ifndef DEMOTEST
|
|
|
|
#ifndef UPLOAD
|
|
|
|
#ifndef GOODTIMES
|
|
#ifndef SPEAR
|
|
#ifndef JAPAN
|
|
if (!param_nowait)
|
|
NonShareware();
|
|
#endif
|
|
#else
|
|
#ifndef GOODTIMES
|
|
#ifndef SPEARDEMO
|
|
extern void CopyProtection(void);
|
|
if(!param_goodtimes)
|
|
CopyProtection();
|
|
#endif
|
|
#endif
|
|
#endif
|
|
#endif
|
|
#endif
|
|
|
|
StartCPMusic(INTROSONG);
|
|
|
|
#ifndef JAPAN
|
|
if (!param_nowait)
|
|
PG13 ();
|
|
#endif
|
|
|
|
#endif
|
|
|
|
while (1)
|
|
{
|
|
while (!param_nowait)
|
|
{
|
|
//
|
|
// title page
|
|
//
|
|
#ifndef DEMOTEST
|
|
|
|
#ifdef SPEAR
|
|
SDL_Color pal[256];
|
|
CA_CacheGrChunk (TITLEPALETTE);
|
|
VL_ConvertPalette(grsegs[TITLEPALETTE], pal, 256);
|
|
|
|
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,pal,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;
|
|
VW_FadeOut();
|
|
if(screenHeight % 200 != 0)
|
|
VL_ClearScreen(0);
|
|
StartCPMusic(INTROSONG);
|
|
}
|
|
|
|
VW_FadeOut ();
|
|
|
|
#ifdef DEBUGKEYS
|
|
if (Keyboard[sc_Tab] && param_debugmode)
|
|
RecordDemo ();
|
|
else
|
|
US_ControlPanel (0);
|
|
#else
|
|
US_ControlPanel (0);
|
|
#endif
|
|
|
|
if (startgame || loadedgame)
|
|
{
|
|
GameLoop ();
|
|
if(!param_nowait)
|
|
{
|
|
VW_FadeOut();
|
|
StartCPMusic(INTROSONG);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
//===========================================================================
|
|
|
|
#define IFARG(str) if(!strcmp(arg, (str)))
|
|
|
|
void CheckParameters(int argc, char *argv[])
|
|
{
|
|
bool hasError = false, showHelp = false;
|
|
bool sampleRateGiven = false, audioBufferGiven = false;
|
|
int defaultSampleRate = param_samplerate;
|
|
|
|
for(int i = 1; i < argc; i++)
|
|
{
|
|
char *arg = argv[i];
|
|
#ifndef SPEAR
|
|
IFARG("--goobers")
|
|
#else
|
|
IFARG("--debugmode")
|
|
#endif
|
|
param_debugmode = true;
|
|
else IFARG("--baby")
|
|
param_difficulty = 0;
|
|
else IFARG("--easy")
|
|
param_difficulty = 1;
|
|
else IFARG("--normal")
|
|
param_difficulty = 2;
|
|
else IFARG("--hard")
|
|
param_difficulty = 3;
|
|
else IFARG("--nowait")
|
|
param_nowait = true;
|
|
else IFARG("--tedlevel")
|
|
{
|
|
if(++i >= argc)
|
|
{
|
|
printf("The tedlevel option is missing the level argument!\n");
|
|
hasError = true;
|
|
}
|
|
else param_tedlevel = atoi(argv[i]);
|
|
}
|
|
else IFARG("--windowed")
|
|
fullscreen = false;
|
|
else IFARG("--windowed-mouse")
|
|
{
|
|
fullscreen = false;
|
|
forcegrabmouse = true;
|
|
}
|
|
else IFARG("--res")
|
|
{
|
|
if(i + 2 >= argc)
|
|
{
|
|
printf("The res option needs the width and/or the height argument!\n");
|
|
hasError = true;
|
|
}
|
|
else
|
|
{
|
|
screenWidth = atoi(argv[++i]);
|
|
screenHeight = atoi(argv[++i]);
|
|
unsigned factor = screenWidth / 320;
|
|
if(screenWidth % 320 || screenHeight != 200 * factor && screenHeight != 240 * factor)
|
|
printf("Screen size must be a multiple of 320x200 or 320x240!\n"), hasError = true;
|
|
}
|
|
}
|
|
else IFARG("--resf")
|
|
{
|
|
if(i + 2 >= argc)
|
|
{
|
|
printf("The resf option needs the width and/or the height argument!\n");
|
|
hasError = true;
|
|
}
|
|
else
|
|
{
|
|
screenWidth = atoi(argv[++i]);
|
|
screenHeight = atoi(argv[++i]);
|
|
if(screenWidth < 320)
|
|
printf("Screen width must be at least 320!\n"), hasError = true;
|
|
if(screenHeight < 200)
|
|
printf("Screen height must be at least 200!\n"), hasError = true;
|
|
}
|
|
}
|
|
else IFARG("--bits")
|
|
{
|
|
if(++i >= argc)
|
|
{
|
|
printf("The bits option is missing the color depth argument!\n");
|
|
hasError = true;
|
|
}
|
|
else
|
|
{
|
|
screenBits = atoi(argv[i]);
|
|
switch(screenBits)
|
|
{
|
|
case 8:
|
|
case 16:
|
|
case 24:
|
|
case 32:
|
|
break;
|
|
|
|
default:
|
|
printf("Screen color depth must be 8, 16, 24, or 32!\n");
|
|
hasError = true;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
else IFARG("--nodblbuf")
|
|
usedoublebuffering = false;
|
|
else IFARG("--extravbls")
|
|
{
|
|
if(++i >= argc)
|
|
{
|
|
printf("The extravbls option is missing the vbls argument!\n");
|
|
hasError = true;
|
|
}
|
|
else
|
|
{
|
|
extravbls = atoi(argv[i]);
|
|
if(extravbls < 0)
|
|
{
|
|
printf("Extravbls must be positive!\n");
|
|
hasError = true;
|
|
}
|
|
}
|
|
}
|
|
else IFARG("--joystick")
|
|
{
|
|
if(++i >= argc)
|
|
{
|
|
printf("The joystick option is missing the index argument!\n");
|
|
hasError = true;
|
|
}
|
|
else param_joystickindex = atoi(argv[i]); // index is checked in InitGame
|
|
}
|
|
else IFARG("--joystickhat")
|
|
{
|
|
if(++i >= argc)
|
|
{
|
|
printf("The joystickhat option is missing the index argument!\n");
|
|
hasError = true;
|
|
}
|
|
else param_joystickhat = atoi(argv[i]);
|
|
}
|
|
else IFARG("--samplerate")
|
|
{
|
|
if(++i >= argc)
|
|
{
|
|
printf("The samplerate option is missing the rate argument!\n");
|
|
hasError = true;
|
|
}
|
|
else param_samplerate = atoi(argv[i]);
|
|
sampleRateGiven = true;
|
|
}
|
|
else IFARG("--audiobuffer")
|
|
{
|
|
if(++i >= argc)
|
|
{
|
|
printf("The audiobuffer option is missing the size argument!\n");
|
|
hasError = true;
|
|
}
|
|
else param_audiobuffer = atoi(argv[i]);
|
|
audioBufferGiven = true;
|
|
}
|
|
else IFARG("--mission")
|
|
{
|
|
if(++i >= argc)
|
|
{
|
|
printf("The mission option is missing the mission argument!\n");
|
|
hasError = true;
|
|
}
|
|
else
|
|
{
|
|
param_mission = atoi(argv[i]);
|
|
if(param_mission < 0 || param_mission > 3)
|
|
{
|
|
printf("The mission option must be between 0 and 3!\n");
|
|
hasError = true;
|
|
}
|
|
}
|
|
}
|
|
else IFARG("--configdir")
|
|
{
|
|
if(++i >= argc)
|
|
{
|
|
printf("The configdir option is missing the dir argument!\n");
|
|
hasError = true;
|
|
}
|
|
else
|
|
{
|
|
size_t len = strlen(argv[i]);
|
|
if(len + 2 > sizeof(configdir))
|
|
{
|
|
printf("The config directory is too long!\n");
|
|
hasError = true;
|
|
}
|
|
else
|
|
{
|
|
strcpy(configdir, argv[i]);
|
|
if(argv[i][len] != '/' && argv[i][len] != '\\')
|
|
strcat(configdir, "/");
|
|
}
|
|
}
|
|
}
|
|
else IFARG("--goodtimes")
|
|
param_goodtimes = true;
|
|
else IFARG("--ignorenumchunks")
|
|
param_ignorenumchunks = true;
|
|
else IFARG("--help")
|
|
showHelp = true;
|
|
else hasError = true;
|
|
}
|
|
if(hasError || showHelp)
|
|
{
|
|
if(hasError) printf("\n");
|
|
printf(
|
|
"Wolf4SDL v1.7 ($Revision: 256 $)\n"
|
|
"Ported by Chaos-Software (http://www.chaos-software.de.vu)\n"
|
|
"Original Wolfenstein 3D by id Software\n\n"
|
|
"Usage: Wolf4SDL [options]\n"
|
|
"Options:\n"
|
|
" --help This help page\n"
|
|
" --tedlevel <level> Starts the game in the given level\n"
|
|
" --baby Sets the difficulty to baby for tedlevel\n"
|
|
" --easy Sets the difficulty to easy for tedlevel\n"
|
|
" --normal Sets the difficulty to normal for tedlevel\n"
|
|
" --hard Sets the difficulty to hard for tedlevel\n"
|
|
" --nowait Skips intro screens\n"
|
|
" --windowed[-mouse] Starts the game in a window [and grabs mouse]\n"
|
|
" --res <width> <height> Sets the screen resolution\n"
|
|
" (must be multiple of 320x200 or 320x240)\n"
|
|
" --resf <w> <h> Sets any screen resolution >= 320x200\n"
|
|
" (which may result in graphic errors)\n"
|
|
" --bits <b> Sets the screen color depth\n"
|
|
" (use this when you have palette/fading problems\n"
|
|
" allowed: 8, 16, 24, 32, default: \"best\" depth)\n"
|
|
" --nodblbuf Don't use SDL's double buffering\n"
|
|
" --extravbls <vbls> Sets a delay after each frame, which may help to\n"
|
|
" reduce flickering (unit is currently 8 ms, default: 0)\n"
|
|
" --joystick <index> Use the index-th joystick if available\n"
|
|
" (-1 to disable joystick, default: 0)\n"
|
|
" --joystickhat <index> Enables movement with the given coolie hat\n"
|
|
" --samplerate <rate> Sets the sound sample rate (given in Hz, default: %i)\n"
|
|
" --audiobuffer <size> Sets the size of the audio buffer (-> sound latency)\n"
|
|
" (given in bytes, default: 2048 / (44100 / samplerate))\n"
|
|
" --ignorenumchunks Ignores the number of chunks in VGAHEAD.*\n"
|
|
" (may be useful for some broken mods)\n"
|
|
" --configdir <dir> Directory where config file and save games are stored\n"
|
|
#if defined(_WIN32)
|
|
" (default: current directory)\n"
|
|
#else
|
|
" (default: $HOME/.wolf4sdl)\n"
|
|
#endif
|
|
#if defined(SPEAR) && !defined(SPEARDEMO)
|
|
" --mission <mission> Mission number to play (0-3)\n"
|
|
" (default: 0 -> .sod, 1-3 -> .sd*)\n"
|
|
" --goodtimes Disable copy protection quiz\n"
|
|
#endif
|
|
, defaultSampleRate
|
|
);
|
|
exit(1);
|
|
}
|
|
|
|
if(sampleRateGiven && !audioBufferGiven)
|
|
param_audiobuffer = 2048 / (44100 / param_samplerate);
|
|
}
|
|
|
|
/*
|
|
==========================
|
|
=
|
|
= main
|
|
=
|
|
==========================
|
|
*/
|
|
|
|
int main (int argc, char *argv[])
|
|
{
|
|
|
|
CheckParameters(argc, argv);
|
|
|
|
CheckForEpisodes();
|
|
|
|
InitGame();
|
|
|
|
DemoLoop();
|
|
|
|
Quit("Demo loop exited???");
|
|
return 1;
|
|
}
|