summaryrefslogtreecommitdiffstats
path: root/apps/plugins/sdl/progs/wolf3d/wl_main.c
diff options
context:
space:
mode:
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;
+}