From 8fcf93d65a7689f99573a1c94200e1f979287e3a Mon Sep 17 00:00:00 2001 From: Randy Heit Date: Fri, 12 May 2006 03:14:40 +0000 Subject: [PATCH] - Merged a lot of these static destructor-only structs into regular functions added to the exit chain with atterm so that they can be called in a deterministic order and not whatever order the linker decides to put them in. - Fixed: DCajunMaster did not free its getspawned. - Fixed: P_FreeLevelData() did not free ACS scripts. - Fixed: Level snapshots were not freed at exit. - Fixed: The save/load menu list was not freed at exit. - Fixed: FCompressedMemFile needs a destructor to free the m_ImplodedBuffer. - Fixed: G_DoLoadGame() did not free the engine string. - Fixed: M_ReadSaveStrings() did not free the engine string. - Fixed: Processing DEM_SAVEGAME did not free the pathname string. - Added a check for truncated flats to FFlatTexture::MakeTexture() because Heretic's F_SKY1 is only four bytes long. - Added a dump of the offending state to the "Cannot find state..." diagnostic. - Fixed: FCompressedFile did not initialize m_Mode in its default constructor. - Fixed: Heretic and Hexen status bars did not initialize ArtiRefresh. - Fixed: PNGHandle destructor should use delete[] to free TextChunks. SVN r111 (trunk) --- docs/rh-log.txt | 20 +++ src/b_game.cpp | 5 + src/c_console.cpp | 158 ++++++++++++++++---- src/c_console.h | 2 + src/c_cvars.cpp | 16 -- src/c_cvars.h | 2 +- src/c_dispatch.cpp | 23 --- src/d_main.cpp | 65 +-------- src/d_net.cpp | 6 +- src/d_net.h | 2 +- src/dobject.cpp | 2 +- src/dobject.h | 2 +- src/dobjtype.cpp | 74 +++++----- src/dobjtype.h | 1 + src/farchive.cpp | 9 ++ src/farchive.h | 4 +- src/g_game.cpp | 9 +- src/g_heretic/heretic_sbar.cpp | 5 +- src/g_hexen/hexen_sbar.cpp | 1 + src/g_level.cpp | 48 +++--- src/g_level.h | 1 + src/g_shared/a_keys.cpp | 19 ++- src/g_shared/a_keys.h | 1 + src/info.cpp | 9 +- src/m_menu.cpp | 58 ++++++-- src/m_menu.h | 5 +- src/m_misc.cpp | 2 +- src/m_misc.h | 2 +- src/m_options.cpp | 33 +++-- src/m_png.cpp | 2 +- src/p_setup.cpp | 70 +++++---- src/p_setup.h | 1 + src/r_bsp.cpp | 12 -- src/r_data.cpp | 57 +++++--- src/r_data.h | 1 + src/r_main.cpp | 19 ++- src/r_plane.cpp | 43 +++--- src/r_plane.h | 1 + src/r_things.cpp | 77 +++++----- src/r_things.h | 2 + src/s_advsound.cpp | 36 ++--- src/s_environment.cpp | 39 ++--- src/s_sound.cpp | 50 ++++--- src/s_sound.h | 2 + src/sdl/hardware.cpp | 2 +- src/sdl/hardware.h | 2 +- src/sdl/i_main.cpp | 14 +- src/sdl/i_net.cpp | 4 +- src/sdl/i_system.cpp | 2 +- src/sdl/i_system.h | 4 +- src/sound/i_music.cpp | 2 +- src/sound/i_music.h | 2 +- src/sound/i_sound.cpp | 2 +- src/sound/i_sound.h | 2 +- src/v_font.cpp | 11 -- src/v_font.h | 2 + src/v_video.cpp | 15 +- src/v_video.h | 4 +- src/win32/hardware.cpp | 2 +- src/win32/hardware.h | 2 +- src/win32/i_cd.cpp | 2 +- src/win32/i_input.cpp | 2 +- src/win32/i_input.h | 2 +- src/win32/i_main.cpp | 17 ++- src/win32/i_net.cpp | 4 +- src/win32/i_system.cpp | 2 +- src/win32/i_system.h | 4 +- zdoom.vcproj | 258 +++++++++++++++++++++++++++++++++ 68 files changed, 870 insertions(+), 489 deletions(-) diff --git a/docs/rh-log.txt b/docs/rh-log.txt index c22d2d81b..454b4f739 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -1,3 +1,23 @@ +May 11, 2006 +- Merged a lot of these static destructor-only structs into regular + functions added to the exit chain with atterm so that they can be called + in a deterministic order and not whatever order the linker decides to put + them in. +- Fixed: DCajunMaster did not free its getspawned. +- Fixed: P_FreeLevelData() did not free ACS scripts. +- Fixed: Level snapshots were not freed at exit. +- Fixed: The save/load menu list was not freed at exit. +- Fixed: FCompressedMemFile needs a destructor to free the m_ImplodedBuffer. +- Fixed: G_DoLoadGame() did not free the engine string. +- Fixed: M_ReadSaveStrings() did not free the engine string. +- Fixed: Processing DEM_SAVEGAME did not free the pathname string. +- Added a check for truncated flats to FFlatTexture::MakeTexture() because + Heretic's F_SKY1 is only four bytes long. +- Added a dump of the offending state to the "Cannot find state..." diagnostic. +- Fixed: FCompressedFile did not initialize m_Mode in its default constructor. +- Fixed: Heretic and Hexen status bars did not initialize ArtiRefresh. +- Fixed: PNGHandle destructor should use delete[] to free TextChunks. + May 11, 2006 (Changes by Graf Zahl) - Converted the stealth monsters to DECORATE. - Added string replacement option to obituary strings. diff --git a/src/b_game.cpp b/src/b_game.cpp index ba89b66d7..1df7a4a2f 100644 --- a/src/b_game.cpp +++ b/src/b_game.cpp @@ -93,6 +93,11 @@ void G_DoReborn (int playernum, bool freshbot); DCajunMaster::~DCajunMaster() { ForgetBots(); + if (getspawned != NULL) + { + delete getspawned; + getspawned = NULL; + } } //This function is called every tick (from g_game.c), diff --git a/src/c_console.cpp b/src/c_console.cpp index fe9deaeea..5a13c79a7 100644 --- a/src/c_console.cpp +++ b/src/c_console.cpp @@ -87,6 +87,9 @@ extern int gametic; extern bool automapactive; // in AM_map.c extern BOOL advancedemo; +extern FBaseCVar *CVars; +extern FConsoleCommand *Commands[FConsoleCommand::HASH_SIZE]; + int ConCols, PhysRows; BOOL vidactive = false, gotconback = false; BOOL cursoron = false; @@ -103,6 +106,13 @@ static char *BufferRover = ConsoleBuffer; static void ClearConsole (); +struct GameAtExit +{ + GameAtExit *Next; + char Command[1]; +}; + +static GameAtExit *ExitCmdList; #define SCROLLUP 1 #define SCROLLDN 2 @@ -116,6 +126,11 @@ static const char *TickerLabel; static bool TickerVisible; static bool ConsoleDrawing; +// Buffer for AddToConsole() +static char *work = NULL; +static int worklen = 0; + + struct History { struct History *Older; @@ -133,22 +148,6 @@ static byte CmdLine[260]; static struct History *HistHead = NULL, *HistTail = NULL, *HistPos = NULL; static int HistSize; -static struct HistoryFree -{ - ~HistoryFree() - { - History *hist = HistTail; - - while (hist != NULL) - { - History *next = hist->Newer; - free (hist); - hist = next; - } - } -} HistoryFree_er; - - CVAR (Float, con_notifytime, 3.f, CVAR_ARCHIVE) CVAR (Bool, con_centernotify, false, CVAR_ARCHIVE) CUSTOM_CVAR (Int, con_scaletext, 0, CVAR_ARCHIVE) // Scale notify text at high resolutions? @@ -421,6 +420,113 @@ void C_InitConsole (int width, int height, BOOL ingame) } } +//========================================================================== +// +// CCMD atexit +// +//========================================================================== + +CCMD (atexit) +{ + if (argv.argc() == 1) + { + Printf ("Registered atexit commands:\n"); + GameAtExit *record = ExitCmdList; + while (record != NULL) + { + Printf ("%s\n", record->Command); + record = record->Next; + } + return; + } + for (int i = 1; i < argv.argc(); ++i) + { + GameAtExit *record = (GameAtExit *)M_Malloc ( + sizeof(GameAtExit)+strlen(argv[i])); + strcpy (record->Command, argv[i]); + record->Next = ExitCmdList; + ExitCmdList = record; + } +} + +//========================================================================== +// +// C_DeinitConsole +// +// Executes the contents of the atexit cvar, if any, at quit time. +// Then releases all of the console's memory. +// +//========================================================================== + +void C_DeinitConsole () +{ + GameAtExit *cmd = ExitCmdList; + + while (cmd != NULL) + { + GameAtExit *next = cmd->Next; + AddCommandString (cmd->Command); + free (cmd); + cmd = next; + } + + // Free command history + History *hist = HistTail; + + while (hist != NULL) + { + History *next = hist->Newer; + free (hist); + hist = next; + } + HistTail = HistHead = HistPos = NULL; + + // Free cvars allocated at runtime + FBaseCVar *var, *next, **nextp; + for (var = CVars, nextp = &CVars; var != NULL; var = next) + { + next = var->m_Next; + if (var->GetFlags() & CVAR_UNSETTABLE) + { + delete var; + *nextp = next; + } + else + { + nextp = &var->m_Next; + } + } + + // Free alias commands. (i.e. The "commands" that can be allocated + // at runtime.) + for (size_t i = 0; i < countof(Commands); ++i) + { + FConsoleCommand *cmd = Commands[i]; + + while (cmd != NULL) + { + FConsoleCommand *next = cmd->m_Next; + if (cmd->IsAlias()) + { + delete cmd; + } + cmd = next; + } + } + + // Make sure all tab commands are cleared before the memory for + // their names is deallocated. + C_ClearTabCommands (); + + // Free AddToConsole()'s work buffer + if (work != NULL) + { + free (work); + work = NULL; + worklen = 0; + } +} + static void ClearConsole () { RowAdjust = 0; @@ -544,21 +650,6 @@ static void AddLine (const char *text, bool more, int len) } } -static char *work = NULL; -static int worklen = 0; - -static struct FreeWork -{ - ~FreeWork() - { - if (work != NULL) - { - free (work); - work = NULL; - } - } -} FreeTheWork; - void AddToConsole (int printlevel, const char *text) { static enum @@ -1814,6 +1905,11 @@ void C_RemoveTabCommand (const char *name) } } +void C_ClearTabCommands () +{ + TabCommands.Clear(); +} + static int FindDiffPoint (FName name1, const char *str2) { const char *str1 = name1.GetChars(); diff --git a/src/c_console.h b/src/c_console.h index eab866c79..e6dc873ad 100644 --- a/src/c_console.h +++ b/src/c_console.h @@ -51,6 +51,7 @@ extern constate_e ConsoleState; // Initialize the console void C_InitConsole (int width, int height, BOOL ingame); +void C_DeinitConsole (); // Adjust the console for a new screen mode void C_NewModeAdjust (void); @@ -78,5 +79,6 @@ BOOL C_Responder (event_t *ev); void C_AddTabCommand (const char *name); void C_RemoveTabCommand (const char *name); +void C_ClearTabCommands(); // Removes all tab commands #endif diff --git a/src/c_cvars.cpp b/src/c_cvars.cpp index cb7d9c8ed..6fe593a5f 100644 --- a/src/c_cvars.cpp +++ b/src/c_cvars.cpp @@ -68,22 +68,6 @@ FBaseCVar *CVars = NULL; int cvar_defflags; -static struct RuntimeCVarDestroyer -{ - ~RuntimeCVarDestroyer() - { - FBaseCVar *var, *next; - for (var = CVars; var != NULL; var = next) - { - next = var->m_Next; - if (var->GetFlags() & CVAR_UNSETTABLE) - { - delete var; - } - } - } -} DestroyTheRuntimeCVars; - FBaseCVar::FBaseCVar (const FBaseCVar &var) { I_FatalError ("Use of cvar copy constructor"); diff --git a/src/c_cvars.h b/src/c_cvars.h index 554f9e0e7..e1034ff73 100644 --- a/src/c_cvars.h +++ b/src/c_cvars.h @@ -175,7 +175,7 @@ private: friend void FilterCompactCVars (TArray &cvars, DWORD filter); - friend struct RuntimeCVarDestroyer; + friend void C_DeinitConsole(); }; class FBoolCVar : public FBaseCVar diff --git a/src/c_dispatch.cpp b/src/c_dispatch.cpp index 55e3acb88..d542a8714 100644 --- a/src/c_dispatch.cpp +++ b/src/c_dispatch.cpp @@ -149,29 +149,6 @@ FActionMap ActionMaps[] = #define NUM_ACTIONS countof(ActionMaps) -static struct AliasKiller -{ - ~AliasKiller() - { - // Scan the hash table for all aliases and delete them. - // Regular commands will be destroyed automatically. - for (size_t i = 0; i < countof(Commands); ++i) - { - FConsoleCommand *cmd = Commands[i]; - - while (cmd != NULL) - { - FConsoleCommand *next = cmd->m_Next; - if (cmd->IsAlias()) - { - delete cmd; - } - cmd = next; - } - } - } -} KillTheAliases; - IMPLEMENT_CLASS (DWaitingCommand) diff --git a/src/d_main.cpp b/src/d_main.cpp index c526835c0..d0132ff21 100644 --- a/src/d_main.cpp +++ b/src/d_main.cpp @@ -91,12 +91,6 @@ // TYPES ------------------------------------------------------------------- -struct GameAtExit -{ - GameAtExit *Next; - char Command[1]; -}; - // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- extern void M_RestoreMode (); @@ -117,7 +111,6 @@ void D_AddWildFile (const char *pattern); void D_DoomLoop (); static const char *BaseFileSearch (const char *file, const char *ext, bool lookfirstinprogdir=false); -static void STACK_ARGS DoConsoleAtExit (); // EXTERNAL DATA DECLARATIONS ---------------------------------------------- @@ -221,7 +214,6 @@ static const char *IWADNames[] = "strife0.wad", NULL }; -static GameAtExit *ExitCmdList; // CODE -------------------------------------------------------------------- @@ -620,56 +612,6 @@ void D_Display (bool screenshot) FrameCycles = cycles; } -//========================================================================== -// -// DoConsoleAtExit -// -// Executes the contents of the atexit cvar, if any, at quit time. -// -//========================================================================== - -static void STACK_ARGS DoConsoleAtExit () -{ - GameAtExit *cmd = ExitCmdList; - - while (cmd != NULL) - { - GameAtExit *next = cmd->Next; - AddCommandString (cmd->Command); - free (cmd); - cmd = next; - } -} - -//========================================================================== -// -// CCMD atexit -// -//========================================================================== - -CCMD (atexit) -{ - if (argv.argc() == 1) - { - Printf ("Registered atexit commands:\n"); - GameAtExit *record = ExitCmdList; - while (record != NULL) - { - Printf ("%s\n", record->Command); - record = record->Next; - } - return; - } - for (int i = 1; i < argv.argc(); ++i) - { - GameAtExit *record = (GameAtExit *)M_Malloc ( - sizeof(GameAtExit)+strlen(argv[i])); - strcpy (record->Command, argv[i]); - record->Next = ExitCmdList; - ExitCmdList = record; - } -} - //========================================================================== // // D_ErrorCleanup () @@ -1905,12 +1847,9 @@ void D_DoomMain (void) file[PATH_MAX-1] = 0; -#if defined(_MSC_VER) || defined(__GNUC__) - PClass::StaticInit (); -#endif - atterm (DObject::StaticShutdown); - atterm (DoConsoleAtExit); + PClass::StaticInit (); + atterm (C_DeinitConsole); gamestate = GS_STARTUP; diff --git a/src/d_net.cpp b/src/d_net.cpp index 5a19953c4..a610691ea 100644 --- a/src/d_net.cpp +++ b/src/d_net.cpp @@ -1629,7 +1629,7 @@ void D_CheckNetGame (void) // Called before quitting to leave a net game // without hanging the other players // -void STACK_ARGS D_QuitNetGame (void) +void D_QuitNetGame (void) { int i, j, k; @@ -2184,7 +2184,9 @@ void Net_DoCommand (int type, byte **stream, int player) case DEM_SAVEGAME: if (gamestate == GS_LEVEL) { - savegamefile = ReadString (stream); + s = ReadString (stream); + savegamefile = s; + delete[] s; s = ReadString (stream); memset (savedescription, 0, sizeof(savedescription)); strncpy (savedescription, s, sizeof(savedescription)); diff --git a/src/d_net.h b/src/d_net.h index b3ed64402..c6b15b76c 100644 --- a/src/d_net.h +++ b/src/d_net.h @@ -108,7 +108,7 @@ void NetUpdate (void); // Broadcasts special packets to other players // to notify of game exit -void STACK_ARGS D_QuitNetGame (void); +void D_QuitNetGame (void); //? how many ticks to run? void TryRunTics (void); diff --git a/src/dobject.cpp b/src/dobject.cpp index 7e2715e0c..75351be01 100644 --- a/src/dobject.cpp +++ b/src/dobject.cpp @@ -595,7 +595,7 @@ void DObject::DestroyScan () } } -void STACK_ARGS DObject::StaticShutdown () +void DObject::StaticShutdown () { Inactive = true; } diff --git a/src/dobject.h b/src/dobject.h index f8c03a49f..00c458d6c 100644 --- a/src/dobject.h +++ b/src/dobject.h @@ -254,7 +254,7 @@ public: // use this method. static void PointerSubstitution (DObject *old, DObject *notOld); - static void STACK_ARGS StaticShutdown (); + static void StaticShutdown (); PClass *GetClass() const { diff --git a/src/dobjtype.cpp b/src/dobjtype.cpp index 60e29bc59..fa88a0c47 100644 --- a/src/dobjtype.cpp +++ b/src/dobjtype.cpp @@ -10,42 +10,51 @@ PClass *PClass::TypeHash[PClass::HASH_SIZE]; // A harmless non_NULL FlatPointer for classes without pointers. static const size_t TheEnd = ~0; -static struct TypeInfoDataFreeer +void PClass::StaticInit () { - ~TypeInfoDataFreeer() - { - TArray uniqueFPs(64); - unsigned int i, j; + atterm (StaticShutdown); - for (i = 0; i < PClass::m_Types.Size(); ++i) + TAutoSegIterator probe; + + while (++probe != NULL) + { + probe->RegisterClass (); + } +} + +void PClass::StaticShutdown () +{ + TArray uniqueFPs(64); + unsigned int i, j; + + for (i = 0; i < PClass::m_Types.Size(); ++i) + { + PClass *type = PClass::m_Types[i]; + PClass::m_Types[i] = NULL; + if (type->FlatPointers != &TheEnd && type->FlatPointers != type->Pointers) { - PClass *type = PClass::m_Types[i]; - PClass::m_Types[i] = NULL; - if (type->FlatPointers != &TheEnd && type->FlatPointers != type->Pointers) + // FlatPointers are shared by many classes, so we must check for + // duplicates and only delete those that are unique. + for (j = 0; j < uniqueFPs.Size(); ++j) { - // FlatPointers are shared by many classes, so we must check for - // duplicates and only delete those that are unique. - for (j = 0; j < uniqueFPs.Size(); ++j) + if (type->FlatPointers == uniqueFPs[j]) { - if (type->FlatPointers == uniqueFPs[j]) - { - break; - } - } - if (j == uniqueFPs.Size()) - { - uniqueFPs.Push(const_cast(type->FlatPointers)); + break; } } - // For runtime classes, this call will also delete the PClass. - PClass::StaticFreeData (type); - } - for (i = 0; i < uniqueFPs.Size(); ++i) - { - delete[] uniqueFPs[i]; + if (j == uniqueFPs.Size()) + { + uniqueFPs.Push(const_cast(type->FlatPointers)); + } } + // For runtime classes, this call will also delete the PClass. + PClass::StaticFreeData (type); } -} FreeTypeInfoData; + for (i = 0; i < uniqueFPs.Size(); ++i) + { + delete[] uniqueFPs[i]; + } +} void PClass::StaticFreeData (PClass *type) { @@ -70,17 +79,6 @@ void PClass::StaticFreeData (PClass *type) } } - -void PClass::StaticInit () -{ - TAutoSegIterator probe; - - while (++probe != NULL) - { - probe->RegisterClass (); - } -} - void ClassReg::RegisterClass () { assert (MyClass != NULL); diff --git a/src/dobjtype.h b/src/dobjtype.h index 02bbf4d7a..725b842f3 100644 --- a/src/dobjtype.h +++ b/src/dobjtype.h @@ -8,6 +8,7 @@ struct PClass { static void StaticInit (); + static void StaticShutdown (); static void StaticFreeData (PClass *type); // Per-class information ------------------------------------- diff --git a/src/farchive.cpp b/src/farchive.cpp index 484f39c61..0b4fce966 100644 --- a/src/farchive.cpp +++ b/src/farchive.cpp @@ -135,6 +135,7 @@ void FCompressedFile::BeEmpty () m_Buffer = NULL; m_File = NULL; m_NoCompress = false; + m_Mode = ENotOpen; } static const char LZOSig[4] = { 'F', 'L', 'Z', 'O' }; @@ -425,6 +426,14 @@ FCompressedMemFile::FCompressedMemFile (const char *name, EOpenMode mode) } */ +FCompressedMemFile::~FCompressedMemFile () +{ + if (m_ImplodedBuffer != NULL) + { + free (m_ImplodedBuffer); + } +} + bool FCompressedMemFile::Open (const char *name, EOpenMode mode) { if (mode == EWriting) diff --git a/src/farchive.h b/src/farchive.h index 9591ec00f..155e2f68d 100644 --- a/src/farchive.h +++ b/src/farchive.h @@ -46,7 +46,8 @@ public: enum EOpenMode { EReading, - EWriting + EWriting, + ENotOpen }; enum ESeekPos @@ -117,6 +118,7 @@ class FCompressedMemFile : public FCompressedFile public: FCompressedMemFile (); FCompressedMemFile (FILE *file); // Create for reading + ~FCompressedMemFile (); bool Open (const char *name, EOpenMode mode); // Works for reading only bool Open (void *memblock); // Open for reading only diff --git a/src/g_game.cpp b/src/g_game.cpp index e4feb1062..7e064ecfe 100644 --- a/src/g_game.cpp +++ b/src/g_game.cpp @@ -1623,7 +1623,7 @@ void G_DoLoadGame () // Check whether this savegame actually has been created by a compatible engine. // Since there are ZDoom derivates using the exact same savegame format but // with mutual incompatibilities this check simplifies things significantly. - char * engine = M_GetPNGText (png, "Engine"); + char *engine = M_GetPNGText (png, "Engine"); if (engine == NULL || 0 != strcmp (engine, GAMESIG)) { // Make a special case for the message printed for old savegames that don't @@ -1634,12 +1634,17 @@ void G_DoLoadGame () } else { - Printf ("Savegame is from another ZDoom-based engine\n"); + Printf ("Savegame is from another ZDoom-based engine: %s\n", engine); + delete[] engine; } delete png; fclose (stdfile); return; } + if (engine != NULL) + { + delete[] engine; + } if (!M_GetPNGText (png, "ZDoom Save Version", sigcheck, 16) || 0 != strncmp (sigcheck, SAVESIG, 9) || // ZDOOMSAVE is the first 9 chars diff --git a/src/g_heretic/heretic_sbar.cpp b/src/g_heretic/heretic_sbar.cpp index 71fc52f44..ce9b212a8 100644 --- a/src/g_heretic/heretic_sbar.cpp +++ b/src/g_heretic/heretic_sbar.cpp @@ -211,6 +211,7 @@ public: oldlife = -1; oldkeys = -1; oldhealth = -1; + ArtiRefresh = 0; } DrawMainBar (); } @@ -408,10 +409,10 @@ private: // Ammo GetCurrentAmmo (ammo1, ammo2, ammocount1, ammocount2); - if (ammo1==ammo2) + if (ammo1 == ammo2) { // Don't show the same ammo twice. - ammo2=NULL; + ammo2 = NULL; } if (oldammo1 != ammo1 || oldammo2 != ammo2 || oldammocount1 != ammocount1 || oldammocount2 != ammocount2) diff --git a/src/g_hexen/hexen_sbar.cpp b/src/g_hexen/hexen_sbar.cpp index 715fbb560..944be31fd 100644 --- a/src/g_hexen/hexen_sbar.cpp +++ b/src/g_hexen/hexen_sbar.cpp @@ -278,6 +278,7 @@ public: oldfrags = -9999; //can't use -1, 'cuz of negative frags oldlife = -1; oldkeys[0] = oldkeys[1] = oldkeys[2] = oldkeys[3] = oldkeys[4] = NULL; + ArtiRefresh = 0; //oldhealth = -1; } if (!automapactive) diff --git a/src/g_level.cpp b/src/g_level.cpp index ac5da5f55..2945cc36f 100644 --- a/src/g_level.cpp +++ b/src/g_level.cpp @@ -99,14 +99,6 @@ static void ClearEpisodes (); static void ClearLevelInfoStrings (level_info_t *linfo); static void ClearClusterInfoStrings (cluster_info_t *cinfo); -static struct EpisodeKiller -{ - ~EpisodeKiller() - { - ClearEpisodes(); - } -} KillTheEpisodes; - static FRandom pr_classchoice ("RandomPlayerClassChoice"); TArray EndSequences; @@ -141,23 +133,6 @@ level_locals_t level; // info about current level static TArray wadclusterinfos; TArray wadlevelinfos; -static struct LevelClusterInfoKiller -{ - ~LevelClusterInfoKiller() - { - unsigned int i; - - for (i = 0; i < wadlevelinfos.Size(); ++i) - { - ClearLevelInfoStrings (&wadlevelinfos[i]); - } - for (i = 0; i < wadclusterinfos.Size(); ++i) - { - ClearClusterInfoStrings (&wadclusterinfos[i]); - } - } -} KillTheLevelAndClusterInfos; - // MAPINFO is parsed slightly differently when the map name is just a number. static bool HexenHack; @@ -469,6 +444,8 @@ void G_ParseMapInfo () { int lump, lastlump = 0; + atterm (G_UnloadMapInfo); + // Parse the default MAPINFO for the current game. switch (gameinfo.gametype) { @@ -1181,6 +1158,27 @@ void G_SetForEndGame (char *nextmap) } } +void G_UnloadMapInfo () +{ + unsigned int i; + + G_ClearSnapshots (); + + for (i = 0; i < wadlevelinfos.Size(); ++i) + { + ClearLevelInfoStrings (&wadlevelinfos[i]); + } + wadlevelinfos.Clear(); + + for (i = 0; i < wadclusterinfos.Size(); ++i) + { + ClearClusterInfoStrings (&wadclusterinfos[i]); + } + wadclusterinfos.Clear(); + + ClearEpisodes(); +} + level_info_t *FindLevelByWarpTrans (int num) { for (unsigned i = wadlevelinfos.Size(); i-- != 0; ) diff --git a/src/g_level.h b/src/g_level.h index 6dd3a00ea..2142a16fe 100644 --- a/src/g_level.h +++ b/src/g_level.h @@ -318,6 +318,7 @@ level_info_t *CheckLevelRedirect (level_info_t *info); char *CalcMapName (int episode, int level); void G_ParseMapInfo (void); +void G_UnloadMapInfo (); void G_ClearSnapshots (void); void G_SnapshotLevel (void); diff --git a/src/g_shared/a_keys.cpp b/src/g_shared/a_keys.cpp index 4c6ed5971..36287f837 100644 --- a/src/g_shared/a_keys.cpp +++ b/src/g_shared/a_keys.cpp @@ -87,14 +87,6 @@ static bool ignorekey; // set to true when the current lock is not being used static void ClearLocks(); -static struct LockDeleter -{ - ~LockDeleter() - { - ClearLocks(); - } -} DeleteTheLocks; - static const char * keywords_lock[]={ "ANY", "MESSAGE", @@ -327,6 +319,7 @@ static void ClearLocks() //=========================================================================== // +// P_InitKeyMessages // //=========================================================================== @@ -359,6 +352,16 @@ void P_InitKeyMessages() keysdone=true; } +//=========================================================================== +// +// P_DeinitKeyMessages +// +//=========================================================================== + +void P_DeinitKeyMessages() +{ + ClearLocks(); +} //=========================================================================== // diff --git a/src/g_shared/a_keys.h b/src/g_shared/a_keys.h index 912d6e4c4..2004f6a1f 100644 --- a/src/g_shared/a_keys.h +++ b/src/g_shared/a_keys.h @@ -17,6 +17,7 @@ protected: bool P_CheckKeys (AActor *owner, int keynum, bool remote); void P_InitKeyMessages (); +void P_DeinitKeyMessages (); int P_GetMapColorForLock (int lock); int P_GetMapColorForKey (AInventory *key); diff --git a/src/info.cpp b/src/info.cpp index 90b30281f..3523e1eee 100644 --- a/src/info.cpp +++ b/src/info.cpp @@ -86,7 +86,14 @@ FArchive &operator<< (FArchive &arc, FState *&state) } else { - I_Error ("Cannot find owner for state %p\n", state); + I_Error ("Cannot find owner for state %p:\n" + "%s %c%c %3d [%p] -> %p", state, + sprites[state->sprite.index].name, + state->GetFrame() + 'A', + state->GetFullbright() ? '*' : ' ', + state->GetTics(), + state->GetAction(), + state->GetNextState()); } } else diff --git a/src/m_menu.cpp b/src/m_menu.cpp index 044cfcda4..7f9167f86 100644 --- a/src/m_menu.cpp +++ b/src/m_menu.cpp @@ -112,6 +112,8 @@ static void M_QuickLoad (); static void M_LoadSelect (const FSaveGameNode *file); static void M_SaveSelect (const FSaveGameNode *file); static void M_ReadSaveStrings (); +static void M_UnloadSaveStrings (); +static FSaveGameNode *M_RemoveSaveSlot (FSaveGameNode *file); static void M_ExtractSaveData (const FSaveGameNode *file); static void M_UnloadSaveData (); static void M_InsertSaveNode (FSaveGameNode *node); @@ -605,7 +607,7 @@ void M_GameFiles (int choice) // // Find savegames and read their titles // -void M_ReadSaveStrings () +static void M_ReadSaveStrings () { if (SaveGames.IsEmpty ()) { @@ -613,6 +615,8 @@ void M_ReadSaveStrings () findstate_t c_file; FString filter; + atterm (M_UnloadSaveStrings); + filter = G_BuildSaveName ("*.zds", -1); filefirst = I_FindFirst (filter.GetChars(), &c_file); if (filefirst != ((void *)(-1))) @@ -676,6 +680,10 @@ void M_ReadSaveStrings () } delete[] ver; } + if (engine != NULL) + { + delete[] engine; + } delete png; } else @@ -725,6 +733,36 @@ void M_ReadSaveStrings () } } +static void M_UnloadSaveStrings() +{ + M_UnloadSaveData(); + while (!SaveGames.IsEmpty()) + { + M_RemoveSaveSlot (static_cast(SaveGames.Head)); + } +} + +static FSaveGameNode *M_RemoveSaveSlot (FSaveGameNode *file) +{ + FSaveGameNode *next = static_cast(file->Succ); + + if (file == TopSaveGame) + { + TopSaveGame = next; + } + if (quickSaveSlot == file) + { + quickSaveSlot = NULL; + } + if (lastSaveSlot == file) + { + lastSaveSlot = NULL; + } + file->Remove (); + delete file; + return next; +} + void M_InsertSaveNode (FSaveGameNode *node) { FSaveGameNode *probe; @@ -2800,21 +2838,7 @@ static void M_DeleteSaveResponse (int choice) remove (SelSaveGame->Filename.GetChars()); M_UnloadSaveData (); - if (SelSaveGame == TopSaveGame) - { - TopSaveGame = next; - } - if (quickSaveSlot == SelSaveGame) - { - quickSaveSlot = NULL; - } - if (lastSaveSlot == SelSaveGame) - { - lastSaveSlot = NULL; - } - SelSaveGame->Remove (); - delete SelSaveGame; - SelSaveGame = next; + SelSaveGame = M_RemoveSaveSlot (SelSaveGame); M_ExtractSaveData (SelSaveGame); } } @@ -3107,6 +3131,8 @@ void M_Init (void) { int i; + atterm (M_Deinit); + if (gameinfo.gametype & (GAME_Doom|GAME_Strife)) { TopLevelMenu = currentMenu = &MainDef; diff --git a/src/m_menu.h b/src/m_menu.h index 55f66106e..23108bd3d 100644 --- a/src/m_menu.h +++ b/src/m_menu.h @@ -44,10 +44,11 @@ void M_Ticker (void); // draws the menus directly into the screen buffer. void M_Drawer (void); -// Called by D_DoomMain, -// loads the config file. +// Called by D_DoomMain, loads the config file. void M_Init (void); +void M_Deinit (); + // Called by intro code to force menu up upon a keypress, // does nothing if menu is already up. void M_StartControlPanel (bool makeSound); diff --git a/src/m_misc.cpp b/src/m_misc.cpp index 9d2f7bbeb..aa43169c8 100644 --- a/src/m_misc.cpp +++ b/src/m_misc.cpp @@ -337,7 +337,7 @@ FString GetUserFile (const char *file, bool nodir) // M_SaveDefaults // -void STACK_ARGS M_SaveDefaults () +void M_SaveDefaults () { GameConfig->ArchiveGlobalData (); if (GameNames[gameinfo.gametype] != NULL) diff --git a/src/m_misc.h b/src/m_misc.h index d369a6c38..64b02edd0 100644 --- a/src/m_misc.h +++ b/src/m_misc.h @@ -40,7 +40,7 @@ void M_ScreenShot (char *filename); void M_LoadDefaults (); -void STACK_ARGS M_SaveDefaults (); +void M_SaveDefaults (); void M_SaveCustomKeys (FConfigFile *config, char *section, char *subsection); FString GetUserFile (const char *path, bool nodir=false); diff --git a/src/m_options.cpp b/src/m_options.cpp index 5a8a31ccb..7f3b82370 100644 --- a/src/m_options.cpp +++ b/src/m_options.cpp @@ -812,22 +812,6 @@ EXTERN_CVAR (Bool, fullscreen) static value_t Depths[22]; -static struct DepthNameKiller -{ - ~DepthNameKiller() - { - for (int i = 0; i < countof(Depths); ++i) - { - if (Depths[i].name != NULL) - { - delete[] Depths[i].name; - Depths[i].name = NULL; - } - } - M_FreeModesList(); - } -} KillTheDepthValues; - EXTERN_CVAR (Bool, vid_tft) // Defined below CUSTOM_CVAR (Int, menu_screenratios, 0, CVAR_ARCHIVE) { @@ -3055,3 +3039,20 @@ CCMD (addmenukey) ControlsMenu.items = &CustomControlsItems[0]; ControlsMenu.numitems = (int)CustomControlsItems.Size(); } + +void M_Deinit () +{ + // Free bitdepth names for the modes menu. + for (int i = 0; i < countof(Depths); ++i) + { + if (Depths[i].name != NULL) + { + delete[] Depths[i].name; + Depths[i].name = NULL; + } + } + + // Free resolutions from the modes menu. + M_FreeModesList(); +} + diff --git a/src/m_png.cpp b/src/m_png.cpp index 8bf0d0d85..002673a20 100644 --- a/src/m_png.cpp +++ b/src/m_png.cpp @@ -81,7 +81,7 @@ PNGHandle::~PNGHandle () { for (unsigned int i = 0; i < TextChunks.Size(); ++i) { - delete TextChunks[i]; + delete[] TextChunks[i]; } if (bDeleteFilePtr) { diff --git a/src/p_setup.cpp b/src/p_setup.cpp index 53e5e68e1..ab2152145 100644 --- a/src/p_setup.cpp +++ b/src/p_setup.cpp @@ -74,6 +74,7 @@ CVAR (Bool, genglnodes, false, CVAR_SERVERINFO); CVAR (Bool, showloadtimes, false, 0); static void P_InitTagLists (); +static void P_Shutdown (); // // MAP related Lookup tables. @@ -2798,6 +2799,8 @@ void P_FreeLevelData () level.total_monsters = level.total_items = level.total_secrets = level.killed_monsters = level.found_items = level.found_secrets = wminfo.maxfrags = 0; + FBehavior::StaticUnloadModules (); + level.behavior = NULL; if (vertexes != NULL) { delete[] vertexes; @@ -2915,42 +2918,32 @@ void P_FreeLevelData () extern msecnode_t *headsecnode; -static struct AutoFreeLevelData +void P_FreeExtraLevelData() { - ~AutoFreeLevelData() + // Free all blocknodes and msecnodes. + // *NEVER* call this function without calling + // P_FreeLevelData() first, or they might not all be freed. { - P_FreeLevelData(); - - // Blocknodes and msecnodes should be freed now, when we - // can be sure they are all easily located in their - // free lists. + FBlockNode *node = FBlockNode::FreeBlocks; + while (node != NULL) { - FBlockNode *node = FBlockNode::FreeBlocks; - while (node != NULL) - { - FBlockNode *next = node->NextBlock; - delete node; - node = next; - } - } - { - msecnode_t *node = headsecnode; - - while (node != NULL) - { - msecnode_t *next = node->m_snext; - free (node); - node = next; - } - headsecnode = NULL; - } - if (StatusBar != NULL) - { - delete StatusBar; - StatusBar = NULL; + FBlockNode *next = node->NextBlock; + delete node; + node = next; } } -} LevelDataFree_er; + { + msecnode_t *node = headsecnode; + + while (node != NULL) + { + msecnode_t *next = node->m_snext; + free (node); + node = next; + } + headsecnode = NULL; + } +} // // P_SetupLevel @@ -3349,6 +3342,8 @@ void P_SetupLevel (char *lumpname, int position) // void P_Init () { + atterm (P_Shutdown); + P_InitEffects (); // [RH] P_InitPicAnims (); P_InitSwitchList (); @@ -3357,6 +3352,19 @@ void P_Init () R_InitSprites (); } +static void P_Shutdown () +{ + R_DeinitSprites (); + P_DeinitKeyMessages (); + P_FreeLevelData (); + P_FreeExtraLevelData (); + if (StatusBar != NULL) + { + delete StatusBar; + StatusBar = NULL; + } +} + #if 0 #include "c_dispatch.h" CCMD (lineloc) diff --git a/src/p_setup.h b/src/p_setup.h index 148bf19d4..83b3da1e2 100644 --- a/src/p_setup.h +++ b/src/p_setup.h @@ -33,6 +33,7 @@ void P_SetupLevel (char *mapname, int position); void P_FreeLevelData(); +void P_FreeExtraLevelData(); // Called by startup code. void P_Init (void); diff --git a/src/r_bsp.cpp b/src/r_bsp.cpp index 3193a563c..5a94b2696 100644 --- a/src/r_bsp.cpp +++ b/src/r_bsp.cpp @@ -83,18 +83,6 @@ drawseg_t *drawsegs; drawseg_t* firstdrawseg; drawseg_t* ds_p; -static struct DrawSegFree -{ - ~DrawSegFree() - { - if (drawsegs != NULL) - { - free (drawsegs); - drawsegs = NULL; - } - } -} FreeDrawSegs; - size_t FirstInterestingDrawseg; TArray InterestingDrawsegs; diff --git a/src/r_data.cpp b/src/r_data.cpp index d121d381d..004c6c4a8 100644 --- a/src/r_data.cpp +++ b/src/r_data.cpp @@ -1508,7 +1508,11 @@ void FFlatTexture::MakeTexture () { FWadLump lump = Wads.OpenLumpNum (SourceLump); Pixels = new BYTE[Width*Height]; - lump.Read (Pixels, Width*Height); + long numread = lump.Read (Pixels, Width*Height); + if (numread < Width*Height) + { + memset (Pixels + numread, 0xBB, Width*Height - numread); + } FlipSquareBlockRemap (Pixels, Width, Height, GPalette.Remap); } @@ -2842,23 +2846,6 @@ int firstfakecmap; byte *realcolormaps; int lastusedcolormap; -static struct ColorMapKiller -{ - ~ColorMapKiller() - { - if (fakecmaps != NULL) - { - delete[] fakecmaps; - fakecmaps = NULL; - } - if (realcolormaps != NULL) - { - delete[] realcolormaps; - realcolormaps = NULL; - } - } -} KillTheColormaps; - void R_SetDefaultColormap (const char *name) { if (strnicmp (fakecmaps[0].name, name, 8) != 0) @@ -2983,6 +2970,20 @@ void R_InitColormaps () } } +void R_DeinitColormaps () +{ + if (fakecmaps != NULL) + { + delete[] fakecmaps; + fakecmaps = NULL; + } + if (realcolormaps != NULL) + { + delete[] realcolormaps; + realcolormaps = NULL; + } +} + // [RH] Returns an index into realcolormaps. Multiply it by // 256*NUMCOLORMAPS to find the start of the colormap to use. // WATERMAP is an exception and returns a blending value instead. @@ -3026,7 +3027,25 @@ void R_InitData () C_InitConsole (SCREENWIDTH, SCREENHEIGHT, true); } +void R_DeinitData () +{ + R_DeinitColormaps (); + // Free openings + if (openings != NULL) + { + free (openings); + openings = NULL; + } + + // Free drawsegs + if (drawsegs != NULL) + { + free (drawsegs); + drawsegs = NULL; + } + +} // // R_PrecacheLevel @@ -3382,7 +3401,7 @@ static void R_InitPatches () } } -#if 0 +#ifdef _DEBUG // Prints the spans generated for a texture. Only needed for debugging. CCMD (printspans) { diff --git a/src/r_data.h b/src/r_data.h index 4cada3728..8a3b094f7 100644 --- a/src/r_data.h +++ b/src/r_data.h @@ -289,6 +289,7 @@ private: // I/O, setting up the stuff. void R_InitData (void); +void R_DeinitData (); void R_PrecacheLevel (void); diff --git a/src/r_main.cpp b/src/r_main.cpp index 64f265218..a72640ee5 100644 --- a/src/r_main.cpp +++ b/src/r_main.cpp @@ -77,6 +77,8 @@ bool RP_SetupFrame (bool backside); // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- +static void R_Shutdown(); + // EXTERNAL DATA DECLARATIONS ---------------------------------------------- extern bool DrawFSHUD; // [RH] Defined in d_main.cpp @@ -764,8 +766,10 @@ CUSTOM_CVAR (Int, r_columnmethod, 1, CVAR_ARCHIVE|CVAR_GLOBALCONFIG) // //========================================================================== -void R_Init (void) +void R_Init () { + atterm (R_Shutdown); + R_InitData (); R_InitPointToAngle (); R_InitTables (); @@ -790,6 +794,19 @@ void R_Init (void) framecount = 0; } +//========================================================================== +// +// R_Shutdown +// +//========================================================================== + +static void R_Shutdown () +{ + R_DeinitParticles(); + R_DeinitPlanes(); + R_DeinitData(); +} + //========================================================================== // // R_PointInSubsector diff --git a/src/r_plane.cpp b/src/r_plane.cpp index b74af0138..57cf520a7 100644 --- a/src/r_plane.cpp +++ b/src/r_plane.cpp @@ -72,20 +72,6 @@ static visplane_t *visplanes[MAXVISPLANES+1]; // killough static visplane_t *freetail; // killough static visplane_t **freehead = &freetail; // killough -static struct VisPlaneFree -{ - ~VisPlaneFree() - { - R_ClearPlanes(false); - for (visplane_t *pl = freetail; pl != NULL; ) - { - visplane_t *next = pl->next; - free (pl); - pl = next; - } - } -} VisPlaneFree_er; - visplane_t *floorplane; visplane_t *ceilingplane; @@ -113,18 +99,6 @@ size_t maxopenings; short *openings; ptrdiff_t lastopening; -static struct OpeningsFree -{ - ~OpeningsFree() - { - if (openings != NULL) - { - free (openings); - openings = NULL; - } - } -} FreeOpenings; - // // Clip values are the solid pixel bounding the range. // floorclip starts out SCREENHEIGHT and is just outside the range @@ -181,6 +155,23 @@ void R_InitPlanes () { } +//========================================================================== +// +// R_DeinitPlanes +// +//========================================================================== + +void R_DeinitPlanes () +{ + R_ClearPlanes(false); + for (visplane_t *pl = freetail; pl != NULL; ) + { + visplane_t *next = pl->next; + free (pl); + pl = next; + } +} + //========================================================================== // // R_MapPlane diff --git a/src/r_plane.h b/src/r_plane.h index 13653ada1..9b68a5d8f 100644 --- a/src/r_plane.h +++ b/src/r_plane.h @@ -80,6 +80,7 @@ extern short ceilingclip[MAXWIDTH]; extern fixed_t yslope[MAXHEIGHT]; void R_InitPlanes (); +void R_DeinitPlanes (); void R_ClearPlanes (bool fullclear); void R_DrawPlanes (); diff --git a/src/r_things.cpp b/src/r_things.cpp index 20c10adff..00ec1a24f 100644 --- a/src/r_things.cpp +++ b/src/r_things.cpp @@ -678,17 +678,9 @@ vissprite_t **vissprite_p; vissprite_t **lastvissprite; int newvissprite; -static struct VisSpriteDeleter -{ - ~VisSpriteDeleter() - { - for (int i = 0; i < MaxVisSprites; ++i) - { - delete vissprites[i]; - } - free (vissprites); - } -} DeleteTheVisSprites; +static vissprite_t **spritesorter; +static int spritesortersize = 0; +static int vsprcount; static void R_CreateSkinTranslation (const char *palname) { @@ -797,14 +789,33 @@ void R_InitSprites () qsort (&skins[1], numskins-1, sizeof(FPlayerSkin), skinsorter); } -static struct SkinDeleter +void R_DeinitSprites() { - ~SkinDeleter() + // Free skins + if (skins != NULL) { - if (skins!=NULL) delete[] skins; + delete[] skins; + skins = NULL; } -} DeleteTheSkins; + // Free vissprites + for (int i = 0; i < MaxVisSprites; ++i) + { + delete vissprites[i]; + } + free (vissprites); + vissprites = NULL; + vissprite_p = lastvissprite = NULL; + MaxVisSprites = 0; + + // Free vissprites sorter + if (spritesorter != NULL) + { + delete[] spritesorter; + spritesortersize = 0; + spritesorter = NULL; + } +} // // R_ClearSprites @@ -1562,23 +1573,6 @@ void R_DrawPlayerSprites (void) // more vissprites that need to be sorted, the better the performance // gain compared to the old function. // -static vissprite_t **spritesorter; -static int spritesortersize = 0; -static int vsprcount; - -static struct SpriteSorterFree -{ - ~SpriteSorterFree() - { - if (spritesorter != NULL) - { - delete[] spritesorter; - spritesortersize = 0; - spritesorter = NULL; - } - } -} SpriteSorterFree_er; - // Sort vissprites by depth, far to near static int STACK_ARGS sv_compare (const void *arg1, const void *arg2) { @@ -2006,14 +2000,6 @@ void R_DrawMasked (void) // [RH] Particle functions // -static void STACK_ARGS FreeParticles() -{ - if (Particles != NULL) - { - delete[] Particles; - } -} - void R_InitParticles () { char *i; @@ -2027,7 +2013,16 @@ void R_InitParticles () Particles = new particle_t[NumParticles]; R_ClearParticles (); - atterm (FreeParticles); + atterm (R_DeinitParticles); +} + +void R_DeinitParticles() +{ + if (Particles != NULL) + { + delete[] Particles; + Particles = NULL; + } } void R_ClearParticles () diff --git a/src/r_things.h b/src/r_things.h index 203dab280..791d0d1de 100644 --- a/src/r_things.h +++ b/src/r_things.h @@ -59,6 +59,7 @@ inline particle_t *NewParticle (void) } void R_InitParticles (); +void R_DeinitParticles (); void R_ClearParticles (); void R_DrawParticle (vissprite_t *); void R_ProjectParticle (particle_t *, const sector_t *sector, int shade, int fakeside); @@ -97,6 +98,7 @@ void R_AddSprites (sector_t *sec, int lightlevel, int fakeside); void R_AddPSprites (); void R_DrawSprites (); void R_InitSprites (); +void R_DeinitSprites (); void R_ClearSprites (); void R_DrawMasked (); diff --git a/src/s_advsound.cpp b/src/s_advsound.cpp index a3cc7a47a..904035dc7 100644 --- a/src/s_advsound.cpp +++ b/src/s_advsound.cpp @@ -49,6 +49,7 @@ #include "r_data.h" #include "m_random.h" #include "d_netinf.h" +#include "i_system.h" // MACROS ------------------------------------------------------------------ @@ -210,19 +211,6 @@ static const char *SICommandStrings[] = static TArray S_rnd; static FMusicVolume *MusicVolumes; -static struct MusicVolumeDeleter -{ - ~MusicVolumeDeleter() - { - while(MusicVolumes!=NULL) - { - FMusicVolume * next = MusicVolumes->Next; - free(MusicVolumes); - MusicVolumes=next; - } - } -} DeleteTheMusicVolumes; - static int NumPlayerReserves; static bool DoneReserving; static bool PlayerClassesIsSorted; @@ -568,26 +556,29 @@ static void S_ClearSoundData() S_sfx.Clear(); - for(i=0;i<256;i++) + for(i = 0; i < countof(Ambients); i++) { - if (Ambients[i]) delete Ambients[i]; - Ambients[i]=NULL; + if (Ambients[i] != NULL) + { + delete Ambients[i]; + Ambients[i] = NULL; + } } while (MusicVolumes != NULL) { - FMusicVolume * me = MusicVolumes; + FMusicVolume *me = MusicVolumes; MusicVolumes = me->Next; delete me; } S_rnd.Clear(); - DoneReserving=false; - NumPlayerReserves=0; - PlayerClassesIsSorted=false; + DoneReserving = false; + NumPlayerReserves = 0; + PlayerClassesIsSorted = false; PlayerClasses.Clear(); PlayerSounds.Clear(); - DefPlayerClass=0; - *DefPlayerClassName=0; + DefPlayerClass = 0; + *DefPlayerClassName = 0; } //========================================================================== @@ -602,6 +593,7 @@ void S_ParseSndInfo () { int lump; + atterm (S_ClearSoundData); S_ClearSoundData(); // remove old sound data first! CurrentPitchMask = 0; diff --git a/src/s_environment.cpp b/src/s_environment.cpp index 79631abeb..fe96e15d7 100644 --- a/src/s_environment.cpp +++ b/src/s_environment.cpp @@ -6,6 +6,7 @@ #include "cmdlib.h" #include "templates.h" #include "w_wad.h" +#include "i_system.h" struct FEAXField { @@ -382,25 +383,6 @@ ReverbContainer *DefaultEnvironments[26] = ReverbContainer *Environments = &Off; -static struct ReverbContainerDeleter -{ - ~ReverbContainerDeleter() - { - ReverbContainer *probe = Environments; - - while (probe != NULL) - { - ReverbContainer *next = probe->Next; - if (!probe->Builtin) - { - delete[] const_cast(probe->Name); - delete probe; - } - probe = next; - } - } -} DeleteTheReverbContainers; - ReverbContainer *S_FindEnvironment (const char *name) { ReverbContainer *probe = Environments; @@ -587,6 +569,8 @@ void S_ParseSndEax () { int lump, lastlump = 0; + atterm (S_UnloadSndEax); + while ((lump = Wads.FindLump ("SNDEAX", &lastlump)) != -1) { SC_OpenLumpNum (lump, "SNDEAX"); @@ -594,3 +578,20 @@ void S_ParseSndEax () SC_Close (); } } + +void S_UnloadSndEax () +{ + ReverbContainer *probe = Environments; + + while (probe != NULL) + { + ReverbContainer *next = probe->Next; + if (!probe->Builtin) + { + delete[] const_cast(probe->Name); + delete probe; + } + probe = next; + } + Environments = &Off; +} diff --git a/src/s_sound.cpp b/src/s_sound.cpp index bfb418aa5..cff5119ba 100644 --- a/src/s_sound.cpp +++ b/src/s_sound.cpp @@ -167,29 +167,6 @@ CVAR (Bool, snd_flipstereo, false, CVAR_ARCHIVE|CVAR_GLOBALCONFIG) // CODE -------------------------------------------------------------------- -static struct FreeSoundData -{ - ~FreeSoundData() - { - if (Channel != NULL) - { - delete[] Channel; - Channel = NULL; - numChannels = 0; - } - if (SoundCurve != NULL) - { - delete[] SoundCurve; - SoundCurve = NULL; - } - if (PlayList != NULL) - { - delete PlayList; - PlayList = NULL; - } - } -} SoundDataFree_er; - //========================================================================== // // P_AproxDistance2 @@ -306,6 +283,7 @@ void S_Init () int curvelump; Printf ("S_Init\n"); + atterm (S_Shutdown); // remove old data (S_Init can be called multiple times!) LastLocalSndInfo = LastLocalSndSeq = ""; @@ -365,6 +343,32 @@ void S_Init () // S_sfx[i].usefulness = -1; } +//========================================================================== +// +// S_Shutdown +// +//========================================================================== + +void S_Shutdown () +{ + if (Channel != NULL) + { + delete[] Channel; + Channel = NULL; + numChannels = 0; + } + if (SoundCurve != NULL) + { + delete[] SoundCurve; + SoundCurve = NULL; + } + if (PlayList != NULL) + { + delete PlayList; + PlayList = NULL; + } +} + //========================================================================== // // S_Start diff --git a/src/s_sound.h b/src/s_sound.h index 98425a6d3..5388821e9 100644 --- a/src/s_sound.h +++ b/src/s_sound.h @@ -76,6 +76,7 @@ extern TArray S_sfx; // allocates channel buffer, sets S_sfx lookup. // void S_Init (); +void S_Shutdown (); // Per level startup code. // Kills playing sounds at start of level and starts new music. @@ -181,6 +182,7 @@ void S_UpdateSounds (void *listener); // [RH] S_sfx "maintenance" routines void S_ParseSndInfo (); void S_ParseSndEax (); +void S_UnloadSndEax (); void S_HashSounds (); int S_FindSound (const char *logicalname); diff --git a/src/sdl/hardware.cpp b/src/sdl/hardware.cpp index c357f4cd1..e7eed35ea 100644 --- a/src/sdl/hardware.cpp +++ b/src/sdl/hardware.cpp @@ -49,7 +49,7 @@ EXTERN_CVAR (Float, vid_winscale) IVideo *Video; -void STACK_ARGS I_ShutdownHardware () +void I_ShutdownHardware () { if (screen) delete screen, screen = NULL; diff --git a/src/sdl/hardware.h b/src/sdl/hardware.h index 55fe53c34..f07e41618 100644 --- a/src/sdl/hardware.h +++ b/src/sdl/hardware.h @@ -88,6 +88,6 @@ class IJoystick : public IInputDevice }; void I_InitHardware (); -void STACK_ARGS I_ShutdownHardware (); +void I_ShutdownHardware (); #endif // __HARDWARE_H__ diff --git a/src/sdl/i_main.cpp b/src/sdl/i_main.cpp index a767c5df0..4f416cc53 100644 --- a/src/sdl/i_main.cpp +++ b/src/sdl/i_main.cpp @@ -39,13 +39,21 @@ DArgs Args; -#define MAX_TERMS 16 -void (STACK_ARGS *TermFuncs[MAX_TERMS]) (); +#define MAX_TERMS 32 +void (*TermFuncs[MAX_TERMS]) (); const char *TermNames[MAX_TERMS]; static int NumTerms; -void addterm (void (STACK_ARGS *func) (), const char *name) +void addterm (void (*func) (), const char *name) { + // Make sure this function wasn't already registered. + for (int i = 0; i < NumTerms; ++i) + { + if (TermFuncs[i] == func) + { + return; + } + } if (NumTerms == MAX_TERMS) { func (); diff --git a/src/sdl/i_net.cpp b/src/sdl/i_net.cpp index c710ff62d..32dbcb067 100644 --- a/src/sdl/i_net.cpp +++ b/src/sdl/i_net.cpp @@ -323,7 +323,7 @@ void BuildAddress (sockaddr_in *address, char *name) *portpart = ':'; } -void STACK_ARGS CloseNetwork (void) +void CloseNetwork (void) { if (mysocket != INVALID_SOCKET) { @@ -386,7 +386,7 @@ void WaitForPlayers (int i) doomcom.numplayers = doomcom.numnodes; } -void STACK_ARGS SendAbort (void) +void SendAbort (void) { BYTE dis[2] = { PRE_FAKE, PRE_DISCONNECT }; diff --git a/src/sdl/i_system.cpp b/src/sdl/i_system.cpp index 8dffe2f3d..7818d72c9 100644 --- a/src/sdl/i_system.cpp +++ b/src/sdl/i_system.cpp @@ -277,7 +277,7 @@ void CalculateCPUSpeed () // static int has_exited; -void STACK_ARGS I_Quit (void) +void I_Quit (void) { has_exited = 1; /* Prevent infinitely recursive exits -- killough */ diff --git a/src/sdl/i_system.h b/src/sdl/i_system.h index 04aee83ac..c16de2cad 100644 --- a/src/sdl/i_system.h +++ b/src/sdl/i_system.h @@ -166,7 +166,7 @@ ticcmd_t *I_BaseTiccmd (void); // Called by M_Responder when quit is selected. // Clean exit, displays sell blurb. -void STACK_ARGS I_Quit (void); +void I_Quit (void); void I_Tactile (int on, int off, int total); @@ -174,7 +174,7 @@ void I_Tactile (int on, int off, int total); void STACK_ARGS I_Error (const char *error, ...) GCCPRINTF(1,2); void STACK_ARGS I_FatalError (const char *error, ...) GCCPRINTF(1,2); -void addterm (void (STACK_ARGS *func)(void), const char *name); +void addterm (void (*func)(void), const char *name); #define atterm(t) addterm (t, #t) void popterm (); diff --git a/src/sound/i_music.cpp b/src/sound/i_music.cpp index 66472fcc2..de4c35391 100644 --- a/src/sound/i_music.cpp +++ b/src/sound/i_music.cpp @@ -137,7 +137,7 @@ void I_InitMusic (void) } -void STACK_ARGS I_ShutdownMusic(void) +void I_ShutdownMusic(void) { if (MusicDown) return; diff --git a/src/sound/i_music.h b/src/sound/i_music.h index ae666503c..04dbb64bb 100644 --- a/src/sound/i_music.h +++ b/src/sound/i_music.h @@ -42,7 +42,7 @@ // MUSIC I/O // void I_InitMusic (); -void STACK_ARGS I_ShutdownMusic (); +void I_ShutdownMusic (); void I_BuildMIDIMenuList (struct value_s **values, float *numValues); // Volume. diff --git a/src/sound/i_sound.cpp b/src/sound/i_sound.cpp index d31f00843..87ba195bc 100644 --- a/src/sound/i_sound.cpp +++ b/src/sound/i_sound.cpp @@ -237,7 +237,7 @@ void I_InitSound () } -void STACK_ARGS I_ShutdownSound (void) +void I_ShutdownSound (void) { if (GSnd != NULL) { diff --git a/src/sound/i_sound.h b/src/sound/i_sound.h index 66fade015..e49f91bfd 100644 --- a/src/sound/i_sound.h +++ b/src/sound/i_sound.h @@ -124,6 +124,6 @@ public: extern SoundRenderer *GSnd; void I_InitSound (); -void STACK_ARGS I_ShutdownSound (); +void I_ShutdownSound (); #endif diff --git a/src/v_font.cpp b/src/v_font.cpp index 406ff0408..e862e0925 100644 --- a/src/v_font.cpp +++ b/src/v_font.cpp @@ -110,17 +110,6 @@ static const byte myislower[256] = FFont *FFont::FirstFont = NULL; -static struct FontsDeleter -{ - ~FontsDeleter() - { - while (FFont::FirstFont != NULL) - { - delete FFont::FirstFont; - } - } -} DeleteAllTheFonts; - #if defined(_MSC_VER) && _MSC_VER < 1310 template<> FArchive &operator<< (FArchive &arc, FFont* &font) #else diff --git a/src/v_font.h b/src/v_font.h index 9d7ff78b5..04fe0c314 100644 --- a/src/v_font.h +++ b/src/v_font.h @@ -110,6 +110,8 @@ protected: static FFont *FirstFont; friend struct FontsDeleter; + friend void V_Shutdown(); + #if defined(_MSC_VER) && _MSC_VER < 1310 template<> friend FArchive &operator<< (FArchive &arc, FFont* &font); #else diff --git a/src/v_video.cpp b/src/v_video.cpp index 653e7b64b..2951c5a95 100644 --- a/src/v_video.cpp +++ b/src/v_video.cpp @@ -853,6 +853,8 @@ void V_Init (void) char *i; int width, height, bits; + atterm (V_Shutdown); + // [RH] Initialize palette management InitPalette (); @@ -919,8 +921,6 @@ void V_Init (void) bits = vid_defbits; } - atterm (FreeCanvasChain); - I_ClosestResolution (&width, &height, bits); if (!V_SetResolution (width, height, bits)) @@ -935,7 +935,16 @@ void V_Init (void) BuildTransTable (GPalette.BaseColors); } -void STACK_ARGS FreeCanvasChain () +void V_Shutdown() +{ + FreeCanvasChain(); + while (FFont::FirstFont != NULL) + { + delete FFont::FirstFont; + } +} + +void FreeCanvasChain () { if (screen != NULL) { diff --git a/src/v_video.h b/src/v_video.h index b16aa7c1e..d4e3264e5 100644 --- a/src/v_video.h +++ b/src/v_video.h @@ -189,7 +189,7 @@ private: DCanvas *Next; static DCanvas *CanvasChain; - friend void STACK_ARGS FreeCanvasChain (); + friend void FreeCanvasChain (); }; // A canvas in system memory. @@ -286,6 +286,8 @@ extern "C" DWORD *Col2RGB8_LessPrecision[65]; // Allocates buffer screens, call before R_Init. void V_Init (); +void V_Shutdown (); + void V_MarkRect (int x, int y, int width, int height); // Returns the closest color to the one desired. String diff --git a/src/win32/hardware.cpp b/src/win32/hardware.cpp index 553a7ad3b..c523c08b6 100644 --- a/src/win32/hardware.cpp +++ b/src/win32/hardware.cpp @@ -55,7 +55,7 @@ IVideo *Video; //static IMouse *Mouse; //static IJoystick *Joystick; -void STACK_ARGS I_ShutdownHardware () +void I_ShutdownHardware () { if (screen) delete screen, screen = NULL; diff --git a/src/win32/hardware.h b/src/win32/hardware.h index 46181d277..8026ead45 100644 --- a/src/win32/hardware.h +++ b/src/win32/hardware.h @@ -88,6 +88,6 @@ class IJoystick : public IInputDevice }; void I_InitHardware (); -void STACK_ARGS I_ShutdownHardware (); +void I_ShutdownHardware (); #endif // __HARDWARE_H__ diff --git a/src/win32/i_cd.cpp b/src/win32/i_cd.cpp index 7aef4958c..c852f55bc 100644 --- a/src/win32/i_cd.cpp +++ b/src/win32/i_cd.cpp @@ -434,7 +434,7 @@ DWORD FCDThread::Dispatch (DWORD method, DWORD parm1, DWORD parm2, DWORD parm3) // //========================================================================== -static void STACK_ARGS KillThread () +static void KillThread () { if (CDThread != NULL) { diff --git a/src/win32/i_input.cpp b/src/win32/i_input.cpp index f562dcc38..ae22569a3 100644 --- a/src/win32/i_input.cpp +++ b/src/win32/i_input.cpp @@ -1479,7 +1479,7 @@ BOOL I_InitInput (void *hwnd) // Free all input resources -void STACK_ARGS I_ShutdownInput () +void I_ShutdownInput () { if (g_pKey) { diff --git a/src/win32/i_input.h b/src/win32/i_input.h index 5d758c6cb..b87d79a1b 100644 --- a/src/win32/i_input.h +++ b/src/win32/i_input.h @@ -37,7 +37,7 @@ #include "doomtype.h" BOOL I_InitInput (void *hwnd); -void STACK_ARGS I_ShutdownInput (); +void I_ShutdownInput (); void I_PutInClipboard (const char *str); char *I_GetFromClipboard (); diff --git a/src/win32/i_main.cpp b/src/win32/i_main.cpp index e9e1acbea..5d9ae4472 100644 --- a/src/win32/i_main.cpp +++ b/src/win32/i_main.cpp @@ -99,14 +99,25 @@ BOOL (*pIsDebuggerPresent)(VOID); extern UINT TimerPeriod; extern HCURSOR TheArrowCursor, TheInvisibleCursor; -#define MAX_TERMS 16 -void (STACK_ARGS *TermFuncs[MAX_TERMS])(void); +#define MAX_TERMS 32 +void (*TermFuncs[MAX_TERMS])(void); static int NumTerms; void atterm (void (STACK_ARGS *func)(void)) { + // Make sure this function wasn't already registered. + for (int i = 0; i < NumTerms; ++i) + { + if (TermFuncs[i] == func) + { + return; + } + } if (NumTerms == MAX_TERMS) + { + func (); I_FatalError ("Too many exit functions registered.\nIncrease MAX_TERMS in i_main.cpp"); + } TermFuncs[NumTerms++] = func; } @@ -132,7 +143,7 @@ static int STACK_ARGS NewFailure (size_t size) } #endif -static void STACK_ARGS UnCOM (void) +static void UnCOM (void) { CoUninitialize (); } diff --git a/src/win32/i_net.cpp b/src/win32/i_net.cpp index c710ff62d..32dbcb067 100644 --- a/src/win32/i_net.cpp +++ b/src/win32/i_net.cpp @@ -323,7 +323,7 @@ void BuildAddress (sockaddr_in *address, char *name) *portpart = ':'; } -void STACK_ARGS CloseNetwork (void) +void CloseNetwork (void) { if (mysocket != INVALID_SOCKET) { @@ -386,7 +386,7 @@ void WaitForPlayers (int i) doomcom.numplayers = doomcom.numnodes; } -void STACK_ARGS SendAbort (void) +void SendAbort (void) { BYTE dis[2] = { PRE_FAKE, PRE_DISCONNECT }; diff --git a/src/win32/i_system.cpp b/src/win32/i_system.cpp index 71b490969..5dc54032b 100644 --- a/src/win32/i_system.cpp +++ b/src/win32/i_system.cpp @@ -484,7 +484,7 @@ void CalculateCPUSpeed () // static int has_exited; -void STACK_ARGS I_Quit (void) +void I_Quit (void) { has_exited = 1; /* Prevent infinitely recursive exits -- killough */ diff --git a/src/win32/i_system.h b/src/win32/i_system.h index 84f57ed22..f595792fe 100644 --- a/src/win32/i_system.h +++ b/src/win32/i_system.h @@ -172,7 +172,7 @@ ticcmd_t *I_BaseTiccmd (void); // Called by M_Responder when quit is selected. // Clean exit, displays sell blurb. -void STACK_ARGS I_Quit (void); +void I_Quit (void); void I_Tactile (int on, int off, int total); @@ -180,7 +180,7 @@ void I_Tactile (int on, int off, int total); void STACK_ARGS I_Error (const char *error, ...) GCCPRINTF(1,2); void STACK_ARGS I_FatalError (const char *error, ...) GCCPRINTF(1,2); -void atterm (void (STACK_ARGS *func)(void)); +void atterm (void (*func)(void)); void popterm (); // Repaint the pre-game console diff --git a/zdoom.vcproj b/zdoom.vcproj index 550cc5639..f6a95439e 100644 --- a/zdoom.vcproj +++ b/zdoom.vcproj @@ -4435,6 +4435,264 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +