From 1ddd026a9ab514d3a1e4b754a52ec790e0150716 Mon Sep 17 00:00:00 2001 From: Bart Roossien Date: Mon, 21 Apr 2025 18:53:01 +0200 Subject: [PATCH 1/2] [GEN] Backport fast-forward of replays (#827) --- .../GameEngine/Include/Common/GlobalData.h | 2 ++ .../GameEngine/Include/Common/MessageStream.h | 2 ++ .../GameEngine/Source/Common/GameEngine.cpp | 34 ++++++++++++------- .../GameEngine/Source/Common/GlobalData.cpp | 2 ++ .../Source/Common/MessageStream.cpp | 3 ++ .../GameClient/MessageStream/CommandXlat.cpp | 19 ++++++++++- .../GameClient/MessageStream/MetaEvent.cpp | 23 +++++++++++++ .../Source/GameLogic/System/GameLogic.cpp | 1 + .../W3DDevice/GameClient/W3DDisplay.cpp | 5 +++ 9 files changed, 78 insertions(+), 13 deletions(-) diff --git a/Generals/Code/GameEngine/Include/Common/GlobalData.h b/Generals/Code/GameEngine/Include/Common/GlobalData.h index d09dda2a222..af967c63eb9 100644 --- a/Generals/Code/GameEngine/Include/Common/GlobalData.h +++ b/Generals/Code/GameEngine/Include/Common/GlobalData.h @@ -437,6 +437,8 @@ class GlobalData : public SubsystemInterface Real m_keyboardCameraRotateSpeed; ///< How fast the camera rotates when rotated via keyboard controls. Int m_playStats; ///< Int whether we want to log play stats or not, if <= 0 then we don't log + Bool m_TiVOFastMode; ///< When true, the client speeds up the framerate... set by HOTKEY! + #if defined(RTS_DEBUG) || defined(RTS_INTERNAL) Bool m_wireframe; Bool m_stateMachineDebug; diff --git a/Generals/Code/GameEngine/Include/Common/MessageStream.h b/Generals/Code/GameEngine/Include/Common/MessageStream.h index b01a6f41a3f..6592d771f1c 100644 --- a/Generals/Code/GameEngine/Include/Common/MessageStream.h +++ b/Generals/Code/GameEngine/Include/Common/MessageStream.h @@ -266,6 +266,8 @@ class GameMessage : public MemoryPoolObject MSG_META_BEGIN_CAMERA_ZOOM_OUT, MSG_META_END_CAMERA_ZOOM_OUT, MSG_META_CAMERA_RESET, + MSG_META_TOGGLE_FAST_FORWARD_REPLAY, ///< Toggle the fast forward feature + // META items that are really for debug/demo/development use only... // They do not get built into RELEASE builds. diff --git a/Generals/Code/GameEngine/Source/Common/GameEngine.cpp b/Generals/Code/GameEngine/Source/Common/GameEngine.cpp index 3e72de1445a..bca49f07ccd 100644 --- a/Generals/Code/GameEngine/Source/Common/GameEngine.cpp +++ b/Generals/Code/GameEngine/Source/Common/GameEngine.cpp @@ -667,19 +667,29 @@ void GameEngine::execute( void ) ::Sleep(1); // give everyone else a tiny time slice. #endif - // limit the framerate - DWORD now = timeGetTime(); - DWORD limit = (1000.0f/m_maxFPS)-1; - while (TheGlobalData->m_useFpsLimit && (now - prevTime) < limit) - { - ::Sleep(0); - now = timeGetTime(); - } - //Int slept = now - prevTime; - //DEBUG_LOG(("delayed %d\n",slept)); - prevTime = now; - } + #if defined(_ALLOW_DEBUG_CHEATS_IN_RELEASE) + if ( ! TheGlobalData->m_TiVOFastMode ) + #else //always allow this cheatkey if we're in a replaygame. + if ( ! (TheGlobalData->m_TiVOFastMode && TheGameLogic->isInReplayGame())) + #endif + { + // limit the framerate + DWORD now = timeGetTime(); + DWORD limit = (1000.0f/m_maxFPS)-1; + while (TheGlobalData->m_useFpsLimit && (now - prevTime) < limit) + { + ::Sleep(0); + now = timeGetTime(); + } + //Int slept = now - prevTime; + //DEBUG_LOG(("delayed %d\n",slept)); + + prevTime = now; + + } + + } } } // perfgather for execute_loop diff --git a/Generals/Code/GameEngine/Source/Common/GlobalData.cpp b/Generals/Code/GameEngine/Source/Common/GlobalData.cpp index 1a78613cead..8683c98372a 100644 --- a/Generals/Code/GameEngine/Source/Common/GlobalData.cpp +++ b/Generals/Code/GameEngine/Source/Common/GlobalData.cpp @@ -543,6 +543,8 @@ GlobalData::GlobalData() m_theOriginal = this; m_next = NULL; + m_TiVOFastMode = FALSE; + #if defined(RTS_DEBUG) || defined(RTS_INTERNAL) m_wireframe = 0; m_stateMachineDebug = FALSE; diff --git a/Generals/Code/GameEngine/Source/Common/MessageStream.cpp b/Generals/Code/GameEngine/Source/Common/MessageStream.cpp index d465878159d..062b88f2d76 100644 --- a/Generals/Code/GameEngine/Source/Common/MessageStream.cpp +++ b/Generals/Code/GameEngine/Source/Common/MessageStream.cpp @@ -364,6 +364,9 @@ AsciiString GameMessage::getCommandTypeAsAsciiString(GameMessage::Type t) CHECK_IF(MSG_META_BEGIN_CAMERA_ZOOM_OUT) CHECK_IF(MSG_META_END_CAMERA_ZOOM_OUT) CHECK_IF(MSG_META_CAMERA_RESET) + + CHECK_IF(MSG_META_TOGGLE_FAST_FORWARD_REPLAY) + #if defined(RTS_DEBUG) || defined(RTS_INTERNAL) CHECK_IF(MSG_META_DEMO_TOGGLE_BEHIND_BUILDINGS) CHECK_IF(MSG_META_DEMO_TOGGLE_LETTERBOX) diff --git a/Generals/Code/GameEngine/Source/GameClient/MessageStream/CommandXlat.cpp b/Generals/Code/GameEngine/Source/GameClient/MessageStream/CommandXlat.cpp index 30f806d83a2..876d1a20b21 100644 --- a/Generals/Code/GameEngine/Source/GameClient/MessageStream/CommandXlat.cpp +++ b/Generals/Code/GameEngine/Source/GameClient/MessageStream/CommandXlat.cpp @@ -3050,7 +3050,24 @@ GameMessageDisposition CommandTranslator::translateGameMessage(const GameMessage case GameMessage::MSG_META_CAMERA_RESET: TheInGameUI->resetCamera(); break; - + case GameMessage::MSG_META_TOGGLE_FAST_FORWARD_REPLAY: + { + if (TheGlobalData) + { +#if !defined(_ALLOW_DEBUG_CHEATS_IN_RELEASE)//may be defined in GameCommon.h + if (TheGameLogic->isInReplayGame()) +#endif + { + TheWritableGlobalData->m_TiVOFastMode = 1 - TheGlobalData->m_TiVOFastMode; + TheInGameUI->message(UnicodeString(L"m_TiVOFastMode: %s"), + TheGlobalData->m_TiVOFastMode ? L"ON" : L"OFF"); + } + } // end if + + disp = DESTROY_MESSAGE; + break; + + } // end toggle special power delays //----------------------------------------------------------------------------------------- case GameMessage::MSG_META_BEGIN_FORCEMOVE: DEBUG_ASSERTCRASH(!TheInGameUI->isInForceMoveToMode(), ("forceMoveToMode mismatch")); diff --git a/Generals/Code/GameEngine/Source/GameClient/MessageStream/MetaEvent.cpp b/Generals/Code/GameEngine/Source/GameClient/MessageStream/MetaEvent.cpp index 550cbff187a..1d988295d49 100644 --- a/Generals/Code/GameEngine/Source/GameClient/MessageStream/MetaEvent.cpp +++ b/Generals/Code/GameEngine/Source/GameClient/MessageStream/MetaEvent.cpp @@ -30,6 +30,7 @@ // INCLUDES /////////////////////////////////////////////////////////////////////////////////////// #include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine +#include "GameClient/GameText.h" #include "Common/INI.h" #include "Common/MessageStream.h" #include "Common/Player.h" @@ -171,6 +172,7 @@ static const LookupListRec GameMessageMetaTypeNames[] = { "BEGIN_CAMERA_ZOOM_OUT", GameMessage::MSG_META_BEGIN_CAMERA_ZOOM_OUT }, { "END_CAMERA_ZOOM_OUT", GameMessage::MSG_META_END_CAMERA_ZOOM_OUT }, { "CAMERA_RESET", GameMessage::MSG_META_CAMERA_RESET }, + { "TOGGLE_FAST_FORWARD_REPLAY", GameMessage::MSG_META_TOGGLE_FAST_FORWARD_REPLAY }, #if defined(RTS_DEBUG) || defined(RTS_INTERNAL) { "HELP", GameMessage::MSG_META_HELP }, @@ -448,6 +450,27 @@ GameMessageDisposition MetaEventTranslator::translateGameMessage(const GameMessa } else { + + // THIS IS A GREASY HACK... MESSAGE SHOULD BE HANDLED IN A TRANSLATOR, BUT DURING CINEMATICS THE TRANSLATOR IS DISABLED + if (map->m_meta == GameMessage::MSG_META_TOGGLE_FAST_FORWARD_REPLAY) + { +#if defined(_ALLOW_DEBUG_CHEATS_IN_RELEASE)//may be defined in GameCommon.h + if (TheGlobalData) +#else + if (TheGlobalData && TheGameLogic->isInReplayGame()) +#endif + { + if (TheWritableGlobalData) + TheWritableGlobalData->m_TiVOFastMode = 1 - TheGlobalData->m_TiVOFastMode; + + if (TheInGameUI) + TheInGameUI->message(TheGlobalData->m_TiVOFastMode ? TheGameText->fetch("GUI:FF_ON") : TheGameText->fetch("GUI:FF_OFF")); + } + disp = KEEP_MESSAGE; // cause for goodness sake, this key gets used a lot by non-replay hotkeys + break; + } + + /*GameMessage *metaMsg =*/ TheMessageStream->appendMessage(map->m_meta); //DEBUG_LOG(("Frame %d: MetaEventTranslator::translateGameMessage() normal: %s\n", TheGameLogic->getFrame(), findGameMessageNameByType(map->m_meta))); } diff --git a/Generals/Code/GameEngine/Source/GameLogic/System/GameLogic.cpp b/Generals/Code/GameEngine/Source/GameLogic/System/GameLogic.cpp index c1051b3d1f3..3879f0674e0 100644 --- a/Generals/Code/GameEngine/Source/GameLogic/System/GameLogic.cpp +++ b/Generals/Code/GameEngine/Source/GameLogic/System/GameLogic.cpp @@ -1036,6 +1036,7 @@ void GameLogic::startNewGame( Bool saveGame ) m_rankLevelLimit = 1000; // this is reset every game. setDefaults( saveGame ); TheWritableGlobalData->m_loadScreenRender = TRUE; ///< mark it so only a few select things are rendered during load + TheWritableGlobalData->m_TiVOFastMode = FALSE; //always disable the TIVO fast-forward mode at the start of a new game. m_showBehindBuildingMarkers = TRUE; m_drawIconUI = TRUE; diff --git a/Generals/Code/GameEngineDevice/Source/W3DDevice/GameClient/W3DDisplay.cpp b/Generals/Code/GameEngineDevice/Source/W3DDevice/GameClient/W3DDisplay.cpp index 9f582cccc5c..54208810fe0 100644 --- a/Generals/Code/GameEngineDevice/Source/W3DDevice/GameClient/W3DDisplay.cpp +++ b/Generals/Code/GameEngineDevice/Source/W3DDevice/GameClient/W3DDisplay.cpp @@ -1761,6 +1761,11 @@ void W3DDisplay::draw( void ) Int numRenderTargetVertices=Debug_Statistics::Get_DX8_Vertices(); // start render block +#if defined(_ALLOW_DEBUG_CHEATS_IN_RELEASE) + if ((TheGameLogic->getFrame() % 30 == 1) || (!(!TheGameLogic->isGamePaused() && TheGlobalData->m_TiVOFastMode))) +#else + if ((TheGameLogic->getFrame() % 30 == 1) || (!(!TheGameLogic->isGamePaused() && TheGlobalData->m_TiVOFastMode && TheGameLogic->isInReplayGame()))) +#endif { //USE_PERF_TIMER(BigAssRenderLoop) static Bool couldRender = true; From 5171f1fff7ec9f076516b5553c0af51a9414b906 Mon Sep 17 00:00:00 2001 From: xezon <4720891+xezon@users.noreply.github.com> Date: Thu, 8 May 2025 18:40:39 +0200 Subject: [PATCH 2/2] Fix whitespace differences --- .../GameEngine/Include/Common/GlobalData.h | 2 + .../GameEngine/Source/Common/GlobalData.cpp | 2 +- .../Source/Common/MessageStream.cpp | 4 +- .../GameClient/MessageStream/CommandXlat.cpp | 12 +++--- .../GameClient/MessageStream/MetaEvent.cpp | 39 +++++++++---------- .../W3DDevice/GameClient/W3DDisplay.cpp | 10 ++--- 6 files changed, 36 insertions(+), 33 deletions(-) diff --git a/Generals/Code/GameEngine/Include/Common/GlobalData.h b/Generals/Code/GameEngine/Include/Common/GlobalData.h index af967c63eb9..f53073f33c3 100644 --- a/Generals/Code/GameEngine/Include/Common/GlobalData.h +++ b/Generals/Code/GameEngine/Include/Common/GlobalData.h @@ -438,6 +438,8 @@ class GlobalData : public SubsystemInterface Int m_playStats; ///< Int whether we want to log play stats or not, if <= 0 then we don't log Bool m_TiVOFastMode; ///< When true, the client speeds up the framerate... set by HOTKEY! + + #if defined(RTS_DEBUG) || defined(RTS_INTERNAL) Bool m_wireframe; diff --git a/Generals/Code/GameEngine/Source/Common/GlobalData.cpp b/Generals/Code/GameEngine/Source/Common/GlobalData.cpp index 8683c98372a..ccaa5b5f7d1 100644 --- a/Generals/Code/GameEngine/Source/Common/GlobalData.cpp +++ b/Generals/Code/GameEngine/Source/Common/GlobalData.cpp @@ -543,7 +543,7 @@ GlobalData::GlobalData() m_theOriginal = this; m_next = NULL; - m_TiVOFastMode = FALSE; + m_TiVOFastMode = FALSE; #if defined(RTS_DEBUG) || defined(RTS_INTERNAL) m_wireframe = 0; diff --git a/Generals/Code/GameEngine/Source/Common/MessageStream.cpp b/Generals/Code/GameEngine/Source/Common/MessageStream.cpp index 062b88f2d76..28e226172ba 100644 --- a/Generals/Code/GameEngine/Source/Common/MessageStream.cpp +++ b/Generals/Code/GameEngine/Source/Common/MessageStream.cpp @@ -365,8 +365,10 @@ AsciiString GameMessage::getCommandTypeAsAsciiString(GameMessage::Type t) CHECK_IF(MSG_META_END_CAMERA_ZOOM_OUT) CHECK_IF(MSG_META_CAMERA_RESET) - CHECK_IF(MSG_META_TOGGLE_FAST_FORWARD_REPLAY) + CHECK_IF(MSG_META_TOGGLE_FAST_FORWARD_REPLAY) + + #if defined(RTS_DEBUG) || defined(RTS_INTERNAL) CHECK_IF(MSG_META_DEMO_TOGGLE_BEHIND_BUILDINGS) CHECK_IF(MSG_META_DEMO_TOGGLE_LETTERBOX) diff --git a/Generals/Code/GameEngine/Source/GameClient/MessageStream/CommandXlat.cpp b/Generals/Code/GameEngine/Source/GameClient/MessageStream/CommandXlat.cpp index 876d1a20b21..a6faef03557 100644 --- a/Generals/Code/GameEngine/Source/GameClient/MessageStream/CommandXlat.cpp +++ b/Generals/Code/GameEngine/Source/GameClient/MessageStream/CommandXlat.cpp @@ -3052,22 +3052,22 @@ GameMessageDisposition CommandTranslator::translateGameMessage(const GameMessage break; case GameMessage::MSG_META_TOGGLE_FAST_FORWARD_REPLAY: { - if (TheGlobalData) + if( TheGlobalData ) { -#if !defined(_ALLOW_DEBUG_CHEATS_IN_RELEASE)//may be defined in GameCommon.h + #if !defined(_ALLOW_DEBUG_CHEATS_IN_RELEASE)//may be defined in GameCommon.h if (TheGameLogic->isInReplayGame()) -#endif + #endif { TheWritableGlobalData->m_TiVOFastMode = 1 - TheGlobalData->m_TiVOFastMode; - TheInGameUI->message(UnicodeString(L"m_TiVOFastMode: %s"), - TheGlobalData->m_TiVOFastMode ? L"ON" : L"OFF"); + TheInGameUI->message( UnicodeString( L"m_TiVOFastMode: %s" ), + TheGlobalData->m_TiVOFastMode ? L"ON" : L"OFF" ); } } // end if disp = DESTROY_MESSAGE; break; - } // end toggle special power delays + } // end toggle special power delays //----------------------------------------------------------------------------------------- case GameMessage::MSG_META_BEGIN_FORCEMOVE: DEBUG_ASSERTCRASH(!TheInGameUI->isInForceMoveToMode(), ("forceMoveToMode mismatch")); diff --git a/Generals/Code/GameEngine/Source/GameClient/MessageStream/MetaEvent.cpp b/Generals/Code/GameEngine/Source/GameClient/MessageStream/MetaEvent.cpp index 1d988295d49..fbb450c4bd2 100644 --- a/Generals/Code/GameEngine/Source/GameClient/MessageStream/MetaEvent.cpp +++ b/Generals/Code/GameEngine/Source/GameClient/MessageStream/MetaEvent.cpp @@ -30,7 +30,6 @@ // INCLUDES /////////////////////////////////////////////////////////////////////////////////////// #include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine -#include "GameClient/GameText.h" #include "Common/INI.h" #include "Common/MessageStream.h" #include "Common/Player.h" @@ -48,7 +47,7 @@ #include "GameClient/WindowLayout.h" #include "GameClient/GUICallbacks.h" #include "GameClient/DebugDisplay.h" // for AudioDebugDisplay - +#include "GameClient/GameText.h" #include "GameClient/MetaEvent.h" #include "GameLogic/GameLogic.h" // for TheGameLogic->getFrame() @@ -451,24 +450,24 @@ GameMessageDisposition MetaEventTranslator::translateGameMessage(const GameMessa else { - // THIS IS A GREASY HACK... MESSAGE SHOULD BE HANDLED IN A TRANSLATOR, BUT DURING CINEMATICS THE TRANSLATOR IS DISABLED - if (map->m_meta == GameMessage::MSG_META_TOGGLE_FAST_FORWARD_REPLAY) - { -#if defined(_ALLOW_DEBUG_CHEATS_IN_RELEASE)//may be defined in GameCommon.h - if (TheGlobalData) -#else - if (TheGlobalData && TheGameLogic->isInReplayGame()) -#endif - { - if (TheWritableGlobalData) - TheWritableGlobalData->m_TiVOFastMode = 1 - TheGlobalData->m_TiVOFastMode; - - if (TheInGameUI) - TheInGameUI->message(TheGlobalData->m_TiVOFastMode ? TheGameText->fetch("GUI:FF_ON") : TheGameText->fetch("GUI:FF_OFF")); - } - disp = KEEP_MESSAGE; // cause for goodness sake, this key gets used a lot by non-replay hotkeys - break; - } + // THIS IS A GREASY HACK... MESSAGE SHOULD BE HANDLED IN A TRANSLATOR, BUT DURING CINEMATICS THE TRANSLATOR IS DISABLED + if( map->m_meta == GameMessage::MSG_META_TOGGLE_FAST_FORWARD_REPLAY) + { + #if defined(_ALLOW_DEBUG_CHEATS_IN_RELEASE)//may be defined in GameCommon.h + if( TheGlobalData ) + #else + if( TheGlobalData && TheGameLogic->isInReplayGame()) + #endif + { + if ( TheWritableGlobalData ) + TheWritableGlobalData->m_TiVOFastMode = 1 - TheGlobalData->m_TiVOFastMode; + + if ( TheInGameUI ) + TheInGameUI->message( TheGlobalData->m_TiVOFastMode ? TheGameText->fetch("GUI:FF_ON") : TheGameText->fetch("GUI:FF_OFF") ); + } + disp = KEEP_MESSAGE; // cause for goodness sake, this key gets used a lot by non-replay hotkeys + break; + } /*GameMessage *metaMsg =*/ TheMessageStream->appendMessage(map->m_meta); diff --git a/Generals/Code/GameEngineDevice/Source/W3DDevice/GameClient/W3DDisplay.cpp b/Generals/Code/GameEngineDevice/Source/W3DDevice/GameClient/W3DDisplay.cpp index 54208810fe0..bf1e0938f72 100644 --- a/Generals/Code/GameEngineDevice/Source/W3DDevice/GameClient/W3DDisplay.cpp +++ b/Generals/Code/GameEngineDevice/Source/W3DDevice/GameClient/W3DDisplay.cpp @@ -1761,11 +1761,11 @@ void W3DDisplay::draw( void ) Int numRenderTargetVertices=Debug_Statistics::Get_DX8_Vertices(); // start render block -#if defined(_ALLOW_DEBUG_CHEATS_IN_RELEASE) - if ((TheGameLogic->getFrame() % 30 == 1) || (!(!TheGameLogic->isGamePaused() && TheGlobalData->m_TiVOFastMode))) -#else - if ((TheGameLogic->getFrame() % 30 == 1) || (!(!TheGameLogic->isGamePaused() && TheGlobalData->m_TiVOFastMode && TheGameLogic->isInReplayGame()))) -#endif + #if defined(_ALLOW_DEBUG_CHEATS_IN_RELEASE) + if ( (TheGameLogic->getFrame() % 30 == 1) || ( ! ( !TheGameLogic->isGamePaused() && TheGlobalData->m_TiVOFastMode) ) ) + #else + if ( (TheGameLogic->getFrame() % 30 == 1) || ( ! (!TheGameLogic->isGamePaused() && TheGlobalData->m_TiVOFastMode && TheGameLogic->isInReplayGame())) ) + #endif { //USE_PERF_TIMER(BigAssRenderLoop) static Bool couldRender = true;