mirror of
https://github.com/Mauler125/r5sdk.git
synced 2025-02-09 19:15:03 +01:00
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.
285 lines
10 KiB
C++
285 lines
10 KiB
C++
//===== 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);
|
||
}
|