From 81b19746fea64269629891b93c38d5b0193fa669 Mon Sep 17 00:00:00 2001 From: Cong Date: Thu, 30 Nov 2023 23:47:40 +1100 Subject: [PATCH] Fix memory leak screens not terminating --- src/game_loop.c | 9 ++--- src/game_loop.h | 3 +- src/hiscores.c | 13 +++---- src/loading_screens.c | 13 ++++--- src/prep.c | 84 +++++++++++++++++++++---------------------- 5 files changed, 58 insertions(+), 64 deletions(-) diff --git a/src/game_loop.c b/src/game_loop.c index 2f02e0fca..d81089057 100644 --- a/src/game_loop.c +++ b/src/game_loop.c @@ -2,7 +2,7 @@ C-Dogs SDL A port of the legendary (and fun) action/arcade cdogs. - Copyright (c) 2014, 2016-2018, 2021-2022 Cong Xu + Copyright (c) 2014, 2016-2018, 2021-2023 Cong Xu All rights reserved. Redistribution and use in source and binary forms, with or without @@ -385,13 +385,12 @@ void LoopRunnerChange(LoopRunner *l, GameLoopData *newData) void LoopRunnerPush(LoopRunner *l, GameLoopData *newData) { CArrayPushBack(&l->Loops, &newData); - newData->IsUsed = true; } void LoopRunnerPop(LoopRunner *l) { GameLoopData *data = GetCurrentLoop(l); GameLoopOnExit(data); - data->IsUsed = false; + GameLoopTerminate(data); CArrayDelete(&l->Loops, l->Loops.size - 1); } @@ -420,10 +419,6 @@ static void GameLoopOnExit(GameLoopData *data) { data->OnExit(data); } - if (!data->IsUsed) - { - GameLoopTerminate(data); - } data->HasExited = true; data->HasEntered = false; } diff --git a/src/game_loop.h b/src/game_loop.h index 8cad4cf8d..9adf5510f 100644 --- a/src/game_loop.h +++ b/src/game_loop.h @@ -2,7 +2,7 @@ C-Dogs SDL A port of the legendary (and fun) action/arcade cdogs. - Copyright (c) 2014, 2017-2018, 2022 Cong Xu + Copyright (c) 2014, 2017-2018, 2022-2023 Cong Xu All rights reserved. Redistribution and use in source and binary forms, with or without @@ -63,7 +63,6 @@ typedef struct sGameLoopData bool HasEntered; bool HasExited; bool HasDrawnFirst; - bool IsUsed; bool DrawParent; } GameLoopData; diff --git a/src/hiscores.c b/src/hiscores.c index 145581ba0..ee6ddd7f2 100644 --- a/src/hiscores.c +++ b/src/hiscores.c @@ -93,9 +93,10 @@ static void HighScoresScreenTerminate(GameLoopData *data) } static GameLoopResult HighScoresScreenUpdate(GameLoopData *data, LoopRunner *l) { - HighScoresScreenData *hData = data->Data; + // Make copy before popping loop + HighScoresScreenData hData = *(HighScoresScreenData *)data->Data; LoopRunnerPop(l); - if (!IsPVP(hData->co->Entry.Mode) && + if (!IsPVP(hData.co->Entry.Mode) && GetNumPlayers(PLAYER_ANY, false, true) > 0) { LoadHighScores(); @@ -103,7 +104,7 @@ static GameLoopResult HighScoresScreenUpdate(GameLoopData *data, LoopRunner *l) bool todays = false; CA_FOREACH(PlayerData, p, gPlayerDatas) const bool isPlayerComplete = - (!hData->co->IsQuit && !p->survived) || hData->co->IsComplete; + (!hData.co->IsQuit && !p->survived) || hData.co->IsComplete; if (isPlayerComplete && p->IsLocal && IsPlayerHuman(p)) { EnterHighScore(p); @@ -121,18 +122,18 @@ static GameLoopResult HighScoresScreenUpdate(GameLoopData *data, LoopRunner *l) { p->missions++; } - p->lastMission = hData->co->MissionIndex; + p->lastMission = hData.co->MissionIndex; CA_FOREACH_END() SaveHighScores(); // Show high scores screen if high enough if (todays) { - LoopRunnerPush(l, DisplayTodaysHighScores(hData->g)); + LoopRunnerPush(l, DisplayTodaysHighScores(hData.g)); } if (allTime) { - LoopRunnerPush(l, DisplayAllTimeHighScores(hData->g)); + LoopRunnerPush(l, DisplayAllTimeHighScores(hData.g)); } } diff --git a/src/loading_screens.c b/src/loading_screens.c index d425971fe..0bfac82ef 100644 --- a/src/loading_screens.c +++ b/src/loading_screens.c @@ -180,18 +180,21 @@ static GameLoopResult LoopUpdate(GameLoopData *data, LoopRunner *l) sData->count++; if (complete) { + // Remove current loop, but copy its data before destroying it + ScreenLoadingData sDataCopy = *sData; + sData = NULL; LoopRunnerPop(l); - if (sData->ascending) + if (sDataCopy.ascending) { - if (sData->removeParent) + if (sDataCopy.removeParent) { LoopRunnerPop(l); } - if (sData->nextLoop) + if (sDataCopy.nextLoop) { - LoopRunnerPush(l, sData->nextLoop); + LoopRunnerPush(l, sDataCopy.nextLoop); // Show a loading screen with tiles animating out - LoopRunnerPush(l, ScreenLoading(sData->loadingText, false, NULL, false)); + LoopRunnerPush(l, ScreenLoading(sDataCopy.loadingText, false, NULL, false)); } } return UPDATE_RESULT_OK; diff --git a/src/prep.c b/src/prep.c index f5ad9add2..ee8e68e1b 100644 --- a/src/prep.c +++ b/src/prep.c @@ -684,57 +684,55 @@ static GameLoopResult GameOptionsUpdate(GameLoopData *data, LoopRunner *l) MissionOptionsTerminate(&gMission); CampaignUnload(&gCampaign); LoopRunnerPop(l); + return UPDATE_RESULT_OK; + } + if (!ConfigApply(&gConfig, NULL)) + { + LOG(LM_MAIN, LL_ERROR, + "Failed to apply config; reset to last used"); + ConfigResetChanged(&gConfig); } else { - if (!ConfigApply(&gConfig, NULL)) - { - LOG(LM_MAIN, LL_ERROR, - "Failed to apply config; reset to last used"); - ConfigResetChanged(&gConfig); - } - else + // Save options for later + ConfigSave(&gConfig, GetConfigFilePath(CONFIG_FILE)); + } + + // Set allowed weapons + // First check if the player has unwittingly disabled all weapons + // if so, enable all weapons + bool allDisabled = true; + for (int i = 0, j = 0; i < (int)gData->allowed.size; i++, j++) + { + const bool *allowed = CArrayGet(&gData->allowed, i); + if (*allowed) { - // Save options for later - ConfigSave(&gConfig, GetConfigFilePath(CONFIG_FILE)); + allDisabled = false; + break; } - - // Set allowed weapons - // First check if the player has unwittingly disabled all weapons - // if so, enable all weapons - bool allDisabled = true; + } + if (!allDisabled) + { for (int i = 0, j = 0; i < (int)gData->allowed.size; i++, j++) { const bool *allowed = CArrayGet(&gData->allowed, i); - if (*allowed) + if (!*allowed) { - allDisabled = false; - break; - } - } - if (!allDisabled) - { - for (int i = 0, j = 0; i < (int)gData->allowed.size; i++, j++) - { - const bool *allowed = CArrayGet(&gData->allowed, i); - if (!*allowed) - { - CArrayDelete(&gMission.Weapons, j); - j--; - } + CArrayDelete(&gMission.Weapons, j); + j--; } } + } - gCampaign.OptionsSet = true; + gCampaign.OptionsSet = true; - // If enabled, start net server - if (!gCampaign.IsClient && ConfigGetBool(&gConfig, "StartServer")) - { - NetServerOpen(&gNetServer); - } - LoopRunnerPush( - l, ScreenMissionBriefing(&gCampaign.Setting, &gMission)); + // If enabled, start net server + if (!gCampaign.IsClient && ConfigGetBool(&gConfig, "StartServer")) + { + NetServerOpen(&gNetServer); } + LoopRunnerPush( + l, ScreenMissionBriefing(&gCampaign.Setting, &gMission)); return UPDATE_RESULT_OK; } return UPDATE_RESULT_DRAW; @@ -795,13 +793,11 @@ static GameLoopResult CheckGameStart(void *data, LoopRunner *l) if (!gCampaign.IsLoaded) { LoopRunnerPop(l); + return UPDATE_RESULT_OK; } - else - { - LoopRunnerPush( - l, ScreenLoading( - "Starting game...", true, - RunGame(&gCampaign, &gMission, &gMap), true)); - } + LoopRunnerPush( + l, ScreenLoading( + "Starting game...", true, + RunGame(&gCampaign, &gMission, &gMap), true)); return UPDATE_RESULT_OK; }