2006-02-24 04:48:15 +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.
|
|
|
|
//
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
// HEADER FILES ------------------------------------------------------------
|
|
|
|
|
|
|
|
#ifdef _WIN32
|
|
|
|
#include <direct.h>
|
|
|
|
#define mkdir(a,b) _mkdir (a)
|
|
|
|
#else
|
|
|
|
#include <sys/stat.h>
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef unix
|
|
|
|
#include <unistd.h>
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#include <time.h>
|
|
|
|
#include <math.h>
|
|
|
|
#include <assert.h>
|
|
|
|
|
|
|
|
#include "doomerrors.h"
|
|
|
|
|
|
|
|
#include "d_gui.h"
|
|
|
|
#include "m_alloc.h"
|
|
|
|
#include "m_random.h"
|
|
|
|
#include "doomdef.h"
|
|
|
|
#include "doomstat.h"
|
|
|
|
#include "gstrings.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 "c_console.h"
|
|
|
|
#include "c_dispatch.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 "r_sky.h"
|
|
|
|
#include "d_main.h"
|
|
|
|
#include "d_dehacked.h"
|
|
|
|
#include "cmdlib.h"
|
|
|
|
#include "s_sound.h"
|
|
|
|
#include "m_swap.h"
|
|
|
|
#include "v_text.h"
|
|
|
|
#include "gi.h"
|
|
|
|
#include "b_bot.h" //Added by MC:
|
|
|
|
#include "stats.h"
|
|
|
|
#include "a_doomglobal.h"
|
|
|
|
#include "gameconfigfile.h"
|
|
|
|
#include "sbar.h"
|
|
|
|
#include "decallib.h"
|
|
|
|
#include "r_polymost.h"
|
2006-05-14 14:30:13 +00:00
|
|
|
#include "version.h"
|
2006-02-24 04:48:15 +00:00
|
|
|
#include "v_text.h"
|
Note: I have not tried compiling these recent changes under Linux. I wouldn't
be surprised if it doesn't work.
- Reorganized the network startup loops so now they are event driven. There is
a single function that gets called to drive it, and it uses callbacks to
perform the different stages of the synchronization. This lets me have a nice,
responsive abort button instead of the previous unannounced hit-escape-to-
abort behavior, and I think the rearranged code is slightly easier to
understand too.
- Increased the number of bytes for version info during D_ArbitrateNetStart(),
in preparation for the day when NETGAMEVERSION requires more than one byte.
- I noticed an issue with Vista RC1 and the new fatal error setup. Even after
releasing a DirectDraw or Direct3D interface, the DWM can still use the
last image drawn using them when it composites the window. It doesn't always
do it but it does often enough that it is a real problem. At this point, I
don't know if it's a problem with the release version of Vista or not.
After messing around, I discovered the problem was caused by ~Win32Video()
hiding the window and then having it immediately shown soon after. The DWM
kept an image of the window to do the transition effect with, and then when
it didn't get a chance to do the transition, it didn't properly forget about
its saved image and kept plastering it on top of everything else
underneath.
- Added a network synchronization panel to the window during netgame startup.
- Fixed: PClass::CreateDerivedClass() must initialize StateList to NULL.
Otherwise, classic DECORATE definitions generate a big, fat crash.
- Resurrected the R_Init progress bar, now as a standard Windows control.
- Removed the sound failure dialog. The FMOD setup already defaulted to no
sound if initialization failed, so this only applies when snd_output is set
to "alternate" which now also falls back to no sound. In addition, it wasn't
working right, and I didn't feel like fixing it for the probably 0% of users
it affected.
- Fixed: The edit control used for logging output added text in reverse order
on Win9x.
- Went back to the roots and made graphics initialization one of the last
things to happen during setup. Now the startup text is visible again. More
importantly, the main window is no longer created invisible, which seems
to cause trouble with it not always appearing in the taskbar. The fatal
error dialog is now also embedded in the main window instead of being a
separate modal dialog, so you can play with the log window to see any
problems that might be reported there.
Rather than completely restoring the original startup order, I tried to
keep things as close to the way they were with early graphics startup. In
particular, V_Init() now creates a dummy screen so that things that need
screen dimensions can get them. It gets replaced by the real screen later
in I_InitGraphics(). Will need to check this under Linux to make sure it
didn't cause any problems there.
- Removed the following stubs that just called functions in Video:
- I_StartModeIterator()
- I_NextMode()
- I_DisplayType()
I_FullscreenChanged() was also removed, and a new fullscreen parameter
was added to IVideo::StartModeIterator(), since that's all it controlled.
- Renamed I_InitHardware() back to I_InitGraphics(), since that's all it's
initialized post-1.22.
SVN r416 (trunk)
2006-12-19 04:09:10 +00:00
|
|
|
#include "st_start.h"
|
2007-12-18 01:50:08 +00:00
|
|
|
#include "templates.h"
|
2007-12-20 20:22:31 +00:00
|
|
|
#include "teaminfo.h"
|
2006-02-24 04:48:15 +00:00
|
|
|
|
|
|
|
// MACROS ------------------------------------------------------------------
|
|
|
|
|
|
|
|
// TYPES -------------------------------------------------------------------
|
|
|
|
|
|
|
|
// EXTERNAL FUNCTION PROTOTYPES --------------------------------------------
|
|
|
|
|
|
|
|
extern void M_RestoreMode ();
|
|
|
|
extern void M_SetDefaultMode ();
|
|
|
|
extern void R_ExecuteSetViewSize ();
|
|
|
|
extern void G_NewInit ();
|
2006-07-13 10:17:56 +00:00
|
|
|
extern void SetupPlayerClasses ();
|
2006-02-24 04:48:15 +00:00
|
|
|
|
|
|
|
// PUBLIC FUNCTION PROTOTYPES ----------------------------------------------
|
|
|
|
|
|
|
|
void D_CheckNetGame ();
|
|
|
|
void D_ProcessEvents ();
|
|
|
|
void G_BuildTiccmd (ticcmd_t* cmd);
|
|
|
|
void D_DoAdvanceDemo ();
|
|
|
|
void D_AddFile (const char *file);
|
|
|
|
void D_AddWildFile (const char *pattern);
|
|
|
|
|
|
|
|
// PRIVATE FUNCTION PROTOTYPES ---------------------------------------------
|
|
|
|
|
|
|
|
void D_DoomLoop ();
|
2006-04-17 13:53:34 +00:00
|
|
|
static const char *BaseFileSearch (const char *file, const char *ext, bool lookfirstinprogdir=false);
|
2006-02-24 04:48:15 +00:00
|
|
|
|
|
|
|
// EXTERNAL DATA DECLARATIONS ----------------------------------------------
|
|
|
|
|
|
|
|
EXTERN_CVAR (Float, turbo)
|
|
|
|
EXTERN_CVAR (Int, crosshair)
|
|
|
|
EXTERN_CVAR (Bool, freelook)
|
|
|
|
EXTERN_CVAR (Float, m_pitch)
|
|
|
|
EXTERN_CVAR (Float, m_yaw)
|
|
|
|
EXTERN_CVAR (Bool, invertmouse)
|
|
|
|
EXTERN_CVAR (Bool, lookstrafe)
|
|
|
|
|
|
|
|
extern gameinfo_t SharewareGameInfo;
|
|
|
|
extern gameinfo_t RegisteredGameInfo;
|
|
|
|
extern gameinfo_t RetailGameInfo;
|
|
|
|
extern gameinfo_t CommercialGameInfo;
|
|
|
|
extern gameinfo_t HereticGameInfo;
|
|
|
|
extern gameinfo_t HereticSWGameInfo;
|
|
|
|
extern gameinfo_t HexenGameInfo;
|
|
|
|
extern gameinfo_t HexenDKGameInfo;
|
|
|
|
extern gameinfo_t StrifeGameInfo;
|
|
|
|
extern gameinfo_t StrifeTeaserGameInfo;
|
|
|
|
extern gameinfo_t StrifeTeaser2GameInfo;
|
|
|
|
|
|
|
|
extern int testingmode;
|
2006-09-14 00:02:31 +00:00
|
|
|
extern bool setmodeneeded;
|
|
|
|
extern bool netdemo;
|
2006-02-24 04:48:15 +00:00
|
|
|
extern int NewWidth, NewHeight, NewBits, DisplayBits;
|
|
|
|
EXTERN_CVAR (Bool, st_scale)
|
2006-09-14 00:02:31 +00:00
|
|
|
extern bool gameisdead;
|
2006-04-16 19:09:36 +00:00
|
|
|
extern bool demorecording;
|
2006-02-24 04:48:15 +00:00
|
|
|
extern bool M_DemoNoPlay; // [RH] if true, then skip any demos in the loop
|
2006-05-03 14:54:48 +00:00
|
|
|
extern bool insave;
|
2006-02-24 04:48:15 +00:00
|
|
|
|
|
|
|
extern cycle_t WallCycles, PlaneCycles, MaskedCycles, WallScanCycles;
|
|
|
|
|
|
|
|
// PUBLIC DATA DEFINITIONS -------------------------------------------------
|
|
|
|
|
2007-12-15 03:51:17 +00:00
|
|
|
CUSTOM_CVAR (Int, fraglimit, 0, CVAR_SERVERINFO)
|
|
|
|
{
|
|
|
|
// Check for the fraglimit being hit because the fraglimit is being
|
|
|
|
// lowered below somebody's current frag count.
|
|
|
|
if (deathmatch && self > 0)
|
|
|
|
{
|
|
|
|
for (int i = 0; i < MAXPLAYERS; ++i)
|
|
|
|
{
|
|
|
|
if (playeringame[i] && self <= D_GetFragCount(&players[i]))
|
|
|
|
{
|
|
|
|
Printf ("%s\n", GStrings("TXT_FRAGLIMIT"));
|
|
|
|
G_ExitLevel (0, false);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-02-24 04:48:15 +00:00
|
|
|
CVAR (Float, timelimit, 0.f, CVAR_SERVERINFO);
|
|
|
|
CVAR (Bool, queryiwad, true, CVAR_ARCHIVE|CVAR_GLOBALCONFIG);
|
2006-07-08 02:17:35 +00:00
|
|
|
CVAR (String, defaultiwad, "", CVAR_ARCHIVE|CVAR_GLOBALCONFIG);
|
2006-02-24 04:48:15 +00:00
|
|
|
CVAR (Int, wipetype, 1, CVAR_ARCHIVE);
|
|
|
|
|
|
|
|
bool DrawFSHUD; // [RH] Draw fullscreen HUD?
|
|
|
|
wadlist_t *wadfiles; // [RH] remove limit on # of loaded wads
|
2006-09-14 00:02:31 +00:00
|
|
|
bool devparm; // started game with -devparm
|
2006-12-29 03:38:37 +00:00
|
|
|
const char *D_DrawIcon; // [RH] Patch name of icon to draw on next refresh
|
|
|
|
int NoWipe; // [RH] Allow wipe? (Needs to be set each time)
|
2006-09-14 00:02:31 +00:00
|
|
|
bool singletics = false; // debug flag to cancel adaptiveness
|
2006-02-24 04:48:15 +00:00
|
|
|
char startmap[8];
|
2006-09-14 00:02:31 +00:00
|
|
|
bool autostart;
|
|
|
|
bool advancedemo;
|
2006-02-24 04:48:15 +00:00
|
|
|
FILE *debugfile;
|
|
|
|
event_t events[MAXEVENTS];
|
|
|
|
int eventhead;
|
|
|
|
int eventtail;
|
|
|
|
gamestate_t wipegamestate = GS_DEMOSCREEN; // can be -1 to force a wipe
|
|
|
|
bool PageBlank;
|
|
|
|
FTexture *Page;
|
|
|
|
FTexture *Advisory;
|
|
|
|
|
|
|
|
cycle_t FrameCycles;
|
|
|
|
|
2007-12-06 22:38:45 +00:00
|
|
|
// If autoname is NULL, that's either because that game doesn't allow
|
|
|
|
// loading of external wads or because it's already caught by the
|
|
|
|
// general game-specific wads section.
|
Note: I have not tried compiling these recent changes under Linux. I wouldn't
be surprised if it doesn't work.
- Reorganized the network startup loops so now they are event driven. There is
a single function that gets called to drive it, and it uses callbacks to
perform the different stages of the synchronization. This lets me have a nice,
responsive abort button instead of the previous unannounced hit-escape-to-
abort behavior, and I think the rearranged code is slightly easier to
understand too.
- Increased the number of bytes for version info during D_ArbitrateNetStart(),
in preparation for the day when NETGAMEVERSION requires more than one byte.
- I noticed an issue with Vista RC1 and the new fatal error setup. Even after
releasing a DirectDraw or Direct3D interface, the DWM can still use the
last image drawn using them when it composites the window. It doesn't always
do it but it does often enough that it is a real problem. At this point, I
don't know if it's a problem with the release version of Vista or not.
After messing around, I discovered the problem was caused by ~Win32Video()
hiding the window and then having it immediately shown soon after. The DWM
kept an image of the window to do the transition effect with, and then when
it didn't get a chance to do the transition, it didn't properly forget about
its saved image and kept plastering it on top of everything else
underneath.
- Added a network synchronization panel to the window during netgame startup.
- Fixed: PClass::CreateDerivedClass() must initialize StateList to NULL.
Otherwise, classic DECORATE definitions generate a big, fat crash.
- Resurrected the R_Init progress bar, now as a standard Windows control.
- Removed the sound failure dialog. The FMOD setup already defaulted to no
sound if initialization failed, so this only applies when snd_output is set
to "alternate" which now also falls back to no sound. In addition, it wasn't
working right, and I didn't feel like fixing it for the probably 0% of users
it affected.
- Fixed: The edit control used for logging output added text in reverse order
on Win9x.
- Went back to the roots and made graphics initialization one of the last
things to happen during setup. Now the startup text is visible again. More
importantly, the main window is no longer created invisible, which seems
to cause trouble with it not always appearing in the taskbar. The fatal
error dialog is now also embedded in the main window instead of being a
separate modal dialog, so you can play with the log window to see any
problems that might be reported there.
Rather than completely restoring the original startup order, I tried to
keep things as close to the way they were with early graphics startup. In
particular, V_Init() now creates a dummy screen so that things that need
screen dimensions can get them. It gets replaced by the real screen later
in I_InitGraphics(). Will need to check this under Linux to make sure it
didn't cause any problems there.
- Removed the following stubs that just called functions in Video:
- I_StartModeIterator()
- I_NextMode()
- I_DisplayType()
I_FullscreenChanged() was also removed, and a new fullscreen parameter
was added to IVideo::StartModeIterator(), since that's all it controlled.
- Renamed I_InitHardware() back to I_InitGraphics(), since that's all it's
initialized post-1.22.
SVN r416 (trunk)
2006-12-19 04:09:10 +00:00
|
|
|
const IWADInfo IWADInfos[NUM_IWAD_TYPES] =
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
2007-12-06 22:38:45 +00:00
|
|
|
// banner text, autoname, fg color, bg color
|
|
|
|
{ "Final Doom: TNT - Evilution", "TNT", MAKERGB(168,0,0), MAKERGB(168,168,168) },
|
|
|
|
{ "Final Doom: Plutonia Experiment", "Plutonia", MAKERGB(168,0,0), MAKERGB(168,168,168) },
|
|
|
|
{ "Hexen: Beyond Heretic", NULL, MAKERGB(240,240,240), MAKERGB(107,44,24) },
|
|
|
|
{ "Hexen: Deathkings of the Dark Citadel", "HexenDK", MAKERGB(240,240,240), MAKERGB(139,68,9) },
|
|
|
|
{ "DOOM 2: Hell on Earth", "Doom2", MAKERGB(168,0,0), MAKERGB(168,168,168) },
|
|
|
|
{ "Heretic Shareware", NULL, MAKERGB(252,252,0), MAKERGB(168,0,0) },
|
|
|
|
{ "Heretic: Shadow of the Serpent Riders", NULL, MAKERGB(252,252,0), MAKERGB(168,0,0) },
|
|
|
|
{ "Heretic", NULL, MAKERGB(252,252,0), MAKERGB(168,0,0) },
|
|
|
|
{ "DOOM Shareware", NULL, MAKERGB(168,0,0), MAKERGB(168,168,168) },
|
|
|
|
{ "The Ultimate DOOM", "Doom1", MAKERGB(84,84,84), MAKERGB(168,168,168) },
|
|
|
|
{ "DOOM Registered", "Doom1", MAKERGB(84,84,84), MAKERGB(168,168,168) },
|
|
|
|
{ "Strife: Quest for the Sigil", NULL, MAKERGB(224,173,153), MAKERGB(0,107,101) },
|
|
|
|
{ "Strife: Teaser (Old Version)", NULL, MAKERGB(224,173,153), MAKERGB(0,107,101) },
|
|
|
|
{ "Strife: Teaser (New Version)", NULL, MAKERGB(224,173,153), MAKERGB(0,107,101) }
|
2006-02-24 04:48:15 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
// PRIVATE DATA DEFINITIONS ------------------------------------------------
|
|
|
|
|
|
|
|
static wadlist_t **wadtail = &wadfiles;
|
|
|
|
static int demosequence;
|
|
|
|
static int pagetic;
|
|
|
|
static const char *IWADNames[] =
|
|
|
|
{
|
|
|
|
NULL,
|
|
|
|
"doom2f.wad",
|
|
|
|
"doom2.wad",
|
|
|
|
"plutonia.wad",
|
|
|
|
"tnt.wad",
|
|
|
|
"doomu.wad", // Hack from original Linux version. Not necessary, but I threw it in anyway.
|
|
|
|
"doom.wad",
|
|
|
|
"doom1.wad",
|
|
|
|
"heretic.wad",
|
|
|
|
"heretic1.wad",
|
|
|
|
"hexen.wad",
|
|
|
|
"hexdd.wad",
|
|
|
|
"strife1.wad",
|
|
|
|
"strife0.wad",
|
|
|
|
NULL
|
|
|
|
};
|
|
|
|
|
|
|
|
// CODE --------------------------------------------------------------------
|
|
|
|
|
|
|
|
//==========================================================================
|
|
|
|
//
|
|
|
|
// D_ProcessEvents
|
|
|
|
//
|
|
|
|
// Send all the events of the given timestamp down the responder chain.
|
|
|
|
// Events are asynchronous inputs generally generated by the game user.
|
|
|
|
// Events can be discarded if no responder claims them
|
|
|
|
//
|
|
|
|
//==========================================================================
|
|
|
|
|
|
|
|
void D_ProcessEvents (void)
|
|
|
|
{
|
|
|
|
event_t *ev;
|
|
|
|
|
|
|
|
// [RH] If testing mode, do not accept input until test is over
|
|
|
|
if (testingmode)
|
|
|
|
{
|
|
|
|
if (testingmode == 1)
|
|
|
|
{
|
|
|
|
M_SetDefaultMode ();
|
|
|
|
}
|
|
|
|
else if (testingmode <= I_GetTime(false))
|
|
|
|
{
|
|
|
|
M_RestoreMode ();
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (; eventtail != eventhead ; eventtail = (eventtail+1)&(MAXEVENTS-1))
|
|
|
|
{
|
|
|
|
ev = &events[eventtail];
|
|
|
|
if (C_Responder (ev))
|
|
|
|
continue; // console ate the event
|
|
|
|
if (M_Responder (ev))
|
|
|
|
continue; // menu ate the event
|
|
|
|
if (testpolymost)
|
|
|
|
Polymost_Responder (ev);
|
|
|
|
G_Responder (ev);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//==========================================================================
|
|
|
|
//
|
|
|
|
// D_PostEvent
|
|
|
|
//
|
|
|
|
// Called by the I/O functions when input is detected.
|
|
|
|
//
|
|
|
|
//==========================================================================
|
|
|
|
|
|
|
|
void D_PostEvent (const event_t *ev)
|
|
|
|
{
|
|
|
|
events[eventhead] = *ev;
|
|
|
|
if (ev->type == EV_Mouse && !testpolymost && !paused && menuactive == MENU_Off &&
|
|
|
|
ConsoleState != c_down && ConsoleState != c_falling)
|
|
|
|
{
|
|
|
|
if (Button_Mlook.bDown || freelook)
|
|
|
|
{
|
|
|
|
int look = int(ev->y * m_pitch * mouse_sensitivity * 16.0);
|
|
|
|
if (invertmouse)
|
|
|
|
look = -look;
|
|
|
|
G_AddViewPitch (look);
|
|
|
|
events[eventhead].y = 0;
|
|
|
|
}
|
|
|
|
if (!Button_Strafe.bDown && !lookstrafe)
|
|
|
|
{
|
|
|
|
G_AddViewAngle (int(ev->x * m_yaw * mouse_sensitivity * 8.0));
|
|
|
|
events[eventhead].x = 0;
|
|
|
|
}
|
|
|
|
if ((events[eventhead].x | events[eventhead].y) == 0)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
eventhead = (eventhead+1)&(MAXEVENTS-1);
|
|
|
|
}
|
|
|
|
|
|
|
|
//==========================================================================
|
|
|
|
//
|
|
|
|
// CVAR dmflags
|
|
|
|
//
|
|
|
|
//==========================================================================
|
|
|
|
|
|
|
|
CUSTOM_CVAR (Int, dmflags, 0, CVAR_SERVERINFO)
|
|
|
|
{
|
|
|
|
// In case DF_NO_FREELOOK was changed, reinitialize the sky
|
|
|
|
// map. (If no freelook, then no need to stretch the sky.)
|
|
|
|
if (sky1texture != 0)
|
|
|
|
R_InitSkyMap ();
|
|
|
|
|
|
|
|
if (self & DF_NO_FREELOOK)
|
|
|
|
{
|
|
|
|
Net_WriteByte (DEM_CENTERVIEW);
|
|
|
|
}
|
|
|
|
// If nofov is set, force everybody to the arbitrator's FOV.
|
|
|
|
if ((self & DF_NO_FOV) && consoleplayer == Net_Arbitrator)
|
|
|
|
{
|
|
|
|
BYTE fov;
|
|
|
|
|
|
|
|
Net_WriteByte (DEM_FOV);
|
|
|
|
|
|
|
|
// If the game is started with DF_NO_FOV set, the arbitrator's
|
|
|
|
// DesiredFOV will not be set when this callback is run, so
|
|
|
|
// be sure not to transmit a 0 FOV.
|
|
|
|
fov = (BYTE)players[consoleplayer].DesiredFOV;
|
|
|
|
if (fov == 0)
|
|
|
|
{
|
|
|
|
fov = 90;
|
|
|
|
}
|
|
|
|
Net_WriteByte (fov);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
CVAR (Flag, sv_nohealth, dmflags, DF_NO_HEALTH);
|
|
|
|
CVAR (Flag, sv_noitems, dmflags, DF_NO_ITEMS);
|
|
|
|
CVAR (Flag, sv_weaponstay, dmflags, DF_WEAPONS_STAY);
|
|
|
|
CVAR (Flag, sv_falldamage, dmflags, DF_FORCE_FALLINGHX);
|
|
|
|
CVAR (Flag, sv_oldfalldamage, dmflags, DF_FORCE_FALLINGZD);
|
|
|
|
CVAR (Flag, sv_samelevel, dmflags, DF_SAME_LEVEL);
|
|
|
|
CVAR (Flag, sv_spawnfarthest, dmflags, DF_SPAWN_FARTHEST);
|
|
|
|
CVAR (Flag, sv_forcerespawn, dmflags, DF_FORCE_RESPAWN);
|
|
|
|
CVAR (Flag, sv_noarmor, dmflags, DF_NO_ARMOR);
|
|
|
|
CVAR (Flag, sv_noexit, dmflags, DF_NO_EXIT);
|
|
|
|
CVAR (Flag, sv_infiniteammo, dmflags, DF_INFINITE_AMMO);
|
|
|
|
CVAR (Flag, sv_nomonsters, dmflags, DF_NO_MONSTERS);
|
|
|
|
CVAR (Flag, sv_monsterrespawn, dmflags, DF_MONSTERS_RESPAWN);
|
|
|
|
CVAR (Flag, sv_itemrespawn, dmflags, DF_ITEMS_RESPAWN);
|
|
|
|
CVAR (Flag, sv_fastmonsters, dmflags, DF_FAST_MONSTERS);
|
|
|
|
CVAR (Flag, sv_nojump, dmflags, DF_NO_JUMP);
|
|
|
|
CVAR (Flag, sv_nofreelook, dmflags, DF_NO_FREELOOK);
|
|
|
|
CVAR (Flag, sv_respawnsuper, dmflags, DF_RESPAWN_SUPER);
|
|
|
|
CVAR (Flag, sv_nofov, dmflags, DF_NO_FOV);
|
2006-04-11 16:27:41 +00:00
|
|
|
CVAR (Flag, sv_noweaponspawn, dmflags, DF_NO_COOP_WEAPON_SPAWN);
|
2006-05-14 14:30:13 +00:00
|
|
|
CVAR (Flag, sv_nocrouch, dmflags, DF_NO_CROUCH);
|
2006-02-24 04:48:15 +00:00
|
|
|
|
|
|
|
//==========================================================================
|
|
|
|
//
|
|
|
|
// CVAR dmflags2
|
|
|
|
//
|
|
|
|
// [RH] From Skull Tag. Some of these were already done as separate cvars
|
|
|
|
// (such as bfgaiming), but I collected them here like Skull Tag does.
|
|
|
|
//
|
|
|
|
//==========================================================================
|
|
|
|
|
|
|
|
CVAR (Int, dmflags2, 0, CVAR_SERVERINFO);
|
|
|
|
CVAR (Flag, sv_weapondrop, dmflags2, DF2_YES_WEAPONDROP);
|
2007-12-24 14:24:24 +00:00
|
|
|
CVAR (Flag, sv_noteamswitch, dmflags2, DF2_NO_TEAMSWITCH);
|
2007-12-23 14:57:12 +00:00
|
|
|
CVAR (Flag, sv_doubleammo, dmflags2, DF2_YES_DOUBLEAMMO);
|
2007-12-24 14:24:24 +00:00
|
|
|
CVAR (Flag, sv_keepfrags, dmflags2, DF2_YES_KEEPFRAGS);
|
2007-12-23 17:03:52 +00:00
|
|
|
CVAR (Flag, sv_degeneration, dmflags2, DF2_YES_DEGENERATION);
|
2007-12-24 14:24:24 +00:00
|
|
|
CVAR (Flag, sv_norespawn, dmflags2, DF2_NO_RESPAWN);
|
2007-12-23 17:45:53 +00:00
|
|
|
CVAR (Flag, sv_losefrag, dmflags2, DF2_YES_LOSEFRAG);
|
2006-02-24 04:48:15 +00:00
|
|
|
CVAR (Flag, sv_nobfgaim, dmflags2, DF2_NO_FREEAIMBFG);
|
|
|
|
CVAR (Flag, sv_respawnprotect, dmflags2, DF2_YES_INVUL);
|
|
|
|
CVAR (Flag, sv_barrelrespawn, dmflags2, DF2_BARRELS_RESPAWN);
|
|
|
|
|
|
|
|
//==========================================================================
|
|
|
|
//
|
|
|
|
// CVAR compatflags
|
|
|
|
//
|
|
|
|
//==========================================================================
|
|
|
|
|
2006-06-03 12:30:11 +00:00
|
|
|
int i_compatflags; // internal compatflags composed from the compatflags CVAR and MAPINFO settings
|
|
|
|
|
|
|
|
CUSTOM_CVAR (Int, compatflags, 0, CVAR_ARCHIVE|CVAR_SERVERINFO)
|
|
|
|
{
|
|
|
|
if (level.info == NULL) i_compatflags = self;
|
|
|
|
else i_compatflags = (self & ~level.info->compatmask) | (level.info->compatflags & level.info->compatmask);
|
|
|
|
}
|
|
|
|
|
2006-02-24 04:48:15 +00:00
|
|
|
CVAR (Flag, compat_shortTex, compatflags, COMPATF_SHORTTEX);
|
|
|
|
CVAR (Flag, compat_stairs, compatflags, COMPATF_STAIRINDEX);
|
|
|
|
CVAR (Flag, compat_limitpain, compatflags, COMPATF_LIMITPAIN);
|
|
|
|
CVAR (Flag, compat_silentpickup,compatflags, COMPATF_SILENTPICKUP);
|
|
|
|
CVAR (Flag, compat_nopassover, compatflags, COMPATF_NO_PASSMOBJ);
|
|
|
|
CVAR (Flag, compat_soundslots, compatflags, COMPATF_MAGICSILENCE);
|
|
|
|
CVAR (Flag, compat_wallrun, compatflags, COMPATF_WALLRUN);
|
|
|
|
CVAR (Flag, compat_notossdrops, compatflags, COMPATF_NOTOSSDROPS);
|
|
|
|
CVAR (Flag, compat_useblocking, compatflags, COMPATF_USEBLOCKING);
|
|
|
|
CVAR (Flag, compat_nodoorlight, compatflags, COMPATF_NODOORLIGHT);
|
|
|
|
CVAR (Flag, compat_ravenscroll, compatflags, COMPATF_RAVENSCROLL);
|
2006-04-20 14:21:27 +00:00
|
|
|
CVAR (Flag, compat_soundtarget, compatflags, COMPATF_SOUNDTARGET);
|
|
|
|
CVAR (Flag, compat_dehhealth, compatflags, COMPATF_DEHHEALTH);
|
2006-04-24 14:26:06 +00:00
|
|
|
CVAR (Flag, compat_trace, compatflags, COMPATF_TRACE);
|
|
|
|
CVAR (Flag, compat_dropoff, compatflags, COMPATF_DROPOFF);
|
2006-07-11 08:27:05 +00:00
|
|
|
CVAR (Flag, compat_boomscroll, compatflags, COMPATF_BOOMSCROLL);
|
2007-05-12 11:14:09 +00:00
|
|
|
CVAR (Flag, compat_invisibility,compatflags, COMPATF_INVISIBILITY);
|
2006-02-24 04:48:15 +00:00
|
|
|
|
|
|
|
//==========================================================================
|
|
|
|
//
|
|
|
|
// D_Display
|
|
|
|
//
|
|
|
|
// Draw current display, possibly wiping it from the previous
|
|
|
|
//
|
|
|
|
//==========================================================================
|
2007-12-27 04:30:12 +00:00
|
|
|
|
2008-01-01 03:07:05 +00:00
|
|
|
void D_Display ()
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
|
|
|
bool wipe;
|
2007-12-27 04:30:12 +00:00
|
|
|
bool hw2d;
|
2006-02-24 04:48:15 +00:00
|
|
|
|
|
|
|
if (nodrawers)
|
|
|
|
return; // for comparative timing / profiling
|
|
|
|
|
|
|
|
cycle_t cycles = 0;
|
|
|
|
clock (cycles);
|
|
|
|
|
|
|
|
if (players[consoleplayer].camera == NULL)
|
|
|
|
{
|
|
|
|
players[consoleplayer].camera = players[consoleplayer].mo;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (viewactive)
|
|
|
|
{
|
|
|
|
R_SetFOV (players[consoleplayer].camera && players[consoleplayer].camera->player ?
|
|
|
|
players[consoleplayer].camera->player->FOV : 90.f);
|
|
|
|
}
|
|
|
|
|
|
|
|
// [RH] change the screen mode if needed
|
|
|
|
if (setmodeneeded)
|
|
|
|
{
|
|
|
|
// Change screen mode.
|
|
|
|
if (V_SetResolution (NewWidth, NewHeight, NewBits))
|
|
|
|
{
|
|
|
|
// Recalculate various view parameters.
|
|
|
|
setsizeneeded = true;
|
|
|
|
// Let the status bar know the screen size changed
|
|
|
|
if (StatusBar != NULL)
|
|
|
|
{
|
|
|
|
StatusBar->ScreenSizeChanged ();
|
|
|
|
}
|
|
|
|
// Refresh the console.
|
|
|
|
C_NewModeAdjust ();
|
|
|
|
// Reload crosshair if transitioned to a different size
|
|
|
|
crosshair.Callback ();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
RenderTarget = screen;
|
|
|
|
|
|
|
|
// change the view size if needed
|
|
|
|
if (setsizeneeded && StatusBar != NULL)
|
|
|
|
{
|
|
|
|
R_ExecuteSetViewSize ();
|
|
|
|
}
|
|
|
|
setmodeneeded = false;
|
|
|
|
|
2008-01-01 03:07:05 +00:00
|
|
|
if (screen->Lock (false))
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
|
|
|
SB_state = screen->GetPageCount ();
|
|
|
|
BorderNeedRefresh = screen->GetPageCount ();
|
|
|
|
}
|
|
|
|
|
|
|
|
// [RH] Allow temporarily disabling wipes
|
|
|
|
if (NoWipe)
|
|
|
|
{
|
|
|
|
BorderNeedRefresh = screen->GetPageCount ();
|
|
|
|
NoWipe--;
|
|
|
|
wipe = false;
|
|
|
|
wipegamestate = gamestate;
|
|
|
|
}
|
|
|
|
else if (gamestate != wipegamestate && gamestate != GS_FULLCONSOLE && gamestate != GS_TITLELEVEL)
|
|
|
|
{ // save the current screen if about to wipe
|
|
|
|
BorderNeedRefresh = screen->GetPageCount ();
|
|
|
|
if (wipegamestate != GS_FORCEWIPEFADE)
|
|
|
|
{
|
2007-12-30 04:18:39 +00:00
|
|
|
wipe = screen->WipeStartScreen (wipetype);
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2007-12-30 04:18:39 +00:00
|
|
|
wipe = screen->WipeStartScreen (wipe_Fade);
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
|
|
|
wipegamestate = gamestate;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
wipe = false;
|
|
|
|
}
|
|
|
|
|
2007-12-27 04:30:12 +00:00
|
|
|
hw2d = false;
|
|
|
|
|
2006-02-24 04:48:15 +00:00
|
|
|
if (testpolymost)
|
|
|
|
{
|
|
|
|
drawpolymosttest();
|
2007-12-27 04:30:12 +00:00
|
|
|
C_DrawConsole(hw2d);
|
2006-02-24 04:48:15 +00:00
|
|
|
M_Drawer();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
switch (gamestate)
|
|
|
|
{
|
|
|
|
case GS_FULLCONSOLE:
|
2007-12-18 01:50:08 +00:00
|
|
|
screen->SetBlendingRect(0,0,0,0);
|
2008-01-01 03:07:05 +00:00
|
|
|
hw2d = screen->Begin2D();
|
2007-12-27 04:30:12 +00:00
|
|
|
C_DrawConsole (false);
|
2006-02-24 04:48:15 +00:00
|
|
|
M_Drawer ();
|
2008-01-01 03:07:05 +00:00
|
|
|
screen->Update ();
|
2006-02-24 04:48:15 +00:00
|
|
|
return;
|
|
|
|
|
|
|
|
case GS_LEVEL:
|
|
|
|
case GS_TITLELEVEL:
|
|
|
|
if (!gametic)
|
|
|
|
break;
|
|
|
|
|
2007-12-18 01:50:08 +00:00
|
|
|
if (!menuactive)
|
|
|
|
{
|
|
|
|
screen->SetBlendingRect(viewwindowx, MAX(ConBottom,viewwindowy),
|
|
|
|
viewwindowx + realviewwidth, MAX(ConBottom,viewwindowy + realviewheight));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// Don't chop the blending effect off at the status bar when the menu is
|
|
|
|
// active. Mostly, this is just to make Strife's dialogs with portrait
|
|
|
|
// images look okay when a blend is active.
|
|
|
|
screen->SetBlendingRect(0,0,0,0);
|
|
|
|
}
|
2006-02-24 04:48:15 +00:00
|
|
|
R_RefreshViewBorder ();
|
2006-06-11 11:28:48 +00:00
|
|
|
P_CheckPlayerSprites();
|
2006-02-24 04:48:15 +00:00
|
|
|
R_RenderActorView (players[consoleplayer].mo);
|
|
|
|
R_DetailDouble (); // [RH] Apply detail mode expansion
|
|
|
|
// [RH] Let cameras draw onto textures that were visible this frame.
|
|
|
|
FCanvasTextureInfo::UpdateAll ();
|
|
|
|
if (automapactive)
|
|
|
|
{
|
|
|
|
AM_Drawer ();
|
|
|
|
}
|
2008-01-01 03:07:05 +00:00
|
|
|
if ((hw2d = screen->Begin2D()))
|
2007-12-27 04:30:12 +00:00
|
|
|
{
|
2008-01-01 03:07:05 +00:00
|
|
|
// Redraw the status bar every frame when using 2D accel
|
|
|
|
SB_state = screen->GetPageCount();
|
2007-12-27 04:30:12 +00:00
|
|
|
}
|
2006-02-24 04:48:15 +00:00
|
|
|
if (realviewheight == SCREENHEIGHT && viewactive)
|
|
|
|
{
|
|
|
|
StatusBar->Draw (DrawFSHUD ? HUD_Fullscreen : HUD_None);
|
|
|
|
StatusBar->DrawTopStuff (DrawFSHUD ? HUD_Fullscreen : HUD_None);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
StatusBar->Draw (HUD_StatusBar);
|
|
|
|
StatusBar->DrawTopStuff (HUD_StatusBar);
|
|
|
|
}
|
|
|
|
CT_Drawer ();
|
|
|
|
break;
|
|
|
|
|
|
|
|
case GS_INTERMISSION:
|
2007-12-18 01:50:08 +00:00
|
|
|
screen->SetBlendingRect(0,0,0,0);
|
2008-01-01 03:07:05 +00:00
|
|
|
hw2d = screen->Begin2D();
|
2006-02-24 04:48:15 +00:00
|
|
|
WI_Drawer ();
|
|
|
|
CT_Drawer ();
|
|
|
|
break;
|
|
|
|
|
|
|
|
case GS_FINALE:
|
2007-12-18 01:50:08 +00:00
|
|
|
screen->SetBlendingRect(0,0,0,0);
|
2008-01-01 03:07:05 +00:00
|
|
|
hw2d = screen->Begin2D();
|
2006-02-24 04:48:15 +00:00
|
|
|
F_Drawer ();
|
|
|
|
CT_Drawer ();
|
|
|
|
break;
|
|
|
|
|
|
|
|
case GS_DEMOSCREEN:
|
2007-12-18 01:50:08 +00:00
|
|
|
screen->SetBlendingRect(0,0,0,0);
|
2008-01-01 03:07:05 +00:00
|
|
|
hw2d = screen->Begin2D();
|
2006-02-24 04:48:15 +00:00
|
|
|
D_PageDrawer ();
|
|
|
|
CT_Drawer ();
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// draw pause pic
|
|
|
|
if (paused && menuactive == MENU_Off)
|
|
|
|
{
|
|
|
|
FTexture *tex;
|
|
|
|
int x;
|
|
|
|
|
|
|
|
tex = TexMan[gameinfo.gametype & (GAME_Doom|GAME_Strife) ? "M_PAUSE" : "PAUSED"];
|
|
|
|
x = (SCREENWIDTH - tex->GetWidth()*CleanXfac)/2 +
|
|
|
|
tex->LeftOffset*CleanXfac;
|
|
|
|
screen->DrawTexture (tex, x, 4, DTA_CleanNoMove, true, TAG_DONE);
|
|
|
|
}
|
|
|
|
|
|
|
|
// [RH] Draw icon, if any
|
|
|
|
if (D_DrawIcon)
|
|
|
|
{
|
|
|
|
int picnum = TexMan.CheckForTexture (D_DrawIcon, FTexture::TEX_MiscPatch);
|
|
|
|
|
|
|
|
D_DrawIcon = NULL;
|
|
|
|
if (picnum >= 0)
|
|
|
|
{
|
|
|
|
FTexture *tex = TexMan[picnum];
|
|
|
|
screen->DrawTexture (tex, 160-tex->GetWidth()/2, 100-tex->GetHeight()/2,
|
|
|
|
DTA_320x200, true, TAG_DONE);
|
|
|
|
}
|
|
|
|
NoWipe = 10;
|
|
|
|
}
|
|
|
|
|
2008-01-01 03:07:05 +00:00
|
|
|
if (!wipe || NoWipe < 0)
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
2007-12-27 04:30:12 +00:00
|
|
|
NetUpdate (); // send out any new accumulation
|
2006-02-24 04:48:15 +00:00
|
|
|
// normal update
|
2007-12-27 04:30:12 +00:00
|
|
|
C_DrawConsole (hw2d); // draw console
|
|
|
|
M_Drawer (); // menu is drawn even on top of everything
|
2006-02-24 04:48:15 +00:00
|
|
|
FStat::PrintStat ();
|
2008-01-01 03:07:05 +00:00
|
|
|
screen->Update (); // page flip or blit buffer
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// wipe update
|
|
|
|
int wipestart, nowtime, tics;
|
2006-09-14 00:02:31 +00:00
|
|
|
bool done;
|
2006-02-24 04:48:15 +00:00
|
|
|
|
2007-12-30 04:18:39 +00:00
|
|
|
screen->WipeEndScreen ();
|
2006-02-24 04:48:15 +00:00
|
|
|
|
2007-02-15 00:01:21 +00:00
|
|
|
wipestart = I_GetTime (false);
|
|
|
|
|
|
|
|
Net_WriteByte (DEM_WIPEON);
|
|
|
|
NetUpdate (); // send out any new accumulation
|
2006-02-24 04:48:15 +00:00
|
|
|
|
|
|
|
do
|
|
|
|
{
|
2007-02-15 00:01:21 +00:00
|
|
|
nowtime = I_WaitForTic (wipestart);
|
|
|
|
tics = nowtime - wipestart;
|
2006-02-24 04:48:15 +00:00
|
|
|
wipestart = nowtime;
|
2007-12-30 04:18:39 +00:00
|
|
|
done = screen->WipeDo (tics);
|
|
|
|
C_DrawConsole (hw2d); // console and
|
|
|
|
M_Drawer (); // menu are drawn even on top of wipes
|
2006-02-24 04:48:15 +00:00
|
|
|
screen->Update (); // page flip or blit buffer
|
2007-02-15 00:01:21 +00:00
|
|
|
NetUpdate ();
|
2006-02-24 04:48:15 +00:00
|
|
|
} while (!done);
|
2007-12-30 04:18:39 +00:00
|
|
|
screen->WipeCleanup();
|
2007-02-15 00:01:21 +00:00
|
|
|
|
|
|
|
Net_WriteByte (DEM_WIPEOFF);
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
unclock (cycles);
|
|
|
|
FrameCycles = cycles;
|
|
|
|
}
|
|
|
|
|
|
|
|
//==========================================================================
|
|
|
|
//
|
|
|
|
// D_ErrorCleanup ()
|
|
|
|
//
|
|
|
|
// Cleanup after a recoverable error.
|
|
|
|
//==========================================================================
|
|
|
|
|
|
|
|
void D_ErrorCleanup ()
|
|
|
|
{
|
|
|
|
screen->Unlock ();
|
|
|
|
bglobal.RemoveAllBots (true);
|
|
|
|
D_QuitNetGame ();
|
- Added some hackery at the start of MouseRead_Win32() that prevents it from
yanking the mouse around if they keys haven't been read yet to combat the
same situation that causes the keyboard to return DIERR_NOTACQUIRED in
KeyRead(): The window is sort of in focus and sort of not. User.dll
considers it to be focused and it's drawn as such, but another focused
window is on top of it, and DirectInput doesn't see it as focused.
- Fixed: KeyRead() should handle DIERR_NOTACQUIRED errors the same way it
handles DIERR_INPUTLOST errors. This can happen if our window had the
focus stolen away from it before we tried to acquire the keyboard in
DI_Init2(). Strangely, MouseRead_DI() already did this.
- When a stack overflow occurs, report.txt now only includes the first and
last 16KB of the stack to make it more manageable.
- Limited StreamEditBinary() to the first 64KB of the file to keep it from
taking too long on large dumps.
- And now I know why gathering crash information in the same process that
crashed can be bad: Stack overflows. You get one spare page to play with
when the stack overflows. MiniDumpWriteDump() needs more than that and
causes an access violation when it runs out of leftover stack, silently
terminating the application. Windows XP x64 offers SetThreadStackGuarantee()
to increase this, but that isn't available on anything older, including
32-bit XP. To get around this, a new thread is created to write the mini
dump when the stack overflows.
- Changed A_Burnination() to be closer to Strife's.
- Fixed: When playing back demos, DoAddBot() can be called without an
associated call to SpawnBot(). So if the bot can't spawn, botnum can
go negative, which will cause problems later in DCajunMaster::Main()
when it sees that wanted_botnum (0) is higher than botnum (-1).
- Fixed: Stopping demo recording in multiplayer games should not abruptly
drop the recorder out of the game without notifying the other players.
In fact, there's no reason why it should drop them out of multiplayer at
all.
- Fixed: Earthquakes were unreliable in multiplayer games because
P_PredictPlayer() did not preserve the player's xviewshift.
- Fixed: PlayerIsGone() needs to stop any scripts that belong to the player
who left, in addition to executing disconnect scripts.
- Fixed: APlayerPawn::AddInventory() should also check for a NULL player->mo
in case the player left but somebody still has a reference to their actor.
- Fixed: DDrawFB::PaintToWindow() should simulate proper unlocking behavior
and set Buffer to NULL.
- Improved feedback for network game initialization with the console ticker.
- Moved i_net.cpp and i_net.h out of sdl/ and win32/ and into the main source
directory. They are identical, so keeping two copies of them is bad.
- Fixed: (At least with Creative's driver's,) EAX settings are global and not
per-application. So if you play a multiplayer ZDoom game on one computer
(or even another EAX-using application), ZDoom needs to restore the
environment when it regains focus.
- Maybe fixed: (See http://forum.zdoom.org/potato.php?t=10689) Apparently,
PacketGet can receive ECONNRESET from nodes that aren't in the game. It
should be safe to just ignore these packets.
- Fixed: PlayerIsGone() should set the gone player's camera to NULL in case
the player who left was player 0. This is because if a remaining player
receives a "recoverable" error, they will become player 0. Once that happens,
they game will try to update sounds through their camera and crash in
FMODSoundRenderer::UpdateListener() because the zones array is now NULL.
G_NewInit() should also clear all the player structures.
SVN r233 (trunk)
2006-06-30 02:13:26 +00:00
|
|
|
if (demorecording || demoplayback)
|
|
|
|
G_CheckDemoStatus ();
|
2006-02-24 04:48:15 +00:00
|
|
|
Net_ClearBuffers ();
|
|
|
|
G_NewInit ();
|
|
|
|
singletics = false;
|
|
|
|
playeringame[0] = 1;
|
|
|
|
players[0].playerstate = PST_LIVE;
|
|
|
|
gameaction = ga_fullconsole;
|
|
|
|
menuactive = MENU_Off;
|
- Added some hackery at the start of MouseRead_Win32() that prevents it from
yanking the mouse around if they keys haven't been read yet to combat the
same situation that causes the keyboard to return DIERR_NOTACQUIRED in
KeyRead(): The window is sort of in focus and sort of not. User.dll
considers it to be focused and it's drawn as such, but another focused
window is on top of it, and DirectInput doesn't see it as focused.
- Fixed: KeyRead() should handle DIERR_NOTACQUIRED errors the same way it
handles DIERR_INPUTLOST errors. This can happen if our window had the
focus stolen away from it before we tried to acquire the keyboard in
DI_Init2(). Strangely, MouseRead_DI() already did this.
- When a stack overflow occurs, report.txt now only includes the first and
last 16KB of the stack to make it more manageable.
- Limited StreamEditBinary() to the first 64KB of the file to keep it from
taking too long on large dumps.
- And now I know why gathering crash information in the same process that
crashed can be bad: Stack overflows. You get one spare page to play with
when the stack overflows. MiniDumpWriteDump() needs more than that and
causes an access violation when it runs out of leftover stack, silently
terminating the application. Windows XP x64 offers SetThreadStackGuarantee()
to increase this, but that isn't available on anything older, including
32-bit XP. To get around this, a new thread is created to write the mini
dump when the stack overflows.
- Changed A_Burnination() to be closer to Strife's.
- Fixed: When playing back demos, DoAddBot() can be called without an
associated call to SpawnBot(). So if the bot can't spawn, botnum can
go negative, which will cause problems later in DCajunMaster::Main()
when it sees that wanted_botnum (0) is higher than botnum (-1).
- Fixed: Stopping demo recording in multiplayer games should not abruptly
drop the recorder out of the game without notifying the other players.
In fact, there's no reason why it should drop them out of multiplayer at
all.
- Fixed: Earthquakes were unreliable in multiplayer games because
P_PredictPlayer() did not preserve the player's xviewshift.
- Fixed: PlayerIsGone() needs to stop any scripts that belong to the player
who left, in addition to executing disconnect scripts.
- Fixed: APlayerPawn::AddInventory() should also check for a NULL player->mo
in case the player left but somebody still has a reference to their actor.
- Fixed: DDrawFB::PaintToWindow() should simulate proper unlocking behavior
and set Buffer to NULL.
- Improved feedback for network game initialization with the console ticker.
- Moved i_net.cpp and i_net.h out of sdl/ and win32/ and into the main source
directory. They are identical, so keeping two copies of them is bad.
- Fixed: (At least with Creative's driver's,) EAX settings are global and not
per-application. So if you play a multiplayer ZDoom game on one computer
(or even another EAX-using application), ZDoom needs to restore the
environment when it regains focus.
- Maybe fixed: (See http://forum.zdoom.org/potato.php?t=10689) Apparently,
PacketGet can receive ECONNRESET from nodes that aren't in the game. It
should be safe to just ignore these packets.
- Fixed: PlayerIsGone() should set the gone player's camera to NULL in case
the player who left was player 0. This is because if a remaining player
receives a "recoverable" error, they will become player 0. Once that happens,
they game will try to update sounds through their camera and crash in
FMODSoundRenderer::UpdateListener() because the zones array is now NULL.
G_NewInit() should also clear all the player structures.
SVN r233 (trunk)
2006-06-30 02:13:26 +00:00
|
|
|
insave = false;
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
//==========================================================================
|
|
|
|
//
|
|
|
|
// D_DoomLoop
|
|
|
|
//
|
|
|
|
// Manages timing and IO, calls all ?_Responder, ?_Ticker, and ?_Drawer,
|
|
|
|
// calls I_GetTime, I_StartFrame, and I_StartTic
|
|
|
|
//
|
|
|
|
//==========================================================================
|
|
|
|
|
|
|
|
void D_DoomLoop ()
|
|
|
|
{
|
|
|
|
int lasttic = 0;
|
|
|
|
|
|
|
|
for (;;)
|
|
|
|
{
|
|
|
|
try
|
|
|
|
{
|
|
|
|
// frame syncronous IO operations
|
|
|
|
if (gametic > lasttic)
|
|
|
|
{
|
|
|
|
lasttic = gametic;
|
|
|
|
I_StartFrame ();
|
|
|
|
}
|
|
|
|
|
|
|
|
// process one or more tics
|
|
|
|
if (singletics)
|
|
|
|
{
|
|
|
|
I_StartTic ();
|
|
|
|
DObject::BeginFrame ();
|
|
|
|
D_ProcessEvents ();
|
|
|
|
G_BuildTiccmd (&netcmds[consoleplayer][maketic%BACKUPTICS]);
|
|
|
|
//Added by MC: For some of that bot stuff. The main bot function.
|
|
|
|
int i;
|
|
|
|
for (i = 0; i < MAXPLAYERS; i++)
|
|
|
|
{
|
|
|
|
if (playeringame[i] && players[i].isbot && players[i].mo)
|
|
|
|
{
|
|
|
|
players[i].savedyaw = players[i].mo->angle;
|
|
|
|
players[i].savedpitch = players[i].mo->pitch;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
bglobal.Main (maketic%BACKUPTICS);
|
|
|
|
for (i = 0; i < MAXPLAYERS; i++)
|
|
|
|
{
|
|
|
|
if (playeringame[i] && players[i].isbot && players[i].mo)
|
|
|
|
{
|
|
|
|
players[i].mo->angle = players[i].savedyaw;
|
|
|
|
players[i].mo->pitch = players[i].savedpitch;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (advancedemo)
|
|
|
|
D_DoAdvanceDemo ();
|
|
|
|
C_Ticker ();
|
|
|
|
M_Ticker ();
|
|
|
|
G_Ticker ();
|
|
|
|
gametic++;
|
|
|
|
maketic++;
|
|
|
|
DObject::EndFrame ();
|
|
|
|
Net_NewMakeTic ();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
TryRunTics (); // will run at least one tic
|
|
|
|
}
|
|
|
|
// [RH] Use the consoleplayer's camera to update sounds
|
|
|
|
S_UpdateSounds (players[consoleplayer].camera); // move positional sounds
|
|
|
|
// Update display, next frame, with current state.
|
|
|
|
I_StartTic ();
|
2008-01-01 03:07:05 +00:00
|
|
|
D_Display ();
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
|
|
|
catch (CRecoverableError &error)
|
|
|
|
{
|
|
|
|
if (error.GetMessage ())
|
|
|
|
{
|
|
|
|
Printf (PRINT_BOLD, "\n%s\n", error.GetMessage());
|
|
|
|
}
|
|
|
|
D_ErrorCleanup ();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//==========================================================================
|
|
|
|
//
|
|
|
|
// D_PageTicker
|
|
|
|
//
|
|
|
|
//==========================================================================
|
|
|
|
|
|
|
|
void D_PageTicker (void)
|
|
|
|
{
|
|
|
|
if (--pagetic < 0)
|
|
|
|
D_AdvanceDemo ();
|
|
|
|
}
|
|
|
|
|
|
|
|
//==========================================================================
|
|
|
|
//
|
|
|
|
// D_PageDrawer
|
|
|
|
//
|
|
|
|
//==========================================================================
|
|
|
|
|
|
|
|
void D_PageDrawer (void)
|
|
|
|
{
|
|
|
|
if (Page != NULL)
|
|
|
|
{
|
|
|
|
screen->DrawTexture (Page, 0, 0,
|
|
|
|
DTA_VirtualWidth, Page->GetWidth(),
|
|
|
|
DTA_VirtualHeight, Page->GetHeight(),
|
|
|
|
DTA_Masked, false,
|
|
|
|
TAG_DONE);
|
|
|
|
screen->FillBorder (NULL);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2007-12-22 04:52:51 +00:00
|
|
|
screen->Clear (0, 0, SCREENWIDTH, SCREENHEIGHT, 0, 0);
|
2006-02-24 04:48:15 +00:00
|
|
|
if (!PageBlank)
|
|
|
|
{
|
|
|
|
screen->DrawText (CR_WHITE, 0, 0, "Page graphic goes here", TAG_DONE);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (Advisory != NULL)
|
|
|
|
{
|
|
|
|
screen->DrawTexture (Advisory, 4, 160, DTA_320x200, true, TAG_DONE);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//==========================================================================
|
|
|
|
//
|
|
|
|
// D_AdvanceDemo
|
|
|
|
//
|
|
|
|
// Called after each demo or intro demosequence finishes
|
|
|
|
//
|
|
|
|
//==========================================================================
|
|
|
|
|
|
|
|
void D_AdvanceDemo (void)
|
|
|
|
{
|
|
|
|
advancedemo = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
//==========================================================================
|
|
|
|
//
|
|
|
|
// D_DoStrifeAdvanceDemo
|
|
|
|
//
|
|
|
|
//==========================================================================
|
|
|
|
|
|
|
|
void D_DoStrifeAdvanceDemo ()
|
|
|
|
{
|
|
|
|
static const char *const fullVoices[6] =
|
|
|
|
{
|
|
|
|
"svox/pro1", "svox/pro2", "svox/pro3", "svox/pro4", "svox/pro5", "svox/pro6"
|
|
|
|
};
|
|
|
|
static const char *const teaserVoices[6] =
|
|
|
|
{
|
|
|
|
"svox/voc91", "svox/voc92", "svox/voc93", "svox/voc94", "svox/voc95", "svox/voc96"
|
|
|
|
};
|
|
|
|
const char *const *voices = gameinfo.flags & GI_SHAREWARE ? teaserVoices : fullVoices;
|
|
|
|
const char *pagename = NULL;
|
|
|
|
|
|
|
|
gamestate = GS_DEMOSCREEN;
|
|
|
|
PageBlank = false;
|
|
|
|
|
|
|
|
switch (demosequence)
|
|
|
|
{
|
|
|
|
default:
|
|
|
|
case 0:
|
|
|
|
pagetic = 6 * TICRATE;
|
|
|
|
pagename = "TITLEPIC";
|
2006-06-19 15:31:10 +00:00
|
|
|
if (Wads.CheckNumForName ("d_logo", ns_music) < 0)
|
2006-02-24 04:48:15 +00:00
|
|
|
{ // strife0.wad does not have d_logo
|
|
|
|
S_StartMusic ("");
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
S_StartMusic ("d_logo");
|
|
|
|
}
|
|
|
|
C_HideConsole ();
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 1:
|
|
|
|
// [RH] Strife fades to black and then to the Rogue logo, but
|
|
|
|
// I think it looks better if it doesn't fade.
|
|
|
|
pagetic = 10 * TICRATE/35;
|
|
|
|
pagename = ""; // PANEL0, but strife0.wad doesn't have it, so don't use it.
|
|
|
|
PageBlank = true;
|
|
|
|
S_Sound (CHAN_VOICE, "bishop/active", 1, ATTN_NORM);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 2:
|
|
|
|
pagetic = 4 * TICRATE;
|
|
|
|
pagename = "RGELOGO";
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 3:
|
|
|
|
pagetic = 7 * TICRATE;
|
|
|
|
pagename = "PANEL1";
|
|
|
|
S_Sound (CHAN_VOICE, voices[0], 1, ATTN_NORM);
|
|
|
|
S_StartMusic ("d_intro");
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 4:
|
|
|
|
pagetic = 9 * TICRATE;
|
|
|
|
pagename = "PANEL2";
|
|
|
|
S_Sound (CHAN_VOICE, voices[1], 1, ATTN_NORM);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 5:
|
|
|
|
pagetic = 12 * TICRATE;
|
|
|
|
pagename = "PANEL3";
|
|
|
|
S_Sound (CHAN_VOICE, voices[2], 1, ATTN_NORM);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 6:
|
|
|
|
pagetic = 11 * TICRATE;
|
|
|
|
pagename = "PANEL4";
|
|
|
|
S_Sound (CHAN_VOICE, voices[3], 1, ATTN_NORM);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 7:
|
|
|
|
pagetic = 10 * TICRATE;
|
|
|
|
pagename = "PANEL5";
|
|
|
|
S_Sound (CHAN_VOICE, voices[4], 1, ATTN_NORM);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 8:
|
|
|
|
pagetic = 16 * TICRATE;
|
|
|
|
pagename = "PANEL6";
|
|
|
|
S_Sound (CHAN_VOICE, voices[5], 1, ATTN_NORM);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 9:
|
|
|
|
pagetic = 6 * TICRATE;
|
|
|
|
pagename = "vellogo";
|
|
|
|
wipegamestate = GS_FORCEWIPEFADE;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 10:
|
|
|
|
pagetic = 12 * TICRATE;
|
|
|
|
pagename = "CREDIT";
|
|
|
|
wipegamestate = GS_FORCEWIPEFADE;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (demosequence++ > 10)
|
|
|
|
demosequence = 0;
|
|
|
|
if (demosequence == 9 && !(gameinfo.flags & GI_SHAREWARE))
|
|
|
|
demosequence = 10;
|
|
|
|
|
|
|
|
if (pagename)
|
|
|
|
{
|
|
|
|
if (Page != NULL)
|
|
|
|
{
|
|
|
|
Page->Unload ();
|
|
|
|
Page = NULL;
|
|
|
|
}
|
|
|
|
if (pagename[0])
|
|
|
|
{
|
|
|
|
Page = TexMan[pagename];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//==========================================================================
|
|
|
|
//
|
|
|
|
// D_DoAdvanceDemo
|
|
|
|
//
|
|
|
|
//==========================================================================
|
|
|
|
|
|
|
|
void D_DoAdvanceDemo (void)
|
|
|
|
{
|
|
|
|
static char demoname[8] = "DEMO1";
|
|
|
|
static int democount = 0;
|
|
|
|
static int pagecount;
|
|
|
|
const char *pagename = NULL;
|
|
|
|
|
|
|
|
V_SetBlend (0,0,0,0);
|
|
|
|
players[consoleplayer].playerstate = PST_LIVE; // not reborn
|
|
|
|
advancedemo = false;
|
|
|
|
usergame = false; // no save / end game here
|
|
|
|
paused = 0;
|
|
|
|
gameaction = ga_nothing;
|
|
|
|
|
|
|
|
// [RH] If you want something more dynamic for your title, create a map
|
|
|
|
// and name it TITLEMAP. That map will be loaded and used as the title.
|
2006-06-19 15:31:10 +00:00
|
|
|
|
|
|
|
MapData * map = P_OpenMapData("TITLEMAP");
|
|
|
|
if (map != NULL)
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
2006-10-27 08:20:54 +00:00
|
|
|
delete map;
|
2006-02-24 04:48:15 +00:00
|
|
|
G_InitNew ("TITLEMAP", true);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (gameinfo.gametype == GAME_Strife)
|
|
|
|
{
|
|
|
|
D_DoStrifeAdvanceDemo ();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (demosequence)
|
|
|
|
{
|
|
|
|
case 3:
|
|
|
|
if (gameinfo.advisoryTime)
|
|
|
|
{
|
|
|
|
Advisory = TexMan["ADVISOR"];
|
|
|
|
demosequence = 1;
|
|
|
|
pagetic = (int)(gameinfo.advisoryTime * TICRATE);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
// fall through to case 1 if no advisory notice
|
|
|
|
|
|
|
|
case 1:
|
|
|
|
Advisory = NULL;
|
|
|
|
if (!M_DemoNoPlay)
|
|
|
|
{
|
|
|
|
BorderNeedRefresh = screen->GetPageCount ();
|
|
|
|
democount++;
|
|
|
|
sprintf (demoname + 4, "%d", democount);
|
|
|
|
if (Wads.CheckNumForName (demoname) < 0)
|
|
|
|
{
|
|
|
|
demosequence = 0;
|
|
|
|
democount = 0;
|
|
|
|
// falls through to case 0 below
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
G_DeferedPlayDemo (demoname);
|
|
|
|
demosequence = 2;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
default:
|
|
|
|
case 0:
|
|
|
|
gamestate = GS_DEMOSCREEN;
|
|
|
|
pagename = gameinfo.titlePage;
|
|
|
|
pagetic = (int)(gameinfo.titleTime * TICRATE);
|
|
|
|
S_StartMusic (gameinfo.titleMusic);
|
|
|
|
demosequence = 3;
|
|
|
|
pagecount = 0;
|
|
|
|
C_HideConsole ();
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 2:
|
|
|
|
pagetic = (int)(gameinfo.pageTime * TICRATE);
|
|
|
|
gamestate = GS_DEMOSCREEN;
|
|
|
|
if (pagecount == 0)
|
|
|
|
pagename = gameinfo.creditPage1;
|
|
|
|
else
|
|
|
|
pagename = gameinfo.creditPage2;
|
|
|
|
pagecount ^= 1;
|
|
|
|
demosequence = 1;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (pagename)
|
|
|
|
{
|
|
|
|
if (Page != NULL)
|
|
|
|
{
|
|
|
|
Page->Unload ();
|
|
|
|
}
|
|
|
|
Page = TexMan[pagename];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//==========================================================================
|
|
|
|
//
|
|
|
|
// D_StartTitle
|
|
|
|
//
|
|
|
|
//==========================================================================
|
|
|
|
|
|
|
|
void D_StartTitle (void)
|
|
|
|
{
|
|
|
|
gameaction = ga_nothing;
|
|
|
|
demosequence = -1;
|
|
|
|
D_AdvanceDemo ();
|
|
|
|
}
|
|
|
|
|
|
|
|
//==========================================================================
|
|
|
|
//
|
|
|
|
// Cmd_Endgame
|
|
|
|
//
|
|
|
|
// [RH] Quit the current game and go to fullscreen console
|
|
|
|
//
|
|
|
|
//==========================================================================
|
|
|
|
|
|
|
|
CCMD (endgame)
|
|
|
|
{
|
|
|
|
if (!netgame)
|
|
|
|
{
|
|
|
|
gameaction = ga_fullconsole;
|
|
|
|
demosequence = -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//==========================================================================
|
|
|
|
//
|
|
|
|
// D_AddFile
|
|
|
|
//
|
|
|
|
//==========================================================================
|
|
|
|
|
|
|
|
void D_AddFile (const char *file)
|
|
|
|
{
|
|
|
|
if (file == NULL)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!FileExists (file))
|
|
|
|
{
|
|
|
|
const char *f = BaseFileSearch (file, ".wad");
|
|
|
|
if (f == NULL)
|
|
|
|
{
|
|
|
|
Printf ("Can't find '%s'\n", file);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
file = f;
|
|
|
|
}
|
2006-05-04 03:49:46 +00:00
|
|
|
wadlist_t *wad = (wadlist_t *)M_Malloc (sizeof(*wad) + strlen(file));
|
2006-02-24 04:48:15 +00:00
|
|
|
|
|
|
|
*wadtail = wad;
|
|
|
|
wad->next = NULL;
|
|
|
|
strcpy (wad->name, file);
|
|
|
|
wadtail = &wad->next;
|
|
|
|
}
|
|
|
|
|
|
|
|
//==========================================================================
|
|
|
|
//
|
|
|
|
// D_AddWildFile
|
|
|
|
//
|
|
|
|
//==========================================================================
|
|
|
|
|
|
|
|
void D_AddWildFile (const char *value)
|
|
|
|
{
|
|
|
|
const char *wadfile = BaseFileSearch (value, ".wad");
|
|
|
|
|
|
|
|
if (wadfile != NULL)
|
|
|
|
{
|
|
|
|
D_AddFile (wadfile);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{ // Try pattern matching
|
|
|
|
findstate_t findstate;
|
|
|
|
char path[PATH_MAX];
|
|
|
|
char *sep;
|
|
|
|
void *handle = I_FindFirst (value, &findstate);
|
|
|
|
|
|
|
|
strcpy (path, value);
|
|
|
|
sep = strrchr (path, '/');
|
|
|
|
if (sep == NULL)
|
|
|
|
{
|
|
|
|
sep = strrchr (path, '\\');
|
|
|
|
#ifdef _WIN32
|
|
|
|
if (sep == NULL && path[1] == ':')
|
|
|
|
{
|
|
|
|
sep = path + 1;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
if (handle != ((void *)-1))
|
|
|
|
{
|
|
|
|
do
|
|
|
|
{
|
|
|
|
if (sep == NULL)
|
|
|
|
{
|
|
|
|
D_AddFile (I_FindName (&findstate));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
strcpy (sep+1, I_FindName (&findstate));
|
|
|
|
D_AddFile (path);
|
|
|
|
}
|
|
|
|
} while (I_FindNext (handle, &findstate) == 0);
|
|
|
|
}
|
|
|
|
I_FindClose (handle);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//==========================================================================
|
|
|
|
//
|
|
|
|
// D_AddConfigWads
|
|
|
|
//
|
|
|
|
// Adds all files in the specified config file section.
|
|
|
|
//
|
|
|
|
//==========================================================================
|
|
|
|
|
|
|
|
void D_AddConfigWads (const char *section)
|
|
|
|
{
|
|
|
|
if (GameConfig->SetSection (section))
|
|
|
|
{
|
|
|
|
const char *key;
|
|
|
|
const char *value;
|
|
|
|
FConfigFile::Position pos;
|
|
|
|
|
|
|
|
while (GameConfig->NextInSection (key, value))
|
|
|
|
{
|
|
|
|
if (stricmp (key, "Path") == 0)
|
|
|
|
{
|
|
|
|
// D_AddWildFile resets GameConfig's position, so remember it
|
|
|
|
GameConfig->GetPosition (pos);
|
|
|
|
D_AddWildFile (value);
|
|
|
|
// Reset GameConfig's position to get next wad
|
|
|
|
GameConfig->SetPosition (pos);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//==========================================================================
|
|
|
|
//
|
|
|
|
// D_AddDirectory
|
|
|
|
//
|
|
|
|
// Add all .wad files in a directory. Does not descend into subdirectories.
|
|
|
|
//
|
|
|
|
//==========================================================================
|
|
|
|
|
|
|
|
static void D_AddDirectory (const char *dir)
|
|
|
|
{
|
|
|
|
char curdir[PATH_MAX];
|
|
|
|
|
|
|
|
if (getcwd (curdir, PATH_MAX))
|
|
|
|
{
|
|
|
|
char skindir[PATH_MAX];
|
|
|
|
findstate_t findstate;
|
|
|
|
void *handle;
|
|
|
|
size_t stuffstart;
|
|
|
|
|
|
|
|
stuffstart = strlen (dir);
|
|
|
|
memcpy (skindir, dir, stuffstart*sizeof(*dir));
|
|
|
|
skindir[stuffstart] = 0;
|
|
|
|
|
|
|
|
if (skindir[stuffstart-1] == '/')
|
|
|
|
{
|
|
|
|
skindir[--stuffstart] = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!chdir (skindir))
|
|
|
|
{
|
|
|
|
skindir[stuffstart++] = '/';
|
|
|
|
if ((handle = I_FindFirst ("*.wad", &findstate)) != (void *)-1)
|
|
|
|
{
|
|
|
|
do
|
|
|
|
{
|
|
|
|
if (!(I_FindAttr (&findstate) & FA_DIREC))
|
|
|
|
{
|
|
|
|
strcpy (skindir + stuffstart, I_FindName (&findstate));
|
|
|
|
D_AddFile (skindir);
|
|
|
|
}
|
|
|
|
} while (I_FindNext (handle, &findstate) == 0);
|
|
|
|
I_FindClose (handle);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
chdir (curdir);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//==========================================================================
|
|
|
|
//
|
|
|
|
// SetIWAD
|
|
|
|
//
|
|
|
|
// Sets parameters for the game using the specified IWAD.
|
|
|
|
//==========================================================================
|
|
|
|
|
|
|
|
static void SetIWAD (const char *iwadpath, EIWADType type)
|
|
|
|
{
|
|
|
|
static const struct
|
|
|
|
{
|
|
|
|
GameMode_t Mode;
|
|
|
|
const gameinfo_t *Info;
|
|
|
|
GameMission_t Mission;
|
|
|
|
} Datas[NUM_IWAD_TYPES] = {
|
|
|
|
{ commercial, &CommercialGameInfo, pack_tnt }, // Doom2TNT
|
|
|
|
{ commercial, &CommercialGameInfo, pack_plut }, // Doom2Plutonia
|
|
|
|
{ commercial, &HexenGameInfo, doom2 }, // Hexen
|
|
|
|
{ commercial, &HexenDKGameInfo, doom2 }, // HexenDK
|
|
|
|
{ commercial, &CommercialGameInfo, doom2 }, // Doom2
|
|
|
|
{ shareware, &HereticSWGameInfo, doom }, // HereticShareware
|
|
|
|
{ retail, &HereticGameInfo, doom }, // HereticExtended
|
|
|
|
{ retail, &HereticGameInfo, doom }, // Heretic
|
|
|
|
{ shareware, &SharewareGameInfo, doom }, // DoomShareware
|
|
|
|
{ retail, &RetailGameInfo, doom }, // UltimateDoom
|
|
|
|
{ registered, &RegisteredGameInfo, doom }, // DoomRegistered
|
|
|
|
{ commercial, &StrifeGameInfo, doom2 }, // Strife
|
|
|
|
{ commercial, &StrifeTeaserGameInfo, doom2 }, // StrifeTeaser
|
|
|
|
{ commercial, &StrifeTeaser2GameInfo, doom2 }, // StrifeTeaser2
|
|
|
|
};
|
|
|
|
|
|
|
|
D_AddFile (iwadpath);
|
|
|
|
|
|
|
|
if ((unsigned)type < NUM_IWAD_TYPES)
|
|
|
|
{
|
|
|
|
gamemode = Datas[type].Mode;
|
|
|
|
gameinfo = *Datas[type].Info;
|
|
|
|
gamemission = Datas[type].Mission;
|
|
|
|
if (type == IWAD_HereticExtended)
|
|
|
|
{
|
|
|
|
gameinfo.flags |= GI_MENUHACK_EXTENDED;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
gamemode = undetermined;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//==========================================================================
|
|
|
|
//
|
|
|
|
// ScanIWAD
|
|
|
|
//
|
|
|
|
// Scan the contents of an IWAD to determine which one it is
|
|
|
|
//==========================================================================
|
|
|
|
|
|
|
|
static EIWADType ScanIWAD (const char *iwad)
|
|
|
|
{
|
|
|
|
static const char checklumps[][8] =
|
|
|
|
{
|
|
|
|
"E1M1",
|
|
|
|
"E4M1",
|
|
|
|
"MAP01",
|
|
|
|
"MAP60",
|
|
|
|
"TITLE",
|
|
|
|
"REDTNT2",
|
|
|
|
"CAMO1",
|
|
|
|
{ 'E','X','T','E','N','D','E','D'},
|
|
|
|
"ENDSTRF",
|
|
|
|
"MAP33",
|
|
|
|
"INVCURS",
|
|
|
|
"E2M1","E2M2","E2M3","E2M4","E2M5","E2M6","E2M7","E2M8","E2M9",
|
|
|
|
"E3M1","E3M2","E3M3","E3M4","E3M5","E3M6","E3M7","E3M8","E3M9",
|
|
|
|
"DPHOOF","BFGGA0","HEADA1","CYBRA1",
|
|
|
|
{ 'S','P','I','D','A','1','D','1' },
|
|
|
|
};
|
|
|
|
#define NUM_CHECKLUMPS (sizeof(checklumps)/8)
|
|
|
|
enum
|
|
|
|
{
|
|
|
|
Check_e1m1,
|
|
|
|
Check_e4m1,
|
|
|
|
Check_map01,
|
|
|
|
Check_map60,
|
|
|
|
Check_title,
|
|
|
|
Check_redtnt2,
|
|
|
|
Check_cam01,
|
|
|
|
Check_Extended,
|
|
|
|
Check_endstrf,
|
|
|
|
Check_map33,
|
|
|
|
Check_invcurs,
|
|
|
|
Check_e2m1
|
|
|
|
};
|
|
|
|
int lumpsfound[NUM_CHECKLUMPS];
|
|
|
|
size_t i;
|
|
|
|
wadinfo_t header;
|
|
|
|
FILE *f;
|
|
|
|
|
|
|
|
memset (lumpsfound, 0, sizeof(lumpsfound));
|
|
|
|
if ( (f = fopen (iwad, "rb")) )
|
|
|
|
{
|
|
|
|
fread (&header, sizeof(header), 1, f);
|
|
|
|
if (header.Magic == IWAD_ID || header.Magic == PWAD_ID)
|
|
|
|
{
|
|
|
|
header.NumLumps = LittleLong(header.NumLumps);
|
|
|
|
if (0 == fseek (f, LittleLong(header.InfoTableOfs), SEEK_SET))
|
|
|
|
{
|
|
|
|
for (i = 0; i < (size_t)header.NumLumps; i++)
|
|
|
|
{
|
|
|
|
wadlump_t lump;
|
|
|
|
size_t j;
|
|
|
|
|
|
|
|
if (0 == fread (&lump, sizeof(lump), 1, f))
|
|
|
|
break;
|
|
|
|
for (j = 0; j < NUM_CHECKLUMPS; j++)
|
|
|
|
if (strnicmp (lump.Name, checklumps[j], 8) == 0)
|
|
|
|
lumpsfound[j]++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
fclose (f);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (lumpsfound[Check_title] && lumpsfound[Check_map60])
|
|
|
|
{
|
|
|
|
return IWAD_HexenDK;
|
|
|
|
}
|
|
|
|
else if (lumpsfound[Check_map33] && lumpsfound[Check_endstrf])
|
|
|
|
{
|
|
|
|
if (lumpsfound[Check_map01])
|
|
|
|
{
|
|
|
|
return IWAD_Strife;
|
|
|
|
}
|
|
|
|
else if (lumpsfound[Check_invcurs])
|
|
|
|
{
|
|
|
|
return IWAD_StrifeTeaser2;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return IWAD_StrifeTeaser;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (lumpsfound[Check_map01])
|
|
|
|
{
|
|
|
|
if (lumpsfound[Check_redtnt2])
|
|
|
|
{
|
|
|
|
return IWAD_Doom2TNT;
|
|
|
|
}
|
|
|
|
else if (lumpsfound[Check_cam01])
|
|
|
|
{
|
|
|
|
return IWAD_Doom2Plutonia;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (lumpsfound[Check_title])
|
|
|
|
{
|
|
|
|
return IWAD_Hexen;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return IWAD_Doom2;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (lumpsfound[Check_e1m1])
|
|
|
|
{
|
|
|
|
if (lumpsfound[Check_title])
|
|
|
|
{
|
|
|
|
if (!lumpsfound[Check_e2m1])
|
|
|
|
{
|
|
|
|
return IWAD_HereticShareware;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (lumpsfound[Check_Extended])
|
|
|
|
{
|
|
|
|
return IWAD_HereticExtended;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return IWAD_Heretic;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
for (i = Check_e2m1; i < NUM_CHECKLUMPS; i++)
|
|
|
|
{
|
|
|
|
if (!lumpsfound[i])
|
|
|
|
{
|
|
|
|
return IWAD_DoomShareware;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (i == NUM_CHECKLUMPS)
|
|
|
|
{
|
|
|
|
if (lumpsfound[Check_e4m1])
|
|
|
|
{
|
|
|
|
return IWAD_UltimateDoom;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return IWAD_DoomRegistered;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return NUM_IWAD_TYPES; // Don't know
|
|
|
|
}
|
|
|
|
|
|
|
|
//==========================================================================
|
|
|
|
//
|
|
|
|
// CheckIWAD
|
|
|
|
//
|
|
|
|
// Tries to find an IWAD from a set of known IWAD names, and checks the
|
|
|
|
// contents of each one found to determine which game it belongs to.
|
|
|
|
// Returns the number of new wads found in this pass (does not count wads
|
|
|
|
// found from a previous call).
|
|
|
|
//
|
|
|
|
//==========================================================================
|
|
|
|
|
|
|
|
static int CheckIWAD (const char *doomwaddir, WadStuff *wads)
|
|
|
|
{
|
|
|
|
const char *slash;
|
|
|
|
int i;
|
|
|
|
int numfound;
|
|
|
|
|
|
|
|
numfound = 0;
|
|
|
|
|
|
|
|
slash = (doomwaddir[0] && doomwaddir[strlen (doomwaddir)-1] != '/') ? "/" : "";
|
|
|
|
|
|
|
|
// Search for a pre-defined IWAD
|
|
|
|
for (i = IWADNames[0] ? 0 : 1; IWADNames[i]; i++)
|
|
|
|
{
|
2006-05-06 23:43:44 +00:00
|
|
|
if (wads[i].Path.IsEmpty())
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
2006-05-16 02:50:18 +00:00
|
|
|
FString iwad;
|
|
|
|
|
|
|
|
iwad.Format ("%s%s%s", doomwaddir, slash, IWADNames[i]);
|
|
|
|
FixPathSeperator (iwad.LockBuffer());
|
2006-02-24 04:48:15 +00:00
|
|
|
if (FileExists (iwad))
|
|
|
|
{
|
|
|
|
wads[i].Type = ScanIWAD (iwad);
|
|
|
|
if (wads[i].Type != NUM_IWAD_TYPES)
|
|
|
|
{
|
2006-05-06 23:43:44 +00:00
|
|
|
wads[i].Path = iwad;
|
2006-02-24 04:48:15 +00:00
|
|
|
numfound++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return numfound;
|
|
|
|
}
|
|
|
|
|
2006-08-22 22:34:35 +00:00
|
|
|
//==========================================================================
|
|
|
|
//
|
|
|
|
// ExpandEnvVars
|
|
|
|
//
|
|
|
|
// Expands environment variable references in a string. Intended primarily
|
|
|
|
// for use with IWAD search paths in config files.
|
|
|
|
//
|
|
|
|
//==========================================================================
|
|
|
|
|
|
|
|
static FString ExpandEnvVars(const char *searchpathstring)
|
|
|
|
{
|
|
|
|
static const char envvarnamechars[] =
|
|
|
|
"01234567890"
|
|
|
|
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
|
|
|
"_"
|
|
|
|
"abcdefghijklmnopqrstuvwxyz";
|
|
|
|
|
|
|
|
if (searchpathstring == NULL)
|
|
|
|
return FString ("");
|
|
|
|
|
|
|
|
const char *dollar = strchr (searchpathstring,'$');
|
|
|
|
if (dollar == NULL)
|
|
|
|
{
|
|
|
|
return FString (searchpathstring);
|
|
|
|
}
|
|
|
|
|
|
|
|
const char *nextchars = searchpathstring;
|
|
|
|
FString out = FString (searchpathstring, dollar - searchpathstring);
|
|
|
|
while ( (dollar != NULL) && (*nextchars != 0) )
|
|
|
|
{
|
|
|
|
size_t length = strspn(dollar + 1, envvarnamechars);
|
|
|
|
if (length != 0)
|
|
|
|
{
|
|
|
|
FString varname = FString (dollar + 1, length);
|
|
|
|
if (stricmp (varname, "progdir") == 0)
|
|
|
|
{
|
|
|
|
out += progdir;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
char *varvalue = getenv (varname);
|
|
|
|
if ( (varvalue != NULL) && (strlen(varvalue) != 0) )
|
|
|
|
{
|
|
|
|
out += varvalue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
out += '$';
|
|
|
|
}
|
|
|
|
nextchars = dollar + length + 1;
|
|
|
|
dollar = strchr (nextchars, '$');
|
|
|
|
if (dollar != NULL)
|
|
|
|
{
|
|
|
|
out += FString (nextchars, dollar - nextchars);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (*nextchars != 0)
|
|
|
|
{
|
|
|
|
out += nextchars;
|
|
|
|
}
|
|
|
|
return out;
|
|
|
|
}
|
|
|
|
|
2006-02-24 04:48:15 +00:00
|
|
|
//==========================================================================
|
|
|
|
//
|
|
|
|
// CheckIWADinEnvDir
|
|
|
|
//
|
2006-08-22 22:34:35 +00:00
|
|
|
// Checks for an IWAD in a path that contains one or more environment
|
|
|
|
// variables.
|
2006-02-24 04:48:15 +00:00
|
|
|
//
|
|
|
|
//==========================================================================
|
|
|
|
|
2006-08-22 22:34:35 +00:00
|
|
|
static int CheckIWADinEnvDir (const char *str, WadStuff *wads)
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
2006-08-22 22:34:35 +00:00
|
|
|
FString expanded = ExpandEnvVars (str);
|
2006-02-24 04:48:15 +00:00
|
|
|
|
2006-08-22 22:34:35 +00:00
|
|
|
if (!expanded.IsEmpty())
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
2006-08-22 22:34:35 +00:00
|
|
|
char *dir = expanded.LockBuffer ();
|
2006-02-24 04:48:15 +00:00
|
|
|
FixPathSeperator (dir);
|
2006-08-22 22:34:35 +00:00
|
|
|
expanded.UnlockBuffer ();
|
|
|
|
if (expanded[expanded.Len() - 1] != '/')
|
|
|
|
{
|
|
|
|
expanded += '/';
|
|
|
|
}
|
|
|
|
return CheckIWAD (expanded, wads);
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
//==========================================================================
|
|
|
|
//
|
|
|
|
// IdentifyVersion
|
|
|
|
//
|
|
|
|
// Tries to find an IWAD in one of four directories under DOS or Win32:
|
|
|
|
// 1. Current directory
|
|
|
|
// 2. Executable directory
|
|
|
|
// 3. $DOOMWADDIR
|
|
|
|
// 4. $HOME
|
|
|
|
//
|
|
|
|
// Under UNIX OSes, the search path is:
|
|
|
|
// 1. Current directory
|
|
|
|
// 2. $DOOMWADDIR
|
|
|
|
// 3. $HOME/.zdoom
|
|
|
|
// 4. The share directory defined at compile time (/usr/local/share/zdoom)
|
|
|
|
//
|
|
|
|
// The search path can be altered by editing the IWADSearch.Directories
|
|
|
|
// section of the config file.
|
|
|
|
//
|
|
|
|
//==========================================================================
|
|
|
|
|
2006-05-06 23:43:44 +00:00
|
|
|
static EIWADType IdentifyVersion (const char *zdoom_wad)
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
|
|
|
WadStuff wads[sizeof(IWADNames)/sizeof(char *)];
|
|
|
|
size_t foundwads[NUM_IWAD_TYPES] = { 0 };
|
|
|
|
const char *iwadparm = Args.CheckValue ("-iwad");
|
|
|
|
size_t numwads;
|
|
|
|
int pickwad;
|
|
|
|
size_t i;
|
|
|
|
bool iwadparmfound = false;
|
2006-05-09 03:40:15 +00:00
|
|
|
FString custwad;
|
2006-02-24 04:48:15 +00:00
|
|
|
|
|
|
|
if (iwadparm)
|
|
|
|
{
|
2006-05-09 03:40:15 +00:00
|
|
|
custwad = iwadparm;
|
2006-05-16 02:50:18 +00:00
|
|
|
FixPathSeperator (custwad.LockBuffer());
|
2006-02-24 04:48:15 +00:00
|
|
|
if (CheckIWAD (custwad, wads))
|
|
|
|
{ // -iwad parameter was a directory
|
|
|
|
iwadparm = NULL;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
DefaultExtension (custwad, ".wad");
|
|
|
|
iwadparm = custwad;
|
|
|
|
IWADNames[0] = iwadparm;
|
|
|
|
CheckIWAD ("", wads);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-05-16 02:50:18 +00:00
|
|
|
if (iwadparm == NULL || wads[0].Path.IsEmpty())
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
|
|
|
if (GameConfig->SetSection ("IWADSearch.Directories"))
|
|
|
|
{
|
|
|
|
const char *key;
|
|
|
|
const char *value;
|
|
|
|
|
|
|
|
while (GameConfig->NextInSection (key, value))
|
|
|
|
{
|
|
|
|
if (stricmp (key, "Path") == 0)
|
|
|
|
{
|
2006-08-22 22:34:35 +00:00
|
|
|
if (strchr (value, '$') != NULL)
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
2006-08-22 22:34:35 +00:00
|
|
|
CheckIWADinEnvDir (value, wads);
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
|
|
|
#ifdef unix
|
|
|
|
else if (*value == '~' && (*(value + 1) == 0 || *(value + 1) == '/'))
|
|
|
|
{
|
2006-06-09 08:19:46 +00:00
|
|
|
FString homepath = GetUserFile (*(value + 1) ? value + 2 : value + 1, true);
|
2006-05-03 22:45:01 +00:00
|
|
|
CheckIWAD (homepath, wads);
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
else
|
|
|
|
{
|
|
|
|
CheckIWAD (value, wads);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2007-12-06 19:15:07 +00:00
|
|
|
#ifdef _WIN32
|
|
|
|
FString steam_path = I_GetSteamPath();
|
|
|
|
if (steam_path.IsNotEmpty())
|
|
|
|
{
|
|
|
|
static const char *const steam_dirs[] =
|
|
|
|
{
|
|
|
|
"doom 2/base",
|
|
|
|
"final doom/base",
|
|
|
|
"heretic shadow of the serpent riders/base",
|
|
|
|
"hexen/base",
|
|
|
|
"hexen deathkings of the dark citadel/base",
|
|
|
|
"ultimate doom/base"
|
|
|
|
};
|
|
|
|
steam_path += "/SteamApps/common/";
|
|
|
|
for (i = 0; i < countof(steam_dirs); ++i)
|
|
|
|
{
|
|
|
|
CheckIWAD (steam_path + steam_dirs[i], wads);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
|
|
|
|
2006-05-16 02:50:18 +00:00
|
|
|
if (iwadparm != NULL && !wads[0].Path.IsEmpty())
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
|
|
|
iwadparmfound = true;
|
|
|
|
}
|
|
|
|
|
2007-12-06 19:15:07 +00:00
|
|
|
for (i = numwads = 0; i < countof(IWADNames); i++)
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
2006-05-16 04:19:20 +00:00
|
|
|
if (!wads[i].Path.IsEmpty())
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
|
|
|
if (i != numwads)
|
|
|
|
{
|
|
|
|
wads[numwads] = wads[i];
|
|
|
|
}
|
|
|
|
foundwads[wads[numwads].Type] = numwads+1;
|
|
|
|
numwads++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (foundwads[IWAD_HexenDK] && !foundwads[IWAD_Hexen])
|
|
|
|
{ // Cannot play Hexen DK without Hexen
|
|
|
|
size_t kill = foundwads[IWAD_HexenDK];
|
|
|
|
if (kill != numwads)
|
|
|
|
{
|
|
|
|
memmove (&wads[kill-1], &wads[kill], numwads - kill);
|
|
|
|
}
|
|
|
|
numwads--;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (numwads == 0)
|
|
|
|
{
|
|
|
|
I_FatalError ("Cannot find a game IWAD (doom.wad, doom2.wad, heretic.wad, etc.).\n"
|
|
|
|
"Did you install ZDoom properly? You can do either of the following:\n"
|
|
|
|
"\n"
|
|
|
|
"1. Place one or more of these wads in the same directory as ZDoom.\n"
|
2006-07-08 02:17:35 +00:00
|
|
|
"2. Edit your zdoom-username.ini and add the directories of your iwads\n"
|
2006-02-24 04:48:15 +00:00
|
|
|
"to the list beneath [IWADSearch.Directories]");
|
|
|
|
}
|
|
|
|
|
|
|
|
pickwad = 0;
|
|
|
|
|
2006-07-08 02:17:35 +00:00
|
|
|
if (!iwadparmfound && numwads > 1)
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
2006-07-08 02:17:35 +00:00
|
|
|
int defiwad = 0;
|
|
|
|
|
|
|
|
// Locate the user's prefered IWAD, if it was found.
|
|
|
|
if (defaultiwad[0] != '\0')
|
|
|
|
{
|
|
|
|
for (i = 0; i < numwads; ++i)
|
|
|
|
{
|
|
|
|
FString basename = ExtractFileBase (wads[i].Path);
|
|
|
|
if (stricmp (basename, defaultiwad) == 0)
|
|
|
|
{
|
|
|
|
defiwad = (int)i;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
pickwad = I_PickIWad (wads, (int)numwads, queryiwad, defiwad);
|
|
|
|
if (pickwad >= 0)
|
|
|
|
{
|
|
|
|
// The newly selected IWAD becomes the new default
|
|
|
|
FString basename = ExtractFileBase (wads[pickwad].Path);
|
|
|
|
defaultiwad = basename;
|
|
|
|
}
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (pickwad < 0)
|
|
|
|
exit (0);
|
|
|
|
|
2006-05-06 23:43:44 +00:00
|
|
|
// zdoom.pk3 must always be the first file loaded and the IWAD second.
|
|
|
|
D_AddFile (zdoom_wad);
|
|
|
|
|
2006-02-24 04:48:15 +00:00
|
|
|
if (wads[pickwad].Type == IWAD_HexenDK)
|
|
|
|
{ // load hexen.wad before loading hexdd.wad
|
|
|
|
D_AddFile (wads[foundwads[IWAD_Hexen]-1].Path);
|
|
|
|
}
|
|
|
|
|
|
|
|
SetIWAD (wads[pickwad].Path, wads[pickwad].Type);
|
|
|
|
|
|
|
|
if (wads[pickwad].Type == IWAD_Strife)
|
|
|
|
{ // Try to load voices.wad along with strife1.wad
|
2006-05-16 02:50:18 +00:00
|
|
|
long lastslash = wads[pickwad].Path.LastIndexOf ('/');
|
|
|
|
FString path;
|
|
|
|
|
|
|
|
if (lastslash == -1)
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
2006-05-18 15:03:35 +00:00
|
|
|
path = "";// wads[pickwad].Path;
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2006-05-18 15:03:35 +00:00
|
|
|
path = FString (wads[pickwad].Path.GetChars(), lastslash + 1);
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
2006-05-16 02:50:18 +00:00
|
|
|
path += "voices.wad";
|
|
|
|
D_AddFile (path);
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return wads[pickwad].Type;
|
|
|
|
}
|
|
|
|
|
|
|
|
//==========================================================================
|
|
|
|
//
|
|
|
|
// BaseFileSearch
|
|
|
|
//
|
|
|
|
// If a file does not exist at <file>, looks for it in the directories
|
|
|
|
// specified in the config file. Returns the path to the file, if found,
|
|
|
|
// or NULL if it could not be found.
|
|
|
|
//
|
|
|
|
//==========================================================================
|
|
|
|
|
2006-04-17 13:53:34 +00:00
|
|
|
static const char *BaseFileSearch (const char *file, const char *ext, bool lookfirstinprogdir)
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
|
|
|
static char wad[PATH_MAX];
|
|
|
|
|
2006-04-17 13:53:34 +00:00
|
|
|
if (lookfirstinprogdir)
|
|
|
|
{
|
|
|
|
sprintf (wad, "%s%s%s", progdir, progdir[strlen (progdir) - 1] != '/' ? "/" : "", file);
|
|
|
|
if (FileExists (wad))
|
|
|
|
{
|
|
|
|
return wad;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-02-24 04:48:15 +00:00
|
|
|
if (FileExists (file))
|
|
|
|
{
|
2006-05-11 05:00:35 +00:00
|
|
|
sprintf (wad, "%s", file);
|
|
|
|
return wad;
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (GameConfig->SetSection ("FileSearch.Directories"))
|
|
|
|
{
|
|
|
|
const char *key;
|
|
|
|
const char *value;
|
|
|
|
|
|
|
|
while (GameConfig->NextInSection (key, value))
|
|
|
|
{
|
|
|
|
if (stricmp (key, "Path") == 0)
|
|
|
|
{
|
|
|
|
const char *dir;
|
2006-05-03 22:45:01 +00:00
|
|
|
FString homepath;
|
2006-02-24 04:48:15 +00:00
|
|
|
|
|
|
|
if (*value == '$')
|
|
|
|
{
|
|
|
|
if (stricmp (value + 1, "progdir") == 0)
|
|
|
|
{
|
|
|
|
dir = progdir;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
dir = getenv (value + 1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#ifdef unix
|
|
|
|
else if (*value == '~' && (*(value + 1) == 0 || *(value + 1) == '/'))
|
|
|
|
{
|
2006-06-09 08:19:46 +00:00
|
|
|
homepath = GetUserFile (*(value + 1) ? value + 2 : value + 1, true);
|
2006-05-03 22:45:01 +00:00
|
|
|
dir = homepath;
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
else
|
|
|
|
{
|
|
|
|
dir = value;
|
|
|
|
}
|
|
|
|
if (dir != NULL)
|
|
|
|
{
|
|
|
|
sprintf (wad, "%s%s%s", dir, dir[strlen (dir) - 1] != '/' ? "/" : "", file);
|
|
|
|
if (FileExists (wad))
|
|
|
|
{
|
|
|
|
return wad;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Retry, this time with a default extension
|
|
|
|
if (ext != NULL)
|
|
|
|
{
|
2006-05-03 22:45:01 +00:00
|
|
|
FString tmp = file;
|
2006-02-24 04:48:15 +00:00
|
|
|
DefaultExtension (tmp, ext);
|
2006-05-03 22:45:01 +00:00
|
|
|
return BaseFileSearch (tmp, NULL);
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
//==========================================================================
|
|
|
|
//
|
|
|
|
// ConsiderPatches
|
|
|
|
//
|
|
|
|
// Tries to add any deh/bex patches from the command line.
|
|
|
|
//
|
|
|
|
//==========================================================================
|
|
|
|
|
|
|
|
bool ConsiderPatches (const char *arg, const char *ext)
|
|
|
|
{
|
|
|
|
bool noDef = false;
|
|
|
|
DArgs *files = Args.GatherFiles (arg, ext, false);
|
|
|
|
|
|
|
|
if (files->NumArgs() > 0)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
const char *f;
|
|
|
|
|
|
|
|
for (i = 0; i < files->NumArgs(); ++i)
|
|
|
|
{
|
|
|
|
if ( (f = BaseFileSearch (files->GetArg (i), ".deh")) )
|
|
|
|
DoDehPatch (f, false);
|
|
|
|
else if ( (f = BaseFileSearch (files->GetArg (i), ".bex")) )
|
|
|
|
DoDehPatch (f, false);
|
|
|
|
}
|
|
|
|
noDef = true;
|
|
|
|
}
|
|
|
|
delete files;
|
|
|
|
return noDef;
|
|
|
|
}
|
|
|
|
|
|
|
|
//==========================================================================
|
|
|
|
//
|
|
|
|
// D_LoadWadSettings
|
|
|
|
//
|
|
|
|
// Parses any loaded KEYCONF lumps. These are restricted console scripts
|
|
|
|
// that can only execute the alias, defaultbind, addkeysection,
|
|
|
|
// addmenukey, weaponsection, and addslotdefault commands.
|
|
|
|
//
|
|
|
|
//==========================================================================
|
|
|
|
|
|
|
|
void D_LoadWadSettings ()
|
|
|
|
{
|
|
|
|
char cmd[4096];
|
|
|
|
int lump, lastlump = 0;
|
|
|
|
|
|
|
|
ParsingKeyConf = true;
|
|
|
|
|
|
|
|
while ((lump = Wads.FindLump ("KEYCONF", &lastlump)) != -1)
|
|
|
|
{
|
|
|
|
FMemLump data = Wads.ReadLump (lump);
|
|
|
|
const char *eof = (char *)data.GetMem() + Wads.LumpLength (lump);
|
|
|
|
const char *conf = (char *)data.GetMem();
|
|
|
|
|
|
|
|
while (conf < eof)
|
|
|
|
{
|
|
|
|
size_t i;
|
|
|
|
|
|
|
|
// Fetch a line to execute
|
|
|
|
for (i = 0; conf + i < eof && conf[i] != '\n'; ++i)
|
|
|
|
{
|
|
|
|
cmd[i] = conf[i];
|
|
|
|
}
|
|
|
|
cmd[i] = 0;
|
|
|
|
conf += i;
|
|
|
|
if (*conf == '\n')
|
|
|
|
{
|
|
|
|
conf++;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Comments begin with //
|
|
|
|
char *stop = cmd + i - 1;
|
|
|
|
char *comment = cmd;
|
|
|
|
int inQuote = 0;
|
|
|
|
|
|
|
|
if (*stop == '\r')
|
|
|
|
*stop-- = 0;
|
|
|
|
|
|
|
|
while (comment < stop)
|
|
|
|
{
|
|
|
|
if (*comment == '\"')
|
|
|
|
{
|
|
|
|
inQuote ^= 1;
|
|
|
|
}
|
|
|
|
else if (!inQuote && *comment == '/' && *(comment + 1) == '/')
|
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
comment++;
|
|
|
|
}
|
|
|
|
if (comment == cmd)
|
|
|
|
{ // Comment at line beginning
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
else if (comment < stop)
|
|
|
|
{ // Comment in middle of line
|
|
|
|
*comment = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
AddCommandString (cmd);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
ParsingKeyConf = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
//==========================================================================
|
|
|
|
//
|
|
|
|
// D_MultiExec
|
|
|
|
//
|
|
|
|
//==========================================================================
|
|
|
|
|
|
|
|
void D_MultiExec (DArgs *list, bool usePullin)
|
|
|
|
{
|
|
|
|
for (int i = 0; i < list->NumArgs(); ++i)
|
|
|
|
{
|
|
|
|
C_ExecFile (list->GetArg (i), usePullin);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//==========================================================================
|
|
|
|
//
|
|
|
|
// D_DoomMain
|
|
|
|
//
|
|
|
|
//==========================================================================
|
|
|
|
|
|
|
|
void D_DoomMain (void)
|
|
|
|
{
|
|
|
|
int p, flags;
|
2007-12-06 22:38:45 +00:00
|
|
|
FString file;
|
2006-02-24 04:48:15 +00:00
|
|
|
char *v;
|
|
|
|
const char *wad;
|
|
|
|
DArgs *execFiles;
|
2007-12-06 22:38:45 +00:00
|
|
|
const IWADInfo *iwad_info;
|
2006-02-24 04:48:15 +00:00
|
|
|
|
2006-06-11 11:28:48 +00:00
|
|
|
srand(I_MSTime());
|
|
|
|
|
2006-02-24 04:48:15 +00:00
|
|
|
atterm (DObject::StaticShutdown);
|
2006-05-12 03:14:40 +00:00
|
|
|
PClass::StaticInit ();
|
|
|
|
atterm (C_DeinitConsole);
|
2006-02-24 04:48:15 +00:00
|
|
|
|
|
|
|
gamestate = GS_STARTUP;
|
|
|
|
|
|
|
|
SetLanguageIDs ();
|
|
|
|
|
|
|
|
rngseed = (DWORD)time (NULL);
|
|
|
|
FRandom::StaticClearRandom ();
|
|
|
|
M_FindResponseFile ();
|
Note: I have not tried compiling these recent changes under Linux. I wouldn't
be surprised if it doesn't work.
- Reorganized the network startup loops so now they are event driven. There is
a single function that gets called to drive it, and it uses callbacks to
perform the different stages of the synchronization. This lets me have a nice,
responsive abort button instead of the previous unannounced hit-escape-to-
abort behavior, and I think the rearranged code is slightly easier to
understand too.
- Increased the number of bytes for version info during D_ArbitrateNetStart(),
in preparation for the day when NETGAMEVERSION requires more than one byte.
- I noticed an issue with Vista RC1 and the new fatal error setup. Even after
releasing a DirectDraw or Direct3D interface, the DWM can still use the
last image drawn using them when it composites the window. It doesn't always
do it but it does often enough that it is a real problem. At this point, I
don't know if it's a problem with the release version of Vista or not.
After messing around, I discovered the problem was caused by ~Win32Video()
hiding the window and then having it immediately shown soon after. The DWM
kept an image of the window to do the transition effect with, and then when
it didn't get a chance to do the transition, it didn't properly forget about
its saved image and kept plastering it on top of everything else
underneath.
- Added a network synchronization panel to the window during netgame startup.
- Fixed: PClass::CreateDerivedClass() must initialize StateList to NULL.
Otherwise, classic DECORATE definitions generate a big, fat crash.
- Resurrected the R_Init progress bar, now as a standard Windows control.
- Removed the sound failure dialog. The FMOD setup already defaulted to no
sound if initialization failed, so this only applies when snd_output is set
to "alternate" which now also falls back to no sound. In addition, it wasn't
working right, and I didn't feel like fixing it for the probably 0% of users
it affected.
- Fixed: The edit control used for logging output added text in reverse order
on Win9x.
- Went back to the roots and made graphics initialization one of the last
things to happen during setup. Now the startup text is visible again. More
importantly, the main window is no longer created invisible, which seems
to cause trouble with it not always appearing in the taskbar. The fatal
error dialog is now also embedded in the main window instead of being a
separate modal dialog, so you can play with the log window to see any
problems that might be reported there.
Rather than completely restoring the original startup order, I tried to
keep things as close to the way they were with early graphics startup. In
particular, V_Init() now creates a dummy screen so that things that need
screen dimensions can get them. It gets replaced by the real screen later
in I_InitGraphics(). Will need to check this under Linux to make sure it
didn't cause any problems there.
- Removed the following stubs that just called functions in Video:
- I_StartModeIterator()
- I_NextMode()
- I_DisplayType()
I_FullscreenChanged() was also removed, and a new fullscreen parameter
was added to IVideo::StartModeIterator(), since that's all it controlled.
- Renamed I_InitHardware() back to I_InitGraphics(), since that's all it's
initialized post-1.22.
SVN r416 (trunk)
2006-12-19 04:09:10 +00:00
|
|
|
|
|
|
|
Printf ("M_LoadDefaults: Load system defaults.\n");
|
2006-02-24 04:48:15 +00:00
|
|
|
M_LoadDefaults (); // load before initing other systems
|
|
|
|
|
2006-04-29 12:40:09 +00:00
|
|
|
// [RH] Make sure zdoom.pk3 is always loaded,
|
2006-02-24 04:48:15 +00:00
|
|
|
// as it contains magic stuff we need.
|
2006-04-17 13:53:34 +00:00
|
|
|
|
2006-05-13 21:22:08 +00:00
|
|
|
wad = BaseFileSearch (BASEWAD, NULL, true);
|
2006-05-06 23:43:44 +00:00
|
|
|
if (wad == NULL)
|
|
|
|
{
|
2006-05-13 21:22:08 +00:00
|
|
|
I_FatalError ("Cannot find " BASEWAD);
|
2006-05-06 23:43:44 +00:00
|
|
|
}
|
2006-02-24 04:48:15 +00:00
|
|
|
|
2007-12-06 22:38:45 +00:00
|
|
|
iwad_info = &IWADInfos[IdentifyVersion(wad)];
|
|
|
|
I_SetIWADInfo(iwad_info);
|
2006-02-24 04:48:15 +00:00
|
|
|
GameConfig->DoGameSetup (GameNames[gameinfo.gametype]);
|
|
|
|
|
|
|
|
if (!(gameinfo.flags & GI_SHAREWARE))
|
|
|
|
{
|
2006-11-27 21:51:36 +00:00
|
|
|
// [RH] zvox.wad - A wad I had intended to be automatically generated
|
|
|
|
// from Q2's pak0.pak so the female and cyborg player could have
|
|
|
|
// voices. I never got around to writing the utility to do it, though.
|
|
|
|
// And I probably never will now. But I know at least one person uses
|
|
|
|
// it for something else, so this gets to stay here.
|
|
|
|
wad = BaseFileSearch ("zvox.wad", NULL);
|
|
|
|
if (wad)
|
|
|
|
D_AddFile (wad);
|
|
|
|
|
|
|
|
// [RH] Add any .wad files in the skins directory
|
|
|
|
#ifdef unix
|
2007-12-06 22:38:45 +00:00
|
|
|
file = SHARE_DIR;
|
2006-11-27 21:51:36 +00:00
|
|
|
#else
|
2007-12-06 22:38:45 +00:00
|
|
|
file = progdir;
|
2006-11-27 21:51:36 +00:00
|
|
|
#endif
|
2007-12-06 22:38:45 +00:00
|
|
|
file += "skins";
|
2006-11-27 21:51:36 +00:00
|
|
|
D_AddDirectory (file);
|
|
|
|
|
|
|
|
const char *home = getenv ("HOME");
|
|
|
|
if (home)
|
|
|
|
{
|
2007-12-06 22:38:45 +00:00
|
|
|
file = home;
|
|
|
|
if (home[strlen(home) - 1] != '/')
|
|
|
|
{
|
|
|
|
file += '/';
|
|
|
|
}
|
|
|
|
file += ".zdoom/skins";
|
2006-11-27 21:51:36 +00:00
|
|
|
D_AddDirectory (file);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-02-24 04:48:15 +00:00
|
|
|
// Add common (global) wads
|
|
|
|
D_AddConfigWads ("Global.Autoload");
|
|
|
|
|
|
|
|
// Add game-specific wads
|
2007-12-06 22:38:45 +00:00
|
|
|
file = GameNames[gameinfo.gametype];
|
|
|
|
file += ".Autoload";
|
2006-02-24 04:48:15 +00:00
|
|
|
D_AddConfigWads (file);
|
2007-12-06 22:38:45 +00:00
|
|
|
|
|
|
|
// Add IWAD-specific wads
|
|
|
|
if (iwad_info->Autoname != NULL)
|
|
|
|
{
|
|
|
|
file = iwad_info->Autoname;
|
|
|
|
file += ".Autoload";
|
|
|
|
D_AddConfigWads(file);
|
|
|
|
}
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
|
|
|
|
2006-04-12 01:50:09 +00:00
|
|
|
// Run automatically executed files
|
|
|
|
execFiles = new DArgs;
|
|
|
|
GameConfig->AddAutoexec (execFiles, GameNames[gameinfo.gametype]);
|
|
|
|
D_MultiExec (execFiles, true);
|
|
|
|
delete execFiles;
|
|
|
|
|
|
|
|
// Run .cfg files at the start of the command line.
|
|
|
|
execFiles = Args.GatherFiles (NULL, ".cfg", false);
|
|
|
|
D_MultiExec (execFiles, true);
|
|
|
|
delete execFiles;
|
|
|
|
|
|
|
|
C_ExecCmdLineParams (); // [RH] do all +set commands on the command line
|
|
|
|
|
2006-02-24 04:48:15 +00:00
|
|
|
DArgs *files = Args.GatherFiles ("-file", ".wad", true);
|
2006-04-15 15:00:29 +00:00
|
|
|
DArgs *files1 = Args.GatherFiles (NULL, ".zip", false);
|
|
|
|
DArgs *files2 = Args.GatherFiles (NULL, ".pk3", false);
|
|
|
|
if (files->NumArgs() > 0 || files1->NumArgs() > 0 || files2->NumArgs() > 0)
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
|
|
|
// Check for -file in shareware
|
|
|
|
if (gameinfo.flags & GI_SHAREWARE)
|
|
|
|
{
|
|
|
|
I_FatalError ("You cannot -file with the shareware version. Register!");
|
|
|
|
}
|
|
|
|
|
|
|
|
// the files gathered are wadfile/lump names
|
|
|
|
for (int i = 0; i < files->NumArgs(); i++)
|
|
|
|
{
|
|
|
|
D_AddWildFile (files->GetArg (i));
|
|
|
|
}
|
2006-04-15 15:00:29 +00:00
|
|
|
for (int i = 0; i < files1->NumArgs(); i++)
|
|
|
|
{
|
|
|
|
D_AddWildFile (files1->GetArg (i));
|
|
|
|
}
|
|
|
|
for (int i = 0; i < files2->NumArgs(); i++)
|
|
|
|
{
|
|
|
|
D_AddWildFile (files2->GetArg (i));
|
|
|
|
}
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
|
|
|
delete files;
|
2006-04-15 15:00:29 +00:00
|
|
|
delete files1;
|
|
|
|
delete files2;
|
2006-02-24 04:48:15 +00:00
|
|
|
|
Note: I have not tried compiling these recent changes under Linux. I wouldn't
be surprised if it doesn't work.
- Reorganized the network startup loops so now they are event driven. There is
a single function that gets called to drive it, and it uses callbacks to
perform the different stages of the synchronization. This lets me have a nice,
responsive abort button instead of the previous unannounced hit-escape-to-
abort behavior, and I think the rearranged code is slightly easier to
understand too.
- Increased the number of bytes for version info during D_ArbitrateNetStart(),
in preparation for the day when NETGAMEVERSION requires more than one byte.
- I noticed an issue with Vista RC1 and the new fatal error setup. Even after
releasing a DirectDraw or Direct3D interface, the DWM can still use the
last image drawn using them when it composites the window. It doesn't always
do it but it does often enough that it is a real problem. At this point, I
don't know if it's a problem with the release version of Vista or not.
After messing around, I discovered the problem was caused by ~Win32Video()
hiding the window and then having it immediately shown soon after. The DWM
kept an image of the window to do the transition effect with, and then when
it didn't get a chance to do the transition, it didn't properly forget about
its saved image and kept plastering it on top of everything else
underneath.
- Added a network synchronization panel to the window during netgame startup.
- Fixed: PClass::CreateDerivedClass() must initialize StateList to NULL.
Otherwise, classic DECORATE definitions generate a big, fat crash.
- Resurrected the R_Init progress bar, now as a standard Windows control.
- Removed the sound failure dialog. The FMOD setup already defaulted to no
sound if initialization failed, so this only applies when snd_output is set
to "alternate" which now also falls back to no sound. In addition, it wasn't
working right, and I didn't feel like fixing it for the probably 0% of users
it affected.
- Fixed: The edit control used for logging output added text in reverse order
on Win9x.
- Went back to the roots and made graphics initialization one of the last
things to happen during setup. Now the startup text is visible again. More
importantly, the main window is no longer created invisible, which seems
to cause trouble with it not always appearing in the taskbar. The fatal
error dialog is now also embedded in the main window instead of being a
separate modal dialog, so you can play with the log window to see any
problems that might be reported there.
Rather than completely restoring the original startup order, I tried to
keep things as close to the way they were with early graphics startup. In
particular, V_Init() now creates a dummy screen so that things that need
screen dimensions can get them. It gets replaced by the real screen later
in I_InitGraphics(). Will need to check this under Linux to make sure it
didn't cause any problems there.
- Removed the following stubs that just called functions in Video:
- I_StartModeIterator()
- I_NextMode()
- I_DisplayType()
I_FullscreenChanged() was also removed, and a new fullscreen parameter
was added to IVideo::StartModeIterator(), since that's all it controlled.
- Renamed I_InitHardware() back to I_InitGraphics(), since that's all it's
initialized post-1.22.
SVN r416 (trunk)
2006-12-19 04:09:10 +00:00
|
|
|
Printf ("W_Init: Init WADfiles.\n");
|
2006-02-24 04:48:15 +00:00
|
|
|
Wads.InitMultipleFiles (&wadfiles);
|
|
|
|
|
|
|
|
// [RH] Initialize localizable strings.
|
|
|
|
GStrings.LoadStrings (false);
|
|
|
|
|
|
|
|
// [RH] Moved these up here so that we can do most of our
|
|
|
|
// startup output in a fullscreen console.
|
|
|
|
|
|
|
|
CT_Init ();
|
Note: I have not tried compiling these recent changes under Linux. I wouldn't
be surprised if it doesn't work.
- Reorganized the network startup loops so now they are event driven. There is
a single function that gets called to drive it, and it uses callbacks to
perform the different stages of the synchronization. This lets me have a nice,
responsive abort button instead of the previous unannounced hit-escape-to-
abort behavior, and I think the rearranged code is slightly easier to
understand too.
- Increased the number of bytes for version info during D_ArbitrateNetStart(),
in preparation for the day when NETGAMEVERSION requires more than one byte.
- I noticed an issue with Vista RC1 and the new fatal error setup. Even after
releasing a DirectDraw or Direct3D interface, the DWM can still use the
last image drawn using them when it composites the window. It doesn't always
do it but it does often enough that it is a real problem. At this point, I
don't know if it's a problem with the release version of Vista or not.
After messing around, I discovered the problem was caused by ~Win32Video()
hiding the window and then having it immediately shown soon after. The DWM
kept an image of the window to do the transition effect with, and then when
it didn't get a chance to do the transition, it didn't properly forget about
its saved image and kept plastering it on top of everything else
underneath.
- Added a network synchronization panel to the window during netgame startup.
- Fixed: PClass::CreateDerivedClass() must initialize StateList to NULL.
Otherwise, classic DECORATE definitions generate a big, fat crash.
- Resurrected the R_Init progress bar, now as a standard Windows control.
- Removed the sound failure dialog. The FMOD setup already defaulted to no
sound if initialization failed, so this only applies when snd_output is set
to "alternate" which now also falls back to no sound. In addition, it wasn't
working right, and I didn't feel like fixing it for the probably 0% of users
it affected.
- Fixed: The edit control used for logging output added text in reverse order
on Win9x.
- Went back to the roots and made graphics initialization one of the last
things to happen during setup. Now the startup text is visible again. More
importantly, the main window is no longer created invisible, which seems
to cause trouble with it not always appearing in the taskbar. The fatal
error dialog is now also embedded in the main window instead of being a
separate modal dialog, so you can play with the log window to see any
problems that might be reported there.
Rather than completely restoring the original startup order, I tried to
keep things as close to the way they were with early graphics startup. In
particular, V_Init() now creates a dummy screen so that things that need
screen dimensions can get them. It gets replaced by the real screen later
in I_InitGraphics(). Will need to check this under Linux to make sure it
didn't cause any problems there.
- Removed the following stubs that just called functions in Video:
- I_StartModeIterator()
- I_NextMode()
- I_DisplayType()
I_FullscreenChanged() was also removed, and a new fullscreen parameter
was added to IVideo::StartModeIterator(), since that's all it controlled.
- Renamed I_InitHardware() back to I_InitGraphics(), since that's all it's
initialized post-1.22.
SVN r416 (trunk)
2006-12-19 04:09:10 +00:00
|
|
|
|
|
|
|
Printf ("I_Init: Setting up machine state.\n");
|
2006-02-24 04:48:15 +00:00
|
|
|
I_Init ();
|
2006-05-09 03:40:15 +00:00
|
|
|
|
Note: I have not tried compiling these recent changes under Linux. I wouldn't
be surprised if it doesn't work.
- Reorganized the network startup loops so now they are event driven. There is
a single function that gets called to drive it, and it uses callbacks to
perform the different stages of the synchronization. This lets me have a nice,
responsive abort button instead of the previous unannounced hit-escape-to-
abort behavior, and I think the rearranged code is slightly easier to
understand too.
- Increased the number of bytes for version info during D_ArbitrateNetStart(),
in preparation for the day when NETGAMEVERSION requires more than one byte.
- I noticed an issue with Vista RC1 and the new fatal error setup. Even after
releasing a DirectDraw or Direct3D interface, the DWM can still use the
last image drawn using them when it composites the window. It doesn't always
do it but it does often enough that it is a real problem. At this point, I
don't know if it's a problem with the release version of Vista or not.
After messing around, I discovered the problem was caused by ~Win32Video()
hiding the window and then having it immediately shown soon after. The DWM
kept an image of the window to do the transition effect with, and then when
it didn't get a chance to do the transition, it didn't properly forget about
its saved image and kept plastering it on top of everything else
underneath.
- Added a network synchronization panel to the window during netgame startup.
- Fixed: PClass::CreateDerivedClass() must initialize StateList to NULL.
Otherwise, classic DECORATE definitions generate a big, fat crash.
- Resurrected the R_Init progress bar, now as a standard Windows control.
- Removed the sound failure dialog. The FMOD setup already defaulted to no
sound if initialization failed, so this only applies when snd_output is set
to "alternate" which now also falls back to no sound. In addition, it wasn't
working right, and I didn't feel like fixing it for the probably 0% of users
it affected.
- Fixed: The edit control used for logging output added text in reverse order
on Win9x.
- Went back to the roots and made graphics initialization one of the last
things to happen during setup. Now the startup text is visible again. More
importantly, the main window is no longer created invisible, which seems
to cause trouble with it not always appearing in the taskbar. The fatal
error dialog is now also embedded in the main window instead of being a
separate modal dialog, so you can play with the log window to see any
problems that might be reported there.
Rather than completely restoring the original startup order, I tried to
keep things as close to the way they were with early graphics startup. In
particular, V_Init() now creates a dummy screen so that things that need
screen dimensions can get them. It gets replaced by the real screen later
in I_InitGraphics(). Will need to check this under Linux to make sure it
didn't cause any problems there.
- Removed the following stubs that just called functions in Video:
- I_StartModeIterator()
- I_NextMode()
- I_DisplayType()
I_FullscreenChanged() was also removed, and a new fullscreen parameter
was added to IVideo::StartModeIterator(), since that's all it controlled.
- Renamed I_InitHardware() back to I_InitGraphics(), since that's all it's
initialized post-1.22.
SVN r416 (trunk)
2006-12-19 04:09:10 +00:00
|
|
|
Printf ("V_Init: allocate screen.\n");
|
2006-02-24 04:48:15 +00:00
|
|
|
V_Init ();
|
|
|
|
|
|
|
|
// Base systems have been inited; enable cvar callbacks
|
|
|
|
FBaseCVar::EnableCallbacks ();
|
|
|
|
|
Note: I have not tried compiling these recent changes under Linux. I wouldn't
be surprised if it doesn't work.
- Reorganized the network startup loops so now they are event driven. There is
a single function that gets called to drive it, and it uses callbacks to
perform the different stages of the synchronization. This lets me have a nice,
responsive abort button instead of the previous unannounced hit-escape-to-
abort behavior, and I think the rearranged code is slightly easier to
understand too.
- Increased the number of bytes for version info during D_ArbitrateNetStart(),
in preparation for the day when NETGAMEVERSION requires more than one byte.
- I noticed an issue with Vista RC1 and the new fatal error setup. Even after
releasing a DirectDraw or Direct3D interface, the DWM can still use the
last image drawn using them when it composites the window. It doesn't always
do it but it does often enough that it is a real problem. At this point, I
don't know if it's a problem with the release version of Vista or not.
After messing around, I discovered the problem was caused by ~Win32Video()
hiding the window and then having it immediately shown soon after. The DWM
kept an image of the window to do the transition effect with, and then when
it didn't get a chance to do the transition, it didn't properly forget about
its saved image and kept plastering it on top of everything else
underneath.
- Added a network synchronization panel to the window during netgame startup.
- Fixed: PClass::CreateDerivedClass() must initialize StateList to NULL.
Otherwise, classic DECORATE definitions generate a big, fat crash.
- Resurrected the R_Init progress bar, now as a standard Windows control.
- Removed the sound failure dialog. The FMOD setup already defaulted to no
sound if initialization failed, so this only applies when snd_output is set
to "alternate" which now also falls back to no sound. In addition, it wasn't
working right, and I didn't feel like fixing it for the probably 0% of users
it affected.
- Fixed: The edit control used for logging output added text in reverse order
on Win9x.
- Went back to the roots and made graphics initialization one of the last
things to happen during setup. Now the startup text is visible again. More
importantly, the main window is no longer created invisible, which seems
to cause trouble with it not always appearing in the taskbar. The fatal
error dialog is now also embedded in the main window instead of being a
separate modal dialog, so you can play with the log window to see any
problems that might be reported there.
Rather than completely restoring the original startup order, I tried to
keep things as close to the way they were with early graphics startup. In
particular, V_Init() now creates a dummy screen so that things that need
screen dimensions can get them. It gets replaced by the real screen later
in I_InitGraphics(). Will need to check this under Linux to make sure it
didn't cause any problems there.
- Removed the following stubs that just called functions in Video:
- I_StartModeIterator()
- I_NextMode()
- I_DisplayType()
I_FullscreenChanged() was also removed, and a new fullscreen parameter
was added to IVideo::StartModeIterator(), since that's all it controlled.
- Renamed I_InitHardware() back to I_InitGraphics(), since that's all it's
initialized post-1.22.
SVN r416 (trunk)
2006-12-19 04:09:10 +00:00
|
|
|
Printf ("S_Init: Setting up sound.\n");
|
|
|
|
S_Init ();
|
|
|
|
|
|
|
|
Printf ("ST_Init: Init startup screen.\n");
|
2007-03-06 01:33:18 +00:00
|
|
|
StartScreen = FStartupScreen::CreateInstance (R_GuesstimateNumTextures() + 5);
|
2006-02-24 04:48:15 +00:00
|
|
|
|
Note: I have not tried compiling these recent changes under Linux. I wouldn't
be surprised if it doesn't work.
- Reorganized the network startup loops so now they are event driven. There is
a single function that gets called to drive it, and it uses callbacks to
perform the different stages of the synchronization. This lets me have a nice,
responsive abort button instead of the previous unannounced hit-escape-to-
abort behavior, and I think the rearranged code is slightly easier to
understand too.
- Increased the number of bytes for version info during D_ArbitrateNetStart(),
in preparation for the day when NETGAMEVERSION requires more than one byte.
- I noticed an issue with Vista RC1 and the new fatal error setup. Even after
releasing a DirectDraw or Direct3D interface, the DWM can still use the
last image drawn using them when it composites the window. It doesn't always
do it but it does often enough that it is a real problem. At this point, I
don't know if it's a problem with the release version of Vista or not.
After messing around, I discovered the problem was caused by ~Win32Video()
hiding the window and then having it immediately shown soon after. The DWM
kept an image of the window to do the transition effect with, and then when
it didn't get a chance to do the transition, it didn't properly forget about
its saved image and kept plastering it on top of everything else
underneath.
- Added a network synchronization panel to the window during netgame startup.
- Fixed: PClass::CreateDerivedClass() must initialize StateList to NULL.
Otherwise, classic DECORATE definitions generate a big, fat crash.
- Resurrected the R_Init progress bar, now as a standard Windows control.
- Removed the sound failure dialog. The FMOD setup already defaulted to no
sound if initialization failed, so this only applies when snd_output is set
to "alternate" which now also falls back to no sound. In addition, it wasn't
working right, and I didn't feel like fixing it for the probably 0% of users
it affected.
- Fixed: The edit control used for logging output added text in reverse order
on Win9x.
- Went back to the roots and made graphics initialization one of the last
things to happen during setup. Now the startup text is visible again. More
importantly, the main window is no longer created invisible, which seems
to cause trouble with it not always appearing in the taskbar. The fatal
error dialog is now also embedded in the main window instead of being a
separate modal dialog, so you can play with the log window to see any
problems that might be reported there.
Rather than completely restoring the original startup order, I tried to
keep things as close to the way they were with early graphics startup. In
particular, V_Init() now creates a dummy screen so that things that need
screen dimensions can get them. It gets replaced by the real screen later
in I_InitGraphics(). Will need to check this under Linux to make sure it
didn't cause any problems there.
- Removed the following stubs that just called functions in Video:
- I_StartModeIterator()
- I_NextMode()
- I_DisplayType()
I_FullscreenChanged() was also removed, and a new fullscreen parameter
was added to IVideo::StartModeIterator(), since that's all it controlled.
- Renamed I_InitHardware() back to I_InitGraphics(), since that's all it's
initialized post-1.22.
SVN r416 (trunk)
2006-12-19 04:09:10 +00:00
|
|
|
Printf ("P_Init: Checking cmd-line parameters...\n");
|
2007-02-28 19:08:02 +00:00
|
|
|
flags = dmflags;
|
2006-02-24 04:48:15 +00:00
|
|
|
if (Args.CheckParm ("-nomonsters")) flags |= DF_NO_MONSTERS;
|
|
|
|
if (Args.CheckParm ("-respawn")) flags |= DF_MONSTERS_RESPAWN;
|
|
|
|
if (Args.CheckParm ("-fast")) flags |= DF_FAST_MONSTERS;
|
|
|
|
|
2006-09-14 00:02:31 +00:00
|
|
|
devparm = !!Args.CheckParm ("-devparm");
|
2006-02-24 04:48:15 +00:00
|
|
|
|
|
|
|
if (Args.CheckParm ("-altdeath"))
|
|
|
|
{
|
|
|
|
deathmatch = 1;
|
|
|
|
flags |= DF_ITEMS_RESPAWN;
|
|
|
|
}
|
|
|
|
else if (Args.CheckParm ("-deathmatch"))
|
|
|
|
{
|
|
|
|
deathmatch = 1;
|
|
|
|
flags |= DF_WEAPONS_STAY | DF_ITEMS_RESPAWN;
|
|
|
|
}
|
|
|
|
|
|
|
|
dmflags = flags;
|
|
|
|
|
|
|
|
// get skill / episode / map from parms
|
|
|
|
if (gameinfo.gametype != GAME_Hexen)
|
|
|
|
{
|
|
|
|
strcpy (startmap, (gameinfo.flags & GI_MAPxx) ? "MAP01" : "E1M1");
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
strcpy (startmap, "&wt@01");
|
|
|
|
}
|
|
|
|
autostart = false;
|
|
|
|
|
|
|
|
const char *val = Args.CheckValue ("-skill");
|
|
|
|
if (val)
|
|
|
|
{
|
|
|
|
gameskill = val[0] - '1';
|
|
|
|
autostart = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
p = Args.CheckParm ("-warp");
|
|
|
|
if (p && p < Args.NumArgs() - 1)
|
|
|
|
{
|
|
|
|
int ep, map;
|
|
|
|
|
|
|
|
if (gameinfo.flags & GI_MAPxx)
|
|
|
|
{
|
|
|
|
ep = 1;
|
|
|
|
map = atoi (Args.GetArg(p+1));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2006-04-16 13:29:50 +00:00
|
|
|
ep = atoi (Args.GetArg(p+1));
|
|
|
|
map = p < Args.NumArgs() - 2 ? atoi (Args.GetArg(p+2)) : 10;
|
- Fixed compilation with mingw again.
- Added multiple-choice sound sequences. These overcome one of the major
deficiences of the Hexen-inherited SNDSEQ system while still being Hexen
compatible: Custom door sounds can now use different opening and closing
sequences, for both normal and blazing speeds.
- Added a serializer for TArray.
- Added a countof macro to doomtype.h. See the1's blog to find out why
it's implemented the way it is.
<http://blogs.msdn.com/the1/articles/210011.aspx>
- Added a new method to FRandom for getting random numbers larger than 255,
which lets me:
- Fixed: SNDSEQ delayrand commands could delay for no more than 255 tics.
- Fixed: If you're going to have sector_t.SoundTarget, then they need to
be included in the pointer cleanup scans.
- Ported back newer name code from 2.1.
- Fixed: Using -warp with only one parameter in Doom and Heretic to
select a map on episode 1 no longer worked.
- New: Loading a multiplayer save now restores the players based on
their names rather than on their connection order. Using connection
order was sensible when -net was the only way to start a network game,
but with -host/-join, it's not so nice. Also, if there aren't enough
players in the save, then the extra players will be spawned normally,
so you can continue a saved game with more players than you started it
with.
- Added some new SNDSEQ commands to make it possible to define Heretic's
ambient sounds in SNDSEQ: volumerel, volumerand, slot, randomsequence,
delayonce, and restart. With these, it is basically possible to obsolete
all of the $ambient SNDINFO commands.
- Fixed: Sound sequences would only execute one command each time they were
ticked.
- Fixed: No bounds checking was done on the volume sound sequences played at.
- Fixed: The tic parameter to playloop was useless and caused it to
act like a redundant playrepeat. I have removed all the logic that
caused playloop to play repeating sounds, and now it acts like an
infinite sequence of play/delay commands until the sequence is
stopped.
- Fixed: Sound sequences were ticked every frame, not every tic, so all
the delay commands were timed incorrectly and varied depending on your
framerate. Since this is useful for restarting looping sounds that got
cut off, I have not changed this. Instead, the delay commands now
record the tic when execution should resume, not the number of tics
left to delay.
SVN r57 (trunk)
2006-04-21 01:22:55 +00:00
|
|
|
if (map < 1 || map > 9)
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
|
|
|
map = ep;
|
|
|
|
ep = 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
strncpy (startmap, CalcMapName (ep, map), 8);
|
|
|
|
autostart = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
// [RH] Hack to handle +map
|
|
|
|
p = Args.CheckParm ("+map");
|
|
|
|
if (p && p < Args.NumArgs()-1)
|
|
|
|
{
|
2006-06-19 15:31:10 +00:00
|
|
|
MapData * map = P_OpenMapData(Args.GetArg (p+1));
|
|
|
|
if (map == NULL)
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
|
|
|
Printf ("Can't find map %s\n", Args.GetArg (p+1));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2006-06-19 15:31:10 +00:00
|
|
|
delete map;
|
2006-02-24 04:48:15 +00:00
|
|
|
strncpy (startmap, Args.GetArg (p+1), 8);
|
|
|
|
Args.GetArg (p)[0] = '-';
|
|
|
|
autostart = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (devparm)
|
|
|
|
{
|
|
|
|
Printf (GStrings("D_DEVSTR"));
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifndef unix
|
|
|
|
// We do not need to support -cdrom under Unix, because all the files
|
|
|
|
// that would go to c:\\zdoomdat are already stored in .zdoom inside
|
|
|
|
// the user's home directory.
|
|
|
|
if (Args.CheckParm("-cdrom"))
|
|
|
|
{
|
|
|
|
Printf (GStrings("D_CDROM"));
|
2007-12-26 09:56:09 +00:00
|
|
|
mkdir (CDROM_DIR, 0);
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
// turbo option // [RH] (now a cvar)
|
|
|
|
{
|
2007-01-02 09:51:04 +00:00
|
|
|
UCVarValue value;
|
2006-12-29 03:38:37 +00:00
|
|
|
static char one_hundred[] = "100";
|
2006-02-24 04:48:15 +00:00
|
|
|
|
|
|
|
value.String = Args.CheckValue ("-turbo");
|
|
|
|
if (value.String == NULL)
|
2006-12-29 03:38:37 +00:00
|
|
|
value.String = one_hundred;
|
2006-02-24 04:48:15 +00:00
|
|
|
else
|
|
|
|
Printf ("turbo scale: %s%%\n", value.String);
|
|
|
|
|
|
|
|
turbo.SetGenericRepDefault (value, CVAR_String);
|
|
|
|
}
|
|
|
|
|
|
|
|
v = Args.CheckValue ("-timer");
|
|
|
|
if (v)
|
|
|
|
{
|
|
|
|
double time = strtod (v, NULL);
|
|
|
|
Printf ("Levels will end after %g minute%s.\n", time, time > 1 ? "s" : "");
|
|
|
|
timelimit = (float)time;
|
|
|
|
}
|
|
|
|
|
|
|
|
v = Args.CheckValue ("-avg");
|
|
|
|
if (v)
|
|
|
|
{
|
|
|
|
Printf ("Austin Virtual Gaming: Levels will end after 20 minutes\n");
|
|
|
|
timelimit = 20.f;
|
|
|
|
}
|
|
|
|
|
2007-03-06 01:33:18 +00:00
|
|
|
//
|
|
|
|
// Build status bar line!
|
|
|
|
//
|
|
|
|
if (deathmatch)
|
|
|
|
StartScreen->AppendStatusLine("DeathMatch...");
|
|
|
|
if (dmflags & DF_NO_MONSTERS)
|
|
|
|
StartScreen->AppendStatusLine("No Monsters...");
|
|
|
|
if (dmflags & DF_MONSTERS_RESPAWN)
|
|
|
|
StartScreen->AppendStatusLine("Respawning...");
|
|
|
|
if (autostart)
|
|
|
|
{
|
|
|
|
FString temp;
|
|
|
|
temp.Format ("Warp to map %s, Skill %d ", startmap, gameskill + 1);
|
|
|
|
StartScreen->AppendStatusLine(temp);
|
|
|
|
}
|
2007-02-28 19:08:02 +00:00
|
|
|
|
|
|
|
// [RH] Now that all text strings are set up,
|
|
|
|
// insert them into the level and cluster data.
|
|
|
|
G_MakeEpisodes ();
|
|
|
|
|
|
|
|
// [RH] Parse through all loaded mapinfo lumps
|
|
|
|
Printf ("G_ParseMapInfo: Load map definitions.\n");
|
|
|
|
G_ParseMapInfo ();
|
|
|
|
|
|
|
|
// [RH] Parse any SNDINFO lumps
|
|
|
|
Printf ("S_InitData: Load sound definitions.\n");
|
|
|
|
S_InitData ();
|
|
|
|
|
2007-12-20 20:22:31 +00:00
|
|
|
// [CW] Parse any TEAMINFO lumps
|
|
|
|
Printf ("TEAMINFO_Init: Load team definitions.\n");
|
|
|
|
TEAMINFO_Init ();
|
|
|
|
|
2007-02-28 19:08:02 +00:00
|
|
|
FActorInfo::StaticInit ();
|
|
|
|
|
2007-04-28 09:06:32 +00:00
|
|
|
// Now that all actors have been defined we can finally set up the weapon slots
|
|
|
|
GameConfig->DoWeaponSetup (GameNames[gameinfo.gametype]);
|
|
|
|
|
2007-02-28 19:08:02 +00:00
|
|
|
// [GRB] Initialize player class list
|
|
|
|
SetupPlayerClasses ();
|
|
|
|
|
|
|
|
// [RH] Load custom key and weapon settings from WADs
|
|
|
|
D_LoadWadSettings ();
|
|
|
|
|
|
|
|
// [GRB] Check if someone used clearplayerclasses but not addplayerclass
|
|
|
|
if (PlayerClasses.Size () == 0)
|
|
|
|
{
|
|
|
|
I_FatalError ("No player classes defined");
|
|
|
|
}
|
|
|
|
|
|
|
|
FActorInfo::StaticGameSet ();
|
2007-03-06 01:33:18 +00:00
|
|
|
StartScreen->Progress ();
|
2007-02-28 19:08:02 +00:00
|
|
|
|
|
|
|
Printf ("R_Init: Init %s refresh subsystem.\n", GameNames[gameinfo.gametype]);
|
2007-03-06 01:33:18 +00:00
|
|
|
StartScreen->LoadingStatus ("Loading graphics", 0x3f);
|
2007-02-28 19:08:02 +00:00
|
|
|
R_Init ();
|
|
|
|
|
|
|
|
Printf ("DecalLibrary: Load decals.\n");
|
|
|
|
DecalLibrary.Clear ();
|
|
|
|
DecalLibrary.ReadAllDecals ();
|
|
|
|
|
|
|
|
// [RH] Try adding .deh and .bex files on the command line.
|
|
|
|
// If there are none, try adding any in the config file.
|
|
|
|
|
|
|
|
//if (gameinfo.gametype == GAME_Doom)
|
|
|
|
{
|
|
|
|
if (!ConsiderPatches ("-deh", ".deh") &&
|
|
|
|
!ConsiderPatches ("-bex", ".bex") &&
|
|
|
|
(gameinfo.gametype == GAME_Doom) &&
|
|
|
|
GameConfig->SetSection ("Doom.DefaultDehacked"))
|
|
|
|
{
|
|
|
|
const char *key;
|
|
|
|
const char *value;
|
|
|
|
|
|
|
|
while (GameConfig->NextInSection (key, value))
|
|
|
|
{
|
|
|
|
if (stricmp (key, "Path") == 0 && FileExists (value))
|
|
|
|
{
|
|
|
|
Printf ("Applying patch %s\n", value);
|
|
|
|
DoDehPatch (value, true);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
DoDehPatch (NULL, true); // See if there's a patch in a PWAD
|
|
|
|
FinishDehPatch (); // Create replacements for dehacked pickups
|
|
|
|
}
|
|
|
|
FActorInfo::StaticSetActorNums ();
|
|
|
|
|
|
|
|
|
|
|
|
// [RH] User-configurable startup strings. Because BOOM does.
|
|
|
|
static const char *startupString[5] = {
|
|
|
|
"STARTUP1", "STARTUP2", "STARTUP3", "STARTUP4", "STARTUP5"
|
|
|
|
};
|
|
|
|
for (p = 0; p < 5; ++p)
|
|
|
|
{
|
|
|
|
const char *str = GStrings[startupString[p]];
|
|
|
|
if (str != NULL && str[0] != '\0')
|
|
|
|
{
|
|
|
|
Printf ("%s\n", str);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//Added by MC:
|
|
|
|
bglobal.getspawned = Args.GatherFiles ("-bots", "", false);
|
|
|
|
if (bglobal.getspawned->NumArgs() == 0)
|
|
|
|
{
|
|
|
|
delete bglobal.getspawned;
|
|
|
|
bglobal.getspawned = NULL;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
bglobal.spawn_tries = 0;
|
|
|
|
bglobal.wanted_botnum = bglobal.getspawned->NumArgs();
|
|
|
|
}
|
|
|
|
|
Note: I have not tried compiling these recent changes under Linux. I wouldn't
be surprised if it doesn't work.
- Reorganized the network startup loops so now they are event driven. There is
a single function that gets called to drive it, and it uses callbacks to
perform the different stages of the synchronization. This lets me have a nice,
responsive abort button instead of the previous unannounced hit-escape-to-
abort behavior, and I think the rearranged code is slightly easier to
understand too.
- Increased the number of bytes for version info during D_ArbitrateNetStart(),
in preparation for the day when NETGAMEVERSION requires more than one byte.
- I noticed an issue with Vista RC1 and the new fatal error setup. Even after
releasing a DirectDraw or Direct3D interface, the DWM can still use the
last image drawn using them when it composites the window. It doesn't always
do it but it does often enough that it is a real problem. At this point, I
don't know if it's a problem with the release version of Vista or not.
After messing around, I discovered the problem was caused by ~Win32Video()
hiding the window and then having it immediately shown soon after. The DWM
kept an image of the window to do the transition effect with, and then when
it didn't get a chance to do the transition, it didn't properly forget about
its saved image and kept plastering it on top of everything else
underneath.
- Added a network synchronization panel to the window during netgame startup.
- Fixed: PClass::CreateDerivedClass() must initialize StateList to NULL.
Otherwise, classic DECORATE definitions generate a big, fat crash.
- Resurrected the R_Init progress bar, now as a standard Windows control.
- Removed the sound failure dialog. The FMOD setup already defaulted to no
sound if initialization failed, so this only applies when snd_output is set
to "alternate" which now also falls back to no sound. In addition, it wasn't
working right, and I didn't feel like fixing it for the probably 0% of users
it affected.
- Fixed: The edit control used for logging output added text in reverse order
on Win9x.
- Went back to the roots and made graphics initialization one of the last
things to happen during setup. Now the startup text is visible again. More
importantly, the main window is no longer created invisible, which seems
to cause trouble with it not always appearing in the taskbar. The fatal
error dialog is now also embedded in the main window instead of being a
separate modal dialog, so you can play with the log window to see any
problems that might be reported there.
Rather than completely restoring the original startup order, I tried to
keep things as close to the way they were with early graphics startup. In
particular, V_Init() now creates a dummy screen so that things that need
screen dimensions can get them. It gets replaced by the real screen later
in I_InitGraphics(). Will need to check this under Linux to make sure it
didn't cause any problems there.
- Removed the following stubs that just called functions in Video:
- I_StartModeIterator()
- I_NextMode()
- I_DisplayType()
I_FullscreenChanged() was also removed, and a new fullscreen parameter
was added to IVideo::StartModeIterator(), since that's all it controlled.
- Renamed I_InitHardware() back to I_InitGraphics(), since that's all it's
initialized post-1.22.
SVN r416 (trunk)
2006-12-19 04:09:10 +00:00
|
|
|
Printf ("M_Init: Init miscellaneous info.\n");
|
2006-02-24 04:48:15 +00:00
|
|
|
M_Init ();
|
|
|
|
|
Note: I have not tried compiling these recent changes under Linux. I wouldn't
be surprised if it doesn't work.
- Reorganized the network startup loops so now they are event driven. There is
a single function that gets called to drive it, and it uses callbacks to
perform the different stages of the synchronization. This lets me have a nice,
responsive abort button instead of the previous unannounced hit-escape-to-
abort behavior, and I think the rearranged code is slightly easier to
understand too.
- Increased the number of bytes for version info during D_ArbitrateNetStart(),
in preparation for the day when NETGAMEVERSION requires more than one byte.
- I noticed an issue with Vista RC1 and the new fatal error setup. Even after
releasing a DirectDraw or Direct3D interface, the DWM can still use the
last image drawn using them when it composites the window. It doesn't always
do it but it does often enough that it is a real problem. At this point, I
don't know if it's a problem with the release version of Vista or not.
After messing around, I discovered the problem was caused by ~Win32Video()
hiding the window and then having it immediately shown soon after. The DWM
kept an image of the window to do the transition effect with, and then when
it didn't get a chance to do the transition, it didn't properly forget about
its saved image and kept plastering it on top of everything else
underneath.
- Added a network synchronization panel to the window during netgame startup.
- Fixed: PClass::CreateDerivedClass() must initialize StateList to NULL.
Otherwise, classic DECORATE definitions generate a big, fat crash.
- Resurrected the R_Init progress bar, now as a standard Windows control.
- Removed the sound failure dialog. The FMOD setup already defaulted to no
sound if initialization failed, so this only applies when snd_output is set
to "alternate" which now also falls back to no sound. In addition, it wasn't
working right, and I didn't feel like fixing it for the probably 0% of users
it affected.
- Fixed: The edit control used for logging output added text in reverse order
on Win9x.
- Went back to the roots and made graphics initialization one of the last
things to happen during setup. Now the startup text is visible again. More
importantly, the main window is no longer created invisible, which seems
to cause trouble with it not always appearing in the taskbar. The fatal
error dialog is now also embedded in the main window instead of being a
separate modal dialog, so you can play with the log window to see any
problems that might be reported there.
Rather than completely restoring the original startup order, I tried to
keep things as close to the way they were with early graphics startup. In
particular, V_Init() now creates a dummy screen so that things that need
screen dimensions can get them. It gets replaced by the real screen later
in I_InitGraphics(). Will need to check this under Linux to make sure it
didn't cause any problems there.
- Removed the following stubs that just called functions in Video:
- I_StartModeIterator()
- I_NextMode()
- I_DisplayType()
I_FullscreenChanged() was also removed, and a new fullscreen parameter
was added to IVideo::StartModeIterator(), since that's all it controlled.
- Renamed I_InitHardware() back to I_InitGraphics(), since that's all it's
initialized post-1.22.
SVN r416 (trunk)
2006-12-19 04:09:10 +00:00
|
|
|
Printf ("P_Init: Init Playloop state.\n");
|
2007-03-06 01:33:18 +00:00
|
|
|
StartScreen->LoadingStatus ("Init game engine", 0x3f);
|
2006-02-24 04:48:15 +00:00
|
|
|
P_Init ();
|
|
|
|
|
Note: I have not tried compiling these recent changes under Linux. I wouldn't
be surprised if it doesn't work.
- Reorganized the network startup loops so now they are event driven. There is
a single function that gets called to drive it, and it uses callbacks to
perform the different stages of the synchronization. This lets me have a nice,
responsive abort button instead of the previous unannounced hit-escape-to-
abort behavior, and I think the rearranged code is slightly easier to
understand too.
- Increased the number of bytes for version info during D_ArbitrateNetStart(),
in preparation for the day when NETGAMEVERSION requires more than one byte.
- I noticed an issue with Vista RC1 and the new fatal error setup. Even after
releasing a DirectDraw or Direct3D interface, the DWM can still use the
last image drawn using them when it composites the window. It doesn't always
do it but it does often enough that it is a real problem. At this point, I
don't know if it's a problem with the release version of Vista or not.
After messing around, I discovered the problem was caused by ~Win32Video()
hiding the window and then having it immediately shown soon after. The DWM
kept an image of the window to do the transition effect with, and then when
it didn't get a chance to do the transition, it didn't properly forget about
its saved image and kept plastering it on top of everything else
underneath.
- Added a network synchronization panel to the window during netgame startup.
- Fixed: PClass::CreateDerivedClass() must initialize StateList to NULL.
Otherwise, classic DECORATE definitions generate a big, fat crash.
- Resurrected the R_Init progress bar, now as a standard Windows control.
- Removed the sound failure dialog. The FMOD setup already defaulted to no
sound if initialization failed, so this only applies when snd_output is set
to "alternate" which now also falls back to no sound. In addition, it wasn't
working right, and I didn't feel like fixing it for the probably 0% of users
it affected.
- Fixed: The edit control used for logging output added text in reverse order
on Win9x.
- Went back to the roots and made graphics initialization one of the last
things to happen during setup. Now the startup text is visible again. More
importantly, the main window is no longer created invisible, which seems
to cause trouble with it not always appearing in the taskbar. The fatal
error dialog is now also embedded in the main window instead of being a
separate modal dialog, so you can play with the log window to see any
problems that might be reported there.
Rather than completely restoring the original startup order, I tried to
keep things as close to the way they were with early graphics startup. In
particular, V_Init() now creates a dummy screen so that things that need
screen dimensions can get them. It gets replaced by the real screen later
in I_InitGraphics(). Will need to check this under Linux to make sure it
didn't cause any problems there.
- Removed the following stubs that just called functions in Video:
- I_StartModeIterator()
- I_NextMode()
- I_DisplayType()
I_FullscreenChanged() was also removed, and a new fullscreen parameter
was added to IVideo::StartModeIterator(), since that's all it controlled.
- Renamed I_InitHardware() back to I_InitGraphics(), since that's all it's
initialized post-1.22.
SVN r416 (trunk)
2006-12-19 04:09:10 +00:00
|
|
|
Printf ("D_CheckNetGame: Checking network game status.\n");
|
2007-03-06 01:33:18 +00:00
|
|
|
StartScreen->LoadingStatus ("Checking network game status.", 0x3f);
|
2006-02-24 04:48:15 +00:00
|
|
|
D_CheckNetGame ();
|
|
|
|
|
|
|
|
// [RH] Lock any cvars that should be locked now that we're
|
|
|
|
// about to begin the game.
|
|
|
|
FBaseCVar::EnableNoSet ();
|
|
|
|
|
|
|
|
// [RH] Run any saved commands from the command line or autoexec.cfg now.
|
|
|
|
gamestate = GS_FULLCONSOLE;
|
|
|
|
Net_NewMakeTic ();
|
|
|
|
DObject::BeginFrame ();
|
|
|
|
DThinker::RunThinkers ();
|
|
|
|
DObject::EndFrame ();
|
|
|
|
gamestate = GS_STARTUP;
|
|
|
|
|
|
|
|
// start the apropriate game based on parms
|
|
|
|
v = Args.CheckValue ("-record");
|
|
|
|
|
|
|
|
if (v)
|
|
|
|
{
|
|
|
|
G_RecordDemo (v);
|
|
|
|
autostart = true;
|
|
|
|
}
|
|
|
|
|
2007-03-06 01:33:18 +00:00
|
|
|
delete StartScreen;
|
|
|
|
StartScreen = NULL;
|
Note: I have not tried compiling these recent changes under Linux. I wouldn't
be surprised if it doesn't work.
- Reorganized the network startup loops so now they are event driven. There is
a single function that gets called to drive it, and it uses callbacks to
perform the different stages of the synchronization. This lets me have a nice,
responsive abort button instead of the previous unannounced hit-escape-to-
abort behavior, and I think the rearranged code is slightly easier to
understand too.
- Increased the number of bytes for version info during D_ArbitrateNetStart(),
in preparation for the day when NETGAMEVERSION requires more than one byte.
- I noticed an issue with Vista RC1 and the new fatal error setup. Even after
releasing a DirectDraw or Direct3D interface, the DWM can still use the
last image drawn using them when it composites the window. It doesn't always
do it but it does often enough that it is a real problem. At this point, I
don't know if it's a problem with the release version of Vista or not.
After messing around, I discovered the problem was caused by ~Win32Video()
hiding the window and then having it immediately shown soon after. The DWM
kept an image of the window to do the transition effect with, and then when
it didn't get a chance to do the transition, it didn't properly forget about
its saved image and kept plastering it on top of everything else
underneath.
- Added a network synchronization panel to the window during netgame startup.
- Fixed: PClass::CreateDerivedClass() must initialize StateList to NULL.
Otherwise, classic DECORATE definitions generate a big, fat crash.
- Resurrected the R_Init progress bar, now as a standard Windows control.
- Removed the sound failure dialog. The FMOD setup already defaulted to no
sound if initialization failed, so this only applies when snd_output is set
to "alternate" which now also falls back to no sound. In addition, it wasn't
working right, and I didn't feel like fixing it for the probably 0% of users
it affected.
- Fixed: The edit control used for logging output added text in reverse order
on Win9x.
- Went back to the roots and made graphics initialization one of the last
things to happen during setup. Now the startup text is visible again. More
importantly, the main window is no longer created invisible, which seems
to cause trouble with it not always appearing in the taskbar. The fatal
error dialog is now also embedded in the main window instead of being a
separate modal dialog, so you can play with the log window to see any
problems that might be reported there.
Rather than completely restoring the original startup order, I tried to
keep things as close to the way they were with early graphics startup. In
particular, V_Init() now creates a dummy screen so that things that need
screen dimensions can get them. It gets replaced by the real screen later
in I_InitGraphics(). Will need to check this under Linux to make sure it
didn't cause any problems there.
- Removed the following stubs that just called functions in Video:
- I_StartModeIterator()
- I_NextMode()
- I_DisplayType()
I_FullscreenChanged() was also removed, and a new fullscreen parameter
was added to IVideo::StartModeIterator(), since that's all it controlled.
- Renamed I_InitHardware() back to I_InitGraphics(), since that's all it's
initialized post-1.22.
SVN r416 (trunk)
2006-12-19 04:09:10 +00:00
|
|
|
V_Init2();
|
|
|
|
|
2006-02-24 04:48:15 +00:00
|
|
|
files = Args.GatherFiles ("-playdemo", ".lmp", false);
|
|
|
|
if (files->NumArgs() > 0)
|
|
|
|
{
|
|
|
|
singledemo = true; // quit after one demo
|
|
|
|
G_DeferedPlayDemo (files->GetArg (0));
|
|
|
|
delete files;
|
|
|
|
D_DoomLoop (); // never returns
|
|
|
|
}
|
|
|
|
delete files;
|
|
|
|
|
|
|
|
v = Args.CheckValue ("-timedemo");
|
|
|
|
if (v)
|
|
|
|
{
|
|
|
|
G_TimeDemo (v);
|
|
|
|
D_DoomLoop (); // never returns
|
|
|
|
}
|
|
|
|
|
|
|
|
v = Args.CheckValue ("-loadgame");
|
|
|
|
if (v)
|
|
|
|
{
|
2007-12-06 22:38:45 +00:00
|
|
|
file = v;
|
2006-02-24 04:48:15 +00:00
|
|
|
FixPathSeperator (file);
|
|
|
|
DefaultExtension (file, ".zds");
|
|
|
|
G_LoadGame (file);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (gameaction != ga_loadgame)
|
|
|
|
{
|
|
|
|
if (autostart || netgame)
|
|
|
|
{
|
2007-02-15 00:01:21 +00:00
|
|
|
// Do not do any screenwipes when autostarting a game.
|
|
|
|
NoWipe = 35;
|
2006-02-24 04:48:15 +00:00
|
|
|
CheckWarpTransMap (startmap, true);
|
2006-04-16 19:09:36 +00:00
|
|
|
if (demorecording)
|
|
|
|
G_BeginRecording (startmap);
|
2006-02-24 04:48:15 +00:00
|
|
|
G_InitNew (startmap, false);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
D_StartTitle (); // start up intro loop
|
|
|
|
}
|
|
|
|
}
|
2006-04-16 19:09:36 +00:00
|
|
|
else if (demorecording)
|
|
|
|
{
|
|
|
|
G_BeginRecording (NULL);
|
|
|
|
}
|
2006-02-24 04:48:15 +00:00
|
|
|
|
|
|
|
atterm (D_QuitNetGame); // killough
|
|
|
|
|
|
|
|
D_DoomLoop (); // never returns
|
|
|
|
}
|
|
|
|
|
2007-03-10 01:53:52 +00:00
|
|
|
//==========================================================================
|
|
|
|
//
|
|
|
|
// FStartupScreen Constructor
|
|
|
|
//
|
|
|
|
//==========================================================================
|
|
|
|
|
|
|
|
FStartupScreen::FStartupScreen(int max_progress)
|
|
|
|
{
|
|
|
|
MaxPos = max_progress;
|
|
|
|
CurPos = 0;
|
|
|
|
NotchPos = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
//==========================================================================
|
|
|
|
//
|
|
|
|
// FStartupScreen Destructor
|
|
|
|
//
|
|
|
|
//==========================================================================
|
|
|
|
|
|
|
|
FStartupScreen::~FStartupScreen()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
//==========================================================================
|
|
|
|
//
|
|
|
|
// FStartupScreen :: LoadingStatus
|
|
|
|
//
|
|
|
|
// Used by Heretic for the Loading Status "window."
|
|
|
|
//
|
|
|
|
//==========================================================================
|
|
|
|
|
|
|
|
void FStartupScreen::LoadingStatus(const char *message, int colors)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
//==========================================================================
|
|
|
|
//
|
|
|
|
// FStartupScreen :: AppendStatusLine
|
|
|
|
//
|
|
|
|
// Used by Heretic for the "status line" at the bottom of the screen.
|
|
|
|
//
|
|
|
|
//==========================================================================
|
|
|
|
|
|
|
|
void FStartupScreen::AppendStatusLine(const char *status)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2006-02-24 04:48:15 +00:00
|
|
|
//==========================================================================
|
|
|
|
//
|
|
|
|
// STAT fps
|
|
|
|
//
|
|
|
|
// Displays statistics about rendering times
|
|
|
|
//
|
|
|
|
//==========================================================================
|
|
|
|
|
2006-09-14 00:02:31 +00:00
|
|
|
ADD_STAT (fps)
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
2006-09-14 00:02:31 +00:00
|
|
|
FString out;
|
|
|
|
out.Format("frame=%04.1f ms walls=%04.1f ms planes=%04.1f ms masked=%04.1f ms",
|
2006-02-24 04:48:15 +00:00
|
|
|
(double)FrameCycles * SecondsPerCycle * 1000,
|
|
|
|
(double)WallCycles * SecondsPerCycle * 1000,
|
|
|
|
(double)PlaneCycles * SecondsPerCycle * 1000,
|
|
|
|
(double)MaskedCycles * SecondsPerCycle * 1000
|
|
|
|
);
|
2006-09-14 00:02:31 +00:00
|
|
|
return out;
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
//==========================================================================
|
|
|
|
//
|
|
|
|
// STAT wallcycles
|
|
|
|
//
|
|
|
|
// Displays the minimum number of cycles spent drawing walls
|
|
|
|
//
|
|
|
|
//==========================================================================
|
|
|
|
|
|
|
|
static cycle_t bestwallcycles = INT_MAX;
|
|
|
|
|
2006-09-14 00:02:31 +00:00
|
|
|
ADD_STAT (wallcycles)
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
2006-09-14 00:02:31 +00:00
|
|
|
FString out;
|
2006-02-24 04:48:15 +00:00
|
|
|
if (WallCycles && WallCycles < bestwallcycles)
|
|
|
|
bestwallcycles = WallCycles;
|
2006-09-14 00:02:31 +00:00
|
|
|
out.Format ("%llu", bestwallcycles);
|
|
|
|
return out;
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
//==========================================================================
|
|
|
|
//
|
|
|
|
// CCMD clearwallcycles
|
|
|
|
//
|
|
|
|
// Resets the count of minimum wall drawing cycles
|
|
|
|
//
|
|
|
|
//==========================================================================
|
|
|
|
|
|
|
|
CCMD (clearwallcycles)
|
|
|
|
{
|
|
|
|
bestwallcycles = INT_MAX;
|
|
|
|
}
|
|
|
|
|
|
|
|
#if 1
|
|
|
|
// To use these, also uncomment the clock/unclock in wallscan
|
|
|
|
static cycle_t bestscancycles = INT_MAX;
|
|
|
|
|
2006-09-14 00:02:31 +00:00
|
|
|
ADD_STAT (scancycles)
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
2006-09-14 00:02:31 +00:00
|
|
|
FString out;
|
2006-02-24 04:48:15 +00:00
|
|
|
if (WallScanCycles && WallScanCycles < bestscancycles)
|
|
|
|
bestscancycles = WallScanCycles;
|
2006-09-14 00:02:31 +00:00
|
|
|
out.Format ("%llu", bestscancycles);
|
|
|
|
return out;
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
CCMD (clearscancycles)
|
|
|
|
{
|
|
|
|
bestscancycles = INT_MAX;
|
|
|
|
}
|
|
|
|
#endif
|