@@ -56,7 +56,7 @@ static HMODULE WINAPI SkipDirectPlay_LoadLibraryA(LPCSTR fileName)
5656 if (!StrCmpIA (" enbseries\\ enbhelper.dll" , fileName))
5757 {
5858 std::error_code ec;
59-
59+
6060 // Try to load enbhelper.dll from our custom launch directory first.
6161 const fs::path inLaunchDir = fs::path{FromUTF8 (GetLaunchPath ())} / " enbseries" / " enbhelper.dll" ;
6262
@@ -146,18 +146,16 @@ CCore::CCore()
146146 // Setup our hooks.
147147 ApplyHooks ();
148148
149- // No initial fps limit
150- m_bDoneFrameRateLimit = false ;
151- m_uiFrameRateLimit = 0 ;
152- m_uiServerFrameRateLimit = 0 ;
153149 m_iUnminimizeFrameCounter = 0 ;
154150 m_bDidRecreateRenderTargets = false ;
155151 m_fMinStreamingMemory = 0 ;
156152 m_fMaxStreamingMemory = 0 ;
157153 m_bGettingIdleCallsFromMultiplayer = false ;
158154 m_bWindowsTimerEnabled = false ;
159155 m_timeDiscordAppLastUpdate = 0 ;
160- m_CurrentRefreshRate = 60 ;
156+
157+ // Initialize FPS limiter
158+ m_pFPSLimiter = std::make_unique<FPSLimiter::FPSLimiter>();
161159
162160 // Create tray icon
163161 m_pTrayIcon = new CTrayIcon ();
@@ -180,6 +178,8 @@ CCore::~CCore()
180178 // Destroy tray icon
181179 delete m_pTrayIcon;
182180
181+ m_pFPSLimiter.reset ();
182+
183183 // This will set the GTA volume to the GTA volume value in the settings,
184184 // and is not affected by the master volume setting.
185185 m_pLocalGUI->GetMainMenu ()->GetSettingsWindow ()->ResetGTAVolume ();
@@ -1347,7 +1347,7 @@ void CCore::OnModUnload()
13471347 m_pKeyBinds->RemoveAllControlFunctions ();
13481348
13491349 // Reset client script frame rate limit
1350- m_uiClientScriptFrameRateLimit = 0 ;
1350+ GetFPSLimiter ()-> SetClientEnforcedFPS (FPSLimits::FPS_UNLIMITED) ;
13511351
13521352 // Clear web whitelist
13531353 if (m_pWebCore)
@@ -1772,8 +1772,8 @@ void CCore::OnPostColorFilterRender()
17721772{
17731773 if (!CGraphics::GetSingleton ().HasLine3DPostFXQueueItems () && !CGraphics::GetSingleton ().HasPrimitive3DPostFXQueueItems ())
17741774 return ;
1775-
1776- CGraphics::GetSingleton ().EnteringMTARenderZone ();
1775+
1776+ CGraphics::GetSingleton ().EnteringMTARenderZone ();
17771777
17781778 CGraphics::GetSingleton ().DrawPrimitive3DPostFXQueue ();
17791779 CGraphics::GetSingleton ().DrawLine3DPostFXQueue ();
@@ -1831,141 +1831,14 @@ void CCore::ApplyCoreInitSettings()
18311831//
18321832void CCore::OnGameTimerUpdate ()
18331833{
1834- ApplyQueuedFrameRateLimit ();
1834+ // NOTE: (pxd) We are handling the frame limiting updates
1835+ // earlier in the callpath (CModManager::DoPulsePreFrame, CModManager::DoPulsePostFrame)
18351836}
18361837
1837- //
1838- // Recalculate FPS limit to use
1839- //
1840- // Uses client rate from config
1841- // Uses client rate from script
1842- // Uses server rate from argument, or last time if not supplied
1843- //
1844- void CCore::RecalculateFrameRateLimit (uint uiServerFrameRateLimit, bool bLogToConsole)
1838+ void CCore::OnFPSLimitChange (std::uint16_t fps)
18451839{
1846- // Save rate from server if valid
1847- if (uiServerFrameRateLimit != -1 )
1848- m_uiServerFrameRateLimit = uiServerFrameRateLimit;
1849-
1850- // Start with value set by the server
1851- m_uiFrameRateLimit = m_uiServerFrameRateLimit;
1852-
1853- // Apply client config setting
1854- uint uiClientConfigRate;
1855- g_pCore->GetCVars ()->Get (" fps_limit" , uiClientConfigRate);
1856- if (uiClientConfigRate > 0 )
1857- uiClientConfigRate = std::max (45U , uiClientConfigRate);
1858- // Lowest wins (Although zero is highest)
1859- if ((m_uiFrameRateLimit == 0 || uiClientConfigRate < m_uiFrameRateLimit) && uiClientConfigRate > 0 )
1860- m_uiFrameRateLimit = uiClientConfigRate;
1861-
1862- // Apply client script setting
1863- uint uiClientScriptRate = m_uiClientScriptFrameRateLimit;
1864- // Lowest wins (Although zero is highest)
1865- if ((m_uiFrameRateLimit == 0 || uiClientScriptRate < m_uiFrameRateLimit) && uiClientScriptRate > 0 )
1866- m_uiFrameRateLimit = uiClientScriptRate;
1867-
1868- if (!IsConnected ())
1869- m_uiFrameRateLimit = m_CurrentRefreshRate;
1870-
1871- // Removes Limiter from Frame Graph if limit is zero and skips frame limit
1872- if (m_uiFrameRateLimit == 0 )
1873- {
1874- m_bQueuedFrameRateValid = false ;
1875- GetGraphStats ()->RemoveTimingPoint (" Limiter" );
1876- }
1877-
1878- // Print new limits to the console
1879- if (bLogToConsole)
1880- {
1881- SString strStatus (" Server FPS limit: %d" , m_uiServerFrameRateLimit);
1882- if (m_uiFrameRateLimit != m_uiServerFrameRateLimit)
1883- strStatus += SString (" (Using %d)" , m_uiFrameRateLimit);
1884- CCore::GetSingleton ().GetConsole ()->Print (strStatus);
1885- }
1886- }
1887-
1888- //
1889- // Change client rate as set by script
1890- //
1891- void CCore::SetClientScriptFrameRateLimit (uint uiClientScriptFrameRateLimit)
1892- {
1893- m_uiClientScriptFrameRateLimit = uiClientScriptFrameRateLimit;
1894- RecalculateFrameRateLimit (-1 , false );
1895- }
1896-
1897- void CCore::SetCurrentRefreshRate (uint value)
1898- {
1899- m_CurrentRefreshRate = value;
1900- RecalculateFrameRateLimit (-1 , false );
1901- }
1902-
1903- //
1904- // Make sure the frame rate limit has been applied since the last call
1905- //
1906- void CCore::EnsureFrameRateLimitApplied ()
1907- {
1908- if (!m_bDoneFrameRateLimit)
1909- {
1910- ApplyFrameRateLimit ();
1911- }
1912- m_bDoneFrameRateLimit = false ;
1913- }
1914-
1915- //
1916- // Do FPS limiting
1917- //
1918- // This is called once a frame even if minimized
1919- //
1920- void CCore::ApplyFrameRateLimit (uint uiOverrideRate)
1921- {
1922- TIMING_CHECKPOINT (" -CallIdle1" );
1923- ms_TimingCheckpoints.EndTimingCheckpoints ();
1924-
1925- // Frame rate limit stuff starts here
1926- m_bDoneFrameRateLimit = true ;
1927-
1928- uint uiUseRate = uiOverrideRate != -1 ? uiOverrideRate : m_uiFrameRateLimit;
1929-
1930- if (uiUseRate > 0 )
1931- {
1932- // Apply previous frame rate if is hasn't been done yet
1933- ApplyQueuedFrameRateLimit ();
1934-
1935- // Limit is usually applied in OnGameTimerUpdate
1936- m_uiQueuedFrameRate = uiUseRate;
1937- m_bQueuedFrameRateValid = true ;
1938- }
1939-
1940- DoReliablePulse ();
1941-
1942- TIMING_GRAPH (" FrameEnd" );
1943- TIMING_GRAPH (" " );
1944- }
1945-
1946- //
1947- // Frame rate limit (wait) is done here.
1948- //
1949- void CCore::ApplyQueuedFrameRateLimit ()
1950- {
1951- if (m_bQueuedFrameRateValid)
1952- {
1953- m_bQueuedFrameRateValid = false ;
1954- // Calc required time in ms between frames
1955- const double dTargetTimeToUse = 1000.0 / m_uiQueuedFrameRate;
1956-
1957- while (true )
1958- {
1959- // See if we need to wait
1960- double dSpare = dTargetTimeToUse - m_FrameRateTimer.Get ();
1961- if (dSpare <= 0.0 )
1962- break ;
1963- if (dSpare >= 10.0 )
1964- Sleep (1 );
1965- }
1966- m_FrameRateTimer.Reset ();
1967- TIMING_GRAPH (" Limiter" );
1968- }
1840+ if (m_pNet != nullptr ) // We have to wait for the network module to be loaded
1841+ GetWebCore ()->OnFPSLimitChange (fps);
19691842}
19701843
19711844//
@@ -2020,7 +1893,7 @@ void CCore::OnDeviceRestore()
20201893void CCore::OnPreFxRender ()
20211894{
20221895 if (!CGraphics::GetSingleton ().HasLine3DPreGUIQueueItems () && !CGraphics::GetSingleton ().HasPrimitive3DPreGUIQueueItems ())
2023- return ;
1896+ return ;
20241897
20251898 CGraphics::GetSingleton ().EnteringMTARenderZone ();
20261899
@@ -2035,7 +1908,7 @@ void CCore::OnPreFxRender()
20351908//
20361909void CCore::OnPreHUDRender ()
20371910{
2038- CGraphics::GetSingleton ().EnteringMTARenderZone ();
1911+ CGraphics::GetSingleton ().EnteringMTARenderZone ();
20391912
20401913 // Maybe capture screen and other stuff
20411914 CGraphics::GetSingleton ().GetRenderItemManager ()->DoPulse ();
@@ -2396,7 +2269,8 @@ SString CCore::GetBlueCopyrightString()
23962269
23972270// Set streaming memory size override [See `engineStreamingSetMemorySize`]
23982271// Use `0` to turn it off, and thus restore the value to the `cvar` setting
2399- void CCore::SetCustomStreamingMemory (size_t sizeBytes) {
2272+ void CCore::SetCustomStreamingMemory (size_t sizeBytes)
2273+ {
24002274 // NOTE: The override is applied to the game in `CClientGame::DoPulsePostFrame`
24012275 // There's no specific reason we couldn't do it here, but we wont
24022276 m_CustomStreamingMemoryLimitBytes = sizeBytes;
0 commit comments