mirror of
https://github.com/ZDoom/gzdoom.git
synced 2024-11-13 07:57:52 +00:00
- added a 'restart' CCMD that allows restarting the engine with different WADs being loaded without quitting first
SVN r3042 (trunk)
This commit is contained in:
parent
772d59dff4
commit
b42952b85c
17 changed files with 466 additions and 281 deletions
|
@ -600,6 +600,11 @@ void FBaseCVar::EnableCallbacks ()
|
|||
}
|
||||
}
|
||||
|
||||
void FBaseCVar::DisableCallbacks ()
|
||||
{
|
||||
m_UseCallback = false;
|
||||
}
|
||||
|
||||
//
|
||||
// Boolean cvar implementation
|
||||
//
|
||||
|
|
|
@ -117,6 +117,7 @@ public:
|
|||
|
||||
static void EnableNoSet (); // enable the honoring of CVAR_NOSET
|
||||
static void EnableCallbacks ();
|
||||
static void DisableCallbacks ();
|
||||
static void ResetColors (); // recalc color cvars' indices after screen change
|
||||
|
||||
static void ListVars (const char *filter, bool plain);
|
||||
|
|
115
src/d_main.cpp
115
src/d_main.cpp
|
@ -223,6 +223,8 @@ FTexture *Page;
|
|||
FTexture *Advisory;
|
||||
bool nospriterename;
|
||||
FStartupInfo DoomStartupInfo;
|
||||
FString lastIWAD;
|
||||
int restart = 0;
|
||||
|
||||
cycle_t FrameCycles;
|
||||
|
||||
|
@ -890,7 +892,7 @@ void D_Display ()
|
|||
//
|
||||
// D_ErrorCleanup ()
|
||||
//
|
||||
// Cleanup after a recoverable error.
|
||||
// Cleanup after a recoverable error or a restart
|
||||
//==========================================================================
|
||||
|
||||
void D_ErrorCleanup ()
|
||||
|
@ -2025,18 +2027,35 @@ void D_DoomMain (void)
|
|||
}
|
||||
FString basewad = wad;
|
||||
|
||||
|
||||
// reinit from here
|
||||
|
||||
do
|
||||
{
|
||||
if (restart)
|
||||
{
|
||||
C_InitConsole(SCREENWIDTH, SCREENHEIGHT, false);
|
||||
}
|
||||
nospriterename = false;
|
||||
|
||||
// Load zdoom.pk3 alone so that we can get access to the internal gameinfos before
|
||||
// the IWAD is known.
|
||||
|
||||
GetCmdLineFiles(pwads);
|
||||
FString iwad = CheckGameInfo(pwads);
|
||||
|
||||
// The IWAD selection dialogue dpes not show in fullscreen so if the
|
||||
// restart is initiated without a defined IWAD assume for now that it's not going to change.
|
||||
if (iwad.Len() == 0) iwad = lastIWAD;
|
||||
|
||||
FIWadManager *iwad_man = new FIWadManager;
|
||||
const FIWADInfo *iwad_info = iwad_man->FindIWAD(allwads, iwad, basewad);
|
||||
gameinfo.gametype = iwad_info->gametype;
|
||||
gameinfo.flags = iwad_info->flags;
|
||||
gameinfo.ConfigName = iwad_info->Configname;
|
||||
lastIWAD = iwad;
|
||||
|
||||
FBaseCVar::DisableCallbacks();
|
||||
GameConfig->DoGameSetup (gameinfo.ConfigName);
|
||||
|
||||
AddAutoloadFiles(iwad_info->Autoname);
|
||||
|
@ -2074,11 +2093,14 @@ void D_DoomMain (void)
|
|||
|
||||
CT_Init ();
|
||||
|
||||
if (!restart)
|
||||
{
|
||||
Printf ("I_Init: Setting up machine state.\n");
|
||||
I_Init ();
|
||||
}
|
||||
|
||||
Printf ("V_Init: allocate screen.\n");
|
||||
V_Init ();
|
||||
V_Init (!!restart);
|
||||
|
||||
// Base systems have been inited; enable cvar callbacks
|
||||
FBaseCVar::EnableCallbacks ();
|
||||
|
@ -2087,7 +2109,8 @@ void D_DoomMain (void)
|
|||
S_Init ();
|
||||
|
||||
Printf ("ST_Init: Init startup screen.\n");
|
||||
StartScreen = FStartupScreen::CreateInstance (TexMan.GuesstimateNumTextures() + 5);
|
||||
if (!restart) StartScreen = FStartupScreen::CreateInstance (TexMan.GuesstimateNumTextures() + 5);
|
||||
else StartScreen = new FStartupScreen(0);
|
||||
|
||||
ParseCompatibility();
|
||||
|
||||
|
@ -2202,9 +2225,12 @@ void D_DoomMain (void)
|
|||
}
|
||||
}
|
||||
|
||||
if (!restart)
|
||||
{
|
||||
Printf ("D_CheckNetGame: Checking network game status.\n");
|
||||
StartScreen->LoadingStatus ("Checking network game status.", 0x3f);
|
||||
D_CheckNetGame ();
|
||||
}
|
||||
|
||||
// [RH] Lock any cvars that should be locked now that we're
|
||||
// about to begin the game.
|
||||
|
@ -2218,6 +2244,8 @@ void D_DoomMain (void)
|
|||
DThinker::RunThinkers ();
|
||||
gamestate = GS_STARTUP;
|
||||
|
||||
if (!restart)
|
||||
{
|
||||
// start the apropriate game based on parms
|
||||
v = Args->CheckValue ("-record");
|
||||
|
||||
|
@ -2286,9 +2314,82 @@ void D_DoomMain (void)
|
|||
}
|
||||
|
||||
atterm (D_QuitNetGame); // killough
|
||||
}
|
||||
else
|
||||
{
|
||||
// These calls from inside V_Init2 are still necessary
|
||||
C_NewModeAdjust();
|
||||
M_InitVideoModesMenu();
|
||||
D_StartTitle (); // start up intro loop
|
||||
setmodeneeded = false; // This may be set to true here, but isn't needed for a restart
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
D_DoomLoop (); // never returns
|
||||
}
|
||||
catch (CRestartException &ex)
|
||||
{
|
||||
// Music and sound should be stopped first
|
||||
S_StopMusic(true);
|
||||
S_StopAllChannels ();
|
||||
|
||||
// clean up game state
|
||||
ST_Clear();
|
||||
D_ErrorCleanup ();
|
||||
P_FreeLevelData();
|
||||
P_FreeExtraLevelData();
|
||||
|
||||
M_SaveDefaults(NULL); // save config before the restart
|
||||
|
||||
// delete all data that cannot be left until reinitialization
|
||||
V_ClearFonts(); // must clear global font pointers
|
||||
R_DeinitTranslationTables(); // some tables are initialized from outside the translation code.
|
||||
gameinfo.~gameinfo_t();
|
||||
new (&gameinfo) gameinfo_t; // Reset gameinfo
|
||||
S_Shutdown(); // free all channels and delete playlist
|
||||
C_ClearAliases(); // CCMDs won't be reinitialized so these need to be deleted here
|
||||
|
||||
GC::FullGC(); // perform one final garbage collection before deleting the class data
|
||||
PClass::ClearRuntimeData(); // clear all runtime generated class data
|
||||
restart++;
|
||||
}
|
||||
}
|
||||
while (1);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// restart the game
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
CCMD(restart)
|
||||
{
|
||||
// remove command line args that would get in the way during restart
|
||||
Args->RemoveArgs("-iwad");
|
||||
Args->RemoveArgs("-deh");
|
||||
Args->RemoveArgs("-bex");
|
||||
Args->RemoveArgs("-playdemo");
|
||||
Args->RemoveArgs("-file");
|
||||
Args->RemoveArgs("-altdeath");
|
||||
Args->RemoveArgs("-deathmatch");
|
||||
Args->RemoveArgs("-skill");
|
||||
Args->RemoveArgs("-savedir");
|
||||
Args->RemoveArgs("-xlat");
|
||||
Args->RemoveArgs("-oldsprites");
|
||||
|
||||
if (argv.argc() > 1)
|
||||
{
|
||||
for(int i=1;i<argv.argc(); i++)
|
||||
{
|
||||
Args->AppendArg(argv[i]);
|
||||
}
|
||||
}
|
||||
|
||||
// initiate the restart
|
||||
throw CRestartException();
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
|
@ -2337,6 +2438,14 @@ void FStartupScreen::AppendStatusLine(const char *status)
|
|||
{
|
||||
}
|
||||
|
||||
|
||||
void FStartupScreen::Progress(void) {}
|
||||
void FStartupScreen::NetInit(char const *,int) {}
|
||||
void FStartupScreen::NetProgress(int) {}
|
||||
void FStartupScreen::NetMessage(char const *,...) {}
|
||||
void FStartupScreen::NetDone(void) {}
|
||||
bool FStartupScreen::NetLoop(bool (*)(void *),void *) { return false; }
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// STAT fps
|
||||
|
|
|
@ -36,6 +36,12 @@ struct event_t;
|
|||
// calls all startup code, parses command line options.
|
||||
// If not overrided by user input, calls N_AdvanceDemo.
|
||||
//
|
||||
|
||||
struct CRestartException
|
||||
{
|
||||
char dummy;
|
||||
};
|
||||
|
||||
void D_DoomMain (void);
|
||||
|
||||
|
||||
|
|
|
@ -80,6 +80,24 @@ void PClass::StaticInit ()
|
|||
}
|
||||
}
|
||||
|
||||
void PClass::ClearRuntimeData ()
|
||||
{
|
||||
StaticShutdown();
|
||||
|
||||
m_RuntimeActors.Clear();
|
||||
m_Types.Clear();
|
||||
memset(TypeHash, 0, sizeof(TypeHash));
|
||||
bShutdown = false;
|
||||
|
||||
// Immediately reinitialize the internal classes
|
||||
FAutoSegIterator probe(CRegHead, CRegTail);
|
||||
|
||||
while (*++probe != NULL)
|
||||
{
|
||||
((ClassReg *)*probe)->RegisterClass ();
|
||||
}
|
||||
}
|
||||
|
||||
void PClass::StaticShutdown ()
|
||||
{
|
||||
TArray<size_t *> uniqueFPs(64);
|
||||
|
@ -105,6 +123,8 @@ void PClass::StaticShutdown ()
|
|||
uniqueFPs.Push(const_cast<size_t *>(type->FlatPointers));
|
||||
}
|
||||
}
|
||||
type->FlatPointers = NULL;
|
||||
|
||||
// For runtime classes, this call will also delete the PClass.
|
||||
PClass::StaticFreeData (type);
|
||||
}
|
||||
|
|
|
@ -125,6 +125,7 @@ struct PClass
|
|||
static void StaticInit ();
|
||||
static void StaticShutdown ();
|
||||
static void StaticFreeData (PClass *type);
|
||||
static void ClearRuntimeData();
|
||||
|
||||
// Per-class information -------------------------------------
|
||||
FName TypeName; // this class's name
|
||||
|
|
|
@ -2573,6 +2573,7 @@ bool G_CheckDemoStatus (void)
|
|||
|
||||
C_RestoreCVars (); // [RH] Restore cvars demo might have changed
|
||||
M_Free (demobuffer);
|
||||
demobuffer = NULL;
|
||||
|
||||
P_SetupWeapons_ntohton();
|
||||
demoplayback = false;
|
||||
|
|
|
@ -253,6 +253,7 @@ void DBaseStatusBar::Destroy ()
|
|||
msg->Destroy();
|
||||
msg = next;
|
||||
}
|
||||
Messages = NULL;
|
||||
Super::Destroy();
|
||||
}
|
||||
|
||||
|
|
|
@ -58,6 +58,7 @@ void DeinitIntermissions()
|
|||
delete pair->Value;
|
||||
pair->Value = NULL;
|
||||
}
|
||||
IntermissionDescriptors.Clear();
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
|
|
|
@ -230,6 +230,26 @@ FString DArgs::TakeValue(const char *check)
|
|||
return out;
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// DArgs :: RemoveArg
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
void DArgs::RemoveArgs(const char *check)
|
||||
{
|
||||
int i = CheckParm(check);
|
||||
|
||||
if (i > 0 && i < (int)Argv.Size() - 1)
|
||||
{
|
||||
do
|
||||
{
|
||||
RemoveArg(i);
|
||||
}
|
||||
while (Argv[i][0] != '+' && Argv[i][0] != '-' && i < (int)Argv.Size() - 1);
|
||||
}
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// DArgs :: GetArg
|
||||
|
|
|
@ -54,6 +54,7 @@ public:
|
|||
void AppendArg(FString arg);
|
||||
void AppendArgs(int argc, const FString *argv);
|
||||
void RemoveArg(int argindex);
|
||||
void RemoveArgs(const char *check);
|
||||
void SetArgs(int argc, char **argv);
|
||||
void CollectFiles(const char *param, const char *extension);
|
||||
DArgs *GatherFiles(const char *param) const;
|
||||
|
|
|
@ -85,6 +85,8 @@ static void DeinitMenus()
|
|||
pair->Value = NULL;
|
||||
}
|
||||
}
|
||||
MenuDescriptors.Clear();
|
||||
OptionValues.Clear();
|
||||
DMenu::CurrentMenu = NULL;
|
||||
DefaultListMenuSettings.mItems.Clear();
|
||||
ClearSaveGames();
|
||||
|
@ -1236,10 +1238,11 @@ void M_CreateMenus()
|
|||
// THe skill menu must be refeshed each time it starts up
|
||||
//
|
||||
//=============================================================================
|
||||
extern int restart;
|
||||
|
||||
void M_StartupSkillMenu(FGameStartup *gs)
|
||||
{
|
||||
static bool done = false;
|
||||
static int done = -1;
|
||||
bool success = false;
|
||||
FMenuDescriptor **desc = MenuDescriptors.CheckKey(NAME_Skillmenu);
|
||||
if (desc != NULL)
|
||||
|
@ -1265,9 +1268,9 @@ void M_StartupSkillMenu(FGameStartup *gs)
|
|||
}
|
||||
}
|
||||
|
||||
if (!done)
|
||||
if (done != restart)
|
||||
{
|
||||
done = true;
|
||||
done = restart;
|
||||
int defskill = DefaultSkill;
|
||||
if ((unsigned int)defskill >= AllSkills.Size())
|
||||
{
|
||||
|
|
|
@ -502,6 +502,24 @@ static void AssignHexenTranslations (void)
|
|||
}
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// S_ClearSndSeq
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void S_ClearSndSeq()
|
||||
{
|
||||
for (unsigned int i = 0; i < Sequences.Size(); i++)
|
||||
{
|
||||
if (Sequences[i])
|
||||
{
|
||||
M_Free(Sequences[i]);
|
||||
}
|
||||
}
|
||||
Sequences.Clear();
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// S_ParseSndSeq
|
||||
|
@ -523,14 +541,7 @@ void S_ParseSndSeq (int levellump)
|
|||
|
||||
// First free the old SNDSEQ data. This allows us to reload this for each level
|
||||
// and specify a level specific SNDSEQ lump!
|
||||
for (unsigned int i = 0; i < Sequences.Size(); i++)
|
||||
{
|
||||
if (Sequences[i])
|
||||
{
|
||||
M_Free(Sequences[i]);
|
||||
}
|
||||
}
|
||||
Sequences.Clear();
|
||||
S_ClearSndSeq();
|
||||
|
||||
// be gone, compiler warnings
|
||||
stopsound = 0;
|
||||
|
|
|
@ -42,15 +42,15 @@ public:
|
|||
FStartupScreen(int max_progress);
|
||||
virtual ~FStartupScreen();
|
||||
|
||||
virtual void Progress() = 0;
|
||||
virtual void Progress();
|
||||
virtual void LoadingStatus(const char *message, int colors); // Used by Heretic only
|
||||
virtual void AppendStatusLine(const char *status); // Used by Heretic only
|
||||
|
||||
virtual void NetInit(const char *message, int num_players) = 0;
|
||||
virtual void NetProgress(int count) = 0;
|
||||
virtual void NetMessage(const char *format, ...) = 0; // cover for printf
|
||||
virtual void NetDone() = 0;
|
||||
virtual bool NetLoop(bool (*timer_callback)(void *), void *userdata) = 0;
|
||||
virtual void NetInit(const char *message, int num_players);
|
||||
virtual void NetProgress(int count);
|
||||
virtual void NetMessage(const char *format, ...); // cover for printf
|
||||
virtual void NetDone();
|
||||
virtual bool NetLoop(bool (*timer_callback)(void *), void *userdata);
|
||||
protected:
|
||||
int MaxPos, CurPos, NotchPos;
|
||||
};
|
||||
|
|
|
@ -447,6 +447,7 @@ void InitPalette ()
|
|||
int lump;
|
||||
|
||||
atterm (FreeSpecialLights);
|
||||
FreeSpecialLights();
|
||||
|
||||
if ((lump = Wads.CheckNumForFullName ("palette.dat")) >= 0 && Wads.LumpLength (lump) >= 768)
|
||||
{
|
||||
|
@ -780,6 +781,7 @@ static void FreeSpecialLights()
|
|||
delete[] colormap->Maps;
|
||||
delete colormap;
|
||||
}
|
||||
NormalLight.Next = NULL;
|
||||
}
|
||||
|
||||
// Builds NUMCOLORMAPS colormaps lit with the specified color
|
||||
|
|
|
@ -1605,7 +1605,7 @@ CCMD (vid_setmode)
|
|||
// V_Init
|
||||
//
|
||||
|
||||
void V_Init (void)
|
||||
void V_Init (bool restart)
|
||||
{
|
||||
const char *i;
|
||||
int width, height, bits;
|
||||
|
@ -1615,6 +1615,8 @@ void V_Init (void)
|
|||
// [RH] Initialize palette management
|
||||
InitPalette ();
|
||||
|
||||
if (!restart)
|
||||
{
|
||||
width = height = bits = 0;
|
||||
|
||||
if ( (i = Args->CheckValue ("-width")) )
|
||||
|
@ -1647,8 +1649,9 @@ void V_Init (void)
|
|||
{
|
||||
bits = vid_defbits;
|
||||
}
|
||||
|
||||
screen = new DDummyFrameBuffer (width, height);
|
||||
}
|
||||
|
||||
|
||||
BuildTransTable (GPalette.BaseColors);
|
||||
}
|
||||
|
|
|
@ -473,7 +473,7 @@ extern "C" DWORD Col2RGB8_Inverse[65][256];
|
|||
// --111111111111111111111111111111 = 0x3FFFFFFF
|
||||
|
||||
// Allocates buffer screens, call before R_Init.
|
||||
void V_Init ();
|
||||
void V_Init (bool restart);
|
||||
|
||||
// Initializes graphics mode for the first time.
|
||||
void V_Init2 ();
|
||||
|
|
Loading…
Reference in a new issue