- restructured the main loop code so that the actual loop is in the common code.

This commit is contained in:
Christoph Oelckers 2020-08-23 17:47:05 +02:00
parent 85875da77a
commit adb98a47ba
12 changed files with 231 additions and 286 deletions

View file

@ -68,8 +68,6 @@ void LocalKeys(void);
void InitCheats(); void InitCheats();
bool bNoDemo = false; bool bNoDemo = false;
bool bQuickStart = true;
char gUserMapFilename[BMAX_PATH]; char gUserMapFilename[BMAX_PATH];
@ -714,13 +712,12 @@ static const char* actions[] = {
"Toggle_Crouch", "Toggle_Crouch",
}; };
static void app_init() void GameInterface::app_init()
{ {
InitCheats(); InitCheats();
buttonMap.SetButtons(actions, NUM_ACTIONS); buttonMap.SetButtons(actions, NUM_ACTIONS);
memcpy(&gGameOptions, &gSingleGameOptions, sizeof(GAMEOPTIONS)); memcpy(&gGameOptions, &gSingleGameOptions, sizeof(GAMEOPTIONS));
gGameOptions.nMonsterSettings = !userConfig.nomonsters; gGameOptions.nMonsterSettings = !userConfig.nomonsters;
bQuickStart = userConfig.nologo;
ReadAllRFS(); ReadAllRFS();
HookReplaceFunctions(); HookReplaceFunctions();
@ -854,7 +851,7 @@ static void drawBackground()
netBroadcastMyLogoff(gQuitRequest == 2); netBroadcastMyLogoff(gQuitRequest == 2);
} }
static void commonTicker(bool &playvideo) static void commonTicker()
{ {
if (TestBitString(gotpic, 2342)) if (TestBitString(gotpic, 2342))
{ {
@ -895,85 +892,61 @@ static void commonTicker(bool &playvideo)
gQuitRequest = 0; gQuitRequest = 0;
gRestartGame = 0; gRestartGame = 0;
if (gGameOptions.nGameType != 0)
{
playvideo = !bQuickStart;
}
else playvideo = false;
// Don't switch to startup if we're already outside the game. // Don't switch to startup if we're already outside the game.
if (gamestate == GS_LEVEL) gamestate = GS_STARTUP; if (gamestate == GS_LEVEL) gamestate = GS_STARTUP;
} }
} }
int GameInterface::app_main() void GameInterface::RunGameFrame()
{ {
if (gamestate == GS_STARTUP) gameInit();
app_init(); commonTicker();
gamestate = GS_STARTUP; netGetPackets();
bool playvideo = !bQuickStart; handleevents();
while (true) updatePauseStatus();
D_ProcessEvents();
ctrlGetInput();
switch (gamestate)
{ {
try default:
case GS_STARTUP:
if (userConfig.CommandMap.IsNotEmpty())
{ {
if (gamestate == GS_STARTUP) gameInit(); }
else
commonTicker(playvideo); {
netGetPackets(); if (!userConfig.nologo && gGameOptions.nGameType == 0) playlogos();
handleevents(); else
updatePauseStatus();
D_ProcessEvents();
ctrlGetInput();
switch (gamestate)
{ {
default: gamestate = GS_MENUSCREEN;
case GS_STARTUP: M_StartControlPanel(false);
if (userConfig.CommandMap.IsNotEmpty()) M_SetMenu(NAME_Mainmenu);
{
}
else
{
if (playvideo) playlogos();
else
{
gamestate = GS_MENUSCREEN;
M_StartControlPanel(false);
M_SetMenu(NAME_Mainmenu);
}
}
break;
case GS_MENUSCREEN:
case GS_FULLCONSOLE:
drawBackground();
break;
case GS_INTRO:
case GS_INTERMISSION:
RunScreenJobFrame(); // This handles continuation through its completion callback.
break;
case GS_LEVEL:
gameTicker();
LocalKeys();
break;
case GS_FINALE:
gEndGameMgr.ProcessKeys();
gEndGameMgr.Draw();
break;
} }
}
break;
videoNextPage(); case GS_MENUSCREEN:
} case GS_FULLCONSOLE:
catch (CRecoverableError& err) drawBackground();
{ break;
C_FullConsole();
Printf(TEXTCOLOR_RED "%s\n", err.what()); case GS_INTRO:
} case GS_INTERMISSION:
RunScreenJobFrame(); // This handles continuation through its completion callback.
break;
case GS_LEVEL:
gameTicker();
LocalKeys();
break;
case GS_FINALE:
gEndGameMgr.ProcessKeys();
gEndGameMgr.Draw();
break;
} }
return 0;
} }
bool DemoRecordStatus(void) { bool DemoRecordStatus(void) {

View file

@ -107,7 +107,8 @@ void sndPlaySpecialMusicOrNothing(int nMusic);
struct GameInterface : ::GameInterface struct GameInterface : ::GameInterface
{ {
const char* Name() override { return "Blood"; } const char* Name() override { return "Blood"; }
int app_main() override; void app_init() override;
void RunGameFrame() override;
bool GenerateSavePic() override; bool GenerateSavePic() override;
void FreeGameData() override; void FreeGameData() override;
FString statFPS() override; FString statFPS() override;

View file

@ -117,6 +117,7 @@ void I_SetWindowTitle(const char* caption);
void S_ParseSndInfo(); void S_ParseSndInfo();
void I_DetectOS(void); void I_DetectOS(void);
void LoadScripts(); void LoadScripts();
void app_loop();
bool AppActive; bool AppActive;
@ -817,6 +818,7 @@ int RunGame()
{ {
playername = userConfig.CommandName; playername = userConfig.CommandName;
} }
GameTicRate = 30;
CheckUserMap(); CheckUserMap();
GPalette.Init(MAXPALOOKUPS + 2); // one slot for each translation, plus a separate one for the base palettes and the internal one GPalette.Init(MAXPALOOKUPS + 2); // one slot for each translation, plus a separate one for the base palettes and the internal one
TexMan.Init([]() {}, [](BuildInfo &) {}); TexMan.Init([]() {}, [](BuildInfo &) {});
@ -836,16 +838,44 @@ int RunGame()
if (enginePreInit()) if (enginePreInit())
{ {
I_FatalError("app_main: There was a problem initializing the Build engine: %s\n", engineerrstr); I_FatalError("There was a problem initializing the Build engine: %s\n", engineerrstr);
} }
auto exec = C_ParseCmdLineParams(nullptr); auto exec = C_ParseCmdLineParams(nullptr);
if (exec) exec->ExecCommands(); if (exec) exec->ExecCommands();
gamestate = GS_LEVEL; gamestate = GS_LEVEL;
return gi->app_main(); gi->app_init();
app_loop();
} }
//---------------------------------------------------------------------------
//
// The one and only main loop in the entire engine. Yay!
//
//---------------------------------------------------------------------------
void app_loop()
{
gamestate = GS_STARTUP;
while (true)
{
try
{
gi->RunGameFrame();
videoNextPage();
videoSetBrightness(0); // immediately reset this so that the value doesn't stick around in the backend.
}
catch (CRecoverableError& err)
{
C_FullConsole();
Printf(TEXTCOLOR_RED "%s\n", err.what());
}
}
}
//========================================================================== //==========================================================================
// //
// //

View file

@ -58,7 +58,8 @@ struct GameInterface
virtual const char* Name() { return "$"; } virtual const char* Name() { return "$"; }
virtual ~GameInterface() {} virtual ~GameInterface() {}
virtual bool GenerateSavePic() { return false; } virtual bool GenerateSavePic() { return false; }
virtual int app_main() = 0; virtual void app_init() = 0;
virtual void RunGameFrame() = 0;
virtual void clearlocalinputstate() {} virtual void clearlocalinputstate() {}
virtual void UpdateScreenSize() {} virtual void UpdateScreenSize() {}
virtual void FreeGameData() {} virtual void FreeGameData() {}

View file

@ -621,7 +621,7 @@ static const char* actions[] =
void InitGame() void GameInterface::app_init()
{ {
int i; int i;
//int esi = 1; //int esi = 1;

View file

@ -134,7 +134,6 @@ void CheckKeys();
void CheckKeys2(); void CheckKeys2();
void GameTicker(); void GameTicker();
void InitLevel(int); void InitLevel(int);
void InitGame();
void InitNewGame(); void InitNewGame();
void startmainmenu(); void startmainmenu();
@ -294,8 +293,9 @@ struct SavegameHelper
struct GameInterface : ::GameInterface struct GameInterface : ::GameInterface
{ {
const char* Name() override { return "Exhumed"; } const char* Name() override { return "Exhumed"; }
int app_main() override; void app_init() override;
bool GenerateSavePic() override; void RunGameFrame() override;
bool GenerateSavePic() override;
void DrawNativeMenuText(int fontnum, int state, double xpos, double ypos, float fontscale, const char* text, int flags) override; void DrawNativeMenuText(int fontnum, int state, double xpos, double ypos, float fontscale, const char* text, int flags) override;
void MenuOpened() override; void MenuOpened() override;
void MenuSound(EMenuSounds snd) override; void MenuSound(EMenuSounds snd) override;

View file

@ -59,7 +59,6 @@ extern ClockTicks tclocks;
void RunCinemaScene(int num); void RunCinemaScene(int num);
void GameMove(void); void GameMove(void);
void InitGame();
void DrawClock(); void DrawClock();
int32_t calc_smoothratio(ClockTicks totalclk, ClockTicks ototalclk); int32_t calc_smoothratio(ClockTicks totalclk, ClockTicks ototalclk);
void DoTitle(CompletionFunc completion); void DoTitle(CompletionFunc completion);
@ -262,78 +261,63 @@ void GameLoop()
fps++; fps++;
} }
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
int GameInterface::app_main() void GameInterface::RunGameFrame()
{ {
InitGame(); again:
gamestate = GS_STARTUP; try
while (true)
{ {
try HandleAsync();
updatePauseStatus();
D_ProcessEvents();
CheckProgression();
switch (gamestate)
{ {
HandleAsync(); default:
updatePauseStatus(); case GS_STARTUP:
D_ProcessEvents(); totalclock = 0;
CheckProgression(); ototalclock = 0;
switch (gamestate)
{
default:
case GS_STARTUP:
totalclock = 0;
ototalclock = 0;
GameAction = -1;
EndLevel = false;
if (userConfig.CommandMap.IsNotEmpty())
{
auto map = FindMapByName(userConfig.CommandMap);
if (map) GameAction = map->levelNumber;
userConfig.CommandMap = "";
continue;
}
else
{
DoTitle([](bool) { startmainmenu(); });
}
break;
case GS_MENUSCREEN:
case GS_FULLCONSOLE:
drawmenubackground();
break;
case GS_LEVEL:
GameLoop();
GameDisplay();
break;
case GS_INTERMISSION:
case GS_INTRO:
RunScreenJobFrame(); // This handles continuation through its completion callback.
break;
}
videoNextPage();
}
catch (CRecoverableError& err)
{
// Clear all progression sensitive variables here.
GameAction = -1; GameAction = -1;
EndLevel = false; EndLevel = false;
C_FullConsole();
Printf(TEXTCOLOR_RED "%s\n", err.what()); if (userConfig.CommandMap.IsNotEmpty())
{
auto map = FindMapByName(userConfig.CommandMap);
if (map) GameAction = map->levelNumber;
userConfig.CommandMap = "";
goto again;
}
else
{
DoTitle([](bool) { startmainmenu(); });
}
break;
case GS_MENUSCREEN:
case GS_FULLCONSOLE:
drawmenubackground();
break;
case GS_LEVEL:
GameLoop();
GameDisplay();
break;
case GS_INTERMISSION:
case GS_INTRO:
RunScreenJobFrame(); // This handles continuation through its completion callback.
break;
} }
} }
catch (CRecoverableError&)
{
// Clear all progression sensitive variables here.
GameAction = -1;
EndLevel = false;
throw;
}
} }
END_PS_NS END_PS_NS

View file

@ -34,7 +34,8 @@ extern FFont* DigiFont;
struct GameInterface : public ::GameInterface struct GameInterface : public ::GameInterface
{ {
const char* Name() override { return "Duke"; } const char* Name() override { return "Duke"; }
int app_main() override; void app_init() override;
void RunGameFrame() override;
void clearlocalinputstate() override; void clearlocalinputstate() override;
bool GenerateSavePic() override; bool GenerateSavePic() override;
void PlayHudSound() override; void PlayHudSound() override;

View file

@ -423,14 +423,12 @@ static void Startup(void)
// //
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
void app_loop(); void GameInterface::app_init()
int GameInterface::app_main()
{ {
Startup(); Startup();
enginePostInit(); enginePostInit();
videoInit(); videoInit();
app_loop(); enginecompatibility_mode = ENGINECOMPATIBILITY_19961112;//bVanilla;
return 0;
} }

View file

@ -399,77 +399,60 @@ void startmainmenu()
// //
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
void app_loop() void GameInterface::RunGameFrame()
{ {
gamestate = GS_STARTUP; handleevents();
enginecompatibility_mode = ENGINECOMPATIBILITY_19961112;//bVanilla; updatePauseStatus();
D_ProcessEvents();
while (true) switch (gamestate)
{ {
try default:
case GS_STARTUP:
totalclock = 0;
ototalclock = 0;
lockclock = 0;
ps[myconnectindex].ftq = 0;
if (userConfig.CommandMap.IsNotEmpty())
{ {
handleevents(); auto maprecord = FindMapByName(userConfig.CommandMap);
updatePauseStatus(); userConfig.CommandMap = "";
D_ProcessEvents(); if (maprecord)
switch (gamestate)
{ {
default: ud.m_respawn_monsters = ud.m_player_skill == 4;
case GS_STARTUP:
totalclock = 0;
ototalclock = 0;
lockclock = 0;
ps[myconnectindex].ftq = 0; for (int i = 0; i != -1; i = connectpoint2[i])
if (userConfig.CommandMap.IsNotEmpty())
{ {
auto maprecord = FindMapByName(userConfig.CommandMap); resetweapons(i);
userConfig.CommandMap = ""; resetinventory(i);
if (maprecord)
{
ud.m_respawn_monsters = ud.m_player_skill == 4;
for (int i = 0; i != -1; i = connectpoint2[i])
{
resetweapons(i);
resetinventory(i);
}
startnewgame(maprecord, /*userConfig.skill*/2);
}
} }
else startnewgame(maprecord, /*userConfig.skill*/2);
{
fi.ShowLogo([](bool) { startmainmenu(); });
}
break;
case GS_MENUSCREEN:
case GS_FULLCONSOLE:
drawbackground();
break;
case GS_LEVEL:
if (GameTicker()) gamestate = GS_STARTUP;
else videoSetBrightness(thunder_brightness);
break;
case GS_INTERMISSION:
case GS_INTRO:
RunScreenJobFrame(); // This handles continuation through its completion callback.
break;
} }
videoNextPage();
videoSetBrightness(0); // immediately reset this so that the value doesn't stick around in the backend.
} }
catch (CRecoverableError& err) else
{ {
C_FullConsole(); fi.ShowLogo([](bool) { startmainmenu(); });
Printf(TEXTCOLOR_RED "%s\n", err.what());
} }
break;
case GS_MENUSCREEN:
case GS_FULLCONSOLE:
drawbackground();
break;
case GS_LEVEL:
if (GameTicker()) gamestate = GS_STARTUP;
else videoSetBrightness(thunder_brightness);
break;
case GS_INTERMISSION:
case GS_INTRO:
RunScreenJobFrame(); // This handles continuation through its completion callback.
break;
} }
} }
END_DUKE_NS END_DUKE_NS

View file

@ -213,8 +213,9 @@ static const char* actions[] = {
}; };
bool InitGame() void GameInterface::app_init()
{ {
GameTicRate = 40;
InitCheats(); InitCheats();
buttonMap.SetButtons(actions, NUM_ACTIONS); buttonMap.SetButtons(actions, NUM_ACTIONS);
automapping = 1; automapping = 1;
@ -284,7 +285,6 @@ bool InitGame()
enginePostInit(); enginePostInit();
videoInit(); videoInit();
InitFX(); InitFX();
return true;
} }
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
@ -804,89 +804,62 @@ void GameTicker(void)
} }
} }
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
int32_t GameInterface::app_main() void GameInterface::RunGameFrame()
{ {
InitGame(); try
gamestate = GS_STARTUP;
while (true)
{ {
try // if the menu initiazed a new game or loaded a savegame, switch to play mode.
{ if (SavegameLoaded || NextLevel) gamestate = GS_LEVEL;
// if the menu initiazed a new game or loaded a savegame, switch to play mode.
if (SavegameLoaded || NextLevel) gamestate = GS_LEVEL;
handleevents();
updatePauseStatus();
D_ProcessEvents();
DoUpdateSounds();
switch (gamestate)
{
default:
case GS_STARTUP:
totalclock = 0;
ototalclock = 0;
if (userConfig.CommandMap.IsNotEmpty())
{
}
else
{
if (!userConfig.nologo) Logo([](bool) { StartMenu(); });
else StartMenu();
}
break;
case GS_MENUSCREEN:
case GS_FULLCONSOLE:
DrawMenuLevelScreen();
break;
case GS_LEVEL:
GameTicker();
break;
case GS_INTERMISSION:
case GS_INTRO:
RunScreenJobFrame(); // This handles continuation through its completion callback.
break;
}
videoNextPage();
}
catch (CRecoverableError& err)
{
TerminateLevel();
NextLevel = nullptr;
SavegameLoaded = false;
ExitLevel = false;
FinishAnim = 0;
C_FullConsole();
Printf(TEXTCOLOR_RED "%s\n", err.what());
}
}
#if 0
while (true)
{
handleevents(); handleevents();
C_RunDelayedCommands(); updatePauseStatus();
D_ProcessEvents();
DoUpdateSounds();
switch (gamestate)
{
default:
case GS_STARTUP:
totalclock = 0;
ototalclock = 0;
NewLevel(); if (userConfig.CommandMap.IsNotEmpty())
{
}
else
{
if (!userConfig.nologo) Logo([](bool) { StartMenu(); });
else StartMenu();
}
break;
case GS_MENUSCREEN:
case GS_FULLCONSOLE:
DrawMenuLevelScreen();
break;
case GS_LEVEL:
GameTicker();
break;
case GS_INTERMISSION:
case GS_INTRO:
RunScreenJobFrame(); // This handles continuation through its completion callback.
break;
}
}
catch (CRecoverableError&)
{
// Make sure we do not leave the game in an unstable state
TerminateLevel();
NextLevel = nullptr;
SavegameLoaded = false;
ExitLevel = false;
FinishAnim = 0;
throw;
} }
//SybexScreen();
throw CExitEvent(0);
#endif
return 0;
} }
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------

View file

@ -2364,7 +2364,8 @@ extern short Bunny_Count;
struct GameInterface : ::GameInterface struct GameInterface : ::GameInterface
{ {
const char* Name() override { return "ShadowWarrior"; } const char* Name() override { return "ShadowWarrior"; }
int app_main() override; void app_init() override;
void RunGameFrame() override;
void FreeGameData() override; void FreeGameData() override;
bool GenerateSavePic() override; bool GenerateSavePic() override;
void DrawNativeMenuText(int fontnum, int state, double xpos, double ypos, float fontscale, const char* text, int flags) override; void DrawNativeMenuText(int fontnum, int state, double xpos, double ypos, float fontscale, const char* text, int flags) override;