From 860b888460992d73767a17d969b5289c64ce8005 Mon Sep 17 00:00:00 2001 From: toaster Date: Sat, 31 May 2025 23:12:39 +0100 Subject: [PATCH] P_FreeLevelState A chunk of P_LoadLevel, extracted. Calling it in D_ClearState should clear up some of the straggling pointers that might cause Laz' reported issue. With any luck, it should also significantly reduce the amount of memory the menu uses. --- src/d_main.cpp | 3 +- src/p_setup.cpp | 77 ++++++++++++++++++++++++++----------------------- src/p_setup.h | 1 + 3 files changed, 44 insertions(+), 37 deletions(-) diff --git a/src/d_main.cpp b/src/d_main.cpp index d660cf3a7..e36e8f805 100644 --- a/src/d_main.cpp +++ b/src/d_main.cpp @@ -1245,7 +1245,8 @@ void D_ClearState(void) if (gamedata && gamedata->deferredsave) G_SaveGameData(); - K_UnsetDialogue(); + P_FreeLevelState(); + P_InvalidateThinkersWithoutInit(); G_SetGamestate(GS_NULL); wipegamestate = GS_NULL; diff --git a/src/p_setup.cpp b/src/p_setup.cpp index 8dd1b1e93..8d8b6e55a 100644 --- a/src/p_setup.cpp +++ b/src/p_setup.cpp @@ -8388,6 +8388,46 @@ void P_LoadLevelMusic(void) Music_ResetLevelVolume(); } +void P_FreeLevelState(void) +{ + if (numsectors) + { + F_EndTextPrompt(false, true); + K_UnsetDialogue(); + + ACS_InvalidateMapScope(); + LUA_InvalidateLevel(); + + Obj_ClearCheckpoints(); + + sector_t *ss; + for (ss = sectors; sectors+numsectors != ss; ss++) + { + Z_Free(ss->attached); + Z_Free(ss->attachedsolid); + } + + // This is the simplest guard against double frees. + // No valid map has zero sectors. Or, come to think + // of it, less than two in general! ~toast 310525 + numsectors = 0; + } + + // Clear pointers that would be left dangling by the purge + R_FlushTranslationColormapCache(); + +#ifdef HWRENDER + // Free GPU textures before freeing patches. + if (rendermode == render_opengl && (vid.glstate == VID_GL_LIBRARY_LOADED)) + HWR_ClearAllTextures(); +#endif + + G_FreeGhosts(); // ghosts are allocated with PU_LEVEL + Patch_FreeTag(PU_PATCH_LOWPRIORITY); + Patch_FreeTag(PU_PATCH_ROTATED); + Z_FreeTags(PU_LEVEL, PU_PURGELEVEL - 1); +} + /** Loads a level from a lump or external wad. * * \param fromnetsave If true, skip some stuff because we're loading a netgame snapshot. @@ -8401,7 +8441,6 @@ boolean P_LoadLevel(boolean fromnetsave, boolean reloadinggamestate) // 99% of the things already did, so. // Map header should always be in place at this point INT32 i, ranspecialwipe = 0; - sector_t *ss; virtlump_t *encoreLump = NULL; levelloading = true; @@ -8645,41 +8684,7 @@ boolean P_LoadLevel(boolean fromnetsave, boolean reloadinggamestate) } } - /* - if (!titlemapinaction) - wipegamestate = GS_LEVEL; - */ - - // Close text prompt before freeing the old level - F_EndTextPrompt(false, true); - - K_UnsetDialogue(); - - ACS_InvalidateMapScope(); - - LUA_InvalidateLevel(); - - Obj_ClearCheckpoints(); - - for (ss = sectors; sectors+numsectors != ss; ss++) - { - Z_Free(ss->attached); - Z_Free(ss->attachedsolid); - } - - // Clear pointers that would be left dangling by the purge - R_FlushTranslationColormapCache(); - -#ifdef HWRENDER - // Free GPU textures before freeing patches. - if (rendermode == render_opengl && (vid.glstate == VID_GL_LIBRARY_LOADED)) - HWR_ClearAllTextures(); -#endif - - G_FreeGhosts(); // ghosts are allocated with PU_LEVEL - Patch_FreeTag(PU_PATCH_LOWPRIORITY); - Patch_FreeTag(PU_PATCH_ROTATED); - Z_FreeTags(PU_LEVEL, PU_PURGELEVEL - 1); + P_FreeLevelState(); R_InitializeLevelInterpolators(); diff --git a/src/p_setup.h b/src/p_setup.h index b16db6bb5..0430cdfb5 100644 --- a/src/p_setup.h +++ b/src/p_setup.h @@ -107,6 +107,7 @@ extern mapthing_t *mapthings; void P_SetupLevelSky(const char *skytexname, boolean global); void P_RespawnThings(void); +void P_FreeLevelState(void); void P_ResetLevelMusic(void); boolean P_UseContinuousLevelMusic(void); void P_LoadLevelMusic(void);