Skip to content

Commit 9e64dc9

Browse files
committed
bugfix(fps): Fix and improve Logic and Render Fps decoupling
1 parent 5eaa6aa commit 9e64dc9

File tree

32 files changed

+387
-256
lines changed

32 files changed

+387
-256
lines changed

Core/GameEngine/Include/Common/GameDefines.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818

1919
#pragma once
2020

21+
#include "WWDefines.h"
22+
2123
// Note: Retail compatibility must not be broken before this project officially does.
2224
// Use RETAIL_COMPATIBLE_CRC and RETAIL_COMPATIBLE_XFER_SAVE to guard breaking changes.
2325

Core/Libraries/Source/WWVegas/WWLib/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,7 @@ set(WWLIB_SRC
133133
widestring.h
134134
win.h
135135
WWCommon.h
136+
WWDefines.h
136137
wwfile.cpp
137138
WWFILE.H
138139
wwstring.cpp

Core/Libraries/Source/WWVegas/WWLib/WWCommon.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818

1919
#pragma once
2020

21-
#include <stringex.h>
21+
#include "stringex.h"
2222

2323
#if defined(_MSC_VER) && _MSC_VER < 1300
2424
typedef unsigned MemValueType;
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
/*
2+
** Command & Conquer Generals Zero Hour(tm)
3+
** Copyright 2025 TheSuperHackers
4+
**
5+
** This program is free software: you can redistribute it and/or modify
6+
** it under the terms of the GNU General Public License as published by
7+
** the Free Software Foundation, either version 3 of the License, or
8+
** (at your option) any later version.
9+
**
10+
** This program is distributed in the hope that it will be useful,
11+
** but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
** GNU General Public License for more details.
14+
**
15+
** You should have received a copy of the GNU General Public License
16+
** along with this program. If not, see <http://www.gnu.org/licenses/>.
17+
*/
18+
19+
#pragma once
20+
21+
// The WW3D Sync time. This was originally 33 ms, ~30 fps, integer.
22+
// Changing or removing this will require tweaking all Drawable code that concerns logic time step, including locomotion physics.
23+
#ifndef MSEC_PER_WWSYNC_FRAME
24+
#define MSEC_PER_WWSYNC_FRAME (33)
25+
#endif

Core/Libraries/Source/WWVegas/WWLib/always.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
#define ALWAYS_H
4242

4343
#include "WWCommon.h"
44+
#include "WWDefines.h"
4445

4546
#include <assert.h>
4647
#include <new>

GeneralsMD/Code/GameEngine/Include/Common/GameEngine.h

Lines changed: 25 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -53,11 +53,16 @@ class Radar;
5353
class WebBrowser;
5454
class ParticleSystemManager;
5555

56-
/**
57-
* The implementation of the game engine
58-
*/
5956
class GameEngine : public SubsystemInterface
6057
{
58+
public:
59+
60+
typedef UnsignedInt LogicTimeQueryFlags;
61+
enum LogicTimeQueryFlags_ CPP_11(: LogicTimeQueryFlags)
62+
{
63+
IgnoreFrozenTime = 1<<0, // Ignore frozen time for the query
64+
IgnoreHaltedGame = 1<<1, // Ignore halted game for the query
65+
};
6166

6267
public:
6368

@@ -76,13 +81,18 @@ class GameEngine : public SubsystemInterface
7681
Real getUpdateTime(); ///< Get the last engine update delta time.
7782
Real getUpdateFps(); ///< Get the last engine update fps.
7883

84+
static Bool isTimeFrozen(); ///< Returns true if a script has frozen time.
85+
static Bool isGameHalted(); ///< Returns true if the game is paused or the network is stalling.
86+
7987
virtual void setLogicTimeScaleFps( Int fps ); ///< Set the logic time scale fps and therefore scale the simulation time. Is capped by the max render fps and does not apply to network matches.
8088
virtual Int getLogicTimeScaleFps(); ///< Get the raw logic time scale fps value.
8189
virtual void enableLogicTimeScale( Bool enable ); ///< Enable the logic time scale setup. If disabled, the simulation time scale is bound to the render frame time or network update time.
8290
virtual Bool isLogicTimeScaleEnabled(); ///< Check whether the logic time scale setup is enabled.
83-
Int getActualLogicTimeScaleFps(); ///< Get the real logic time scale fps, depending on the max render fps, network state and enabled state.
84-
Real getActualLogicTimeScaleRatio(); ///< Get the real logic time scale ratio, depending on the max render fps, network state and enabled state.
85-
Real getActualLogicTimeScaleOverFpsRatio(); ///< Get the real logic time scale over render fps ratio, used to scale down steps in render updates to match logic updates.
91+
Int getActualLogicTimeScaleFps(LogicTimeQueryFlags flags = 0); ///< Get the real logic time scale fps, depending on the max render fps, network state and enabled state.
92+
Real getActualLogicTimeScaleRatio(LogicTimeQueryFlags flags = 0); ///< Get the real logic time scale ratio, depending on the max render fps, network state and enabled state.
93+
Real getActualLogicTimeScaleOverFpsRatio(LogicTimeQueryFlags flags = 0); ///< Get the real logic time scale over render fps ratio, used to scale down steps in render updates to match logic updates.
94+
Real getLogicTimeStepSeconds(LogicTimeQueryFlags flags = 0); ///< Get the logic time step in seconds
95+
Real getLogicTimeStepMilliseconds(LogicTimeQueryFlags flags = 0); ///< Get the logic time step in milliseconds
8696

8797
virtual void setQuitting( Bool quitting ); ///< set quitting status
8898
virtual Bool getQuitting(void); ///< is app getting ready to quit.
@@ -96,6 +106,10 @@ class GameEngine : public SubsystemInterface
96106

97107
virtual void resetSubsystems( void );
98108

109+
Bool canUpdateGameLogic();
110+
Bool canUpdateNetworkGameLogic();
111+
Bool canUpdateRegularGameLogic();
112+
99113
virtual FileSystem *createFileSystem( void ); ///< Factory for FileSystem classes
100114
virtual LocalFileSystem *createLocalFileSystem( void ) = 0; ///< Factory for LocalFileSystem classes
101115
virtual ArchiveFileSystem *createArchiveFileSystem( void ) = 0; ///< Factory for ArchiveFileSystem classes
@@ -116,11 +130,14 @@ class GameEngine : public SubsystemInterface
116130
Real m_updateTime; ///< Last engine update delta time
117131
Real m_logicTimeAccumulator; ///< Frame time accumulated towards submitting a new logic frame
118132

119-
Bool m_quitting; ///< true when we need to quit the game
120-
Bool m_isActive; ///< app has OS focus.
133+
Bool m_quitting; ///< true when we need to quit the game
134+
Bool m_isActive; ///< app has OS focus.
121135
Bool m_enableLogicTimeScale;
136+
Bool m_isTimeFrozen;
137+
Bool m_isGameHalted;
122138

123139
};
140+
124141
inline void GameEngine::setQuitting( Bool quitting ) { m_quitting = quitting; }
125142
inline Bool GameEngine::getQuitting(void) { return m_quitting; }
126143

GeneralsMD/Code/GameEngine/Include/GameClient/Drawable.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -406,7 +406,7 @@ class Drawable : public Thing,
406406

407407
const Matrix3D *getTransformMatrix( void ) const; ///< return the world transform
408408

409-
void draw( View *view ); ///< render the drawable to the given view
409+
void draw(); ///< render the drawable to the given view
410410
void updateDrawable(); ///< update the drawable
411411

412412
void drawIconUI( void ); ///< draw "icon"(s) needed on drawable (health bars, veterency, etc)
@@ -640,6 +640,8 @@ class Drawable : public Thing,
640640

641641
private:
642642

643+
const Locomotor* getLocomotor() const;
644+
643645
// note, these are lazily allocated!
644646
TintEnvelope* m_selectionFlashEnvelope; ///< used for selection flash, works WITH m_colorTintEnvelope
645647
TintEnvelope* m_colorTintEnvelope; ///< house color flashing, etc... works WITH m_selectionFlashEnvelope
@@ -685,6 +687,8 @@ class Drawable : public Thing,
685687

686688
DrawableLocoInfo* m_locoInfo; // lazily allocated
687689

690+
PhysicsXformInfo* m_physicsXform;
691+
688692
DynamicAudioEventRTS* m_ambientSound; ///< sound module for ambient sound (lazily allocated)
689693

690694
Module** m_modules[NUM_DRAWABLE_MODULE_TYPES];

GeneralsMD/Code/GameEngine/Include/GameLogic/GameLogic.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,7 @@ class GameLogic : public SubsystemInterface, public Snapshot
212212
void updateObjectsChangedTriggerAreas(void) {m_frameObjectsChangedTriggerAreas = m_frame;}
213213
UnsignedInt getFrameObjectsChangedTriggerAreas(void) {return m_frameObjectsChangedTriggerAreas;}
214214

215+
void exitGame();
215216
void clearGameData(Bool showScoreScreen = TRUE); ///< Clear the game data
216217
void closeWindows( void );
217218

@@ -220,7 +221,7 @@ class GameLogic : public SubsystemInterface, public Snapshot
220221

221222
void bindObjectAndDrawable(Object* obj, Drawable* draw);
222223

223-
void setGamePausedInFrame( UnsignedInt frame );
224+
void setGamePausedInFrame( UnsignedInt frame, Bool disableLogicTimeScale );
224225
UnsignedInt getGamePauseFrame() const { return m_pauseFrame; }
225226
void setGamePaused( Bool paused, Bool pauseMusic = TRUE, Bool pauseInput = TRUE );
226227
Bool isGamePaused( void );
@@ -375,6 +376,7 @@ class GameLogic : public SubsystemInterface, public Snapshot
375376
Bool m_pauseInput;
376377
Bool m_inputEnabledMemory;// Latches used to remember what to restore to after we unpause
377378
Bool m_mouseVisibleMemory;
379+
Bool m_logicTimeScaleEnabledMemory;
378380

379381
Bool m_progressComplete[MAX_SLOTS];
380382
enum { PROGRESS_COMPLETE_TIMEOUT = 60000 }; ///< Timeout we wait for when we've completed our Load

GeneralsMD/Code/GameEngine/Include/GameNetwork/NetworkInterface.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ class NetworkInterface : public SubsystemInterface
6868

6969
virtual void setLocalAddress(UnsignedInt ip, UnsignedInt port) = 0; ///< Tell the network what local ip and port to bind to.
7070
virtual Bool isFrameDataReady( void ) = 0; ///< Are the commands for the next frame available?
71+
virtual Bool isStalling() = 0;
7172
virtual void parseUserList( const GameInfo *game ) = 0; ///< Parse a userlist, creating connections
7273
virtual void startGame(void) = 0; ///< Sets the network game frame counter to -1
7374
virtual UnsignedInt getRunAhead(void) = 0; ///< Get the current RunAhead value

0 commit comments

Comments
 (0)