From d49aedacead33aadb38b5c201aed1c6811cdd2a7 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 30 Aug 2020 00:55:49 +0200 Subject: [PATCH] - continued work on main loop - added a few new entry points to the game interface. --- source/CMakeLists.txt | 1 + source/blood/src/blood.cpp | 2 +- source/blood/src/blood.h | 3 +- source/blood/src/sfx.cpp | 2 +- source/blood/src/sound.h | 1 - source/common/rendering/v_framebuffer.cpp | 2 +- source/core/d_net.cpp | 217 +---------- source/core/d_net.h | 3 + source/core/gamecontrol.cpp | 1 + source/core/gamestruct.h | 3 + source/core/mainloop.cpp | 453 ++++++++++++++++++++++ source/exhumed/src/exhumed.h | 2 + source/exhumed/src/gameloop.cpp | 88 ++--- source/exhumed/src/sound.cpp | 2 +- source/exhumed/src/sound.h | 1 - source/games/duke/src/d_menu.cpp | 2 +- source/games/duke/src/duke3d.h | 1 + source/games/duke/src/gameloop.cpp | 2 +- source/games/duke/src/sounds.cpp | 2 +- source/games/duke/src/sounds.h | 1 - source/sw/src/d_menu.cpp | 2 +- source/sw/src/game.cpp | 90 ++--- source/sw/src/game.h | 2 + source/sw/src/player.cpp | 2 +- source/sw/src/sounds.cpp | 2 +- source/sw/src/sounds.h | 1 - 26 files changed, 566 insertions(+), 322 deletions(-) create mode 100644 source/core/mainloop.cpp diff --git a/source/CMakeLists.txt b/source/CMakeLists.txt index e9cdbfa68..ab56e5543 100644 --- a/source/CMakeLists.txt +++ b/source/CMakeLists.txt @@ -785,6 +785,7 @@ set (PCH_SOURCES core/ct_chat.cpp core/d_net.cpp core/d_protocol.cpp + core/mainloop.cpp core/gameconfigfile.cpp core/gamecvars.cpp core/gamecontrol.cpp diff --git a/source/blood/src/blood.cpp b/source/blood/src/blood.cpp index ce02bf0fc..a8336a6d8 100644 --- a/source/blood/src/blood.cpp +++ b/source/blood/src/blood.cpp @@ -589,7 +589,7 @@ void ProcessFrame(void) ambProcess(); viewUpdateDelirium(); viewUpdateShake(); - sfxUpdate3DSounds(); + gi->UpdateSounds(); if (gMe->hand == 1) { const int CHOKERATE = 8; diff --git a/source/blood/src/blood.h b/source/blood/src/blood.h index a795da1ad..27c57a9f3 100644 --- a/source/blood/src/blood.h +++ b/source/blood/src/blood.h @@ -89,7 +89,8 @@ struct GameInterface : ::GameInterface void QuitToTitle() override; FString GetCoordString() override; ReservedSpace GetReservedScreenSpace(int viewsize) override; - + void UpdateSounds() override; + GameStats getStats() override; }; diff --git a/source/blood/src/sfx.cpp b/source/blood/src/sfx.cpp index 7c600ed12..75a206069 100644 --- a/source/blood/src/sfx.cpp +++ b/source/blood/src/sfx.cpp @@ -121,7 +121,7 @@ void BloodSoundEngine::CalcPosVel(int type, const void* source, const float pt[3 } -void sfxUpdate3DSounds(void) +void GameInterface::UpdateSounds() { SoundListener listener; diff --git a/source/blood/src/sound.h b/source/blood/src/sound.h index b95ac7987..c512ccd16 100644 --- a/source/blood/src/sound.h +++ b/source/blood/src/sound.h @@ -60,7 +60,6 @@ void sfxPlay3DSound(spritetype *pSprite, int soundId, int a3 = -1, int a4 = 0); void sfxPlay3DSoundCP(spritetype* pSprite, int soundId, int a3 = -1, int a4 = 0, int pitch = 0, int volume = -1); void sfxKill3DSound(spritetype *pSprite, int a2 = -1, int a3 = -1); void sfxKillAllSounds(void); -void sfxUpdate3DSounds(void); void sfxSetReverb(bool toggle); void sfxSetReverb2(bool toggle); diff --git a/source/common/rendering/v_framebuffer.cpp b/source/common/rendering/v_framebuffer.cpp index 4d55989c3..315931d1e 100644 --- a/source/common/rendering/v_framebuffer.cpp +++ b/source/common/rendering/v_framebuffer.cpp @@ -58,7 +58,7 @@ CVAR(Bool, gl_scale_viewport, true, CVAR_ARCHIVE); EXTERN_CVAR(Int, vid_maxfps) -CVAR(Bool, cl_capfps, false, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) +EXTERN_CVAR(Bool, cl_capfps) EXTERN_CVAR(Int, screenblocks) //========================================================================== diff --git a/source/core/d_net.cpp b/source/core/d_net.cpp index 9fa2794d1..303ffa62d 100644 --- a/source/core/d_net.cpp +++ b/source/core/d_net.cpp @@ -51,14 +51,15 @@ #include "i_time.h" #include "d_ticcmd.h" +extern bool pauseext; +extern int gametic; + // Placeholders to make it compile. FILE* debugfile; -int gametic; extern bool netgame; bool demoplayback; int Net_Arbitrator; bool playeringame[MAXPLAYERS]; -bool pauseext; bool singletics; char* startmap; int rngseed; @@ -69,12 +70,6 @@ void D_WriteUserInfoStrings(int, uint8_t**, bool) {} FString GetPlayerName(int num); void G_BuildTiccmd(ticcmd_t*) {} - - -EXTERN_CVAR (Int, disableautosave) -EXTERN_CVAR (Int, autosavecount) -EXTERN_CVAR(Bool, cl_capfps) - //#define SIMULATEERRORS (RAND_MAX/3) #define SIMULATEERRORS 0 @@ -1812,212 +1807,6 @@ void D_QuitNetGame (void) fclose (debugfile); } -// Forces playsim processing time to be consistent across frames. -// This improves interpolation for frames in between tics. -// -// With this cvar off the mods with a high playsim processing time will appear -// less smooth as the measured time used for interpolation will vary. - -CVAR(Bool, r_ticstability, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) - -static uint64_t stabilityticduration = 0; -static uint64_t stabilitystarttime = 0; - -static void TicStabilityWait() -{ - using namespace std::chrono; - using namespace std::this_thread; - - if (!r_ticstability) - return; - - uint64_t start = duration_cast(steady_clock::now().time_since_epoch()).count(); - while (true) - { - uint64_t cur = duration_cast(steady_clock::now().time_since_epoch()).count(); - if (cur - start > stabilityticduration) - break; - } -} - -static void TicStabilityBegin() -{ - using namespace std::chrono; - stabilitystarttime = duration_cast(steady_clock::now().time_since_epoch()).count(); -} - -static void TicStabilityEnd() -{ - using namespace std::chrono; - uint64_t stabilityendtime = duration_cast(steady_clock::now().time_since_epoch()).count(); - stabilityticduration = std::min(stabilityendtime - stabilitystarttime, (uint64_t)1'000'000); -} - -// -// TryRunTics -// -void TryRunTics (void) -{ -#if 0 - int i; - int lowtic; - int realtics; - int availabletics; - int counts; - int numplaying; - - // If paused, do not eat more CPU time than we need, because it - // will all be wasted anyway. - if (pauseext) - r_NoInterpolate = true; - bool doWait = cl_capfps || r_NoInterpolate /*|| netgame*/; - - // get real tics - if (doWait) - { - entertic = I_WaitForTic (oldentertics); - } - else - { - entertic = I_GetTime (); - } - realtics = entertic - oldentertics; - oldentertics = entertic; - - // get available tics - NetUpdate (); - - if (pauseext) - return; - - lowtic = INT_MAX; - numplaying = 0; - for (i = 0; i < doomcom.numnodes; i++) - { - if (nodeingame[i]) - { - numplaying++; - if (nettics[i] < lowtic) - lowtic = nettics[i]; - } - } - - if (ticdup == 1) - { - availabletics = lowtic - gametic; - } - else - { - availabletics = lowtic - gametic / ticdup; - } - - // decide how many tics to run - if (realtics < availabletics-1) - counts = realtics+1; - else if (realtics < availabletics) - counts = realtics; - else - counts = availabletics; - - // Uncapped framerate needs seprate checks - if (counts == 0 && !doWait) - { - TicStabilityWait(); - - // Check possible stall conditions - Net_CheckLastReceived(counts); - if (realtics >= 1) - { - C_Ticker(); - M_Ticker(); - // Repredict the player for new buffered movement - P_UnPredictPlayer(); - P_PredictPlayer(&players[myconnectindex]); - } - return; - } - - if (counts < 1) - counts = 1; - - if (debugfile) - fprintf (debugfile, - "=======real: %i avail: %i game: %i\n", - realtics, availabletics, counts); - - // wait for new tics if needed - while (lowtic < gametic + counts) - { - NetUpdate (); - lowtic = INT_MAX; - - for (i = 0; i < doomcom.numnodes; i++) - if (nodeingame[i] && nettics[i] < lowtic) - lowtic = nettics[i]; - - lowtic = lowtic * ticdup; - - if (lowtic < gametic) - I_Error ("TryRunTics: lowtic < gametic"); - - // Check possible stall conditions - Net_CheckLastReceived (counts); - - // Update time returned by I_GetTime, but only if we are stuck in this loop - if (lowtic < gametic + counts) - I_SetFrameTime(); - - // don't stay in here forever -- give the menu a chance to work - if (I_GetTime () - entertic >= 1) - { - C_Ticker (); - M_Ticker (); - // Repredict the player for new buffered movement - P_UnPredictPlayer(); - P_PredictPlayer(&players[myconnectindex]); - return; - } - } - - //Tic lowtic is high enough to process this gametic. Clear all possible waiting info - hadlate = false; - for (i = 0; i < MAXPLAYERS; i++) - players[i].waiting = false; - lastglobalrecvtime = I_GetTime (); //Update the last time the game tic'd over - - // run the count tics - if (counts > 0) - { - P_UnPredictPlayer(); - while (counts--) - { - TicStabilityBegin(); - if (gametic > lowtic) - { - I_Error ("gametic>lowtic"); - } - if (advancedemo) - { - D_DoAdvanceDemo (); - } - if (debugfile) fprintf (debugfile, "run tic %d\n", gametic); - C_Ticker (); - M_Ticker (); - G_Ticker(); - gametic++; - - NetUpdate (); // check for new console commands - TicStabilityEnd(); - } - P_PredictPlayer(&players[myconnectindex]); - S_UpdateSounds (players[myconnectindex].camera); // move positional sounds - } - else - { - TicStabilityWait(); - } -#endif -} void Net_CheckLastReceived (int counts) { diff --git a/source/core/d_net.h b/source/core/d_net.h index 25d6749e7..444c189bf 100644 --- a/source/core/d_net.h +++ b/source/core/d_net.h @@ -69,6 +69,9 @@ extern int nodeforplayer[MAXPLAYERS]; extern ticcmd_t netcmds[MAXPLAYERS][BACKUPTICS]; extern int ticdup; +extern bool nodeingame[MAXNETNODES]; // set false as nodes leave game +extern bool hadlate; +extern uint64_t lastglobalrecvtime; // Identify the last time a packet was received. #endif diff --git a/source/core/gamecontrol.cpp b/source/core/gamecontrol.cpp index 084802a17..9bd27b29e 100644 --- a/source/core/gamecontrol.cpp +++ b/source/core/gamecontrol.cpp @@ -966,6 +966,7 @@ void app_loop() } catch (CRecoverableError& err) { + gi->ErrorCleanup(); C_FullConsole(); Printf(TEXTCOLOR_RED "%s\n", err.what()); } diff --git a/source/core/gamestruct.h b/source/core/gamestruct.h index adbf617d1..fa553dcb1 100644 --- a/source/core/gamestruct.h +++ b/source/core/gamestruct.h @@ -93,6 +93,9 @@ struct GameInterface virtual ReservedSpace GetReservedScreenSpace(int viewsize) { return { 0, 0 }; } virtual void ResetFollowPos(bool) {} virtual void GetInput(InputPacket* packet) {} + virtual void UpdateSounds() {} + virtual void ErrorCleanup() {} + virtual void Render() {} }; diff --git a/source/core/mainloop.cpp b/source/core/mainloop.cpp new file mode 100644 index 000000000..598c992b4 --- /dev/null +++ b/source/core/mainloop.cpp @@ -0,0 +1,453 @@ +/* +** mainloop.cpp +** Implements the main game loop +** +**--------------------------------------------------------------------------- +** Copyright 2020 Christoph Oelckers +** All rights reserved. +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** +** 1. Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** 2. Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** 3. The name of the author may not be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +**--------------------------------------------------------------------------- +** +*/ + + +// For TryRunTics the following applies: +//----------------------------------------------------------------------------- +// +// $Id:$ +// +// Copyright (C) 1993-1996 by id Software, Inc. +// Copyright 1999-2016 Randy Heit +// Copyright 2002-2020 Christoph Oelckers +// +// This source is available for distribution and/or modification +// only under the terms of the DOOM Source Code License as +// published by id Software. All rights reserved. +// +// The source is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// FITNESS FOR A PARTICULAR PURPOSE. See the DOOM Source Code License +// for more details. +// +// $Log:$ +// +// DESCRIPTION: +// DOOM Network game communication and protocol, +// all OS independent parts. +// +//----------------------------------------------------------------------------- + + +#include +#include +#include "c_cvars.h" +#include "i_time.h" +#include "d_net.h" +#include "gamecontrol.h" +#include "c_console.h" +#include "menu.h" +#include "i_system.h" +#include "raze_sound.h" +#include "raze_music.h" +#include "vm.h" + + + +// Forces playsim processing time to be consistent across frames. +// This improves interpolation for frames in between tics. +// +// With this cvar off the mods with a high playsim processing time will appear +// less smooth as the measured time used for interpolation will vary. + +CVAR(Bool, r_ticstability, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) +CVAR(Bool, cl_capfps, false, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) + +static uint64_t stabilityticduration = 0; +static uint64_t stabilitystarttime = 0; + +bool pauseext; +bool r_NoInterpolate; +int entertic; +int oldentertics; +int gametic; + + +static void TicStabilityWait() +{ + using namespace std::chrono; + using namespace std::this_thread; + + if (!r_ticstability) + return; + + uint64_t start = duration_cast(steady_clock::now().time_since_epoch()).count(); + while (true) + { + uint64_t cur = duration_cast(steady_clock::now().time_since_epoch()).count(); + if (cur - start > stabilityticduration) + break; + } +} + +static void TicStabilityBegin() +{ + using namespace std::chrono; + stabilitystarttime = duration_cast(steady_clock::now().time_since_epoch()).count(); +} + +static void TicStabilityEnd() +{ + using namespace std::chrono; + uint64_t stabilityendtime = duration_cast(steady_clock::now().time_since_epoch()).count(); + stabilityticduration = std::min(stabilityendtime - stabilitystarttime, (uint64_t)1'000'000); +} + +// +// TryRunTics +// +void TryRunTics (void) +{ + int i; + int lowtic; + int realtics; + int availabletics; + int counts; + int numplaying; + + // If paused, do not eat more CPU time than we need, because it + // will all be wasted anyway. + if (pauseext) + r_NoInterpolate = true; + bool doWait = cl_capfps || r_NoInterpolate /*|| netgame*/; + + // get real tics + if (doWait) + { + entertic = I_WaitForTic (oldentertics); + } + else + { + entertic = I_GetTime (); + } + realtics = entertic - oldentertics; + oldentertics = entertic; + + // get available tics + NetUpdate (); + + if (pauseext) + return; + + lowtic = INT_MAX; + numplaying = 0; + for (i = 0; i < doomcom.numnodes; i++) + { + if (nodeingame[i]) + { + numplaying++; + if (nettics[i] < lowtic) + lowtic = nettics[i]; + } + } + + if (ticdup == 1) + { + availabletics = lowtic - gametic; + } + else + { + availabletics = lowtic - gametic / ticdup; + } + + // decide how many tics to run + if (realtics < availabletics-1) + counts = realtics+1; + else if (realtics < availabletics) + counts = realtics; + else + counts = availabletics; + + // Uncapped framerate needs seprate checks + if (counts == 0 && !doWait) + { + TicStabilityWait(); + + // Check possible stall conditions + Net_CheckLastReceived(counts); + if (realtics >= 1) + { + C_Ticker(); + M_Ticker(); + // Repredict the player for new buffered movement +#if 0 + gi->Unpredict(); + gi->Predict(myconnectindex); +#endif + } + return; + } + + if (counts < 1) + counts = 1; + + // wait for new tics if needed + while (lowtic < gametic + counts) + { + NetUpdate (); + lowtic = INT_MAX; + + for (i = 0; i < doomcom.numnodes; i++) + if (nodeingame[i] && nettics[i] < lowtic) + lowtic = nettics[i]; + + lowtic = lowtic * ticdup; + + if (lowtic < gametic) + I_Error ("TryRunTics: lowtic < gametic"); + + // Check possible stall conditions + Net_CheckLastReceived (counts); + + // Update time returned by I_GetTime, but only if we are stuck in this loop + if (lowtic < gametic + counts) + I_SetFrameTime(); + + // don't stay in here forever -- give the menu a chance to work + if (I_GetTime () - entertic >= 1) + { + C_Ticker (); + M_Ticker (); + // Repredict the player for new buffered movement +#if 0 + gi->Unpredict(); + gi->Predict(myconnectindex); +#endif + return; + } + } + + //Tic lowtic is high enough to process this gametic. Clear all possible waiting info + hadlate = false; +#if 0 + for (i = 0; i < MAXPLAYERS; i++) + players[i].waiting = false; +#endif + lastglobalrecvtime = I_GetTime (); //Update the last time the game tic'd over + + // run the count tics + if (counts > 0) + { +#if 0 + gi->Unpredict(); +#endif + while (counts--) + { + TicStabilityBegin(); + if (gametic > lowtic) + { + I_Error ("gametic>lowtic"); + } +#if 0 + if (advancedemo) + { + D_DoAdvanceDemo (); + } +#endif + //if (debugfile) fprintf (debugfile, "run tic %d\n", gametic); + C_Ticker (); + M_Ticker (); + //G_Ticker(); + gametic++; + + NetUpdate (); // check for new console commands + TicStabilityEnd(); + } +#if 0 + gi->Predict(myconnectindex); +#endif + gi->UpdateSounds(); + soundEngine->UpdateSounds(I_GetTime()); + } + else + { + TicStabilityWait(); + } +} + + +//========================================================================== +// +// D_DoomLoop +// +// Manages timing and IO, calls all ?_Responder, ?_Ticker, and ?_Drawer, +// calls I_GetTime, I_StartFrame, and I_StartTic +// +//========================================================================== + +void MainLoop () +{ + int lasttic = 0; + + // Clamp the timer to TICRATE until the playloop has been entered. + r_NoInterpolate = true; + + //vid_cursor.Callback(); + + for (;;) + { + try + { + // frame syncronous IO operations + if (gametic > lasttic) + { + lasttic = gametic; + I_StartFrame (); + } + I_SetFrameTime(); + + TryRunTics (); // will run at least one tic + // Update display, next frame, with current state. + I_StartTic (); + gi->Render(); + Mus_UpdateMusic(); // must be at the end. + } + catch (CRecoverableError &error) + { + if (error.GetMessage ()) + { + Printf (PRINT_BOLD, "\n%s\n", error.GetMessage()); + } + gi->ErrorCleanup(); + C_FullConsole(); + } + catch (CVMAbortException &error) + { + error.MaybePrintMessage(); + Printf("%s", error.stacktrace.GetChars()); + gi->ErrorCleanup(); + C_FullConsole(); + } + } +} + + +//--------------------------------------------------------------------------- +// +// The one and only main loop in the entire engine. Yay! +// +//--------------------------------------------------------------------------- +#if 0 + +void _TickSubsystems() +{ + // run these on an independent timer until we got something working for the games. + static const uint64_t tickInterval = 1'000'000'000 / 30; + static uint64_t nexttick = 0; + + auto nowtick = I_nsTime(); + if (nexttick == 0) nexttick = nowtick; + int cnt = 0; + while (nexttick <= nowtick && cnt < 5) + { + nexttick += tickInterval; + C_Ticker(); + M_Ticker(); + C_RunDelayedCommands(); + cnt++; + } + // If this took too long the engine was most likely suspended so recalibrate the timer. + // Perfect precision is not needed here. + if (cnt == 5) nexttick = nowtick + tickInterval; +} + +static void _updatePauseStatus() +{ + // This must go through the network in multiplayer games. + if (M_Active() || System_WantGuiCapture()) + { + paused = 1; + } + else if (!M_Active() || !System_WantGuiCapture()) + { + if (!pausedWithKey) + { + paused = 0; + } + + if (sendPause) + { + sendPause = false; + paused = pausedWithKey ? 0 : 2; + pausedWithKey = !!paused; + } + } + + paused ? S_PauseSound(!pausedWithKey, !paused) : S_ResumeSound(paused); +} + + +void _app_loop() +{ + gamestate = GS_STARTUP; + + while (true) + { + try + { + I_SetFrameTime(); + TickSubsystems(); + twod->SetSize(screen->GetWidth(), screen->GetHeight()); + twodpsp.SetSize(screen->GetWidth(), screen->GetHeight()); + + handleevents(); + updatePauseStatus(); + D_ProcessEvents(); + + gi->RunGameFrame(); + + // Draw overlay elements to the 2D drawer + FStat::PrintStat(twod); + CT_Drawer(); + C_DrawConsole(); + M_Drawer(); + + // Handle the final 2D overlays. + if (gamestate == GS_LEVEL) DrawFullscreenBlends(); + DrawRateStuff(); + + + videoShowFrame(0); + 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()); + } + } +} + + +#endif \ No newline at end of file diff --git a/source/exhumed/src/exhumed.h b/source/exhumed/src/exhumed.h index 4f178b6f1..f79a2bc48 100644 --- a/source/exhumed/src/exhumed.h +++ b/source/exhumed/src/exhumed.h @@ -251,6 +251,8 @@ struct GameInterface : ::GameInterface bool CanSave() override; ReservedSpace GetReservedScreenSpace(int viewsize) override { return { 0, 24 }; } void QuitToTitle() override; + void UpdateSounds() override; + void ErrorCleanup() override; FString statFPS() override; ::GameStats getStats() override; diff --git a/source/exhumed/src/gameloop.cpp b/source/exhumed/src/gameloop.cpp index 55b38bb9d..81db62bbf 100644 --- a/source/exhumed/src/gameloop.cpp +++ b/source/exhumed/src/gameloop.cpp @@ -256,7 +256,7 @@ void GameLoop() { GameTicker(); PlayerInterruptKeys(true); - UpdateSounds(); + gi->UpdateSounds(); CheckKeys2(); } @@ -264,55 +264,51 @@ void GameLoop() void GameInterface::RunGameFrame() { again: - try + CheckProgression(); + switch (gamestate) { - CheckProgression(); - switch (gamestate) - { - default: - case GS_STARTUP: - resettiming(); - GameAction = -1; - EndLevel = false; - - 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. + default: + case GS_STARTUP: + resettiming(); GameAction = -1; EndLevel = false; - throw; - } + 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; + + } +} + +void GameInterface::ErrorCleanup() +{ + // Clear all progression sensitive variables here. + GameAction = -1; + EndLevel = false; } END_PS_NS diff --git a/source/exhumed/src/sound.cpp b/source/exhumed/src/sound.cpp index 96bf57e53..557167338 100644 --- a/source/exhumed/src/sound.cpp +++ b/source/exhumed/src/sound.cpp @@ -490,7 +490,7 @@ void EXSoundEngine::CalcPosVel(int type, const void* source, const float pt[3], // //========================================================================== -void UpdateSounds() +void GameInterface::UpdateSounds() { if (nFreeze) return; diff --git a/source/exhumed/src/sound.h b/source/exhumed/src/sound.h index 9e33e6b04..5904594de 100644 --- a/source/exhumed/src/sound.h +++ b/source/exhumed/src/sound.h @@ -117,7 +117,6 @@ extern short nCreepyTimer; extern short StaticSound[]; -void UpdateSounds(); void UpdateCreepySounds(); void InitFX(); diff --git a/source/games/duke/src/d_menu.cpp b/source/games/duke/src/d_menu.cpp index 172fdb4aa..43dd57d7e 100644 --- a/source/games/duke/src/d_menu.cpp +++ b/source/games/duke/src/d_menu.cpp @@ -293,7 +293,7 @@ void GameInterface::StartGame(FNewGameStartup& gs) while (S_CheckSoundPlaying(skillsound)) { - S_Update(); + gi->UpdateSounds(); soundEngine->UpdateSounds(I_GetTime()); I_GetEvent(); } diff --git a/source/games/duke/src/duke3d.h b/source/games/duke/src/duke3d.h index 0d24c1c62..315422fcb 100644 --- a/source/games/duke/src/duke3d.h +++ b/source/games/duke/src/duke3d.h @@ -58,6 +58,7 @@ struct GameInterface : public ::GameInterface void DrawPlayerSprite(const DVector2& origin, bool onteam) override; void ResetFollowPos(bool message) override; void GetInput(InputPacket* packet) override; + void UpdateSounds() override; }; diff --git a/source/games/duke/src/gameloop.cpp b/source/games/duke/src/gameloop.cpp index 5099e7d19..fc57bd5de 100644 --- a/source/games/duke/src/gameloop.cpp +++ b/source/games/duke/src/gameloop.cpp @@ -331,7 +331,7 @@ void GameTicker() } nonsharedkeys(); - S_Update(); + gi->UpdateSounds(); drawtime.Reset(); drawtime.Clock(); videoSetBrightness(thunder_brightness); diff --git a/source/games/duke/src/sounds.cpp b/source/games/duke/src/sounds.cpp index dfb5ef329..444ebb8ac 100644 --- a/source/games/duke/src/sounds.cpp +++ b/source/games/duke/src/sounds.cpp @@ -318,7 +318,7 @@ void DukeSoundEngine::CalcPosVel(int type, const void* source, const float pt[3] // //========================================================================== -void S_Update(void) +void GameInterface::UpdateSounds(void) { SoundListener listener; vec3_t* c; diff --git a/source/games/duke/src/sounds.h b/source/games/duke/src/sounds.h index 56d015451..6d8c68df9 100644 --- a/source/games/duke/src/sounds.h +++ b/source/games/duke/src/sounds.h @@ -36,7 +36,6 @@ enum esound_t }; void S_InitSound(); -void S_Update(void); void S_CacheAllSounds(void); int S_DefineSound(unsigned index, const char* filename, int ps, int pe, int pr, int m, int vo, float vol); diff --git a/source/sw/src/d_menu.cpp b/source/sw/src/d_menu.cpp index edaa634f6..b00b5aca0 100644 --- a/source/sw/src/d_menu.cpp +++ b/source/sw/src/d_menu.cpp @@ -230,7 +230,7 @@ void GameInterface::StartGame(FNewGameStartup& gs) while (soundEngine->IsSourcePlayingSomething(SOURCE_None, nullptr, CHAN_VOICE)) { - DoUpdateSounds(); + gi->UpdateSounds(); soundEngine->UpdateSounds(I_GetTime()); I_GetEvent(); } diff --git a/source/sw/src/game.cpp b/source/sw/src/game.cpp index 1d1964d2e..c12201525 100644 --- a/source/sw/src/game.cpp +++ b/source/sw/src/game.cpp @@ -767,59 +767,55 @@ void GameTicker(void) void GameInterface::RunGameFrame() { - try + // if the menu initiazed a new game or loaded a savegame, switch to play mode. + if (SavegameLoaded || NextLevel) gamestate = GS_LEVEL; + gi->UpdateSounds(); + switch (gamestate) { - // if the menu initiazed a new game or loaded a savegame, switch to play mode. - if (SavegameLoaded || NextLevel) gamestate = GS_LEVEL; - DoUpdateSounds(); - switch (gamestate) + default: + case GS_STARTUP: + I_ResetTime(); + lastTic = -1; + ogameclock = gameclock = 0; + + if (userConfig.CommandMap.IsNotEmpty()) { - default: - case GS_STARTUP: - I_ResetTime(); - lastTic = -1; - ogameclock = gameclock = 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; - } - } - catch (CRecoverableError&) - { - // Make sure we do not leave the game in an unstable state - TerminateLevel(); - NextLevel = nullptr; - SavegameLoaded = false; - ExitLevel = false; - FinishAnim = 0; - FinishedLevel = false; - throw; - } + 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; + + } } + +void GameInterface::ErrorCleanup() +{ + // Make sure we do not leave the game in an unstable state + TerminateLevel(); + NextLevel = nullptr; + SavegameLoaded = false; + ExitLevel = false; + FinishAnim = 0; + FinishedLevel = false; +} //--------------------------------------------------------------------------- // // diff --git a/source/sw/src/game.h b/source/sw/src/game.h index 7b44571cf..c7a1ec15c 100644 --- a/source/sw/src/game.h +++ b/source/sw/src/game.h @@ -2259,6 +2259,8 @@ struct GameInterface : ::GameInterface ReservedSpace GetReservedScreenSpace(int viewsize) override; void QuitToTitle() override; void ResetFollowPos(bool message) override; + void UpdateSounds() override; + void ErrorCleanup() override; FString statFPS() override; GameStats getStats() override; diff --git a/source/sw/src/player.cpp b/source/sw/src/player.cpp index c49f87bc2..92758ee86 100644 --- a/source/sw/src/player.cpp +++ b/source/sw/src/player.cpp @@ -7727,7 +7727,7 @@ domovethings(void) MultiPlayLimits(); //if (MoveSkip8 == 0) // 8=5x 4=10x, 2=20x, 0=40x per second - DoUpdateSounds(); + gi->UpdateSounds(); CorrectPrediction(movefifoplc - 1); diff --git a/source/sw/src/sounds.cpp b/source/sw/src/sounds.cpp index 8c096a3fb..6339d882c 100644 --- a/source/sw/src/sounds.cpp +++ b/source/sw/src/sounds.cpp @@ -585,7 +585,7 @@ void SWSoundEngine::CalcPosVel(int type, const void* source, const float pt[3], // //========================================================================== -void DoUpdateSounds(void) +void GameInterface::UpdateSounds(void) { PLAYERp pp = Player + screenpeek; SoundListener listener; diff --git a/source/sw/src/sounds.h b/source/sw/src/sounds.h index eab266b92..9cbbc1602 100644 --- a/source/sw/src/sounds.h +++ b/source/sw/src/sounds.h @@ -71,7 +71,6 @@ struct ambientstruct; typedef struct ambientstruct AMB_INFO, *AMB_INFOp; -void DoUpdateSounds(void); void Terminate3DSounds(void); void Set3DSoundOwner(short spritenum);