Source to src/d_main.c
// Emacs style mode select -*- C++ -*-
//-----------------------------------------------------------------------------
//
// $Id:$
//
// Copyright (C) 1993-1996 by id Software, Inc.
//
// This source is available for distribution and/or modification
// only under the terms of the DOOM Source Code License as
// published by id Software. All rights reserved.
//
// The source is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// FITNESS FOR A PARTICULAR PURPOSE. See the DOOM Source Code License
// for more details.
//
// $Log:$
//
// DESCRIPTION:
// DOOM main program (D_DoomMain) and game loop (D_DoomLoop),
// plus functions to determine game mode (shareware, registered),
// parse command line parameters, configure game parameters (turbo),
// and call the startup functions.
//
//-----------------------------------------------------------------------------
static const char rcsid[] = "$Id: d_main.c,v 1.8 1997/02/03 22:45:09 b1 Exp $";
#define BGCOLOR 7
#define FGCOLOR 8
#ifdef NORMALUNIX
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#endif
#include <direct.h>
#include <malloc.h>
#include <io.h>
#include <fcntl.h>
#include "doomdef.h"
#include "doomstat.h"
#include "dstrings.h"
#include "sounds.h"
#include "z_zone.h"
#include "w_wad.h"
#include "s_sound.h"
#include "v_video.h"
#include "f_finale.h"
#include "f_wipe.h"
#include "m_argv.h"
#include "m_misc.h"
#include "m_menu.h"
#include "i_system.h"
#include "i_sound.h"
#include "i_video.h"
#include "g_game.h"
#include "hu_stuff.h"
#include "wi_stuff.h"
#include "st_stuff.h"
#include "am_map.h"
#include "p_setup.h"
#include "r_local.h"
#include "d_main.h"
//#include "d_console.h"
#include "dconsole.h" //11.26.98 for compatibility
char MsgText[256];
void WriteDebug(char *);
extern void dxStartText(char *textline); //startup graphics
extern int dxStCount;
extern int usemouse;
extern int usejoystick;
//
// D-DoomLoop()
// Not a globally visible function,
// just included for source reference,
// called by D_DoomMain, never exits.
// Manages timing and IO,
// calls all ?_Responder, ?_Ticker, and ?_Drawer,
// calls I_GetTime, I_StartFrame, and I_StartTic
//
//void D_DoomLoop (void); 11.9.98 dlw - clean up opt
char* wadfiles[MAXWADFILES];
boolean devparm; // started game with -devparm
boolean nomonsters; // checkparm of -nomonsters
boolean respawnparm; // checkparm of -respawn
boolean fastparm; // checkparm of -fast
boolean drone;
boolean singletics = false; // debug flag to cancel adaptiveness
extern boolean plutonia, tnt;
//extern int soundVolume;
//extern int sfxVolume;
//extern int musicVolume;
extern boolean inhelpscreens;
extern boolean helpfromkey; //10.14.98 workaround for shareware help
extern int GameMode;
skill_t startskill;
int startepisode;
int startmap;
boolean autostart;
FILE* debugfile;
boolean advancedemo;
char wadfile[1024]; // primary wad file
char mapdir[1024]; // directory of development maps
char basedefault[1024]; // default file
void D_CheckNetGame (void);
void D_ProcessEvents (void);
void G_BuildTiccmd (ticcmd_t* cmd);
void D_DoAdvanceDemo (void);
void RenderScene(void);
//
// EVENT HANDLING
//
// Events are asynchronous inputs generally generated by the game user.
// Events can be discarded if no responder claims them
//
event_t events[MAXEVENTS];
int eventhead;
int eventtail;
//
// D_PostEvent
// Called by the I/O functions when input is detected
//
void D_PostEvent(event_t* ev)
{
events[eventhead] = *ev;
eventhead = (++eventhead)&(MAXEVENTS-1);
}
//
// D_ProcessEvents
// Send all the events of the given timestamp down the responder chain
//
void D_ProcessEvents(void)
{
event_t* ev;
// IF STORE DEMO, DO NOT ACCEPT INPUT
if (( gamemode == commercial ) && (W_CheckNumForName("map01")<0))
return;
for (; eventtail != eventhead; eventtail = (++eventtail)&(MAXEVENTS-1))
{
ev = &events[eventtail];
if(CO_Responder(ev)) continue; // console ate the event
if(M_Responder(ev)) continue; // menu ate the event
G_Responder(ev);
}
}
//
// D_Display
// draw current display, possibly wiping it from the previous
//
// wipegamestate can be set to -1 to force a wipe on the next draw
gamestate_t wipegamestate = GS_DEMOSCREEN;
extern boolean setsizeneeded;
extern int showMessages;
void R_ExecuteSetViewSize (void);
// 11.4.98 dlw: I've been optimizing and this thing is a mess.
// There's just too much redundant checking throughout
// There'd be a meg of comments if I noted every little fix
// so it's pretty much gonna be: orinal code pushed down...
// new fast code up top.
void D_Display(void)
{
static boolean viewactivestate = false;
static boolean menuactivestate = false;
static boolean inhelpscreensstate = false;
static boolean fullscreen = false;
static gamestate_t oldgamestate = -1;
static int borderdrawcount;
int nowtime;
int tics;
int wipestart;
int y;
boolean done;
boolean wipe;
boolean redrawsbar;
//if (nodrawers) return; // for comparative timing / profiling
redrawsbar = false;
// change the view size if needed
if(setsizeneeded)
{
//WriteDebug("setsizeneeded...\n");
R_ExecuteSetViewSize();
oldgamestate = -1; // force background redraw
//borderdrawcount = 3; //11.4.98 why 3 times? dlw
borderdrawcount = 1;
}
// save the current screen if about to wipe
if (gamestate != wipegamestate)
{
//WriteDebug("wipe_StartScreen...\n");
wipe = true;
// wipe_StartScreen(0, 0, SCREENWIDTH, SCREENHEIGHT);
wipe_StartScreen(); //11.4.98 dlw optimized version
}
else
{
wipe = false;
//WriteDebug("wipe=false\n");
}
//11.4.98 does this need doing at all? dlw
//11.4.98 NO. screen is erased anyway
//if (gamestate == GS_LEVEL && gametic)
//{
//WriteDebug("HU_Erase...\n");
//11.4.98 does this need doing at all?
//HU_Erase();
//}
// do buffered drawing
switch (gamestate)
{
case GS_LEVEL:
//WriteDebug("GS_LEVEL - 1...\n");
if(!gametic) break;
//WriteDebug("GS_LEVEL - 2...\n");
if(automapactive) AM_Drawer();
//WriteDebug("GS_LEVEL - 3...\n");
if (wipe || (viewheight != SCREENHEIGHT && fullscreen) )
redrawsbar = true;
if(inhelpscreensstate && !inhelpscreens)
{
redrawsbar = true; // just put away the help screen
if(DOUBLESTUFF) // 10.13.98 hi-res leaving help and map at edges
R_DrawViewBorder();
}
//WriteDebug("GS_LEVEL - 4...\n");
ST_Drawer(viewheight == SCREENHEIGHT, redrawsbar );
//WriteDebug("GS_LEVEL - 5...\n");
fullscreen = viewheight == SCREENHEIGHT;
break;
case GS_INTERMISSION:
WI_Drawer();
break;
case GS_FINALE:
F_Drawer();
break;
case GS_DEMOSCREEN:
D_PageDrawer();
break;
}
// draw the view directly 11.4.98 Optimized
// and while yer laffing at me for picking C nits in here...
// these changes made this thing go from 24FPS to 28/29
if(gamestate == GS_LEVEL)
{
if(gametic)
{
if(!automapactive) R_RenderPlayerView(&players[displayplayer]);
HU_Drawer();
}
if(oldgamestate != GS_LEVEL) //11.4.98 redundant see below
{
viewactivestate = false; // view was not active
R_FillBackScreen(); // draw the pattern into the back screen
}
// see if the border needs to be updated to the screen
if(!automapactive && scaledviewwidth != SCREENWIDTH && viewheight != SCREENHEIGHT)
{
if (menuactive || menuactivestate || !viewactivestate)
borderdrawcount = 1;
if (borderdrawcount)
{
R_DrawViewBorder(); // erase old menu stuff
borderdrawcount--;
}
}
}
else // gamestate!=GSLEVEL 11.5.98 optimize
{
// clean up border stuff
if(gamestate != oldgamestate)
I_SetPalette(W_CacheLumpName("PLAYPAL",PU_CACHE));
}
// clean up border stuff 11.5.98 optimized
//if (gamestate != oldgamestate && gamestate != GS_LEVEL)
//{
// I_SetPalette(W_CacheLumpName("PLAYPAL",PU_CACHE));
//}
// draw buffered stuff to screen
// I_UpdateNoBlit(); 10.19.98 dlw unused (dead loop)
// 11.4.98 dlw Optimize: original code redundant checking
// gamestate==GSLEVEL && gametic. Fixed up so only test
// once
// draw the view directly
//if (gamestate == GS_LEVEL && !automapactive && gametic)
//{
//WriteDebug("R_RenderPlayerView...\n");
// R_RenderPlayerView(&players[displayplayer]);
//}
//if (gamestate == GS_LEVEL && gametic)
//{
// HU_Drawer();
//}
// 11.4.98 optimizer -> up in the GSLEVEL stuff above
// see if the border needs to be initially drawn
//if (gamestate == GS_LEVEL && oldgamestate != GS_LEVEL)
//{
// viewactivestate = false; // view was not active
// R_FillBackScreen(); // draw the pattern into the back screen
//}
// see if the border needs to be updated to the screen
//if (gamestate == GS_LEVEL && !automapactive && scaledviewwidth != SCREENWIDTH && viewheight != SCREENHEIGHT)
//{
// if (menuactive || menuactivestate || !viewactivestate)
// borderdrawcount = 3;
// if (borderdrawcount)
// {
// R_DrawViewBorder(); // erase old menu stuff
// borderdrawcount--;
// }
//}
menuactivestate = menuactive;
viewactivestate = viewactive;
inhelpscreensstate = inhelpscreens;
oldgamestate = wipegamestate = gamestate;
// draw pause pic
if(paused)
{
if (automapactive)
y = 4;
else
y = viewwindowy+4;
//V_DrawPatchDirect(viewwindowx+(scaledviewwidth-68)/2,y,0,W_CacheLumpName ("M_PAUSE", PU_CACHE));
V_DrawPatch(viewwindowx+(scaledviewwidth-68)/2,y,0,W_CacheLumpName ("M_PAUSE", PU_CACHE));
}
// menus go directly to the screen
M_Drawer(); // menu is drawn even on top of everything
CO_Drawer(); // Console is drawn on top of even the menu...
if(!internetgame) //11.12.98 dlw less x-mit for internet
NetUpdate(); // send out any new accumulation
// normal update -- 11.4.98 since -devparm doesn't do anything
// but draw dots--hell with it OPTIMIZE
if (!wipe)
{
//I_FinishUpdate(); // page flip or blit buffer
RenderScene();
return;
}
// wipe update -- 11.4.98 optimized version
// wipe_EndScreen(0, 0, SCREENWIDTH, SCREENHEIGHT);
wipe_EndScreen();
wipestart = I_GetTime () - 1;
do
{
do
{
nowtime = I_GetTime();
tics = nowtime - wipestart;
}while(!tics);
wipestart = nowtime;
done = wipe_ScreenWipe(wipe_Melt, 0, 0, SCREENWIDTH, SCREENHEIGHT, tics);
// 11.4.98 Unused -- I_UpdateNoBlit ();
M_Drawer(); // menu is drawn even on top of wipes
CO_Drawer(); // Console is drawn on top of even the menu...
// I_FinishUpdate (); //11.4.98 no dots
RenderScene(); // page flip or blit buffer
}while(!done);
}
//
// D_DoomLoop
//
extern int demotype;
extern boolean demorecording;
/*void D_DoomLoop(void) 11.8.98 dlw clean up opt (My_DoomLoop)
{
if (demorecording) G_BeginRecording();
if (M_CheckParm ("-debugfile"))
{
char filename[20];
sprintf (filename,"debug%i.txt",consoleplayer);
//printf ("debug output to: %s\n",filename);
sprintf(MsgText, "debug output to: %s\n",filename);
WriteDebug(MsgText);
debugfile = fopen (filename,"w");
}
I_InitGraphics();
while (1)
{
// frame syncronous IO operations
I_StartFrame();
// process one or more tics
if (singletics)
{
I_StartTic ();
D_ProcessEvents ();
G_BuildTiccmd (&netcmds[consoleplayer][maketic%BACKUPTICS]);
if (advancedemo)
D_DoAdvanceDemo();
M_Ticker ();
G_Ticker ();
gametic++;
maketic++;
}
else
{
TryRunTics (); // will run at least one tic
}
S_UpdateSounds (players[consoleplayer].mo);// move positional sounds
// Update display, next frame, with current state.
D_Display();
//#ifndef SNDSERV
// Sound mixing for the buffer is snychronous.
//I_UpdateSound();
//#endif
// Synchronous sound output is explicitly called.
//#ifndef SNDINTR
// Update sound output.
//I_SubmitSound();
//#endif
}
} */
void MY_DoomSetup(void)
{
if (demorecording)
G_BeginRecording();
//WriteDebug("MY_DoomSetup...\n");
if(M_CheckParm ("-debugfile"))
{
char filename[20];
sprintf (filename,"debug%i.txt",consoleplayer);
//printf ("debug output to: %s\n",filename);
sprintf(MsgText, "debug output to: %s\n",filename);
WriteDebug(MsgText);
debugfile = fopen (filename,"w");
}
if(gamemode != indetermined) //11.9.98 bug catcher
I_SetPalette(W_CacheLumpName("PLAYPAL", PU_CACHE));
}
void MY_DoomLoop(void)
{
//WriteDebug("MY_DoomLoop...\n");
// frame syncronous IO operations
// UNUSED: I_StartFrame();
// process one or more tics
if(singletics)
{
//WriteDebug("singletics...\n");
//WriteDebug("I_StartTic...\n");
// 11.4.98 dlw UNUSED EMPTY: I_StartTic();
//WriteDebug("D_ProcessEvents...\n");
D_ProcessEvents();
//WriteDebug("MY_DoomLoop calling G_BuildTiccmd...\n");
G_BuildTiccmd(&netcmds[consoleplayer][maketic%BACKUPTICS]);
if(advancedemo)
{
//WriteDebug("D_DoAdvanceDemo...\n");
D_DoAdvanceDemo();
}
CO_Ticker();
//WriteDebug("M_Ticker...\n");
M_Ticker();
//WriteDebug("G_Ticker...\n");
G_Ticker();
gametic++;
maketic++;
}
else
{
//WriteDebug("TryRunTics...\n");
TryRunTics(); // will run at least one tic
}
//WriteDebug("S_UpdateSounds...\n");
S_UpdateSounds(players[consoleplayer].mo);// move positional sounds
// Update display, next frame, with current state.
//WriteDebug("D_Display...\n");
D_Display();
//#ifndef SNDSERV
// Sound mixing for the buffer is snychronous.
//I_UpdateSound();
//#endif
// Synchronous sound output is explicitly called.
//#ifndef SNDINTR
// Update sound output.
//I_SubmitSound();
//#endif
}
//
// DEMO LOOP
//
int demosequence;
int pagetic;
char *pagename;
//
// D_PageTicker
// Handles timing for warped projection
//
void D_PageTicker (void)
{
if (--pagetic < 0)
D_AdvanceDemo ();
}
//
// D_PageDrawer
//
void D_PageDrawer (void)
{
int i;
__int64 *d;
d = (__int64 *)screens[0];
for (i = 0; i < (SCREENMULT/8); i++)
d[i] = 0;
//10.13.98-- big demo/menu screens for double mode 640x400
// updated once more for the way up modes, since center code same
if( DOUBLESTUFF )
V_DrawPatchDouble( ((SCREENWIDTH-640)/2),((SCREENHEIGHT-400)/2),0, W_CacheLumpName(pagename, PU_CACHE));
else // or any other screen size
V_DrawPatch(((SCREENWIDTH-320)/2),((SCREENHEIGHT-200)/2), 0, W_CacheLumpName(pagename, PU_CACHE));
}
//
// D_AdvanceDemo
// Called after each demo or intro demosequence finishes
//
void D_AdvanceDemo (void)
{
advancedemo = true;
}
//
// This cycles through the demo sequences.
// FIXME - version dependend demo numbers?
//
void D_DoAdvanceDemo(void)
{
players[consoleplayer].playerstate = PST_LIVE; // not reborn
advancedemo = false;
usergame = false; // no save / end game here
paused = false;
gameaction = ga_nothing;
if ( gamemode == retail )
demosequence = (demosequence+1)%7;
else
demosequence = (demosequence+1)%6;
//sprintf(MsgText, "Changing screen to %d...\n", demosequence);
//WriteDebug(MsgText);
switch (demosequence)
{
case 0:
if ( gamemode == commercial )
pagetic = 35 * 11;
else
pagetic = 170;
gamestate = GS_DEMOSCREEN;
pagename = "TITLEPIC";
if ( gamemode == commercial )
S_StartMusic(mus_dm2ttl);
else
S_StartMusic (mus_intro);
break;
case 1:
G_DeferedPlayDemo ("demo1");
break;
case 2:
pagetic = 200;
gamestate = GS_DEMOSCREEN;
pagename = "CREDIT";
break;
case 3:
G_DeferedPlayDemo ("demo2");
break;
case 4:
gamestate = GS_DEMOSCREEN;
if ( gamemode == commercial)
{
pagetic = 35 * 11;
pagename = "TITLEPIC";
S_StartMusic(mus_dm2ttl);
}
else
{
pagetic = 200;
if ( gamemode == retail )
pagename = "CREDIT";
else
pagename = "HELP2";
}
break;
case 5:
G_DeferedPlayDemo ("demo3");
break;
// THE DEFINITIVE DOOM Special Edition demo
case 6:
G_DeferedPlayDemo ("demo4");
break;
}
}
//
// D_StartTitle
//
void D_StartTitle (void)
{
gameaction = ga_nothing;
demosequence = -1;
D_AdvanceDemo();
}
// print title for every printed line
char title[128];
//
// D_AddFile
//
void D_AddFile (char *file)
{
int numwadfiles;
char *newfile;
for (numwadfiles = 0 ; wadfiles[numwadfiles] ; numwadfiles++)
;
newfile = malloc (strlen(file)+1);
strcpy (newfile, file);
wadfiles[numwadfiles] = newfile;
}
#define R_OK 4
//
// IdentifyVersion
// Checks availability of IWAD files by name,
// to determine whether registered/commercial features
// should be executed (notably loading PWAD's).
//
void IdentifyVersion(void)
{
char* doom1wad;
char* doomwad;
char* doomuwad;
char* doom2wad;
char* doom2fwad;
char* plutoniawad;
char* tntwad;
//#ifdef NORMALUNIX
// char *home;
char *doomwaddir;
doomwaddir = getenv("DOOMWADDIR");
if (!doomwaddir) doomwaddir = ".";
// Commercial.
doom2wad = malloc(strlen(doomwaddir)+1+9+1);
sprintf(doom2wad, "%s/doom2.wad", doomwaddir);
// Retail. // Bug here too...
doomuwad = malloc(strlen(doomwaddir)+1+9+1);
sprintf(doomuwad, "%s/doomu.wad", doomwaddir);
// Registered.
doomwad = malloc(strlen(doomwaddir)+1+8+1);
sprintf(doomwad, "%s/doom.wad", doomwaddir);
// Shareware.
doom1wad = malloc(strlen(doomwaddir)+1+9+1);
sprintf(doom1wad, "%s/doom1.wad", doomwaddir);
// Bug, dear Shawn.
// Insufficient malloc, caused spurious realloc errors.
plutoniawad = malloc(strlen(doomwaddir)+1+/*9*/12+1);
sprintf(plutoniawad, "%s/plutonia.wad", doomwaddir);
tntwad = malloc(strlen(doomwaddir)+1+9+1);
sprintf(tntwad, "%s/tnt.wad", doomwaddir);
// French stuff.
doom2fwad = malloc(strlen(doomwaddir)+1+10+1);
sprintf(doom2fwad, "%s/doom2f.wad", doomwaddir);
/* Don't HAVE home directory on a single user OS...
home = getenv("HOME");
if (!home)
I_Error("Please set $HOME to your home directory");
sprintf(basedefault, "%s/.doomrc", home);
#endif
*/
if (M_CheckParm ("-shdev"))
{
gamemode = shareware;
devparm = true;
D_AddFile (DEVDATA"doom1.wad");
D_AddFile (DEVMAPS"data_se/texture1.lmp");
D_AddFile (DEVMAPS"data_se/pnames.lmp");
strcpy (basedefault,DEVDATA"default.cfg");
return;
}
if (M_CheckParm ("-regdev"))
{
gamemode = registered;
devparm = true;
D_AddFile (DEVDATA"doom.wad");
D_AddFile (DEVMAPS"data_se/texture1.lmp");
D_AddFile (DEVMAPS"data_se/texture2.lmp");
D_AddFile (DEVMAPS"data_se/pnames.lmp");
strcpy (basedefault,DEVDATA"default.cfg");
return;
}
if (M_CheckParm ("-comdev"))
{
gamemode = commercial;
devparm = true;
/*
if(plutonia)
D_AddFile (DEVDATA"plutonia.wad");
else if(tnt)
D_AddFile (DEVDATA"tnt.wad");
else*/
D_AddFile (DEVDATA"doom2.wad");
D_AddFile (DEVMAPS"cdata/texture1.lmp");
D_AddFile (DEVMAPS"cdata/pnames.lmp");
strcpy (basedefault,DEVDATA"default.cfg");
return;
}
if( !access(doom2fwad,R_OK) )
{
gamemode = commercial;
// C'est ridicule!
// Let's handle languages in config files, okay?
language = french;
//printf("French version\n");
WriteDebug("French version?\n");
++dxStCount;
dxStartText("French version?"); //10.20.98 dlw
D_AddFile(doom2fwad);
return;
}
if( !access(doom2wad,R_OK) )
{
gamemode = commercial;
D_AddFile(doom2wad);
return;
}
if( !access(plutoniawad, R_OK ) )
{
gamemode = commercial;
plutonia = TRUE;
tnt = FALSE;
D_AddFile (plutoniawad);
return;
}
if( !access( tntwad, R_OK ) )
{
gamemode = commercial;
tnt = TRUE;
plutonia = FALSE;
D_AddFile(tntwad);
return;
}
if( !access(doomuwad,R_OK) )
{
gamemode = retail;
D_AddFile(doomuwad);
return;
}
if( !access(doomwad,R_OK) )
{
gamemode = registered;
D_AddFile (doomwad);
return;
}
if( !access(doom1wad,R_OK) )
{
gamemode = shareware;
D_AddFile (doom1wad);
return;
}
//printf("Game mode indeterminate.\n");
WriteDebug("Game mode indeterminate.\n");
dxStCount++;
dxStartText("Game mode indeterminate."); //10.20.98 dlw
gamemode = indetermined;
// We don't abort. Let's see what the PWAD contains.
//exit(1);
//I_Error("Game mode indeterminate\n");
//11.9.98 dlw bug-fix
I_Error("No wad file in installation directory.\n");
}
//
// Find a Response File
//
void FindResponseFile (void)
{
int i;
#define MAXARGVS 100
for (i = 1;i < myargc;i++)
if (myargv[i][0] == '@')
{
FILE * handle;
int size;
int k;
int index;
int indexinfile;
char *infile;
char *file;
char *moreargs[20];
char *firstargv;
// READ THE RESPONSE FILE INTO MEMORY
handle = fopen (&myargv[i][1],"rb");
if (!handle)
{
printf ("\nNo such response file!");
exit(1);
}
printf("Found response file %s!\n",&myargv[i][1]);
fseek (handle,0,SEEK_END);
size = ftell(handle);
fseek (handle,0,SEEK_SET);
file = malloc (size);
fread (file,size,1,handle);
fclose (handle);
// KEEP ALL CMDLINE ARGS FOLLOWING @RESPONSEFILE ARG
for (index = 0,k = i+1; k < myargc; k++)
moreargs[index++] = myargv[k];
firstargv = myargv[0];
myargv = malloc(sizeof(char *)*MAXARGVS);
memset(myargv,0,sizeof(char *)*MAXARGVS);
myargv[0] = firstargv;
infile = file;
indexinfile = k = 0;
indexinfile++; // SKIP PAST ARGV[0] (KEEP IT)
do
{
myargv[indexinfile++] = infile+k;
while(k < size &&
((*(infile+k)>= ' '+1) && (*(infile+k)<='z')))
k++;
*(infile+k) = 0;
while(k < size &&
((*(infile+k)<= ' ') || (*(infile+k)>'z')))
k++;
} while(k < size);
for (k = 0;k < index;k++)
myargv[indexinfile++] = moreargs[k];
myargc = indexinfile;
// DISPLAY ARGS
printf("%d command-line args:\n",myargc);
for (k=1;k<myargc;k++)
printf("%s\n",myargv[k]);
break;
}
}
//
// D_DoomMain
//
void D_DoomMain(void)
{
int p;
char file[256];
//FindResponseFile();
IdentifyVersion();
if(gamemode == indetermined) return; //11.9.98 bugcatcher dlw
setbuf(stdout, NULL);
modifiedgame = false;
nomonsters = M_CheckParm ("-nomonsters");
respawnparm = M_CheckParm ("-respawn");
fastparm = M_CheckParm ("-fast");
devparm = M_CheckParm ("-devparm");
if (M_CheckParm ("-altdeath"))
deathmatch = 2;
else if (M_CheckParm ("-deathmatch"))
deathmatch = 1;
if (devparm)
{
WriteDebug(D_DEVSTR);
WriteDebug("\n");
// printf(D_DEVSTR);
dxStCount++;
dxStartText(D_DEVSTR);
}
if (M_CheckParm("-cdrom"))
{
WriteDebug(D_CDROM);
WriteDebug("\n");
dxStCount++;
dxStartText(D_CDROM); //10.20.98 dlw
//printf(D_CDROM);
//mkdir("c:\\doomdata",0); // What's the ",0" for? Oh yeah, permissions...
mkdir("c:\\doomdata");
strcpy (basedefault,"c:/doomdata/default.cfg");
}
// turbo option
if ( (p=M_CheckParm ("-turbo")) )
{
int scale = 200;
extern int forwardmove[2];
extern int sidemove[2];
if (p<myargc-1)
scale = atoi (myargv[p+1]);
if (scale < 10)
scale = 10;
if (scale > 400)
scale = 400;
//printf ("turbo scale: %i%%\n",scale);
forwardmove[0] = forwardmove[0]*scale/100;
forwardmove[1] = forwardmove[1]*scale/100;
sidemove[0] = sidemove[0]*scale/100;
sidemove[1] = sidemove[1]*scale/100;
}
// add any files specified on the command line with -file wadfile
// to the wad list
//
// convenience hack to allow -wart e m to add a wad file
// prepend a tilde to the filename so wadfile will be reloadable
p = M_CheckParm ("-wart");
if (p)
{
myargv[p][4] = 'p'; // big hack, change to -warp
// Map name handling.
switch (gamemode)
{
case shareware:
case retail:
case registered:
sprintf (file,"~"DEVMAPS"E%cM%c.wad", myargv[p+1][0], myargv[p+2][0]);
// printf("Warping to Episode %s, Map %s.\n",
// myargv[p+1],myargv[p+2]);
sprintf(MsgText, "Warping to Episode %s, Map %s.",
myargv[p+1],myargv[p+2]);
WriteDebug(MsgText);
WriteDebug("\n");
dxStCount++;
dxStartText(MsgText); //10.20.98 dlw
break;
case commercial:
default:
p = atoi (myargv[p+1]);
if (p<10)
sprintf (file,"~"DEVMAPS"cdata/map0%i.wad", p);
else
sprintf (file,"~"DEVMAPS"cdata/map%i.wad", p);
break;
}
D_AddFile(file);
}
p = M_CheckParm ("-file");
if(p)
{
// the parms after p are wadfile/lump names,
// until end of parms or another - preceded parm
modifiedgame = true; // homebrew levels
while (++p != myargc && myargv[p][0] != '-')
{
//score keeping has to have a way to know if user wads
strncpy(scoreuserwad, myargv[p], strlen(myargv[p]));
D_AddFile(myargv[p]);
}
}
p = M_CheckParm ("-playdemo");
if(!p)
{
p = M_CheckParm ("-playdemo2");
demotype = DEMO_II;
}
else
{
demotype = DEMO_I;
}
if(!p)
{
p = M_CheckParm ("-timedemo");
demotype = DEMO_I;
}
if (!p)
{
p = M_CheckParm ("-timedemo2");
demotype = DEMO_II;
}
if (p && p < myargc-1)
{
if (demotype == DEMO_I)
{
sprintf (file,"%s.lmp", myargv[p+1]);
D_AddFile(file);
//printf("Playing demo %s.lmp.\n",myargv[p+1]);
sprintf(MsgText, "Playing demo %s.lmp.",myargv[p+1]);
WriteDebug(MsgText);
WriteDebug("\n");
dxStCount++;
dxStartText(MsgText); //10.20.98 dlw
}
else
{
sprintf(MsgText, "Playing demo II %s.dem.",myargv[p+1]);
WriteDebug(MsgText);
WriteDebug("\n");
dxStCount++;
dxStartText(MsgText); //10.20.98 dlw
}
}
// get skill / episode / map from parms
startskill = sk_medium;
startepisode = 1;
startmap = 1;
autostart = false;
p = M_CheckParm ("-skill");
if (p && p < myargc-1)
{
startskill = myargv[p+1][0]-'1';
autostart = true;
}
p = M_CheckParm ("-episode");
if (p && p < myargc-1)
{
startepisode = myargv[p+1][0]-'0';
startmap = 1;
autostart = true;
}
p = M_CheckParm ("-timer");
if (p && p < myargc-1 && deathmatch)
{
int time;
time = atoi(myargv[p+1]);
// Change over to buffered output...
//printf("Levels will end after %d minute",time);
sprintf(MsgText, "Levels will end after %d minute",time);
if (time>1)
strcat(MsgText, "s");
//printf("s");
strcat(MsgText, ".");
//printf(".\n");
WriteDebug(MsgText);
WriteDebug("\n");
dxStCount++;
dxStartText(MsgText); //10.20.98 dlw
}
p = M_CheckParm ("-avg");
if (p && p < myargc-1 && deathmatch)
{
WriteDebug("Austin Virtual Gaming: Levels will end after 20 minutes\n");
dxStCount++;
dxStartText("Austin Virtual Gaming: Levels will end after 20 minutes."); //10.20.98 dlw
}
p = M_CheckParm ("-warp");
if (p && p < myargc-1)
{
if (gamemode == commercial) startmap = atoi (myargv[p+1]);
else
{
startepisode = myargv[p+1][0]-'0';
startmap = myargv[p+2][0]-'0';
}
autostart = true;
}
//10.15.98 dlw Score keeping command lines now added
keepscore=0;
showscoreHUD=0;
keepscore = M_CheckParm("-keepscore");
//10.15.98 dlw Score showing adds keeping by default
p = M_CheckParm("-showscore");
if(p)
{
showscoreHUD=1;
keepscore=1;
}
// init subsystems
//printf ("V_Init: allocate screens.\n");
WriteDebug("V_Init: allocate screens.\n");
dxStCount++;
dxStartText("V_Init: allocate screens."); //10.20.98 dlw
V_Init();
//printf ("M_LoadDefaults: Load system defaults.\n");
WriteDebug("M_LoadDefaults: Load system defaults.\n");
dxStCount++;
dxStartText("M_LoadDefaults: Load system defaults."); //10.20.98 dlw
M_LoadDefaults(); // load before initing other systems
//11.8.98 now fix the input for command line
p = M_CheckParm("-nomouse");
if(p) usemouse=0;
p = M_CheckParm("-joystick");
if(p) usejoystick=1;
//printf ("Z_Init: Init zone memory allocation daemon. \n");
WriteDebug("Z_Init: Init zone memory allocation daemon. \n");
dxStCount++;
dxStartText("Z_Init: Init zone memory allocation daemon."); //10.20.98 dlw
Z_Init();
//printf ("W_Init: Init WADfiles.\n");
WriteDebug("W_Init: Init WADfiles.\n");
dxStCount++;
dxStartText("W_Init: Init WADfiles."); //10.20.98 dlw
W_InitMultipleFiles(wadfiles);
if ((gamemode == retail) || (gamemode == registered))
{
char name[10][8] = { "e4m1","e4m2","e4m3","e4m4","e4m5","e4m6","e4m7","e4m8","e4m9", "m_epi4" };
int i;
WriteDebug("Checking for Ultimate Doom...\n");
dxStCount++;
dxStartText("Checking for Ultimate Doom..."); //10.20.98 dlw
gamemode = retail;
for (i = 0;i < 10; i++)
{
if (W_CheckNumForName(name[i]) < 0)
{
gamemode = registered;
break;
}
}
if (gamemode == registered)
{
WriteDebug("Normal Doom WAD file...\n");
dxStCount++;
dxStartText("Normal Doom WAD file..."); //10.20.98 dlw
}
else
{
WriteDebug("Ultimate Doom WAD - fourth episode enabled...\n");
dxStCount++;
dxStartText("Ultimate Doom WAD - fourth episode enabled..."); //10.20.98 dlw
}
}
switch ( gamemode )
{
case retail:
sprintf (title,
" "
"The Ultimate DOOM Startup v%i.%i"
" ",
VERSION/100,VERSION%100);
break;
case shareware:
sprintf (title,
" "
"DOOM Shareware Startup v%i.%i"
" ",
VERSION/100,VERSION%100);
break;
case registered:
sprintf (title,
" "
"DOOM Registered Startup v%i.%i"
" ",
VERSION/100,VERSION%100);
break;
case commercial:
if (plutonia == TRUE)
sprintf (title, " DOOM 2: Plutonia Experiment v%i.%i ", VERSION/100,VERSION%100);
else
if (tnt == TRUE)
sprintf (title, " DOOM 2: TNT - Evilution v%i.%i ", VERSION/100,VERSION%100);
else
sprintf (title, " DOOM 2: Hell on Earth v%i.%i ", VERSION/100,VERSION%100);
break;
default:
sprintf (title,
" "
"Public DOOM - v%i.%i"
" ",
VERSION/100,VERSION%100);
break;
}
//printf ("%s\n",title);
WriteDebug(title);
WriteDebug("\n");
dxStCount++;
dxStartText(title); //10.20.98 dlw
// Check for -file in shareware
if (modifiedgame)
{
// These are the lumps that will be checked in IWAD,
// if any one is not present, execution will be aborted.
char name[23][8]=
{
"e2m1","e2m2","e2m3","e2m4","e2m5","e2m6","e2m7","e2m8","e2m9",
"e3m1","e3m3","e3m3","e3m4","e3m5","e3m6","e3m7","e3m8","e3m9",
"dphoof","bfgga0","heada1","cybra1","spida1d1"
};
int i;
if ( gamemode == shareware)
I_Error("\nYou cannot -file with the shareware "
"version. Register!");
// Check for fake IWAD with right name,
// but w/o all the lumps of the registered version.
if (gamemode == registered)
for (i = 0;i < 23; i++)
if (W_CheckNumForName(name[i])<0)
I_Error("\nThis is not the registered version.");
}
// If additonal PWAD files are used, print modified banner
if (modifiedgame)
{
//printf (
WriteDebug("===========================================================================\n");
WriteDebug("ATTENTION: This version of DOOM has been modified. If you would like to\n");
WriteDebug("get a copy of the original game, call 1-800-IDGAMES or see the readme file.\n");
WriteDebug(" You will not receive technical support for modified games.\n");
//WriteDebug(" press enter to continue\n");
WriteDebug("===========================================================================\n");
// );
//getchar ();
//added treasures 10.20.98 dlw... y did I do this to me?
++dxStCount;
dxStartText("ATTENTION:This version of DOOM has been modified.");
}
// Check and print which version is executed.
switch ( gamemode )
{
case shareware:
case indetermined:
//printf (
WriteDebug("===========================================================================\n");
WriteDebug(" Shareware!\n");
WriteDebug("===========================================================================\n");
dxStCount++;
dxStartText(" Shareware!");
//);
break;
case registered:
case retail:
case commercial:
//printf (
WriteDebug("===========================================================================\n");
WriteDebug(" Commercial product - do not distribute!\n");
WriteDebug(" Please report software piracy to the SPA: 1-800-388-PIR8\n");
WriteDebug("===========================================================================\n");
dxStCount++;
dxStartText("*Commercial product - do not distribute!*");
dxStCount++;
dxStartText("Please report software piracy to the SPA");
//);
break;
default:
// Ouch.
break;
}
//printf ("M_Init: Init miscellaneous info.\n");
WriteDebug("M_Init: Init miscellaneous info.\n");
dxStCount++;
dxStartText("M_Init: Init miscellaneous info.");
M_Init();
//printf ("R_Init: Init DOOM refresh daemon - ");
WriteDebug("R_Init: Init DOOM refresh daemon - ");
dxStCount++;
dxStartText("R_Init: Init DOOM refresh daemon -");
R_Init();
//printf ("\nP_Init: Init Playloop state.\n");
WriteDebug("\nP_Init: Init Playloop state.\n");
dxStCount++;
dxStartText("P_Init: Init Playloop state.");
P_Init();
//printf ("I_Init: Setting up machine state.\n");
WriteDebug("I_Init: Setting up machine state.\n");
dxStCount++;
dxStartText("I_Init: Setting up machine state.");
I_Init();
//printf ("D_CheckNetGame: Checking network game status.\n");
WriteDebug("D_CheckNetGame: Checking network game status.\n");
dxStCount++;
dxStartText("D_CheckNetGame:");
dxStCount++;
dxStartText(" Checking network game status."); //fudge for little screens
D_CheckNetGame();
//printf ("S_Init: Setting up sound.\n");
WriteDebug("S_Init: Setting up sound.\n");
dxStCount++;
dxStartText("S_Init: Setting up sound.");
//S_Init (snd_SfxVolume*8, snd_MusicVolume*8 );
S_Init(snd_SfxVolume, snd_MusicVolume );
//printf ("HU_Init: Setting up heads up display.\n");
WriteDebug("HU_Init: Setting up heads up display.\n");
dxStCount++;
dxStartText("S_Init: Setting up heads up display.");
HU_Init();
//printf ("ST_Init: Init status bar.\n");
WriteDebug("ST_Init: Init status bar.\n");
dxStCount++;
dxStartText("ST_Init: Init status bar.");
ST_Init();
//printf ("ST_Init: Init status bar.\n");
WriteDebug("CO_Init: Init console.\n");
dxStCount++;
dxStartText("CO_Init: Init console.");
CO_Init();
// check for a driver that wants intermission stats
p = M_CheckParm ("-statcopy");
if (p && p<myargc-1)
{
// for statistics driver
extern void* statcopy;
statcopy = (void*)atoi(myargv[p+1]);
//printf ("External statistics registered.\n");
WriteDebug("External statistics registered.\n");
}
// start the apropriate game based on parms
p = M_CheckParm("-record");
if (p && p < myargc-1)
{
G_RecordDemo(myargv[p+1]);
autostart = true;
}
p = M_CheckParm("-playdemo");
if (p && p < myargc-1)
{
singledemo = true; // quit after one demo
G_DeferedPlayDemo (myargv[p+1]);
return;
// D_DoomLoop (); // never returns
}
p = M_CheckParm("-playdemo2");
if (p && p < myargc-1)
{
singledemo = true; // quit after one demo
if (G_DeferedPlayDemo_II(myargv[p+1]) == true)
return;
else
{
sprintf(MsgText, "DEMO II [%s.dem] - BAD FILE.\n", myargv[p+1]);
WriteDebug(MsgText);
}
// D_DoomLoop (); // never returns
}
p = M_CheckParm("-timedemo");
if (p && p < myargc-1)
{
WriteDebug("-timedemo\n");
G_TimeDemo (myargv[p+1]);
return;
// D_DoomLoop (); // never returns
}
p = M_CheckParm("-timedemo2");
if (p && p < myargc-1)
{
WriteDebug("-timedemo2\n");
if (G_TimeDemo_II(myargv[p+1]) == true)
return;
else
{
sprintf(MsgText, "DEMO II [%s.dem] - BAD FILE.\n", myargv[p+1]);
WriteDebug(MsgText);
}
// D_DoomLoop (); // never returns
}
p = M_CheckParm ("-loadgame");
if (p && p < myargc-1)
{
if (M_CheckParm("-cdrom"))
sprintf(file, "c:\\doomdata\\"SAVEGAMENAME"%c.dsg",myargv[p+1][0]);
else
sprintf(file, SAVEGAMENAME"%c.dsg",myargv[p+1][0]);
G_LoadGame (file);
}
if ( gameaction != ga_loadgame )
{
if (autostart || netgame)
G_InitNew(startskill, startepisode, startmap);
else
D_StartTitle(); // start up intro loop
}
// D_DoomLoop (); // never returns
}