summaryrefslogtreecommitdiffstats
path: root/apps/plugins/sdl/progs/wolf3d/wl_main.c
diff options
context:
space:
mode:
authorFranklin Wei <git@fwei.tk>2019-07-07 22:00:20 -0400
committerFranklin Wei <git@fwei.tk>2019-07-09 11:20:55 -0400
commit3f59fc8b771625aca9c3aefe03cf1038d8461963 (patch)
treee0623a323613baa0b0993411b38bcaed144b27ed /apps/plugins/sdl/progs/wolf3d/wl_main.c
parent439a0d1d91fa040d261fc39b87278bc9f5391dcc (diff)
downloadrockbox-3f59fc8b771625aca9c3aefe03cf1038d8461963.tar.gz
rockbox-3f59fc8b771625aca9c3aefe03cf1038d8461963.tar.bz2
rockbox-3f59fc8b771625aca9c3aefe03cf1038d8461963.zip
Wolfenstein 3-D!
This is a port of Wolf4SDL, which is derived from the original id software source release. The port runs on top of the SDL plugin runtime and is loaded as an overlay. Licensing of the game code is not an issue, as discussed below (essentially, the Debian project treats Wolf4SDL as GPLv2, with an email from John Carmack backing it up): http://forums.rockbox.org/index.php?topic=52872 Included is a copy of MAME's Yamaha OPL sound chip emulator (fmopl_gpl.c). This file was not part of the original Wolf4SDL source (which includes a non-GPL'd version), but was rather rebased from from a later MAME source which had been relicensed to GPLv2. Change-Id: I64c2ba035e0be7e2f49252f40640641416613439
Diffstat (limited to 'apps/plugins/sdl/progs/wolf3d/wl_main.c')
-rw-r--r--apps/plugins/sdl/progs/wolf3d/wl_main.c1953
1 files changed, 1953 insertions, 0 deletions
diff --git a/apps/plugins/sdl/progs/wolf3d/wl_main.c b/apps/plugins/sdl/progs/wolf3d/wl_main.c
new file mode 100644
index 0000000000..e78274cbac
--- /dev/null
+++ b/apps/plugins/sdl/progs/wolf3d/wl_main.c
@@ -0,0 +1,1953 @@
+// WL_MAIN.C
+
+#include "wl_def.h"
+#pragma hdrstop
+#include "wl_atmos.h"
+#include <SDL_syswm.h>
+
+
+/*
+=============================================================================
+
+ WOLFENSTEIN 3-D
+
+ An Id Software production
+
+ by John Carmack
+
+=============================================================================
+*/
+
+extern byte signon[];
+
+/*
+=============================================================================
+
+ 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];
+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;
+
+#if defined(_arch_dreamcast)
+int param_joystickhat = 0;
+int param_samplerate = 11025; // higher samplerates result in "out of memory"
+int param_audiobuffer = 4096 / (44100 / param_samplerate);
+#elif defined(GP2X_940)
+int param_joystickhat = -1;
+int param_samplerate = 11025; // higher samplerates result in "out of memory"
+int param_audiobuffer = 128;
+#else
+int param_joystickhat = -1;
+int param_samplerate = RB_SAMPR;
+int param_audiobuffer = 2048 / (44100 / RB_SAMPR);
+#endif
+
+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];
+
+#ifdef _arch_dreamcast
+ DC_LoadFromVMU(configname);
+#endif
+
+ 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 >= 0)
+ {
+ //
+ // 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);
+
+ /* hack to always enable sound */
+ sd = sdm_AdLib;
+ sm = smm_AdLib;
+
+ sds = sds_SoundBlaster;
+
+ // 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:
+ // always -FW19
+ sd = sdm_AdLib;
+ sm = smm_AdLib;
+
+ sds = sds_SoundBlaster;
+
+ 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];
+
+#ifdef _arch_dreamcast
+ fs_unlink(configname);
+#endif
+
+ 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);
+ }
+#ifdef _arch_dreamcast
+ DC_SaveToVMU(configname, NULL);
+#endif
+}
+
+
+//===========================================================================
+
+/*
+=====================
+=
+= 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);
+
+ 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 ();
+#if defined(GP2X_940)
+ GP2X_Shutdown();
+#endif
+}
+
+
+//===========================================================================
+
+/*
+==================
+=
+= 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;
+
+#if defined(USE_STARSKY) || defined(USE_RAIN) || defined(USE_SNOW)
+ Init3DPoints();
+#endif
+}
+
+//===========================================================================
+
+
+/*
+====================
+=
+= 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;
+
+ int i = 0;
+ for (map = wolfdigimap; *map != LASTSOUND; map += 3)
+ {
+ rb->splashf(0, "Preparing sounds (%d/%d)", ++i, ARRAYLEN(wolfdigimap)/3);
+ DigiMap[map[0]] = map[1];
+ DigiChannel[map[1]] = map[2];
+ SD_PrepareSound(map[1]);
+ rb->yield();
+ }
+}
+
+#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) < 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);
+ }
+
+#if defined(GP2X_940)
+ GP2X_MemoryInit();
+#endif
+
+ 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 ();
+
+ rb->splash(0, "Reading configuration...");
+
+ ReadConfig();
+
+ rb->splash(0, "Reading saved games...");
+
+ SetupSaveGames();
+
+//
+// HOLDING DOWN 'M' KEY? (Fire for rockbox)
+//
+#ifndef SPEARDEMO
+ if (Keyboard[sc_Control])
+ {
+ DoJukebox();
+ didjukebox=true;
+ }
+ else
+#endif
+
+//
+// draw intro screen stuff
+//
+ IntroScreen ();
+
+#ifdef _arch_dreamcast
+ //TODO: VMU Selection Screen
+#endif
+
+//
+// load in and lock down some basic chunks
+//
+
+ rb->splash(0, "Loading...");
+
+ CA_CacheGrChunk(STARTFONT);
+ CA_CacheGrChunk(STATUSBARPIC);
+
+ LoadLatchMem ();
+ BuildTables (); // trig tables
+ SetupWalls ();
+
+ rb->splash(0, "Loading (50%)...");
+
+ 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);
+ rb->splashf(HZ * 4, "FATAL: %s", error);
+ }
+ 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(_arch_dreamcast) || 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
+=
+==========================
+*/
+
+#define main my_main
+
+int main (int argc, char *argv[])
+{
+#if defined(_arch_dreamcast)
+ DC_Init();
+#else
+ CheckParameters(argc, argv);
+#endif
+
+ CheckForEpisodes();
+
+ InitGame();
+
+ DemoLoop();
+
+ Quit("Demo loop exited???");
+ return 1;
+}