Always exit TryRunTics loop early if deferring gamestate change

Calls to F_ContinueCredits and D_StartTitle, even if deferred,
change the current gamestate. However, the tic loop in TryRunTics
may still have a couple tics to execute to catch up to current
time, and as a consequence G_Ticker may execute game logic while
the current state is not GS_LEVEL or equivalent. As a result, it is
highly likely for the game to crash.

This adds deferred credits start to the tic loop, and exits that
loop if either title or credits are supposed to start after the
current iteration, fixing this crash scenario.

Fixes KartKrew/Kart#1185
This commit is contained in:
Eidolon 2024-04-30 22:54:42 -05:00
parent f4e023a38e
commit fc3128df12
5 changed files with 32 additions and 2 deletions

View file

@ -52,6 +52,7 @@
#include "stun.h"
// SRB2Kart
#include "k_credits.h"
#include "k_kart.h"
#include "k_battle.h"
#include "k_pwrlv.h"
@ -6146,6 +6147,11 @@ boolean TryRunTics(tic_t realtics)
ps_tictime = I_GetPreciseTime() - ps_tictime;
if (F_IsDeferredContinueCredits())
{
F_ContinueCredits();
}
if (D_IsDeferredStartTitle())
{
D_StartTitle();
@ -6156,6 +6162,12 @@ boolean TryRunTics(tic_t realtics)
{
break;
}
// if we're no longer in a level state, just exit
if (!G_GamestateUsesLevel())
{
break;
}
}
}
else

View file

@ -6390,7 +6390,7 @@ void Command_ExitGame_f(void)
// YES, this is where demo.attract gets cleared!
if (demo.attract == DEMO_ATTRACT_CREDITS)
{
F_ContinueCredits(); // <-- clears demo.attract
F_DeferContinueCredits(); // <-- clears demo.attract
}
else if (restoreMenu == NULL) // this is true for attract demos too!
{

View file

@ -4052,7 +4052,7 @@ boolean G_CheckDemoStatus(void)
else if (wasmodeattacking)
M_EndModeAttackRun();
else if (demo.attract == DEMO_ATTRACT_CREDITS)
F_ContinueCredits();
F_DeferContinueCredits();
else
D_SetDeferredStartTitle(true);
}

View file

@ -126,6 +126,8 @@ constexpr const fixed_t kScrollFactor = FRACUNIT * 7 / 8;
constexpr const int kSkipSpeed = 8;
constexpr const int kScrollSkipSpeed = 4;
static bool g_deferred_continue_credits = false;
void F_LoadCreditsDefinitions(void)
{
// Load credits definitions from bios.pk3
@ -448,8 +450,20 @@ static void F_CreditsNextSlide(void)
F_InitCreditsSlide();
}
void F_DeferContinueCredits(void)
{
g_deferred_continue_credits = true;
demo.attract = DEMO_ATTRACT_OFF;
}
boolean F_IsDeferredContinueCredits(void)
{
return g_deferred_continue_credits;
}
void F_ContinueCredits(void)
{
g_deferred_continue_credits = false;
G_SetGamestate(GS_CREDITS);
F_CreditsReset();
demo.attract = DEMO_ATTRACT_OFF;

View file

@ -26,6 +26,10 @@ void F_CreditsReset(void);
void F_StartCredits(void);
void F_DeferContinueCredits(void);
boolean F_IsDeferredContinueCredits(void);
void F_ContinueCredits(void);
void F_TickCreditsDemoExit(void);