r5sdk/r5dev/engine/sys_dll2.cpp
Kawe Mazidjatari 609d705a0c Tier1: static construction of ConVar objects during link time
Fully implemented ConVar class so we could statically construct all SDK convars, this avoids a level of indirection, and allows for creating ConVar's everywhere in the project.

This patch also removed the settings tab of the ImGui server browser, as it has threading issues, while it technically never caused a crash yet, it has been removed as there was no point keeping it vs the work required to make it thread save (it only managed 2 convars which are perfectly manageable through cfg's or the in-game console).

Also temporarily disabled the creation of ConVar's in the mod system due to a memory leak, we would allocate and register a convar based on details parsed out of a mod file definition, but never unregister and free it.
2024-04-05 18:13:32 +02:00

285 lines
10 KiB
C++
Raw Blame History

//===== Copyright <20> 1996-2005, Valve Corporation, All rights reserved. ======//
//
// Purpose:
//
// $NoKeywords: $
//===========================================================================//
#include "core/stdafx.h"
#include "tier0/commandline.h"
#include "tier1/cmd.h"
#include "tier1/cvar.h"
#include "tier1/strtools.h"
#include "engine/sys_engine.h"
#include "engine/sys_dll.h"
#include "engine/sys_dll2.h"
#include "engine/host_cmd.h"
#include "engine/traceinit.h"
#ifndef DEDICATED
#include "engine/sys_mainwind.h"
#include "inputsystem/inputsystem.h"
#include "vgui/vgui_baseui_interface.h"
#include "materialsystem/cmaterialsystem.h"
#include "windows/id3dx.h"
#include "client/vengineclient_impl.h"
#include "geforce/reflex.h"
#endif // !DEDICATED
#include "filesystem/filesystem.h"
constexpr char DFS_ENABLE_PATH[] = "/vpk/enable.txt";
//-----------------------------------------------------------------------------
// Figure out if we're running a Valve mod or not.
//-----------------------------------------------------------------------------
static bool IsValveMod(const char* pModName)
{
return (Q_stricmp(pModName, "cstrike") == 0 ||
Q_stricmp(pModName, "dod") == 0 ||
Q_stricmp(pModName, "hl1mp") == 0 ||
Q_stricmp(pModName, "tf") == 0 ||
Q_stricmp(pModName, "hl2mp") == 0 ||
Q_stricmp(pModName, "csgo") == 0);
}
//-----------------------------------------------------------------------------
// Figure out if we're running a Respawn mod or not.
//-----------------------------------------------------------------------------
static bool IsRespawnMod(const char* pModName)
{
return (Q_stricmp(pModName, "r1") == 0 ||
Q_stricmp(pModName, "r2") == 0 ||
Q_stricmp(pModName, "r5") == 0);
}
//-----------------------------------------------------------------------------
// Initialize the VPK and file cache system
//-----------------------------------------------------------------------------
static void InitVPKSystem()
{
char szCacheEnableFilePath[260]; // [rsp+20h] [rbp-118h] BYREF
char bFixSlashes = FileSystem()->GetCurrentDirectory(szCacheEnableFilePath, sizeof(szCacheEnableFilePath)) ? szCacheEnableFilePath[0] : '\0';
size_t nCachePathLen = strlen(szCacheEnableFilePath);
size_t nCacheFileLen = sizeof(DFS_ENABLE_PATH)-1;
if ((nCachePathLen + nCacheFileLen) < 0x104 || (nCacheFileLen = (sizeof(szCacheEnableFilePath)-1) - nCachePathLen, nCachePathLen != (sizeof(szCacheEnableFilePath)-1)))
{
strncat(szCacheEnableFilePath, DFS_ENABLE_PATH, nCacheFileLen)[sizeof(szCacheEnableFilePath)-1] = '\0';
bFixSlashes = szCacheEnableFilePath[0];
}
if (bFixSlashes)
{
V_FixSlashes(szCacheEnableFilePath, '/');
}
if (!CommandLine()->CheckParm("-novpk") && FileSystem()->FileExists(szCacheEnableFilePath, nullptr))
{
FileSystem()->AddSearchPath(".", "MAIN", SearchPathAdd_t::PATH_ADD_TO_TAIL);
#ifndef DEDICATED
FileSystem()->SetVPKCacheModeClient();
FileSystem()->MountVPKFile("vpk/client_frontend.bsp");
#else // Dedicated runs server vpk's and must have 'vpk/mp_common.bsp' mounted.
FileSystem()->SetVPKCacheModeServer();
FileSystem()->MountVPKFile("vpk/server_mp_common.bsp");
#endif // !DEDICATED
}
}
InitReturnVal_t CEngineAPI::VInit(CEngineAPI* pEngineAPI)
{
return CEngineAPI__Init(pEngineAPI);
}
//-----------------------------------------------------------------------------
// Initialization, shutdown of a mod.
//-----------------------------------------------------------------------------
bool CEngineAPI::VModInit(CEngineAPI* pEngineAPI, const char* pModName, const char* pGameDir)
{
// Register new Pak Assets here!
//RTech_RegisterAsset(0, 1, "", nullptr, nullptr, nullptr, CMemory(0x1660AD0A8).RCast<void**>(), 8, 8, 8, 0, 0xFFFFFFC);
bool results = CEngineAPI__ModInit(pEngineAPI, pModName, pGameDir);
if (!IsValveMod(pModName) && !IsRespawnMod(pModName))
{
#ifndef DEDICATED
g_pEngineClient->SetRestrictServerCommands(true); // Restrict server commands.
g_pEngineClient->SetRestrictClientCommands(true); // Restrict client commands.
#endif // !DEDICATED
}
return results;
}
//-----------------------------------------------------------------------------
// Sets startup info
//-----------------------------------------------------------------------------
void CEngineAPI::VSetStartupInfo(CEngineAPI* pEngineAPI, StartupInfo_t* pStartupInfo)
{
if (*g_bTextMode)
{
return;
}
const size_t nBufLen = sizeof(pStartupInfo->m_szBaseDirectory);
strncpy(g_szBaseDir, pStartupInfo->m_szBaseDirectory, nBufLen);
g_pEngineParms->baseDirectory = g_szBaseDir;
g_szBaseDir[nBufLen-1] = '\0';
void** pCurrentInstance = &pEngineAPI->m_StartupInfo.m_pInstance;
size_t nInstances = 6;
do
{
pCurrentInstance += 16;
uint64_t pInstance = *(_QWORD*)&pStartupInfo->m_pInstance;
pStartupInfo = (StartupInfo_t*)((char*)pStartupInfo + 128);
*((_QWORD*)pCurrentInstance - 8) = pInstance;
*((_QWORD*)pCurrentInstance - 7) = *(_QWORD*)&pStartupInfo[-1].m_pParentAppSystemGroup[132];
*((_QWORD*)pCurrentInstance - 6) = *(_QWORD*)&pStartupInfo[-1].m_pParentAppSystemGroup[148];
*((_QWORD*)pCurrentInstance - 5) = *(_QWORD*)&pStartupInfo[-1].m_pParentAppSystemGroup[164];
*((_QWORD*)pCurrentInstance - 4) = *(_QWORD*)&pStartupInfo[-1].m_pParentAppSystemGroup[180];
*((_QWORD*)pCurrentInstance - 3) = *(_QWORD*)&pStartupInfo[-1].m_pParentAppSystemGroup[196];
*((_QWORD*)pCurrentInstance - 2) = *(_QWORD*)&pStartupInfo[-1].m_pParentAppSystemGroup[212];
*((_QWORD*)pCurrentInstance - 1) = *(_QWORD*)&pStartupInfo[-1].m_pParentAppSystemGroup[228];
--nInstances;
} while (nInstances);
*(_QWORD*)pCurrentInstance = *(_QWORD*)&pStartupInfo->m_pInstance;
*((_QWORD*)pCurrentInstance + 1) = *(_QWORD*)&pStartupInfo->m_szBaseDirectory[8];
InitVPKSystem();
v_TRACEINIT(NULL, "COM_InitFilesystem( m_StartupInfo.m_szInitialMod )", "COM_ShutdownFileSystem()");
v_COM_InitFilesystem(pEngineAPI->m_StartupInfo.m_szInitialMod);
*g_bTextMode = true;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CEngineAPI::PumpMessages()
{
#ifndef DEDICATED
MSG msg;
while (PeekMessageW(&msg, NULL, 0, 0, PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessageW(&msg);
}
if (in_syncRT->GetBool())
(*g_fnSyncRTWithIn)();
g_pInputSystem->PollInputState(v_UIEventDispatcher);
g_pGame->DispatchAllStoredGameMessages();
#endif // !DEDICATED
}
#ifndef DEDICATED
//-----------------------------------------------------------------------------
// Purpose: force update NVIDIA Reflex Low Latency parameters
//-----------------------------------------------------------------------------
static void GFX_NVN_Changed_f(IConVar* pConVar, const char* pOldString)
{
GFX_MarkLowLatencyParametersOutOfDate();
}
static ConVar fps_max_gfx("fps_max_gfx", "0", FCVAR_RELEASE, "Frame rate limiter using NVIDIA Reflex Low Latency SDK. -1 indicates the use of desktop refresh. 0 is disabled.", true, -1.f, true, 295.f, GFX_NVN_Changed_f);
static ConVar gfx_nvnUseLowLatency("gfx_nvnUseLowLatency", "1", FCVAR_RELEASE | FCVAR_ARCHIVE, "Enables NVIDIA Reflex Low Latency SDK.", GFX_NVN_Changed_f);
static ConVar gfx_nvnUseLowLatencyBoost("gfx_nvnUseLowLatencyBoost", "0", FCVAR_RELEASE | FCVAR_ARCHIVE, "Enables NVIDIA Reflex Low Latency Boost.", GFX_NVN_Changed_f);
// NOTE: defaulted to 0 as it causes rubber banding on some hardware.
static ConVar gfx_nvnUseMarkersToOptimize("gfx_nvnUseMarkersToOptimize", "0", FCVAR_RELEASE, "Use NVIDIA Reflex Low Latency markers to optimize (requires Low Latency Boost to be enabled).", GFX_NVN_Changed_f);
#endif // !DEDICATED
void CEngineAPI::UpdateLowLatencyParameters()
{
#ifndef DEDICATED
const bool bUseLowLatencyMode = gfx_nvnUseLowLatency.GetBool();
const bool bUseLowLatencyBoost = gfx_nvnUseLowLatencyBoost.GetBool();
const bool bUseMarkersToOptimize = gfx_nvnUseMarkersToOptimize.GetBool();
float fpsMax = fps_max_gfx.GetFloat();
if (fpsMax == -1.0f)
{
const float globalFps = fps_max->GetFloat();
// Make sure the global fps limiter is 'unlimited'
// before we let the gfx frame limiter cap it to
// the desktop's refresh rate; not adhering to
// this will result in a major performance drop.
if (globalFps == 0.0f)
fpsMax = g_pGame->GetTVRefreshRate();
else
fpsMax = 0.0f; // Don't let NVIDIA limit the frame rate.
}
GFX_UpdateLowLatencyParameters(D3D11Device(), bUseLowLatencyMode,
bUseLowLatencyBoost, bUseMarkersToOptimize, fpsMax);
#endif // !DEDICATED
}
void CEngineAPI::RunLowLatencyFrame()
{
#ifndef DEDICATED
if (GFX_IsLowLatencySDKEnabled())
{
if (GFX_HasPendingLowLatencyParameterUpdates())
{
UpdateLowLatencyParameters();
}
GFX_RunLowLatencyFrame(D3D11Device());
}
#endif // !DEDICATED
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
bool CEngineAPI::MainLoop()
{
#ifndef DEDICATED
bool bRunLowLatency = false;
#endif // !DEDICATED
// Main message pump
while (true)
{
// Pump messages unless someone wants to quit
if (g_pEngine->GetQuitting() != IEngine::QUIT_NOTQUITTING)
{
if (g_pEngine->GetQuitting() != IEngine::QUIT_TODESKTOP) {
return true;
}
return false;
}
#ifndef DEDICATED
if (bRunLowLatency) {
CEngineAPI::RunLowLatencyFrame();
bRunLowLatency = false;
}
CEngineAPI::PumpMessages();
#endif // !DEDICATED
if (g_pEngine->Frame())
{
#ifndef DEDICATED
// Only run reflex if we ran an actual engine frame.
bRunLowLatency = true;
#endif // !DEDICATED
}
}
}
///////////////////////////////////////////////////////////////////////////////
void VSys_Dll2::Detour(const bool bAttach) const
{
DetourSetup(&CEngineAPI__Init, &CEngineAPI::VInit, bAttach);
DetourSetup(&CEngineAPI__ModInit, &CEngineAPI::VModInit, bAttach);
DetourSetup(&CEngineAPI__PumpMessages, &CEngineAPI::PumpMessages, bAttach);
DetourSetup(&CEngineAPI__MainLoop, &CEngineAPI::MainLoop, bAttach);
DetourSetup(&CEngineAPI__SetStartupInfo, &CEngineAPI::VSetStartupInfo, bAttach);
}