mirror of
https://github.com/cxong/cdogs-sdl.git
synced 2025-07-23 07:23:01 +02:00
Fix memory leak screens not terminating
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
@@ -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;
|
||||
|
||||
|
@@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -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;
|
||||
|
90
src/prep.c
90
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));
|
||||
}
|
||||
// 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;
|
||||
}
|
||||
|
Reference in New Issue
Block a user