Fix memory leak screens not terminating

This commit is contained in:
Cong
2023-11-30 23:47:40 +11:00
parent cb89d8bcf3
commit 81b19746fe
5 changed files with 61 additions and 67 deletions

View File

@@ -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;
}

View File

@@ -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;

View File

@@ -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));
}
}

View File

@@ -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;

View File

@@ -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));
}
// 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;
// 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)
{
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)
if (!*allowed)
{
allDisabled = false;
break;
CArrayDelete(&gMission.Weapons, j);
j--;
}
}
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--;
}
}
}
gCampaign.OptionsSet = true;
// If enabled, start net server
if (!gCampaign.IsClient && ConfigGetBool(&gConfig, "StartServer"))
{
NetServerOpen(&gNetServer);
}
LoopRunnerPush(
l, ScreenMissionBriefing(&gCampaign.Setting, &gMission));
}
gCampaign.OptionsSet = true;
// 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 @@ bail:
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;
}