- don't show the IWAD picker upon restart. This doesn't work with fullscreen mode. Instead just pick the first IWAD from the list until a better solution can be implemented.

- handle a 'restart' CCMD a bit more controlled. Instead of throwing an exception in the CCMD handler it now just flags D_DoomLoop to return.

If the exception is thrown within the CCMD this can easily happen deep inside the renderer when it calls NetUpdate. But since the software renderer with its use of global variables is not equipped to be yanked out of lile this it could leave broken data behind that caused glitches or even crashes on subsequently played maps.
This commit is contained in:
Christoph Oelckers 2016-03-08 13:07:21 +01:00
parent e11a0986ce
commit 1815b076ee

View file

@ -205,6 +205,7 @@ CUSTOM_CVAR (String, vid_cursor, "None", CVAR_ARCHIVE | CVAR_NOINITCALL)
}
}
bool wantToRestart;
bool DrawFSHUD; // [RH] Draw fullscreen HUD?
TArray<FString> allwads;
bool devparm; // started game with -devparm
@ -1012,6 +1013,11 @@ void D_DoomLoop ()
I_StartTic ();
D_Display ();
S_UpdateMusic(); // OpenAL needs this to keep the music running, thanks to a complete lack of a sane streaming implementation using callbacks. :(
if (wantToRestart)
{
wantToRestart = false;
return;
}
}
catch (CRecoverableError &error)
{
@ -2635,59 +2641,58 @@ void D_DoomMain (void)
setmodeneeded = false; // This may be set to true here, but isn't needed for a restart
}
try
D_DoomLoop (); // this only returns if a 'restart' CCMD is given.
//
// Clean up after a restart
//
// Music and sound should be stopped first
S_StopMusic(true);
S_StopAllChannels ();
M_ClearMenus(); // close menu if open
F_EndFinale(); // If an intermission is active, end it now
// 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
DestroyCVarsFlagged(CVAR_MOD); // Delete any cvar left by mods
GC::FullGC(); // clean up before taking down the object list.
// Delete the VM functions here. The garbage collector will not do this automatically because they are referenced from the global action function definitions.
FAutoSegIterator probe(ARegHead, ARegTail);
while (*++probe != NULL)
{
D_DoomLoop (); // never returns
AFuncDesc *afunc = (AFuncDesc *)*probe;
*(afunc->VMPointer) = NULL;
}
catch (CRestartException &)
ReleaseGlobalSymbols();
PClass::StaticShutdown();
GC::FullGC(); // perform one final garbage collection after shutdown
for (DObject *obj = GC::Root; obj; obj = obj->ObjNext)
{
// Music and sound should be stopped first
S_StopMusic(true);
S_StopAllChannels ();
M_ClearMenus(); // close menu if open
F_EndFinale(); // If an intermission is active, end it now
// 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
DestroyCVarsFlagged(CVAR_MOD); // Delete any cvar left by mods
GC::FullGC(); // clean up before taking down the object list.
// Delete the VM functions here. The garbage collector will not do this automatically because they are referenced from the global action function definitions.
FAutoSegIterator probe(ARegHead, ARegTail);
while (*++probe != NULL)
{
AFuncDesc *afunc = (AFuncDesc *)*probe;
*(afunc->VMPointer) = NULL;
}
ReleaseGlobalSymbols();
PClass::StaticShutdown();
GC::FullGC(); // perform one final garbage collection after shutdown
for (DObject *obj = GC::Root; obj; obj = obj->ObjNext)
{
obj->ClearClass(); // Delete the Class pointer because the data it points to has been deleted. This will automatically be reset if needed.
}
restart++;
PClass::bShutdown = false;
obj->ClearClass(); // Delete the Class pointer because the data it points to has been deleted. This will automatically be reset if needed.
}
restart++;
PClass::bShutdown = false;
}
while (1);
}
@ -2715,14 +2720,13 @@ CCMD(restart)
if (argv.argc() > 1)
{
for(int i=1;i<argv.argc(); i++)
for (int i = 1; i<argv.argc(); i++)
{
Args->AppendArg(argv[i]);
}
}
// initiate the restart
throw CRestartException();
wantToRestart = true;
}
//==========================================================================