gzdoom/code/D_main.c

1289 lines
27 KiB
C
Raw Normal View History

1998-04-07 00:00:00 +00:00
// 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.
//
//-----------------------------------------------------------------------------
#define BGCOLOR 7
#define FGCOLOR 8
1998-04-07 00:00:00 +00:00
#include "m_alloc.h"
1998-04-07 00:00:00 +00:00
#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"
1998-07-14 00:00:00 +00:00
#include "c_consol.h"
#include "c_cmds.h"
#include "c_dispch.h"
1998-04-07 00:00:00 +00:00
#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"
1998-07-14 00:00:00 +00:00
#include "r_sky.h"
1998-04-07 00:00:00 +00:00
#include "d_main.h"
1998-04-07 00:00:00 +00:00
#include "d_dehack.h"
1998-04-07 00:00:00 +00:00
#include "cmdlib.h"
1998-07-14 00:00:00 +00:00
cvar_t *fraglimit;
cvar_t *timelimit;
cvar_t *turbo;
extern void TurboCallback (cvar_t *);
1998-04-07 00:00:00 +00:00
//
// 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);
char* wadfiles[MAXWADFILES];
1998-07-14 00:00:00 +00:00
BOOL devparm; // started game with -devparm
1998-04-07 00:00:00 +00:00
1998-07-14 00:00:00 +00:00
BOOL DrawNewHUD; // [RH] Draw the new HUD?
1998-04-07 00:00:00 +00:00
1998-07-14 00:00:00 +00:00
BOOL drone;
1998-04-07 00:00:00 +00:00
1998-07-14 00:00:00 +00:00
BOOL singletics = false; // debug flag to cancel adaptiveness
1998-04-07 00:00:00 +00:00
//extern int soundVolume;
//extern int sfxVolume;
//extern int musicVolume;
1998-07-14 00:00:00 +00:00
extern BOOL inhelpscreens;
1998-04-07 00:00:00 +00:00
1998-07-14 00:00:00 +00:00
char startmap[8];
BOOL autostart;
1998-04-07 00:00:00 +00:00
FILE* debugfile;
1998-07-14 00:00:00 +00:00
BOOL advancedemo;
1998-04-07 00:00:00 +00:00
char wadfile[1024]; // primary wad file
void D_CheckNetGame (void);
void D_ProcessEvents (void);
void G_BuildTiccmd (ticcmd_t* cmd);
void D_DoAdvanceDemo (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 (const event_t* ev)
{
events[eventhead] = *ev;
eventhead = (++eventhead)&(MAXEVENTS-1);
}
//
// D_ProcessEvents
// Send all the events of the given timestamp down the responder chain
//
1998-07-14 00:00:00 +00:00
// [RH] Stuff for screenmode testing
extern int testingmode;
extern void M_RestoreMode (void);
1998-04-07 00:00:00 +00:00
void D_ProcessEvents (void)
{
event_t* ev;
// IF STORE DEMO, DO NOT ACCEPT INPUT
if ( ( gamemode == commercial )
&& (W_CheckNumForName("map01")<0) )
return;
1998-07-14 00:00:00 +00:00
// [RH] If testing mode, do not accept input until test is over
if (testingmode) {
if (testingmode <= I_GetTime()) {
M_RestoreMode ();
}
return;
}
1998-04-07 00:00:00 +00:00
for ( ; eventtail != eventhead ; eventtail = (++eventtail)&(MAXEVENTS-1) )
{
ev = &events[eventtail];
if (C_Responder (ev))
continue; // console ate the event
if (M_Responder (ev))
continue; // menu ate the event
G_Responder (ev);
}
}
1998-07-14 00:00:00 +00:00
// [RH] Each time dmflags is changed, this function is called and
// transforms it into an integer so that we don't need to make
// the conversion each time we check its value.
void DMFlagsCallback (cvar_t *var)
{
dmflags = (int)var->value;
// In case DF_NO_FREELOOK was changed, reinitialize the sky
// map. (If no freelook, then no need to stretch the sky.)
if (textureheight)
R_InitSkyMap (r_stretchsky);
if (dmflags & DF_NO_FREELOOK)
AddCommandString ("centerview");
}
1998-04-07 00:00:00 +00:00
//
// 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;
1998-07-14 00:00:00 +00:00
extern BOOL setsizeneeded, setmodeneeded;
extern int NewWidth, NewHeight, NewBpp;
extern cvar_t *st_scale;
1998-04-07 00:00:00 +00:00
void R_ExecuteSetViewSize (void);
void D_Display (void)
{
1998-07-14 00:00:00 +00:00
static BOOL viewactivestate = false;
static BOOL menuactivestate = false;
static BOOL menuwasactive = false;
static BOOL inhelpscreensstate = false;
static BOOL fullscreen = false;
1998-04-07 00:00:00 +00:00
static gamestate_t oldgamestate = -1;
static int borderdrawcount;
int nowtime;
int tics;
int wipestart;
int y;
1998-07-14 00:00:00 +00:00
BOOL done;
BOOL wipe;
BOOL redrawsbar;
1998-04-07 00:00:00 +00:00
if (nodrawers)
return; // for comparative timing / profiling
redrawsbar = false;
if (!menuwasactive && menuactive)
menuwasactive = true;
1998-07-14 00:00:00 +00:00
// [RH] change the screen mode if needed
if (setmodeneeded) {
int oldwidth = screens[0].width;
int oldheight = screens[0].height;
int oldbpp = screens[0].Bpp << 3;
// Change screen mode.
if (!V_SetResolution (NewWidth, NewHeight, NewBpp))
if (!V_SetResolution (oldwidth, oldheight, oldbpp))
I_FatalError ("Could not change screen mode");
// Recalculate various view parameters.
setsizeneeded = true;
// Trick status bar into rethinking its position :-)
SetCVarFloat (st_scale, st_scale->value);
// Redraw status bar.
redrawsbar = true;
// Refresh the console.
C_NewModeAdjust ();
// Fill the back screen.
//R_FillBackScreen ();
}
1998-04-07 00:00:00 +00:00
// change the view size if needed
if (setsizeneeded)
{
R_ExecuteSetViewSize ();
oldgamestate = -1; // force background redraw
borderdrawcount = 3;
1998-07-14 00:00:00 +00:00
if (setmodeneeded) {
setmodeneeded = false;
R_FillBackScreen ();
}
1998-04-07 00:00:00 +00:00
}
1998-07-14 00:00:00 +00:00
I_BeginUpdate ();
1998-04-07 00:00:00 +00:00
// save the current screen if about to wipe
if (gamestate != wipegamestate)
{
wipe = true;
1998-07-14 00:00:00 +00:00
wipe_StartScreen(0, 0, screens[0].width, screens[0].height);
1998-04-07 00:00:00 +00:00
}
else
wipe = false;
1998-04-07 00:00:00 +00:00
if (gamestate == GS_LEVEL && gametic) {
1998-04-07 00:00:00 +00:00
HU_Erase();
1998-04-07 00:00:00 +00:00
}
1998-04-07 00:00:00 +00:00
// do buffered drawing
switch (gamestate)
{
case GS_LEVEL:
if (!gametic)
break;
1998-07-14 00:00:00 +00:00
if (wipe || (realviewheight != screens[0].height && fullscreen) || menuwasactive) {
1998-04-07 00:00:00 +00:00
if (!menuactive)
menuwasactive = false;
redrawsbar = true;
}
if (inhelpscreensstate && !inhelpscreens)
redrawsbar = true; // just put away the help screen
1998-07-14 00:00:00 +00:00
ST_Drawer (realviewheight == screens[0].height, redrawsbar );
fullscreen = realviewheight == screens[0].height;
1998-04-07 00:00:00 +00:00
break;
case GS_INTERMISSION:
WI_Drawer ();
break;
case GS_FINALE:
F_Drawer ();
break;
case GS_DEMOSCREEN:
D_PageDrawer ();
break;
}
// draw buffered stuff to screen
I_UpdateNoBlit ();
// draw the view directly
1998-04-07 00:00:00 +00:00
if (gamestate == GS_LEVEL && (!automapactive || viewactive) && gametic) {
1998-04-07 00:00:00 +00:00
R_RenderPlayerView (&players[displayplayer]);
1998-04-07 00:00:00 +00:00
}
if (gamestate == GS_LEVEL && DrawNewHUD && viewactive) {
ST_newDraw ();
}
if (automapactive) {
AM_Drawer ();
}
1998-04-07 00:00:00 +00:00
1998-04-07 00:00:00 +00:00
if (gamestate == GS_LEVEL && gametic) {
1998-04-07 00:00:00 +00:00
HU_Drawer ();
1998-04-07 00:00:00 +00:00
}
1998-04-07 00:00:00 +00:00
if (gamestate == GS_LEVEL)
C_DrawMid ();
// clean up border stuff
if (gamestate != oldgamestate && gamestate != GS_LEVEL)
1998-07-14 00:00:00 +00:00
V_SetBlend (0,0,0,0);
1998-04-07 00:00:00 +00:00
// 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
1998-04-07 00:00:00 +00:00
if (gamestate == GS_LEVEL && (!automapactive || viewactive))
1998-04-07 00:00:00 +00:00
{
if (menuactive || menuactivestate || !viewactivestate)
borderdrawcount = 3;
if (borderdrawcount)
{
R_DrawViewBorder (); // erase old menu stuff
borderdrawcount--;
}
}
menuactivestate = menuactive;
viewactivestate = viewactive;
inhelpscreensstate = inhelpscreens;
oldgamestate = wipegamestate = gamestate;
1998-04-07 00:00:00 +00:00
// [RH] Refresh the border here if the menu is active
// since it might be dimming the background.
if (menuactive && viewactive)
R_DrawViewBorder ();
1998-04-07 00:00:00 +00:00
// draw pause pic
if (paused)
{
1998-04-07 00:00:00 +00:00
patch_t *pause = W_CacheLumpName ("M_PAUSE", PU_CACHE);
if (automapactive && !viewactive)
1998-04-07 00:00:00 +00:00
y = 4;
else
y = viewwindowy+4;
1998-07-14 00:00:00 +00:00
V_DrawPatchCleanNoMove((screens[0].width-(pause->width)*CleanXfac)/2,y,&screens[0],pause);
1998-04-07 00:00:00 +00:00
}
1998-04-07 00:00:00 +00:00
C_DrawConsole (); // draw console
1998-04-07 00:00:00 +00:00
// menus go directly to the screen
M_Drawer (); // menu is drawn even on top of everything
NetUpdate (); // send out any new accumulation
// normal update
if (!wipe)
{
I_FinishUpdate (); // page flip or blit buffer
return;
}
// wipe update
1998-07-14 00:00:00 +00:00
wipe_EndScreen(0, 0, screens[0].width, screens[0].height);
1998-04-07 00:00:00 +00:00
wipestart = I_GetTime () - 1;
1998-07-14 00:00:00 +00:00
I_FinishUpdate ();
1998-04-07 00:00:00 +00:00
do
{
do
{
nowtime = I_GetTime ();
tics = nowtime - wipestart;
} while (!tics);
wipestart = nowtime;
1998-07-14 00:00:00 +00:00
I_BeginUpdate ();
1998-04-07 00:00:00 +00:00
done = wipe_ScreenWipe(wipe_Melt
1998-07-14 00:00:00 +00:00
, 0, 0, screens[0].width, screens[0].height, tics);
1998-04-07 00:00:00 +00:00
I_UpdateNoBlit ();
C_DrawConsole ();
M_Drawer (); // menu is drawn even on top of wipes
I_FinishUpdate (); // page flip or blit buffer
} while (!done);
}
//
// D_DoomLoop
//
1998-07-14 00:00:00 +00:00
extern BOOL demorecording;
1998-04-07 00:00:00 +00:00
void D_DoomLoop (void)
{
if (demorecording)
G_BeginRecording ();
if (M_CheckParm ("-debugfile"))
{
char filename[20];
sprintf (filename,"debug%i.txt",consoleplayer);
Printf ("debug output to: %s\n",filename);
debugfile = fopen (filename,"w");
}
I_InitGraphics ();
1998-07-14 00:00:00 +00:00
C_InitConsole (screens[0].width, screens[0].height, true);
1998-04-07 00:00:00 +00:00
InitItems ();
1998-07-14 00:00:00 +00:00
// [RH] Lock any cvars that should be locked now that we're
// about to begin the game.
C_EnableNoSet ();
1998-04-07 00:00:00 +00:00
// [RH] Now that all game subsystems have been initialized,
// do all commands on the command line other than +set
C_ExecCmdLineParams (false);
1998-04-07 00:00:00 +00:00
while (1)
{
// frame syncronous IO operations
1998-07-14 00:00:00 +00:00
I_StartFrame ();
1998-04-07 00:00:00 +00:00
// process one or more tics
if (singletics)
{
I_StartTic ();
D_ProcessEvents ();
G_BuildTiccmd (&netcmds[consoleplayer][maketic%BACKUPTICS]);
if (advancedemo)
D_DoAdvanceDemo ();
C_Ticker ();
M_Ticker ();
G_Ticker ();
gametic++;
maketic++;
1998-07-14 00:00:00 +00:00
Net_NewMakeTic ();
1998-04-07 00:00:00 +00:00
}
else
{
TryRunTics (); // will run at least one tic
}
1998-07-14 00:00:00 +00:00
// [RH] Use displayplayer rather than console player
S_UpdateSounds (players[displayplayer].mo);// move positional sounds
1998-04-07 00:00:00 +00:00
// Update display, next frame, with current state.
D_Display ();
// Sound mixing for the buffer is snychronous.
I_UpdateSound();
}
}
//
// 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)
{
1998-07-14 00:00:00 +00:00
V_DrawPatchIndirect (0,0, &screens[0], W_CacheLumpName(pagename, PU_CACHE));
1998-04-07 00:00:00 +00:00
}
//
// 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;
switch (demosequence)
{
case 0:
if ( gamemode == commercial )
1998-07-14 00:00:00 +00:00
pagetic = TICRATE * 11;
1998-04-07 00:00:00 +00:00
else
1998-07-14 00:00:00 +00:00
pagetic = TICRATE * 5;
1998-04-07 00:00:00 +00:00
gamestate = GS_DEMOSCREEN;
pagename = "TITLEPIC";
if ( gamemode == commercial )
S_StartMusic("d_dm2ttl");
else
S_StartMusic ("d_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)
{
1998-07-14 00:00:00 +00:00
pagetic = TICRATE * 11;
1998-04-07 00:00:00 +00:00
pagename = "TITLEPIC";
S_StartMusic("d_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)
{
1998-04-07 00:00:00 +00:00
int numwadfiles;
1998-04-07 00:00:00 +00:00
for (numwadfiles = 0 ; wadfiles[numwadfiles] ; numwadfiles++)
;
1998-04-07 00:00:00 +00:00
wadfiles[numwadfiles] = copystring (file);
1998-04-07 00:00:00 +00:00
}
//
// 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* doom2wad;
char* doom2fwad;
char* plutoniawad;
char* tntwad;
1998-07-14 00:00:00 +00:00
char* custwad;
1998-04-07 00:00:00 +00:00
char* doomwaddir;
char* home;
char iwad[64];
1998-07-14 00:00:00 +00:00
char* iwadfull = NULL;
1998-04-07 00:00:00 +00:00
int iwadindex;
doomwaddir = home = progdir;
// Commercial.
1998-04-07 00:00:00 +00:00
doom2wad = Malloc(strlen(doomwaddir)+9+1);
1998-04-07 00:00:00 +00:00
sprintf(doom2wad, "%sdoom2.wad", doomwaddir);
// Registered.
1998-04-07 00:00:00 +00:00
doomwad = Malloc(strlen(doomwaddir)+8+1);
1998-04-07 00:00:00 +00:00
sprintf(doomwad, "%sdoom.wad", doomwaddir);
// Shareware.
1998-04-07 00:00:00 +00:00
doom1wad = Malloc(strlen(doomwaddir)+9+1);
1998-04-07 00:00:00 +00:00
sprintf(doom1wad, "%sdoom1.wad", doomwaddir);
// Bug, dear Shawn.
// Insufficient malloc, caused spurious realloc errors.
1998-04-07 00:00:00 +00:00
plutoniawad = Malloc(strlen(doomwaddir)+/*9*/12+1);
1998-04-07 00:00:00 +00:00
sprintf(plutoniawad, "%splutonia.wad", doomwaddir);
1998-04-07 00:00:00 +00:00
tntwad = Malloc(strlen(doomwaddir)+9+1);
1998-04-07 00:00:00 +00:00
sprintf(tntwad, "%stnt.wad", doomwaddir);
// French stuff.
1998-04-07 00:00:00 +00:00
doom2fwad = Malloc(strlen(doomwaddir)+10+1);
1998-04-07 00:00:00 +00:00
sprintf(doom2fwad, "%sdoom2f.wad", doomwaddir);
if (FileExists (doom2fwad)) {
iwadfull = doom2fwad;
} else if (FileExists (doom2wad)) {
iwadfull = doom2wad;
} else if (FileExists (plutoniawad)) {
iwadfull = plutoniawad;
1998-07-14 00:00:00 +00:00
} else if (FileExists (tntwad)) {
1998-04-07 00:00:00 +00:00
iwadfull = tntwad;
} else if (FileExists (doomwad)) {
iwadfull = doomwad;
} else if (FileExists (doom1wad)) {
iwadfull = doom1wad;
}
iwadindex = M_CheckParm ("-iwad");
if (iwadindex && iwadindex < myargc - 1) {
iwadindex++;
1998-07-14 00:00:00 +00:00
custwad = Malloc(strlen(myargv[iwadindex]) + 5);
strcpy (custwad, myargv[iwadindex]);
DefaultExtension (custwad, ".wad");
if (FileExists (custwad)) {
iwadfull = custwad;
1998-04-07 00:00:00 +00:00
}
}
1998-07-14 00:00:00 +00:00
if (iwadfull)
ExtractFileBase (iwadfull, iwad);
else
iwad[0] = 0;
1998-04-07 00:00:00 +00:00
if (stricmp (iwad, "doom2f") == 0) {
gamemode = commercial;
1998-07-14 00:00:00 +00:00
gamemission = doom2;
1998-04-07 00:00:00 +00:00
// C'est ridicule!
// Let's handle languages in config files, okay?
language = french;
Printf("French version\n");
} else if (stricmp (iwad, "doom2") == 0) {
gamemode = commercial;
1998-07-14 00:00:00 +00:00
gamemission = doom2;
1998-04-07 00:00:00 +00:00
} else if (stricmp (iwad, "plutonia") == 0) {
gamemode = commercial;
1998-07-14 00:00:00 +00:00
gamemission = pack_plut;
1998-04-07 00:00:00 +00:00
} else if (stricmp (iwad, "tnt") == 0) {
gamemode = commercial;
1998-07-14 00:00:00 +00:00
gamemission = pack_tnt;
1998-04-07 00:00:00 +00:00
} else if (stricmp (iwad, "doom") == 0) {
// Retail checking is handled later
gamemode = registered;
1998-07-14 00:00:00 +00:00
gamemission = doom;
1998-04-07 00:00:00 +00:00
} else if (stricmp (iwad, "doom1") == 0) {
gamemode = shareware;
1998-07-14 00:00:00 +00:00
gamemission = doom;
1998-04-07 00:00:00 +00:00
} else {
Printf("Game mode indeterminate.\n");
gamemode = indetermined;
}
if (gamemode != indetermined) {
D_AddFile (iwadfull);
}
}
//
// 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);
1998-04-07 00:00:00 +00:00
file = Malloc (size);
1998-04-07 00:00:00 +00:00
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];
1998-04-07 00:00:00 +00:00
myargv = Malloc(sizeof(char *)*MAXARGVS);
1998-04-07 00:00:00 +00:00
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;
}
}
1998-07-14 00:00:00 +00:00
extern thinker_t thinkercap;
void P_MobjThinker (mobj_t *mobj);
void TransSoulsCallback (cvar_t *var)
{
thinker_t *currentthinker;
int floop;
if (var->value < 0.25) {
SetCVarFloat (var, 0.25);
} else if (var->value > 1) {
SetCVarFloat (var, 1);
} else {
floop = ((int)(var->value * 4) << MF_TRANSLUCSHIFT) & MF_TRANSLUCBITS;
mobjinfo[MT_SKULL].flags = (mobjinfo[MT_SKULL].flags & ~MF_TRANSLUCBITS) | floop;
// Find all the lost souls in the world and change them, also.
currentthinker = thinkercap.next;
if (!currentthinker)
return;
while (currentthinker != &thinkercap) {
if ( (currentthinker->function.acp1 == (actionf_p1)P_MobjThinker)
&& ((mobj_t *)currentthinker)->type == MT_SKULL )
((mobj_t *)currentthinker)->flags =
(((mobj_t *)currentthinker)->flags & ~MF_TRANSLUCBITS) | floop;
currentthinker = currentthinker->next;
}
}
}
1998-04-07 00:00:00 +00:00
//
// D_DoomMain
//
void D_DoomMain (void)
{
1998-07-14 00:00:00 +00:00
int p, flags;
char file[256];
1998-04-07 00:00:00 +00:00
SetProgDir ();
C_InstallCommands ();
1998-07-14 00:00:00 +00:00
// [RH] Set default cvar values. These will
// be overridden by the configfile.
C_SetCVars ();
{
cvar_t *var = cvar ("transsouls", "0.75", CVAR_ARCHIVE|CVAR_CALLBACK);
var->u.callback = TransSoulsCallback;
}
1998-04-07 00:00:00 +00:00
FindResponseFile ();
{
1998-04-07 00:00:00 +00:00
// [RH] Make sure zdoom.wad is always loaded, since
// it contains stuff we need.
1998-04-07 00:00:00 +00:00
char *zdoomwad;
1998-04-07 00:00:00 +00:00
zdoomwad = Malloc (strlen (progdir) + 10);
1998-04-07 00:00:00 +00:00
sprintf (zdoomwad, "%szdoom.wad", progdir);
D_AddFile (zdoomwad);
}
1998-04-07 00:00:00 +00:00
IdentifyVersion ();
1998-04-07 00:00:00 +00:00
modifiedgame = false;
1998-07-14 00:00:00 +00:00
flags = (int)dmflagsvar->value;
dmflagsvar->u.callback = DMFlagsCallback;
1998-04-07 00:00:00 +00:00
1998-07-14 00:00:00 +00:00
if (M_CheckParm ("-nomonsters"))
flags |= DF_NO_MONSTERS;
if (M_CheckParm ("-respawn"))
flags |= DF_MONSTERS_RESPAWN;
if (M_CheckParm ("-fast"))
flags |= DF_FAST_MONSTERS;
1998-04-07 00:00:00 +00:00
devparm = M_CheckParm ("-devparm");
1998-07-14 00:00:00 +00:00
if (M_CheckParm ("-altdeath")) {
SetCVarFloat (deathmatch, 1.0f);
flags |= DF_ITEMS_RESPAWN;
} else if (M_CheckParm ("-deathmatch")) {
SetCVarFloat (deathmatch, 1.0f);
flags |= DF_WEAPONS_STAY;
}
SetCVarFloat (dmflagsvar, (float)flags);
1998-04-07 00:00:00 +00:00
1998-07-14 00:00:00 +00:00
switch (gamemode) {
case shareware:
I_SetTitleString ("DOOM Shareware Startup");
break;
case registered:
I_SetTitleString ("DOOM Registered Startup");
break;
case commercial:
switch (gamemission) {
case doom2:
I_SetTitleString ("DOOM 2: Hell on Earth");
break;
case pack_plut:
I_SetTitleString ("DOOM 2: Plutonia Experiment");
break;
case pack_tnt:
I_SetTitleString ("DOOM 2: TNT - Evilution");
break;
case doom:
case none:
break;
}
break;
default:
I_SetTitleString ("Public DOOM -");
break;
}
1998-04-07 00:00:00 +00:00
if (devparm)
Printf(D_DEVSTR);
if (M_CheckParm("-cdrom"))
{
Printf(D_CDROM);
}
// turbo option
1998-07-14 00:00:00 +00:00
// [RH] (Also exists as a cvar now.)
1998-04-07 00:00:00 +00:00
{
1998-07-14 00:00:00 +00:00
cvar_t *turbo = cvar ("turbo", "0", CVAR_CALLBACK);
float tval;
1998-04-07 00:00:00 +00:00
1998-07-14 00:00:00 +00:00
turbo->u.callback = TurboCallback;
if ( (p=M_CheckParm ("-turbo")) ) {
if (p < myargc - 1)
tval = (float)atof (myargv[p+1]);
1998-04-07 00:00:00 +00:00
else
1998-07-14 00:00:00 +00:00
tval = 200.0f;
Printf ("turbo scale: %g%%\n", tval);
} else {
tval = 100.0f;
1998-04-07 00:00:00 +00:00
}
1998-07-14 00:00:00 +00:00
SetCVarFloat (turbo, tval);
1998-04-07 00:00:00 +00:00
}
1998-07-14 00:00:00 +00:00
1998-04-07 00:00:00 +00:00
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
1998-04-07 00:00:00 +00:00
while (++p != myargc && myargv[p][0] != '-' && myargv[p][0] != '+')
1998-04-07 00:00:00 +00:00
D_AddFile (myargv[p]);
}
1998-07-14 00:00:00 +00:00
if (!(p = M_CheckParm ("-playdemo")) )
if (!(p = M_CheckParm ("-timedemo")) ) {
if ( (p = M_CheckParm ("-fastdemo")) )
fastdemo = true;
}
1998-04-07 00:00:00 +00:00
if (p && p < myargc-1)
{
1998-04-07 00:00:00 +00:00
strcpy (file, myargv[p+1]);
DefaultExtension (file, ".lmp");
1998-04-07 00:00:00 +00:00
D_AddFile (file);
1998-04-07 00:00:00 +00:00
Printf("Playing demo %s.\n", file);
1998-04-07 00:00:00 +00:00
}
// get skill / episode / map from parms
1998-07-14 00:00:00 +00:00
if (gamemode == commercial)
strcpy (startmap, "MAP01");
else
strcpy (startmap, "E1M1");
1998-04-07 00:00:00 +00:00
autostart = false;
p = M_CheckParm ("-skill");
if (p && p < myargc-1)
{
1998-07-14 00:00:00 +00:00
SetCVarFloat (gameskill, (float)(myargv[p+1][0]-'1'));
1998-04-07 00:00:00 +00:00
autostart = true;
}
p = M_CheckParm ("-timer");
1998-07-14 00:00:00 +00:00
if (p && p < myargc-1)
1998-04-07 00:00:00 +00:00
{
1998-07-14 00:00:00 +00:00
int time = atoi(myargv[p+1]);
1998-04-07 00:00:00 +00:00
Printf("Levels will end after %d minute",time);
1998-07-14 00:00:00 +00:00
if (time > 1)
1998-04-07 00:00:00 +00:00
Printf("s");
Printf(".\n");
1998-07-14 00:00:00 +00:00
SetCVarFloat (timelimit, (float)time);
1998-04-07 00:00:00 +00:00
}
p = M_CheckParm ("-avg");
1998-07-14 00:00:00 +00:00
if (p && p < myargc-1) {
1998-04-07 00:00:00 +00:00
Printf("Austin Virtual Gaming: Levels will end after 20 minutes\n");
1998-07-14 00:00:00 +00:00
SetCVarFloat (timelimit, 20);
}
1998-04-07 00:00:00 +00:00
p = M_CheckParm ("-warp");
if (p && p < myargc-1)
{
1998-07-14 00:00:00 +00:00
int ep, map;
if (gamemode == commercial) {
ep = 1;
map = atoi (myargv[p+1]);
} else {
ep = myargv[p+1][0]-'0';
map = myargv[p+2][0]-'0';
1998-04-07 00:00:00 +00:00
}
1998-07-14 00:00:00 +00:00
strncpy (startmap, CalcMapName (ep, map), 8);
autostart = true;
}
// [RH] Hack to handle +map
p = M_CheckParm ("+map");
if (p && p < myargc-1) {
strncpy (startmap, myargv[p+1], 8);
myargv[p][0] = '-';
1998-04-07 00:00:00 +00:00
autostart = true;
}
// init subsystems
Printf ("M_LoadDefaults: Load system defaults.\n");
M_LoadDefaults (); // load before initing other systems
1998-04-07 00:00:00 +00:00
// [RH] do all +set commands on the command line
C_ExecCmdLineParams (true);
1998-07-14 00:00:00 +00:00
Printf ("Z_Init: Init zone memory allocation daemon. \n");
Z_Init ();
Printf ("W_Init: Init WADfiles.\n");
W_InitMultipleFiles (wadfiles);
// [RH] Load foreign language strings
D_InitStrings ();
1998-04-07 00:00:00 +00:00
1998-04-07 00:00:00 +00:00
// [RH] Apply any DeHackEd patch
{
int hack;
hack = M_CheckParm ("-deh");
if (hack && hack < myargc - 1)
DoDehPatch (myargv[hack + 1]);
1998-07-14 00:00:00 +00:00
else
DoDehPatch (NULL); // See if there's a patch in a PWAD
1998-04-07 00:00:00 +00:00
}
1998-07-14 00:00:00 +00:00
// [RH] Now that all text strings are set up,
// insert them into the level and cluster data.
G_SetLevelStrings ();
1998-04-07 00:00:00 +00:00
1998-07-14 00:00:00 +00:00
// [RH] Parse through all loaded mapinfo lumps
G_ParseMapInfo ();
// [RH] Check for retail game
1998-04-07 00:00:00 +00:00
if (gamemode == registered) {
if (W_CheckNumForName ("e4m1") != -1) {
gamemode = retail;
1998-07-14 00:00:00 +00:00
I_SetTitleString ("The Ultimate DOOM Startup");
1998-04-07 00:00:00 +00:00
}
}
// 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;
1998-07-14 00:00:00 +00:00
if (gamemode == shareware)
1998-04-07 00:00:00 +00:00
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.
1998-07-14 00:00:00 +00:00
if (gamemode == registered || gamemode == retail)
1998-04-07 00:00:00 +00:00
for (i = 0;i < 23; i++)
if (W_CheckNumForName(name[i])<0)
I_Error("\nThis is not the registered version.");
}
// Iff additonal PWAD files are used, print modified banner
if (modifiedgame)
{
/*m*/Printf (
"===========================================================================\n"
"ATTENTION: This version of DOOM has been modified. If you would like to\n"
"get a copy of the original game, call 1-800-IDGAMES or see the readme file.\n"
" You will not receive technical support for modified games.\n"
"===========================================================================\n"
);
}
// Check and print which version is executed.
switch ( gamemode )
{
case shareware:
case indetermined:
Printf (
"===========================================================================\n"
" Shareware!\n"
"===========================================================================\n"
);
break;
case registered:
case retail:
case commercial:
Printf (
"===========================================================================\n"
" Commercial product - do not distribute!\n"
" Please report software piracy to the SPA: 1-800-388-PIR8\n"
"===========================================================================\n"
);
break;
default:
// Ouch.
break;
}
Printf ("\nI_StartGraphics: Determine display hardware.\n");
I_StartGraphics ();
Printf ("V_Init: allocate screens.\n");
V_Init ();
Printf ("M_Init: Init miscellaneous info.\n");
M_Init ();
Printf ("R_Init: Init DOOM refresh daemon - ");
R_Init ();
Printf ("\nP_Init: Init Playloop state.\n");
P_Init ();
Printf ("I_Init: Setting up machine state.\n");
I_Init ();
Printf ("D_CheckNetGame: Checking network game status.\n");
D_CheckNetGame ();
Printf ("S_Init: Setting up sound.\n");
S_Init ((int)snd_SfxVolume->value /* *8 */, snd_MusicVolume->value /* *8*/ );
Printf ("HU_Init: Setting up heads up display.\n");
HU_Init ();
Printf ("ST_Init: Init status bar.\n");
ST_Init ();
// check for a driver that wants intermission stats
p = M_CheckParm ("-statcopy");
if (p && p<myargc-1)
{
// for statistics driver
1998-07-14 00:00:00 +00:00
extern void* statcopy;
1998-04-07 00:00:00 +00:00
statcopy = (void*)atoi(myargv[p+1]);
Printf ("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)
{
1998-04-07 00:00:00 +00:00
char blah[256];
1998-04-07 00:00:00 +00:00
singledemo = true; // quit after one demo
1998-04-07 00:00:00 +00:00
strcpy (blah, myargv[p+1]);
FixPathSeperator (blah);
ExtractFileBase (blah, file);
G_DeferedPlayDemo (file);
1998-04-07 00:00:00 +00:00
D_DoomLoop (); // never returns
}
1998-07-14 00:00:00 +00:00
p = M_CheckParm ("-fastdemo");
if (p && p < myargc-1)
{
extern BOOL timingdemo;
singledemo = true; // quit after one demo
timingdemo = true; // show stats after quit
G_DeferedPlayDemo(myargv[p+1]);
D_DoomLoop(); // never returns
}
1998-04-07 00:00:00 +00:00
p = M_CheckParm ("-timedemo");
if (p && p < myargc-1)
{
G_TimeDemo (myargv[p+1]);
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 )
{
1998-07-14 00:00:00 +00:00
if (autostart || netgame) {
G_InitNew (startmap);
} else {
1998-04-07 00:00:00 +00:00
D_StartTitle (); // start up intro loop
1998-07-14 00:00:00 +00:00
}
1998-04-07 00:00:00 +00:00
}
D_DoomLoop (); // never returns
}