From 5105ea771d13b491340952d9aefe1948e0361a6d Mon Sep 17 00:00:00 2001 From: Kawe Mazidjatari <48657826+Mauler125@users.noreply.github.com> Date: Fri, 22 Dec 2023 14:42:28 +0100 Subject: [PATCH 01/24] NVIDIA: initial implementation of latency markers --- src/common/global.cpp | 6 ++- src/common/global.h | 1 + src/core/init.cpp | 2 + src/engine/CMakeLists.txt | 2 + src/engine/client/cdll_engine_int.cpp | 55 ++++++++++++++++++++++++++ src/engine/gl_drawlights.cpp | 13 ++++++ src/engine/gl_drawlights.h | 23 +++++++++++ src/engine/gl_rsurf.cpp | 9 +++++ src/engine/gl_rsurf.h | 6 +++ src/engine/host.cpp | 20 ++++++++++ src/engine/host.h | 18 ++++++--- src/engine/sys_dll2.cpp | 3 +- src/materialsystem/cmaterialsystem.cpp | 36 +++++++++++------ src/materialsystem/cmaterialsystem.h | 9 ++++- 14 files changed, 182 insertions(+), 21 deletions(-) create mode 100644 src/engine/gl_drawlights.cpp create mode 100644 src/engine/gl_drawlights.h diff --git a/src/common/global.cpp b/src/common/global.cpp index 51b4cff3..850ba453 100644 --- a/src/common/global.cpp +++ b/src/common/global.cpp @@ -75,6 +75,7 @@ ConVar* r_visualizetraces_duration = nullptr; ConVar* gfx_nvnUseLowLatency = nullptr; ConVar* gfx_nvnUseLowLatencyBoost = nullptr; +ConVar* gfx_nvnUseMarkersToOptimize = nullptr; #endif // !DEDICATED ConVar* stream_overlay = nullptr; @@ -337,8 +338,9 @@ void ConVar_StaticInit(void) fps_max_rt_sleep_threshold = ConVar::StaticCreate("fps_max_rt_sleep_threshold", "0.016666667", FCVAR_RELEASE, "Frame limiter starts to sleep when frame time exceeds this threshold.", true, 0.f, false, 0.f, nullptr, nullptr); fps_max_gfx = ConVar::StaticCreate("fps_max_gfx", "0", FCVAR_RELEASE, "Frame rate limiter using NVIDIA Reflex Low Latency SDK. -1 indicates use the desktop refresh. 0 is disabled.", true, -1.f, true, 295.f, &GFX_NVN_Changed_f, nullptr); - gfx_nvnUseLowLatency = ConVar::StaticCreate("gfx_nvnUseLowLatency" , "1", FCVAR_RELEASE | FCVAR_ARCHIVE, "Enables NVIDIA Reflex Low Latency SDK." , false, 0.f, false, 0.f, &GFX_NVN_Changed_f, nullptr); - gfx_nvnUseLowLatencyBoost = ConVar::StaticCreate("gfx_nvnUseLowLatencyBoost", "0", FCVAR_RELEASE | FCVAR_ARCHIVE, "Enables NVIDIA Reflex Low Latency Boost.", false, 0.f, false, 0.f, &GFX_NVN_Changed_f, nullptr); + gfx_nvnUseLowLatency = ConVar::StaticCreate("gfx_nvnUseLowLatency" , "1", FCVAR_RELEASE | FCVAR_ARCHIVE, "Enables NVIDIA Reflex Low Latency SDK." , false, 0.f, false, 0.f, &GFX_NVN_Changed_f, nullptr); + gfx_nvnUseLowLatencyBoost = ConVar::StaticCreate("gfx_nvnUseLowLatencyBoost" , "0", FCVAR_RELEASE | FCVAR_ARCHIVE, "Enables NVIDIA Reflex Low Latency Boost.", false, 0.f, false, 0.f, &GFX_NVN_Changed_f, nullptr); + gfx_nvnUseMarkersToOptimize = ConVar::StaticCreate("gfx_nvnUseMarkersToOptimize", "0", FCVAR_RELEASE | FCVAR_ARCHIVE, "Use NVIDIA Reflex Low Latency markers to optimize (requires Low Latency Boost to be enabled).", false, 0.f, false, 0.f, &GFX_NVN_Changed_f, nullptr); #endif // !DEDICATED //------------------------------------------------------------------------- diff --git a/src/common/global.h b/src/common/global.h index 1c3a1ee3..3d546b56 100644 --- a/src/common/global.h +++ b/src/common/global.h @@ -66,6 +66,7 @@ extern ConVar* r_visualizetraces_duration; extern ConVar* gfx_nvnUseLowLatency; extern ConVar* gfx_nvnUseLowLatencyBoost; +extern ConVar* gfx_nvnUseMarkersToOptimize; #endif // !DEDICATED extern ConVar* stream_overlay; diff --git a/src/core/init.cpp b/src/core/init.cpp index f1be0083..61c80dee 100644 --- a/src/core/init.cpp +++ b/src/core/init.cpp @@ -100,6 +100,7 @@ #include "engine/sys_mainwind.h" #include "engine/matsys_interface.h" #include "engine/gl_matsysiface.h" +#include "engine/gl_drawlights.h" #include "engine/gl_screen.h" #include "engine/gl_rsurf.h" #include "engine/debugoverlay.h" @@ -581,6 +582,7 @@ void DetourRegister() // Register detour classes to be searched and hooked. REGISTER(VGL_RMain); REGISTER(VMatSys_Interface); REGISTER(VGL_MatSysIFace); + REGISTER(VGL_DrawLights); REGISTER(VGL_Screen); #endif // !DEDICATED diff --git a/src/engine/CMakeLists.txt b/src/engine/CMakeLists.txt index 4caac9d9..a27fa06f 100644 --- a/src/engine/CMakeLists.txt +++ b/src/engine/CMakeLists.txt @@ -29,6 +29,8 @@ add_sources( SOURCE_GROUP "Debug" add_sources( SOURCE_GROUP "Render" "framelimit.cpp" "framelimit.h" + "gl_drawlights.cpp" + "gl_drawlights.h" "gl_matsysiface.h" "gl_model_private.h" "gl_rmain.cpp" diff --git a/src/engine/client/cdll_engine_int.cpp b/src/engine/client/cdll_engine_int.cpp index 97f40254..c6acb0e4 100644 --- a/src/engine/client/cdll_engine_int.cpp +++ b/src/engine/client/cdll_engine_int.cpp @@ -18,12 +18,67 @@ /*****************************************************************************/ #ifndef DEDICATED +//----------------------------------------------------------------------------- +// Purpose: pre frame stage notify hook +//----------------------------------------------------------------------------- +void FrameStageNotify_Pre(const ClientFrameStage_t frameStage) +{ + switch (frameStage) + { + case ClientFrameStage_t::FRAME_START: + break; + case ClientFrameStage_t::FRAME_NET_UPDATE_START: + break; + case ClientFrameStage_t::FRAME_NET_UPDATE_POSTDATAUPDATE_START: + break; + case ClientFrameStage_t::FRAME_NET_UPDATE_POSTDATAUPDATE_END: + break; + case ClientFrameStage_t::FRAME_NET_UPDATE_END: + break; + case ClientFrameStage_t::FRAME_RENDER_START: + break; + case ClientFrameStage_t::FRAME_RENDER_END: + break; + case ClientFrameStage_t::FRAME_NET_FULL_FRAME_UPDATE_ON_REMOVE: + break; + } +} + +//----------------------------------------------------------------------------- +// Purpose: post frame stage notify hook +//----------------------------------------------------------------------------- +void FrameStageNotify_Post(const ClientFrameStage_t frameStage) +{ + switch (frameStage) + { + case ClientFrameStage_t::FRAME_START: + break; + case ClientFrameStage_t::FRAME_NET_UPDATE_START: + break; + case ClientFrameStage_t::FRAME_NET_UPDATE_POSTDATAUPDATE_START: + break; + case ClientFrameStage_t::FRAME_NET_UPDATE_POSTDATAUPDATE_END: + break; + case ClientFrameStage_t::FRAME_NET_UPDATE_END: + break; + case ClientFrameStage_t::FRAME_RENDER_START: + break; + case ClientFrameStage_t::FRAME_RENDER_END: + GFX_SetLatencyMarker(D3D11Device(), SIMULATION_END); + break; + case ClientFrameStage_t::FRAME_NET_FULL_FRAME_UPDATE_ON_REMOVE: + break; + } +} + //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CHLClient::FrameStageNotify(CHLClient* pHLClient, ClientFrameStage_t frameStage) { + FrameStageNotify_Pre(frameStage); CHLClient_FrameStageNotify(pHLClient, frameStage); + FrameStageNotify_Post(frameStage); } //----------------------------------------------------------------------------- diff --git a/src/engine/gl_drawlights.cpp b/src/engine/gl_drawlights.cpp new file mode 100644 index 00000000..40b69635 --- /dev/null +++ b/src/engine/gl_drawlights.cpp @@ -0,0 +1,13 @@ +#include "gl_drawlights.h" + + +void DrawLightSprites(void* unkType) +{ + v_DrawLightSprites(unkType); +} + +void VGL_DrawLights::Detour(const bool bAttach) const +{ + // Enable if needed. + //DetourSetup(&v_DrawLightSprites, &DrawLightSprites, bAttach); +} diff --git a/src/engine/gl_drawlights.h b/src/engine/gl_drawlights.h new file mode 100644 index 00000000..6194bbc6 --- /dev/null +++ b/src/engine/gl_drawlights.h @@ -0,0 +1,23 @@ +#pragma once + +inline CMemory p_DrawLightSprites; +inline void(*v_DrawLightSprites)(void*); + + +/////////////////////////////////////////////////////////////////////////////// +class VGL_DrawLights : public IDetour +{ + virtual void GetAdr(void) const + { + LogFunAdr("DrawLightSprites", p_DrawLightSprites.GetPtr()); + } + virtual void GetFun(void) const + { + p_DrawLightSprites = g_GameDll.FindPatternSIMD("48 8B C4 55 57 48 8D 68 A1 48 81 EC ?? ?? ?? ?? 48 8B 15 ?? ?? ?? ??"); + v_DrawLightSprites = p_DrawLightSprites.RCast(); + } + virtual void GetVar(void) const { } + virtual void GetCon(void) const { } + virtual void Detour(const bool bAttach) const; +}; +/////////////////////////////////////////////////////////////////////////////// diff --git a/src/engine/gl_rsurf.cpp b/src/engine/gl_rsurf.cpp index 997a3ccc..695526b5 100644 --- a/src/engine/gl_rsurf.cpp +++ b/src/engine/gl_rsurf.cpp @@ -6,8 +6,16 @@ //===========================================================================// #include "core/stdafx.h" #include "tier1/cvar.h" +#include "windows/id3dx.h" +#include "geforce/reflex.h" #include "engine/gl_rsurf.h" +void* R_DrawDepthOfField(const float a1) +{ + GFX_SetLatencyMarker(D3D11Device(), RENDERSUBMIT_START); + return V_DrawDepthOfField(a1); +} + void* R_DrawWorldMeshes(void* baseEntity, void* renderContext, DrawWorldLists_t worldLists) { if (r_drawWorldMeshes->GetBool()) @@ -34,6 +42,7 @@ void* R_DrawWorldMeshesDepthAtTheEnd(void* ptr1, void* ptr2, void* ptr3, DrawWor void VGL_RSurf::Detour(const bool bAttach) const { + DetourSetup(&V_DrawDepthOfField, &R_DrawDepthOfField, bAttach); DetourSetup(&V_DrawWorldMeshes, &R_DrawWorldMeshes, bAttach); DetourSetup(&V_DrawWorldMeshesDepthOnly, &R_DrawWorldMeshesDepthOnly, bAttach); DetourSetup(&V_DrawWorldMeshesDepthAtTheEnd, &R_DrawWorldMeshesDepthAtTheEnd, bAttach); diff --git a/src/engine/gl_rsurf.h b/src/engine/gl_rsurf.h index ff793a41..902477e2 100644 --- a/src/engine/gl_rsurf.h +++ b/src/engine/gl_rsurf.h @@ -1,6 +1,9 @@ #pragma once #include "public/ivrenderview.h" +inline CMemory P_DrawDepthOfField; +inline void*(*V_DrawDepthOfField)(const float a1); + inline CMemory P_DrawWorldMeshes; inline void*(*V_DrawWorldMeshes)(void* baseEntity, void* renderContext, DrawWorldLists_t worldLists); @@ -15,12 +18,14 @@ class VGL_RSurf : public IDetour { virtual void GetAdr(void) const { + LogFunAdr("R_DrawDepthOfField", P_DrawDepthOfField.GetPtr()); LogFunAdr("R_DrawWorldMeshes", P_DrawWorldMeshes.GetPtr()); LogFunAdr("R_DrawWorldMeshesDepthOnly", P_DrawWorldMeshesDepthOnly.GetPtr()); LogFunAdr("R_DrawWorldMeshesDepthAtTheEnd", P_DrawWorldMeshesDepthAtTheEnd.GetPtr()); } virtual void GetFun(void) const { + P_DrawDepthOfField = g_GameDll.FindPatternSIMD("48 83 EC 48 0F 28 E8"); #if defined (GAMEDLL_S0) || defined (GAMEDLL_S1) P_DrawWorldMeshes = g_GameDll.FindPatternSIMD("48 8B C4 48 89 48 08 53 48 83 EC 70"); #elif defined (GAMEDLL_S2) || defined (GAMEDLL_S3) @@ -29,6 +34,7 @@ class VGL_RSurf : public IDetour P_DrawWorldMeshesDepthOnly = g_GameDll.FindPatternSIMD("40 56 57 B8 ?? ?? ?? ??"); P_DrawWorldMeshesDepthAtTheEnd = g_GameDll.FindPatternSIMD("48 89 5C 24 ?? 48 89 74 24 ?? 57 48 83 EC 20 48 8B 0D ?? ?? ?? ?? 41 8B F9"); + V_DrawDepthOfField = P_DrawDepthOfField.RCast(); V_DrawWorldMeshes = P_DrawWorldMeshes.RCast(); /*48 8B C4 48 89 48 08 53 57 41 55*/ V_DrawWorldMeshesDepthOnly = P_DrawWorldMeshesDepthOnly.RCast(); /*40 56 57 B8 ?? ?? ?? ??*/ V_DrawWorldMeshesDepthAtTheEnd = P_DrawWorldMeshesDepthAtTheEnd.RCast(); /*48 89 5C 24 ?? 48 89 74 24 ? 57 48 83 EC 20 48 8B 0D ?? ?? ?? ?? 41 8B F9*/ diff --git a/src/engine/host.cpp b/src/engine/host.cpp index ae5a8715..f605ce81 100644 --- a/src/engine/host.cpp +++ b/src/engine/host.cpp @@ -9,6 +9,8 @@ #include "tier0/frametask.h" #include "engine/host.h" #ifndef DEDICATED +#include "windows/id3dx.h" +#include "geforce/reflex.h" #include "vgui/vgui_debugpanel.h" #endif // !DEDICATED @@ -30,6 +32,23 @@ void CCommonHostState::SetWorldModel(model_t* pModel) } } +/* +================== +Host_CountRealTimePackets + +Counts the number of +packets in non-prescaled +clock frames (does not +count for bots or Terminal +Services environments) +================== +*/ +void Host_CountRealTimePackets() +{ + v_Host_CountRealTimePackets(); + GFX_SetLatencyMarker(D3D11Device(), SIMULATION_START); +} + /* ================== _Host_RunFrame @@ -77,6 +96,7 @@ void _Host_Error(const char* error, ...) void VHost::Detour(const bool bAttach) const { DetourSetup(&v_Host_RunFrame, &_Host_RunFrame, bAttach); + DetourSetup(&v_Host_CountRealTimePackets, &Host_CountRealTimePackets, bAttach); #ifndef DEDICATED // Dedicated already logs this! DetourSetup(&v_Host_Error, &_Host_Error, bAttach); diff --git a/src/engine/host.h b/src/engine/host.h index 1dce0e30..ec649ddc 100644 --- a/src/engine/host.h +++ b/src/engine/host.h @@ -4,8 +4,11 @@ inline CMemory p_Host_RunFrame; inline void(*v_Host_RunFrame)(void* unused, float time); -//inline CMemory p_Host_RunFrame_Render; // DEDICATED PATCH! -//inline void(*v_Host_RunFrame_Render)(void); +inline CMemory p_Host_RunFrame_Render; +inline void(*v_Host_RunFrame_Render)(void); + +inline CMemory p_Host_CountRealTimePackets; +inline void(*v_Host_CountRealTimePackets)(void); inline CMemory p_Host_ShouldRun; inline bool(*v_Host_ShouldRun)(); @@ -54,7 +57,8 @@ class VHost : public IDetour virtual void GetAdr(void) const { LogFunAdr("_Host_RunFrame", p_Host_RunFrame.GetPtr()); - //LogFunAdr("_Host_RunFrame_Render", p_Host_RunFrame_Render.GetPtr()); + LogFunAdr("_Host_RunFrame_Render", p_Host_RunFrame_Render.GetPtr()); + LogFunAdr("Host_CountRealTimePackets", p_Host_CountRealTimePackets.GetPtr()); LogFunAdr("Host_ShouldRun", p_Host_ShouldRun.GetPtr()); LogFunAdr("Host_Error", p_Host_Error.GetPtr()); //LogFunAdr("VCR_EnterPausedState", p_VCR_EnterPausedState.GetPtr()); @@ -69,16 +73,18 @@ class VHost : public IDetour { p_Host_RunFrame = g_GameDll.FindPatternSIMD("48 8B C4 48 89 58 18 48 89 70 20 F3 0F 11 48 ??"); #if defined (GAMEDLL_S0) || defined (GAMEDLL_S1) - //p_Host_RunFrame_Render = g_GameDll.FindPatternSIMD("48 89 5C 24 ?? 57 48 83 EC 20 48 8B 1D ?? ?? ?? ?? 33 FF"); + p_Host_RunFrame_Render = g_GameDll.FindPatternSIMD("48 89 5C 24 ?? 57 48 83 EC 20 48 8B 1D ?? ?? ?? ?? 33 FF"); #elif defined (GAMEDLL_S2) || defined (GAMEDLL_S3) - //p_Host_RunFrame_Render = g_GameDll.FindPatternSIMD("40 53 48 83 EC 20 48 8B 0D ?? ?? ?? ?? 48 85 C9 75 34"); + p_Host_RunFrame_Render = g_GameDll.FindPatternSIMD("40 53 48 83 EC 20 48 8B 0D ?? ?? ?? ?? 48 85 C9 75 34"); #endif + p_Host_CountRealTimePackets = g_GameDll.FindPatternSIMD("40 53 48 83 EC 30 65 48 8B 04 25 ?? ?? ?? ?? 33 DB"); p_Host_ShouldRun = g_GameDll.FindPatternSIMD("48 83 EC 28 48 8B 05 ?? ?? ?? ?? 83 78 6C 00 75 07 B0 01"); p_Host_Error = g_GameDll.FindPatternSIMD("48 89 4C 24 ?? 48 89 54 24 ?? 4C 89 44 24 ?? 4C 89 4C 24 ?? 53 57 48 81 EC ?? ?? ?? ??"); //p_VCR_EnterPausedState = g_GameDll.FindPatternSIMD("40 53 48 83 EC 20 65 48 8B 04 25 ?? ?? ?? ?? BB ?? ?? ?? ?? C6 05 ?? ?? ?? ?? ??"); v_Host_RunFrame = p_Host_RunFrame.RCast(); - //v_Host_RunFrame_Render = p_Host_Error.RCast(); + v_Host_RunFrame_Render = p_Host_RunFrame_Render.RCast(); + v_Host_CountRealTimePackets = p_Host_CountRealTimePackets.RCast(); v_Host_ShouldRun = p_Host_ShouldRun.RCast(); v_Host_Error = p_Host_Error.RCast(); //v_VCR_EnterPausedState = p_VCR_EnterPausedState.RCast(); diff --git a/src/engine/sys_dll2.cpp b/src/engine/sys_dll2.cpp index 46c583ee..d9dc35c2 100644 --- a/src/engine/sys_dll2.cpp +++ b/src/engine/sys_dll2.cpp @@ -190,6 +190,7 @@ bool CEngineAPI::MainLoop() { const bool bUseLowLatencyMode = gfx_nvnUseLowLatency->GetBool(); const bool bUseLowLatencyBoost = gfx_nvnUseLowLatencyBoost->GetBool(); + const bool bUseMarkersToOptimize = gfx_nvnUseMarkersToOptimize->GetBool(); float fpsMax = fps_max_gfx->GetFloat(); @@ -208,7 +209,7 @@ bool CEngineAPI::MainLoop() } GFX_UpdateLowLatencyParameters(D3D11Device(), bUseLowLatencyMode, - bUseLowLatencyBoost, false, fpsMax); + bUseLowLatencyBoost, bUseMarkersToOptimize, fpsMax); } GFX_RunLowLatencyFrame(D3D11Device()); diff --git a/src/materialsystem/cmaterialsystem.cpp b/src/materialsystem/cmaterialsystem.cpp index 671dae11..851fcd79 100644 --- a/src/materialsystem/cmaterialsystem.cpp +++ b/src/materialsystem/cmaterialsystem.cpp @@ -12,12 +12,13 @@ #include "engine/cmodel_bsp.h" #include "geforce/reflex.h" #ifndef MATERIALSYSTEM_NODX +#include "windows/id3dx.h" #include "materialsystem/cmaterialglue.h" #endif // !MATERIALSYSTEM_NODX #include "materialsystem/cmaterialsystem.h" #ifndef MATERIALSYSTEM_NODX -//PCLSTATS_DEFINE() +PCLSTATS_DEFINE() #endif // MATERIALSYSTEM_NODX //----------------------------------------------------------------------------- @@ -38,10 +39,10 @@ InitReturnVal_t CMaterialSystem::Init(CMaterialSystem* thisptr) // Initialize as usual. GFX_EnableLowLatencySDK(!CommandLine()->CheckParm("-gfx_nvnDisableLowLatency")); - //if (GFX_IsLowLatencySDKEnabled()) - //{ - // PCLSTATS_INIT(0); - //} + if (GFX_IsLowLatencySDKEnabled()) + { + PCLSTATS_INIT(0); + } return CMaterialSystem__Init(thisptr); #endif @@ -52,10 +53,10 @@ InitReturnVal_t CMaterialSystem::Init(CMaterialSystem* thisptr) //----------------------------------------------------------------------------- int CMaterialSystem::Shutdown(CMaterialSystem* thisptr) { - //if (GFX_IsLowLatencySDKEnabled()) - //{ - // PCLSTATS_SHUTDOWN(); - //} + if (GFX_IsLowLatencySDKEnabled()) + { + PCLSTATS_SHUTDOWN(); + } return CMaterialSystem__Shutdown(thisptr); } @@ -108,9 +109,21 @@ void* __fastcall DispatchDrawCall(int64_t a1, uint64_t a2, int a3, int a4, int64 return v_DispatchDrawCall(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14); #endif } -#endif // !MATERIALSYSTEM_NODX -#ifndef MATERIALSYSTEM_NODX +//--------------------------------------------------------------------------------- +// Purpose: run IDXGISwapChain::Present +//--------------------------------------------------------------------------------- +ssize_t SpinPresent(void) +{ + GFX_SetLatencyMarker(D3D11Device(), RENDERSUBMIT_END); + + GFX_SetLatencyMarker(D3D11Device(), PRESENT_START); + const ssize_t val = v_SpinPresent(); + GFX_SetLatencyMarker(D3D11Device(), PRESENT_END); + + return val; +} + //----------------------------------------------------------------------------- // Purpose: finds a material // Input : *pMatSys - @@ -154,6 +167,7 @@ void VMaterialSystem::Detour(const bool bAttach) const #ifndef MATERIALSYSTEM_NODX DetourSetup(&v_StreamDB_Init, &StreamDB_Init, bAttach); DetourSetup(&v_DispatchDrawCall, &DispatchDrawCall, bAttach); + DetourSetup(&v_SpinPresent, &SpinPresent, bAttach); DetourSetup(&CMaterialSystem__FindMaterialEx, &CMaterialSystem::FindMaterialEx, bAttach); #endif // !MATERIALSYSTEM_NODX } diff --git a/src/materialsystem/cmaterialsystem.h b/src/materialsystem/cmaterialsystem.h index f2422631..1058ca96 100644 --- a/src/materialsystem/cmaterialsystem.h +++ b/src/materialsystem/cmaterialsystem.h @@ -75,6 +75,9 @@ inline void*(*v_DispatchDrawCall)(int64_t a1, uint64_t a2, int a3, int a4, char inline CMemory p_DispatchDrawCall; inline void*(*v_DispatchDrawCall)(int64_t a1, uint64_t a2, int a3, int a4, int64_t a5, int a6, uint8_t a7, int64_t a8, uint32_t a9, uint32_t a10, int a11, __m128* a12, int a13, int64_t a14); #endif +inline CMemory p_SpinPresent; +inline ssize_t(*v_SpinPresent)(void); + inline CMemory p_GetStreamOverlay; inline void(*v_GetStreamOverlay)(const char* mode, char* buf, size_t bufSize); @@ -100,9 +103,10 @@ class VMaterialSystem : public IDetour #ifndef MATERIALSYSTEM_NODX LogFunAdr("CMaterialSystem::FindMaterialEx", p_CMaterialSystem__FindMaterialEx.GetPtr()); LogFunAdr("CMaterialSystem::GetScreenSize", p_CMaterialSystem_GetScreenSize.GetPtr()); - LogFunAdr("CMaterialSystem::DispatchDrawCall", p_DispatchDrawCall.GetPtr()); LogFunAdr("CMaterialSystem::GetStreamOverlay", p_GetStreamOverlay.GetPtr()); LogFunAdr("CMaterialSystem::DrawStreamOverlay", p_DrawStreamOverlay.GetPtr()); + LogFunAdr("DispatchDrawCall", p_DispatchDrawCall.GetPtr()); + LogFunAdr("SpinPresent", p_SpinPresent.GetPtr()); LogVarAdr("g_nTotalStreamingTextureMemory", reinterpret_cast(g_nTotalStreamingTextureMemory)); LogVarAdr("g_nUnfreeStreamingTextureMemory", reinterpret_cast(g_nUnfreeStreamingTextureMemory)); LogVarAdr("g_nUnusableStreamingTextureMemory", reinterpret_cast(g_nUnusableStreamingTextureMemory)); @@ -134,6 +138,9 @@ class VMaterialSystem : public IDetour p_DispatchDrawCall = g_GameDll.FindPatternSIMD("44 89 4C 24 ?? 44 89 44 24 ?? 48 89 4C 24 ?? 55 53 56"); v_DispatchDrawCall = p_DispatchDrawCall.RCast(); #endif + p_SpinPresent = g_GameDll.FindPatternSIMD("48 89 5C 24 ?? 48 89 74 24 ?? 57 48 81 EC ?? ?? ?? ?? 8B 15 ?? ?? ?? ??"); + v_SpinPresent = p_SpinPresent.RCast(); + p_GetStreamOverlay = g_GameDll.FindPatternSIMD("E8 ?? ?? ?? ?? 80 7C 24 ?? ?? 0F 84 ?? ?? ?? ?? 48 89 9C 24 ?? ?? ?? ??").FollowNearCallSelf(); v_GetStreamOverlay = p_GetStreamOverlay.RCast(); /*E8 ? ? ? ? 80 7C 24 ? ? 0F 84 ? ? ? ? 48 89 9C 24 ? ? ? ?*/ From 33276544131a38190c17c634617a6a8fd28c3363 Mon Sep 17 00:00:00 2001 From: Kawe Mazidjatari <48657826+Mauler125@users.noreply.github.com> Date: Sat, 23 Dec 2023 01:15:43 +0100 Subject: [PATCH 02/24] Add PCLSTATS marker --- src/geforce/reflex.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/geforce/reflex.cpp b/src/geforce/reflex.cpp index 1e8bd321..824c4fde 100644 --- a/src/geforce/reflex.cpp +++ b/src/geforce/reflex.cpp @@ -159,4 +159,5 @@ void GFX_SetLatencyMarker(IUnknown* device, params.markerType = markerType; NvAPI_D3D_SetLatencyMarker(device, ¶ms); + PCLSTATS_MARKER(markerType, s_ReflexFrameNumber); } From d608c734bd89dc4ccedfc62a6f1c325fb0335e67 Mon Sep 17 00:00:00 2001 From: Kawe Mazidjatari <48657826+Mauler125@users.noreply.github.com> Date: Sat, 23 Dec 2023 01:22:02 +0100 Subject: [PATCH 03/24] Add/update core headers --- src/core/stdafx.h | 2 + src/engine/sys_dll2.h | 6 +- src/public/appframework/IAppSystem.h | 20 +++++-- src/public/tier0/platwindow.h | 82 ++++++++++++++++++++++++++++ src/public/tier1/tier1.h | 25 +++++++++ src/vpc/interfaces.h | 2 +- 6 files changed, 127 insertions(+), 10 deletions(-) create mode 100644 src/public/tier0/platwindow.h create mode 100644 src/public/tier1/tier1.h diff --git a/src/core/stdafx.h b/src/core/stdafx.h index ce176603..e1da61c5 100644 --- a/src/core/stdafx.h +++ b/src/core/stdafx.h @@ -60,6 +60,7 @@ #include "tier0/module.h" #include "tier0/basetypes.h" #include "tier0/platform.h" +#include "tier0/platwindow.h" #include "tier0/annotations.h" #include "tier0/commonmacros.h" #include "tier0/memalloc.h" @@ -67,6 +68,7 @@ #include "tier0/dbg.h" // Tier1 includes. +#include "tier1/tier1.h" #include "tier1/cvar.h" #include "tier1/cmd.h" #include "common/global.h" diff --git a/src/engine/sys_dll2.h b/src/engine/sys_dll2.h index 443208a0..bdf7b0b6 100644 --- a/src/engine/sys_dll2.h +++ b/src/engine/sys_dll2.h @@ -5,13 +5,13 @@ class CEngineAPI : public IEngineAPI { public: - virtual bool Connect(CreateInterfaceFn factory) = 0; + virtual bool Connect(const CreateInterfaceFn factory) = 0; virtual void Disconnect() = 0; - virtual void* QueryInterface(const char* pInterfaceName) = 0; + virtual void* QueryInterface(const char* const pInterfaceName) = 0; virtual InitReturnVal_t Init() = 0; virtual void Shutdown() = 0; virtual AppSystemTier_t GetTier() = 0; - virtual void Reconnect(CreateInterfaceFn factory, const char* pInterfaceName) = 0; + virtual void Reconnect(const CreateInterfaceFn factory, const char* const pInterfaceName) = 0; // This function must be called before init virtual bool SetStartupInfo(StartupInfo_t& info) = 0; diff --git a/src/public/appframework/IAppSystem.h b/src/public/appframework/IAppSystem.h index 25f2ff19..451abed8 100644 --- a/src/public/appframework/IAppSystem.h +++ b/src/public/appframework/IAppSystem.h @@ -57,12 +57,12 @@ public: virtual ~IAppSystem() = 0; // Prepended on each class derived class in assembly. // Here's where the app systems get to learn about each other - virtual bool Connect(CreateInterfaceFn factory) = 0; + virtual bool Connect(const CreateInterfaceFn factory) = 0; virtual void Disconnect() = 0; // Here's where systems can access other interfaces implemented by this object // Returns NULL if it doesn't implement the requested interface - virtual void* QueryInterface(const char* pInterfaceName) = 0; + virtual void* QueryInterface(const char* const pInterfaceName) = 0; // Init, shutdown virtual InitReturnVal_t Init() = 0; @@ -75,7 +75,7 @@ public: virtual AppSystemTier_t GetTier() = 0; // Reconnect to a particular interface - virtual void Reconnect(CreateInterfaceFn factory, const char* pInterfaceName) = 0; + virtual void Reconnect(const CreateInterfaceFn factory, const char* const pInterfaceName) = 0; }; //----------------------------------------------------------------------------- @@ -88,12 +88,12 @@ public: virtual ~CBaseAppSystem() = 0; // Prepended on each class derived class in assembly. // Here's where the app systems get to learn about each other - virtual bool Connect(CreateInterfaceFn factory) = 0; + virtual bool Connect(const CreateInterfaceFn factory) = 0; virtual void Disconnect() = 0; // Here's where systems can access other interfaces implemented by this object // Returns NULL if it doesn't implement the requested interface - virtual void* QueryInterface(const char* pInterfaceName) = 0; + virtual void* QueryInterface(const char* const pInterfaceName) = 0; // Init, shutdown virtual InitReturnVal_t Init() = 0; @@ -106,7 +106,15 @@ public: virtual AppSystemTier_t GetTier() = 0; // Reconnect to a particular interface - virtual void Reconnect(CreateInterfaceFn factory, const char* pInterfaceName) = 0; + virtual void Reconnect(const CreateInterfaceFn factory, const char* const pInterfaceName) = 0; +}; + +//----------------------------------------------------------------------------- +// Helper implementation of an IAppSystem for tier0 +//----------------------------------------------------------------------------- +template< class IInterface > +class CTier0AppSystem : public CBaseAppSystem< IInterface > +{ }; #endif // IAPPSYSTEM_H \ No newline at end of file diff --git a/src/public/tier0/platwindow.h b/src/public/tier0/platwindow.h new file mode 100644 index 00000000..8a93ca03 --- /dev/null +++ b/src/public/tier0/platwindow.h @@ -0,0 +1,82 @@ +//===== Copyright � 1996-2009, Valve Corporation, All rights reserved. ======// +// +// Purpose: +// +// $NoKeywords: $ +// +//===========================================================================// + +#ifndef PLATWINDOW_H +#define PLATWINDOW_H + +#ifdef COMPILER_MSVC32 +#pragma once +#endif + +#include "tier0/platform.h" +#include "tier0/basetypes.h" + +//----------------------------------------------------------------------------- +// Window handle +//----------------------------------------------------------------------------- +DECLARE_POINTER_HANDLE( PlatWindow_t ); +#define PLAT_WINDOW_INVALID ( (PlatWindow_t)0 ) + + +//----------------------------------------------------------------------------- +// Window creation +//----------------------------------------------------------------------------- +enum WindowCreateFlags_t +{ + WINDOW_CREATE_FULLSCREEN = 0x1, + WINDOW_CREATE_RESIZING = 0x2, + +}; + +PLATFORM_INTERFACE PlatWindow_t Plat_CreateWindow( void *hInstance, const char *pTitle, int nWidth, int nHeight, int nFlags ); + + +//----------------------------------------------------------------------------- +// Window title +//----------------------------------------------------------------------------- +PLATFORM_INTERFACE void Plat_SetWindowTitle( PlatWindow_t hWindow, const char *pTitle ); + + +//----------------------------------------------------------------------------- +// Window movement +//----------------------------------------------------------------------------- +PLATFORM_INTERFACE void Plat_SetWindowPos( PlatWindow_t hWindow, int x, int y ); + + +//----------------------------------------------------------------------------- +// Gets the desktop resolution +//----------------------------------------------------------------------------- +PLATFORM_INTERFACE void Plat_GetDesktopResolution( int *pWidth, int *pHeight ); + + +//----------------------------------------------------------------------------- +// Gets a window size +//----------------------------------------------------------------------------- +PLATFORM_INTERFACE void Plat_GetWindowClientSize( PlatWindow_t hWindow, int *pWidth, int *pHeight ); + + +//----------------------------------------------------------------------------- +// Is the window minimized? +//----------------------------------------------------------------------------- +PLATFORM_INTERFACE bool Plat_IsWindowMinimized( PlatWindow_t hWindow ); + + +//----------------------------------------------------------------------------- +// Gets the shell window in a console app +//----------------------------------------------------------------------------- +PLATFORM_INTERFACE PlatWindow_t Plat_GetShellWindow( ); + + +//----------------------------------------------------------------------------- +// Convert window -> Screen coordinates and back +//----------------------------------------------------------------------------- +PLATFORM_INTERFACE void Plat_WindowToScreenCoords( PlatWindow_t hWnd, int &x, int &y ); +PLATFORM_INTERFACE void Plat_ScreenToWindowCoords( PlatWindow_t hWnd, int &x, int &y ); + + +#endif // PLATWINDOW_H diff --git a/src/public/tier1/tier1.h b/src/public/tier1/tier1.h new file mode 100644 index 00000000..47b69b90 --- /dev/null +++ b/src/public/tier1/tier1.h @@ -0,0 +1,25 @@ +//===== Copyright � 1996-2005, Valve Corporation, All rights reserved. ======// +// +// Purpose: A higher level link library for general use in the game and tools. +// +//===========================================================================// +#ifndef TIER1_H +#define TIER1_H +#include "appframework/IAppSystem.h" + +//----------------------------------------------------------------------------- +// Helper empty implementation of an IAppSystem for tier2 libraries +//----------------------------------------------------------------------------- +template< class IInterface, int ConVarFlag = 0 > +class CTier1AppSystem : public CTier0AppSystem< IInterface > +{ + virtual bool Connect( const CreateInterfaceFn factory ) = 0; + virtual void Disconnect( ) = 0; + virtual void* QueryInterface( const char* const pInterfaceName ) = 0; + virtual InitReturnVal_t Init( ) = 0; + virtual void Shutdown( ) = 0; + virtual AppSystemTier_t GetTier( ) = 0; + virtual void Reconnect( const CreateInterfaceFn factory, const char* const pInterfaceName ) = 0; +}; + +#endif // TIER1_H diff --git a/src/vpc/interfaces.h b/src/vpc/interfaces.h index 143f3068..074aae5f 100644 --- a/src/vpc/interfaces.h +++ b/src/vpc/interfaces.h @@ -81,6 +81,6 @@ class VFactory : public IDetour .FollowNearCallSelf().FindPatternSelf("48 8B 1D", CMemory::Direction::DOWN).ResolveRelativeAddressSelf(0x3, 0x7).RCast(); } virtual void GetCon(void) const { } - virtual void Detour(const bool bAttach) const { } + virtual void Detour(const bool /*bAttach*/) const { } }; /////////////////////////////////////////////////////////////////////////////// From 953bf9bd0deff11d72cb6319bfd3cdadd911cfa7 Mon Sep 17 00:00:00 2001 From: Kawe Mazidjatari <48657826+Mauler125@users.noreply.github.com> Date: Sat, 23 Dec 2023 01:51:31 +0100 Subject: [PATCH 04/24] InputSystem: update button codes Xbox enumerants have changed as the game supports Xbox One controllers. Since the joystick button count has changed, 'JOYSTICK_MAX_BUTTON_COUNT' has also changed which affects the size of datatypes used by the CInputSystem class. --- src/public/inputsystem/ButtonCode.h | 56 ++++++++------------- src/public/inputsystem/InputEnums.h | 76 +++++++++++++++++++++++++++++ 2 files changed, 97 insertions(+), 35 deletions(-) diff --git a/src/public/inputsystem/ButtonCode.h b/src/public/inputsystem/ButtonCode.h index 7b47cfa5..8ac9b09c 100644 --- a/src/public/inputsystem/ButtonCode.h +++ b/src/public/inputsystem/ButtonCode.h @@ -1,4 +1,5 @@ #pragma once +#include "InputEnums.h" #define JOYSTICK_BUTTON_INTERNAL( _joystick, _button ) ( JOYSTICK_FIRST_BUTTON + ((_joystick) * JOYSTICK_MAX_BUTTON_COUNT) + (_button) ) #define JOYSTICK_POV_BUTTON_INTERNAL( _joystick, _button ) ( JOYSTICK_FIRST_POV_BUTTON + ((_joystick) * JOYSTICK_POV_BUTTON_COUNT) + (_button) ) @@ -8,27 +9,9 @@ #define JOYSTICK_POV_BUTTON( _joystick, _button ) ( (ButtonCode_t)JOYSTICK_POV_BUTTON_INTERNAL( _joystick, _button ) ) #define JOYSTICK_AXIS_BUTTON( _joystick, _button ) ( (ButtonCode_t)JOYSTICK_AXIS_BUTTON_INTERNAL( _joystick, _button ) ) -// Buttons are not confirmed to be the same. They have been always the same throughout the source engine. Lets hope they did not change them. enum { - MAX_JOYSTICKS = MAX_SPLITSCREEN_CLIENTS, - MOUSE_BUTTON_COUNT = 5, -}; - -enum JoystickAxis_t -{ - JOY_AXIS_X = 0, - JOY_AXIS_Y, - JOY_AXIS_Z, - JOY_AXIS_R, - JOY_AXIS_U, - JOY_AXIS_V, - MAX_JOYSTICK_AXES, -}; - -enum -{ - JOYSTICK_MAX_BUTTON_COUNT = 32, + JOYSTICK_MAX_BUTTON_COUNT = 26, JOYSTICK_POV_BUTTON_COUNT = 4, JOYSTICK_AXIS_BUTTON_COUNT = MAX_JOYSTICK_AXES * 2, }; @@ -183,11 +166,15 @@ enum ButtonCode_t BUTTON_CODE_LAST, BUTTON_CODE_COUNT = BUTTON_CODE_LAST - KEY_FIRST + 1, - // Helpers for XBox 360 + // Helpers for XBox KEY_XBUTTON_UP = JOYSTICK_FIRST_POV_BUTTON, // POV buttons - KEY_XBUTTON_RIGHT, KEY_XBUTTON_DOWN, KEY_XBUTTON_LEFT, + KEY_XBUTTON_RIGHT, + KEY_XBUTTON_START, + KEY_XBUTTON_BACK, + KEY_XBUTTON_STICK1, + KEY_XBUTTON_STICK2, KEY_XBUTTON_A = JOYSTICK_FIRST_BUTTON, // Buttons KEY_XBUTTON_B, @@ -195,20 +182,19 @@ enum ButtonCode_t KEY_XBUTTON_Y, KEY_XBUTTON_LEFT_SHOULDER, KEY_XBUTTON_RIGHT_SHOULDER, - KEY_XBUTTON_BACK, - KEY_XBUTTON_START, - KEY_XBUTTON_STICK1, - KEY_XBUTTON_STICK2, - KEY_XBUTTON_INACTIVE_START, - KEY_XSTICK1_RIGHT = JOYSTICK_FIRST_AXIS_BUTTON, // XAXIS POSITIVE - KEY_XSTICK1_LEFT, // XAXIS NEGATIVE + KEY_XBUTTON_LTRIGGER_PARTIAL, + KEY_XBUTTON_LTRIGGER_FULL, + KEY_XBUTTON_RTRIGGER_PARTIAL, + KEY_XBUTTON_RTRIGGER_FULL, + + KEY_XSTICK1_UP = JOYSTICK_FIRST_AXIS_BUTTON, // YAXIS NEGATIVE KEY_XSTICK1_DOWN, // YAXIS POSITIVE - KEY_XSTICK1_UP, // YAXIS NEGATIVE - KEY_XBUTTON_LTRIGGER, // ZAXIS POSITIVE - KEY_XBUTTON_RTRIGGER, // ZAXIS NEGATIVE - KEY_XSTICK2_RIGHT, // UAXIS POSITIVE - KEY_XSTICK2_LEFT, // UAXIS NEGATIVE - KEY_XSTICK2_DOWN, // VAXIS POSITIVE + KEY_XSTICK1_LEFT, // XAXIS NEGATIVE + KEY_XSTICK1_RIGHT, // XAXIS POSITIVE + KEY_XSTICK2_UP, // VAXIS NEGATIVE -}; \ No newline at end of file + KEY_XSTICK2_DOWN, // VAXIS POSITIVE + KEY_XSTICK2_LEFT, // UAXIS NEGATIVE + KEY_XSTICK2_RIGHT, // UAXIS POSITIVE +}; diff --git a/src/public/inputsystem/InputEnums.h b/src/public/inputsystem/InputEnums.h index 82be83f0..638c7c10 100644 --- a/src/public/inputsystem/InputEnums.h +++ b/src/public/inputsystem/InputEnums.h @@ -6,6 +6,82 @@ #ifndef INPUTENUMS_H #define INPUTENUMS_H +// Standard maximum +/- value of a joystick axis +#define MAX_BUTTONSAMPLE 32768 + +#if !defined( _X360 ) +#define INVALID_USER_ID -1 +#else +#define INVALID_USER_ID XBX_INVALID_USER_ID +#endif + +enum +{ +#ifdef _PS3 + MAX_JOYSTICKS = 7, +#else + MAX_JOYSTICKS = 4, +#endif + MOUSE_BUTTON_COUNT = 5, + MAX_NOVINT_DEVICES = 2, +}; + +enum JoystickAxis_t +{ + JOY_AXIS_X = 0, + JOY_AXIS_Y, + JOY_AXIS_Z, + JOY_AXIS_R, + JOY_AXIS_U, + JOY_AXIS_V, + MAX_JOYSTICK_AXES, +}; + +enum JoystickDeadzoneMode_t +{ + JOYSTICK_DEADZONE_CROSS = 0, + JOYSTICK_DEADZONE_SQUARE = 1, +}; + +//----------------------------------------------------------------------------- +// Events +//----------------------------------------------------------------------------- +enum InputEventType_t +{ + IE_ButtonPressed = 0, // m_nData contains a ButtonCode_t + IE_ButtonReleased, // m_nData contains a ButtonCode_t + IE_ButtonDoubleClicked, // m_nData contains a ButtonCode_t + IE_AnalogValueChanged, // m_nData contains an AnalogCode_t, m_nData2 contains the value + + IE_FirstSystemEvent = 100, + IE_Quit = IE_FirstSystemEvent, + IE_ControllerInserted, // m_nData contains the controller ID + IE_ControllerUnplugged, // m_nData contains the controller ID + IE_Close, + IE_WindowSizeChanged, // m_nData contains width, m_nData2 contains height, m_nData3 = 0 if not minimized, 1 if minimized + IE_PS_CameraUnplugged, // m_nData contains code for type of disconnect. + IE_PS_Move_OutOfView, // m_nData contains bool (0, 1) for whether the move is now out of view (1) or in view (0) + + IE_FirstUIEvent = 200, + IE_LocateMouseClick = IE_FirstUIEvent, + IE_SetCursor, + IE_KeyTyped, + IE_KeyCodeTyped, + IE_InputLanguageChanged, + IE_IMESetWindow, + IE_IMEStartComposition, + IE_IMEComposition, + IE_IMEEndComposition, + IE_IMEShowCandidates, + IE_IMEChangeCandidates, + IE_IMECloseCandidates, + IE_IMERecomputeModes, + IE_OverlayEvent, + + IE_FirstVguiEvent = 1000, // Assign ranges for other systems that post user events here + IE_FirstAppEvent = 2000, +}; + struct InputEvent_t { const char* m_pCommand; From 69e64ac8c39f5415161a1d763d04b595347fd866 Mon Sep 17 00:00:00 2001 From: Kawe Mazidjatari <48657826+Mauler125@users.noreply.github.com> Date: Sat, 23 Dec 2023 17:21:20 +0100 Subject: [PATCH 05/24] Create utlstringmap.h --- src/public/tier1/utlstringmap.h | 185 ++++++++++++++++++++++++++++++++ 1 file changed, 185 insertions(+) create mode 100644 src/public/tier1/utlstringmap.h diff --git a/src/public/tier1/utlstringmap.h b/src/public/tier1/utlstringmap.h new file mode 100644 index 00000000..82c2e975 --- /dev/null +++ b/src/public/tier1/utlstringmap.h @@ -0,0 +1,185 @@ +//===== Copyright � 1996-2005, Valve Corporation, All rights reserved. ======// +// +// Purpose: +// +//===========================================================================// + +#ifndef UTLSTRINGMAP_H +#define UTLSTRINGMAP_H +#ifdef _WIN32 +#pragma once +#endif + +#include "utlsymbol.h" + +template +class CUtlStringMap +{ +public: + typedef UtlSymId_t IndexType_t; + CUtlStringMap( bool caseInsensitive = true, int initsize = 32 ) : + m_SymbolTable( 0, 32, caseInsensitive ), + m_Vector( initsize ) + { + } + + // Get data by the string itself: + T& operator[]( const char *pString ) + { + CUtlSymbol symbol = m_SymbolTable.AddString( pString ); + int index = ( int )( UtlSymId_t )symbol; + if( m_Vector.Count() <= index ) + { + m_Vector.EnsureCount( index + 1 ); + } + return m_Vector[index]; + } + + // Get data by the string's symbol table ID - only used to retrieve a pre-existing symbol, not create a new one! + T& operator[]( UtlSymId_t n ) + { + Assert( n <= m_Vector.Count() ); + return m_Vector[n]; + } + + const T& operator[]( UtlSymId_t n ) const + { + Assert( n <= m_Vector.Count() ); + return m_Vector[n]; + } + + unsigned int Count() const + { + Assert( m_Vector.Count() == m_SymbolTable.GetNumStrings() ); + return m_Vector.Count(); + } + + bool Defined( const char *pString ) const + { + return m_SymbolTable.Find( pString ) != UTL_INVAL_SYMBOL; + } + + UtlSymId_t Find( const char *pString ) const + { + return m_SymbolTable.Find( pString ); + } + + UtlSymId_t AddString( const char *pString ) + { + CUtlSymbol symbol = m_SymbolTable.AddString( pString ); + int index = ( int )( UtlSymId_t )symbol; + if( m_Vector.Count() <= index ) + { + m_Vector.EnsureCount( index + 1 ); + } + return symbol; + } + + /// Add a string to the map and also insert an item at + /// its location in the same operation. Returns the + /// newly created index (or the one that was just + /// overwritten, if pString already existed.) + UtlSymId_t Insert( const char *pString, const T &item ) + { + CUtlSymbol symbol = m_SymbolTable.AddString( pString ); + UtlSymId_t index = symbol; // implicit coercion + if ( m_Vector.Count() > index ) + { + // this string is already in the dictionary. + + } + else if ( m_Vector.Count() == index ) + { + // this is the expected case when we've added one more to the tail. + m_Vector.AddToTail( item ); + } + else // ( m_Vector.Count() < index ) + { + // this is a strange shouldn't-happen case. + AssertMsg( false, "CUtlStringMap insert unexpected entries." ); + m_Vector.EnsureCount( index + 1 ); + m_Vector[index] = item; + } + return index; + } + + /// iterate, not in any particular order. + IndexType_t First() const + { + if ( Count() > 0 ) + { + return 0; + } + else + { + return InvalidIndex(); + } + } + + static UtlSymId_t InvalidIndex() + { + return UTL_INVAL_SYMBOL; + } + + // iterators (for uniformity with other map types) + inline UtlSymId_t Head() const + { + return m_SymbolTable.GetNumStrings() > 0 ? 0 : InvalidIndex(); + } + + inline UtlSymId_t Next( const UtlSymId_t &i ) const + { + UtlSymId_t n = i+1; + return n < m_SymbolTable.GetNumStrings() ? n : InvalidIndex(); + } + + + int GetNumStrings( void ) const + { + return m_SymbolTable.GetNumStrings(); + } + + const char *String( int n ) const + { + return m_SymbolTable.String( n ); + } + + // Clear all of the data from the map + void Clear() + { + m_Vector.RemoveAll(); + m_SymbolTable.RemoveAll(); + } + + void Purge() + { + m_Vector.Purge(); + m_SymbolTable.RemoveAll(); + } + + void PurgeAndDeleteElements() + { + m_Vector.PurgeAndDeleteElements(); + m_SymbolTable.RemoveAll(); + } + + + +private: + CUtlVector m_Vector; + CUtlSymbolTable m_SymbolTable; +}; + + +template< class T > +class CUtlStringMapAutoPurge : public CUtlStringMap < T > +{ +public: + ~CUtlStringMapAutoPurge( void ) + { + this->PurgeAndDeleteElements(); + } + +}; + +#endif // UTLSTRINGMAP_H From 4ba6227759b929b869a03155b869c74cc0d00ba6 Mon Sep 17 00:00:00 2001 From: Kawe Mazidjatari <48657826+Mauler125@users.noreply.github.com> Date: Sat, 23 Dec 2023 17:23:17 +0100 Subject: [PATCH 06/24] InputSystem: largely reversed struct and fully reversed iface Struct has been largely mapped out (still requires a bit of work, mostly the Xbox/Hid data structures). The vftable has been fully mapped out. --- src/common/xbox/xboxstubs.h | 49 +++++++++ src/inputsystem/CMakeLists.txt | 3 + src/inputsystem/inputsystem.cpp | 80 +++++++------- src/inputsystem/inputsystem.h | 144 ++++++++++++++++++++++--- src/public/inputsystem/AnalogCode.h | 38 +++++++ src/public/inputsystem/ButtonCode.h | 3 +- src/public/inputsystem/InputEnums.h | 8 +- src/public/inputsystem/iinputsystem.h | 149 ++++++++++++++++++++++++++ 8 files changed, 418 insertions(+), 56 deletions(-) create mode 100644 src/common/xbox/xboxstubs.h create mode 100644 src/public/inputsystem/AnalogCode.h create mode 100644 src/public/inputsystem/iinputsystem.h diff --git a/src/common/xbox/xboxstubs.h b/src/common/xbox/xboxstubs.h new file mode 100644 index 00000000..cfef77cf --- /dev/null +++ b/src/common/xbox/xboxstubs.h @@ -0,0 +1,49 @@ +//========= Copyright 1996-2004, Valve LLC, All rights reserved. ============ +// +// Purpose: Win32 replacements for XBox. +// +//============================================================================= +#if !defined( XBOXSTUBS_H ) && !defined( _X360 ) +#define XBOXSTUBS_H + +typedef enum +{ + XK_BUTTON_UP, + XK_BUTTON_DOWN, + XK_BUTTON_LEFT, + XK_BUTTON_RIGHT, + + XK_BUTTON_START, + XK_BUTTON_BACK, + + XK_BUTTON_STICK1, + XK_BUTTON_STICK2, + + XK_BUTTON_A, + XK_BUTTON_B, + XK_BUTTON_X, + XK_BUTTON_Y, + + XK_BUTTON_LEFT_SHOULDER, + XK_BUTTON_RIGHT_SHOULDER, + + XK_XBUTTON_LTRIGGER_PARTIAL, + XK_XBUTTON_LTRIGGER_FULL, + + XK_XBUTTON_RTRIGGER_PARTIAL, + XK_XBUTTON_RTRIGGER_FULL, + + XK_STICK1_UP, + XK_STICK1_DOWN, + XK_STICK1_LEFT, + XK_STICK1_RIGHT, + + XK_STICK2_UP, + XK_STICK2_DOWN, + XK_STICK2_LEFT, + XK_STICK2_RIGHT, + + XK_MAX_KEYS, +} xKey_t; + +#endif // XBOXSTUBS_H \ No newline at end of file diff --git a/src/inputsystem/CMakeLists.txt b/src/inputsystem/CMakeLists.txt index c22fca6f..5d6ea714 100644 --- a/src/inputsystem/CMakeLists.txt +++ b/src/inputsystem/CMakeLists.txt @@ -9,7 +9,10 @@ add_sources( SOURCE_GROUP "Private" ) add_sources( SOURCE_GROUP "Public" + "${ENGINE_SOURCE_DIR}/public/inputsystem/iinputsystem.h" + "${ENGINE_SOURCE_DIR}/public/inputsystem/AnalogCode.h" "${ENGINE_SOURCE_DIR}/public/inputsystem/ButtonCode.h" + "${ENGINE_SOURCE_DIR}/public/inputsystem/InputEnums.h" ) end_sources() diff --git a/src/inputsystem/inputsystem.cpp b/src/inputsystem/inputsystem.cpp index d78ed76c..256fc8b0 100644 --- a/src/inputsystem/inputsystem.cpp +++ b/src/inputsystem/inputsystem.cpp @@ -8,46 +8,46 @@ #include "vpc/IAppSystem.h" #include "inputsystem/inputsystem.h" -//----------------------------------------------------------------------------- -// Enables/disables input -//----------------------------------------------------------------------------- -void CInputSystem::EnableInput(bool bEnabled) -{ - const static int index = 10; - CallVFunc(index, this, bEnabled); -} - -//----------------------------------------------------------------------------- -// Enables/disables the inputsystem windows message pump -//----------------------------------------------------------------------------- -void CInputSystem::EnableMessagePump(bool bEnabled) -{ - const static int index = 11; - CallVFunc(index, this, bEnabled); -} - -//----------------------------------------------------------------------------- -// Poll current state -//----------------------------------------------------------------------------- -bool CInputSystem::IsButtonDown(ButtonCode_t Button) -{ - const static int index = 13; - return CallVFunc(index, this, Button); -} - -//----------------------------------------------------------------------------- -// Convert back + forth between ButtonCode/AnalogCode + strings -//----------------------------------------------------------------------------- -bool CInputSystem::ButtonCodeToString(ButtonCode_t Button) -{ - const static int index = 25; - return CallVFunc(index, this, Button); -} -ButtonCode_t CInputSystem::StringToButtonCode(const char* pString) -{ - const static int index = 26; - return CallVFunc(index, this, pString); -} +////----------------------------------------------------------------------------- +//// Enables/disables input +////----------------------------------------------------------------------------- +//void CInputSystem::EnableInput(bool bEnabled) +//{ +// const static int index = 10; +// CallVFunc(index, this, bEnabled); +//} +// +////----------------------------------------------------------------------------- +//// Enables/disables the inputsystem windows message pump +////----------------------------------------------------------------------------- +//void CInputSystem::EnableMessagePump(bool bEnabled) +//{ +// const static int index = 11; +// CallVFunc(index, this, bEnabled); +//} +// +////----------------------------------------------------------------------------- +//// Poll current state +////----------------------------------------------------------------------------- +//bool CInputSystem::IsButtonDown(ButtonCode_t Button) +//{ +// const static int index = 13; +// return CallVFunc(index, this, Button); +//} +// +////----------------------------------------------------------------------------- +//// Convert back + forth between ButtonCode/AnalogCode + strings +////----------------------------------------------------------------------------- +//bool CInputSystem::ButtonCodeToString(ButtonCode_t Button) +//{ +// const static int index = 25; +// return CallVFunc(index, this, Button); +//} +//ButtonCode_t CInputSystem::StringToButtonCode(const char* pString) +//{ +// const static int index = 26; +// return CallVFunc(index, this, pString); +//} /////////////////////////////////////////////////////////////////////////////// CInputSystem* g_pInputSystem = nullptr; \ No newline at end of file diff --git a/src/inputsystem/inputsystem.h b/src/inputsystem/inputsystem.h index 1961b641..a24a4c70 100644 --- a/src/inputsystem/inputsystem.h +++ b/src/inputsystem/inputsystem.h @@ -1,21 +1,141 @@ #pragma once -#include "core/stdafx.h" -#include "inputsystem/ButtonCode.h" +#include "inputsystem/iinputsystem.h" +#include "mathlib/bitvec.h" +#include "tier1/utlstringmap.h" +#include -class CInputSystem +//----------------------------------------------------------------------------- +// Implementation of the input system +//----------------------------------------------------------------------------- +class CInputSystem : public CTier1AppSystem< IInputSystem > { public: - void EnableInput(bool bEnabled); // @0x14039F100 in R5pc_r5launch_N1094_CL456479_2019_10_30_05_20_PM - void EnableMessagePump(bool bEnabled); // @0x14039F110 in R5pc_r5launch_N1094_CL456479_2019_10_30_05_20_PM - bool IsButtonDown(ButtonCode_t Button); // @0x1403A0140 in R5pc_r5launch_N1094_CL456479_2019_10_30_05_20_PM - bool ButtonCodeToString(ButtonCode_t Button); - ButtonCode_t StringToButtonCode(const char* pString); + // !!!interface implemented in engine!!! private: - char pad_0000[16]; //0x0000 -public: - bool m_bEnabled; //0x0010 IsInputEnabled variable. - bool m_bPumpEnabled; //0x0011 EnabledMessagePump variable. + enum + { + INPUT_STATE_QUEUED = 0, + INPUT_STATE_CURRENT, + + INPUT_STATE_COUNT, + }; + + struct xdevice_t + { + struct xvibration_t + { + float leftMainMotor; + float rightMainMotor; + float leftTriggerMotor; + float rightTriggerMotor; + }; + + int userId; + char active; + XINPUT_STATE states[INPUT_STATE_COUNT]; + int newState; + _BYTE gap6[20]; + bool pendingRumbleUpdate; + _BYTE gap41[3]; + xvibration_t vibration; + bool bUnk0; + char field_55; + _BYTE gap56[42]; + int field_80; + _BYTE gap84[316]; + }; + + struct appKey_t + { + int repeats; + int sample; + }; + + struct InputState_t + { + // Analog states + CBitVec m_ButtonState; + int m_pAnalogValue[JOYSTICK_MAX_BUTTON_COUNT]; + }; + + + HWND m_ChainedWndProc; + HWND m_hAttachedHWnd; + bool m_bEnabled; + bool m_bPumpEnabled; + bool m_bIsPolling; + bool m_bIMEComposing; + bool m_bMouseCursorVisible; + bool m_bJoystickCursorVisible; + bool m_bIsInGame; // Delay joystick polling if in-game. + + // Current button state + InputState_t m_InputState[INPUT_STATE_COUNT]; + + // Current button state mutex + CRITICAL_SECTION m_InputStateMutex; + int unknown0; + short unknown1; + bool unknown2; + + // Analog event mutex + CRITICAL_SECTION m_AnalogEventMutex; + int unknown3; + short unknown4; + bool unknown5; + + // Analog events + InputEvent_t m_AnalogEvents[JOYSTICK_AXIS_BUTTON_COUNT]; + int m_AnalogEventTypes[JOYSTICK_AXIS_BUTTON_COUNT]; + + // Button events + InputEvent_t m_Events[128]; + InputEvent_t m_CurrentEvent; + + DWORD m_StartupTimeTick; + int m_nLastPollTick; + int m_nLastSampleTick; + int m_nLastAnalogPollTick; + int m_nLastAnalogSampleTick; + + // Mouse wheel hack + UINT m_uiMouseWheel; + + // Xbox controller info + int m_nJoystickCount; + appKey_t m_appXKeys[XUSER_MAX_COUNT][XK_MAX_KEYS+2]; + char pad_unk[16]; + xdevice_t m_XDevices[XUSER_MAX_COUNT]; + + // Used to determine whether to generate UI events + int m_nUIEventClientCount; + + // Raw mouse input + bool m_bRawInputSupported; + CRITICAL_SECTION m_MouseAccumMutex; + int m_mouseRawAccumX; + int m_mouseRawAccumY; + + _BYTE gap1785[8]; + + // Current mouse capture window + PlatWindow_t m_hCurrentCaptureWnd; + + // For the 'SleepUntilInput' feature + HANDLE m_hEvent; + + InputCursorHandle_t m_pDefaultCursors[INPUT_CURSOR_COUNT]; + CUtlStringMap m_UserCursors; + + CSysModule* m_pXInputDLL; + CSysModule* m_pRawInputDLL; + + // NVNT falcon module + CSysModule* m_pNovintDLL; // Unused in R5? + + bool m_bIgnoreLocalJoystick; + InputCursorHandle_t m_hCursor; }; /////////////////////////////////////////////////////////////////////////////// diff --git a/src/public/inputsystem/AnalogCode.h b/src/public/inputsystem/AnalogCode.h new file mode 100644 index 00000000..cb439583 --- /dev/null +++ b/src/public/inputsystem/AnalogCode.h @@ -0,0 +1,38 @@ +//===== Copyright � 1996-2005, Valve Corporation, All rights reserved. ======// +// +// Purpose: +// +// $NoKeywords: $ +//===========================================================================// + +#ifndef ANALOGCODE_H +#define ANALOGCODE_H +#include "inputsystem/InputEnums.h" + + +//----------------------------------------------------------------------------- +// Macro to get at joystick codes +//----------------------------------------------------------------------------- +#define JOYSTICK_AXIS_INTERNAL( _joystick, _axis ) ( JOYSTICK_FIRST_AXIS + ((_joystick) * MAX_JOYSTICK_AXES) + (_axis) ) +#define JOYSTICK_AXIS( _joystick, _axis ) ( (AnalogCode_t)JOYSTICK_AXIS_INTERNAL( _joystick, _axis ) ) + + +//----------------------------------------------------------------------------- +// Enumeration for analog input devices. Includes joysticks, mousewheel, mouse +//----------------------------------------------------------------------------- +enum AnalogCode_t +{ + ANALOG_CODE_INVALID = -1, + MOUSE_X = 0, + MOUSE_Y, + MOUSE_XY, // Invoked when either x or y changes + MOUSE_WHEEL, + + JOYSTICK_FIRST_AXIS, + JOYSTICK_LAST_AXIS = JOYSTICK_AXIS_INTERNAL(MAX_JOYSTICKS - 1, MAX_JOYSTICK_AXES - 1), + + ANALOG_CODE_LAST, +}; + + +#endif // ANALOGCODE_H diff --git a/src/public/inputsystem/ButtonCode.h b/src/public/inputsystem/ButtonCode.h index 8ac9b09c..0f9c2df1 100644 --- a/src/public/inputsystem/ButtonCode.h +++ b/src/public/inputsystem/ButtonCode.h @@ -1,5 +1,6 @@ #pragma once #include "InputEnums.h" +#include "common/xbox/xboxstubs.h" #define JOYSTICK_BUTTON_INTERNAL( _joystick, _button ) ( JOYSTICK_FIRST_BUTTON + ((_joystick) * JOYSTICK_MAX_BUTTON_COUNT) + (_button) ) #define JOYSTICK_POV_BUTTON_INTERNAL( _joystick, _button ) ( JOYSTICK_FIRST_POV_BUTTON + ((_joystick) * JOYSTICK_POV_BUTTON_COUNT) + (_button) ) @@ -11,7 +12,7 @@ enum { - JOYSTICK_MAX_BUTTON_COUNT = 26, + JOYSTICK_MAX_BUTTON_COUNT = XK_MAX_KEYS, JOYSTICK_POV_BUTTON_COUNT = 4, JOYSTICK_AXIS_BUTTON_COUNT = MAX_JOYSTICK_AXES * 2, }; diff --git a/src/public/inputsystem/InputEnums.h b/src/public/inputsystem/InputEnums.h index 638c7c10..7f7c5f99 100644 --- a/src/public/inputsystem/InputEnums.h +++ b/src/public/inputsystem/InputEnums.h @@ -84,9 +84,11 @@ enum InputEventType_t struct InputEvent_t { - const char* m_pCommand; - int m_nTick; - bool m_bDown; + int m_nType; // Type of the event (see InputEventType_t) + int m_nTick; // Tick on which the event occurred + int m_nData; // Generic 32-bit data, what it contains depends on the event + int m_nData2; // Generic 32-bit data, what it contains depends on the event + int m_nData3; // Generic 32-bit data, what it contains depends on the event }; #endif // INPUTENUMS_H diff --git a/src/public/inputsystem/iinputsystem.h b/src/public/inputsystem/iinputsystem.h new file mode 100644 index 00000000..578ef757 --- /dev/null +++ b/src/public/inputsystem/iinputsystem.h @@ -0,0 +1,149 @@ +//===== Copyright � 1996-2005, Valve Corporation, All rights reserved. ======// +// +// Purpose: +// +//===========================================================================// +#ifndef IINPUTSYSTEM_H +#define IINPUTSYSTEM_H + +#include "inputsystem/ButtonCode.h" +#include "inputsystem/AnalogCode.h" +#include "inputsystem/InputEnums.h" + +///----------------------------------------------------------------------------- +/// A handle to a cursor icon +///----------------------------------------------------------------------------- +DECLARE_POINTER_HANDLE( InputCursorHandle_t ); +#define INPUT_CURSOR_HANDLE_INVALID ( (InputCursorHandle_t)0 ) + + +///----------------------------------------------------------------------------- +/// An enumeration describing well-known cursor icons +///----------------------------------------------------------------------------- +enum InputStandardCursor_t +{ + INPUT_CURSOR_NONE = 0, + INPUT_CURSOR_ARROW, + INPUT_CURSOR_IBEAM, + INPUT_CURSOR_HOURGLASS, + INPUT_CURSOR_CROSSHAIR, + INPUT_CURSOR_WAITARROW, + INPUT_CURSOR_UP, + INPUT_CURSOR_SIZE_NW_SE, + INPUT_CURSOR_SIZE_NE_SW, + INPUT_CURSOR_SIZE_W_E, + INPUT_CURSOR_SIZE_N_S, + INPUT_CURSOR_SIZE_ALL, + INPUT_CURSOR_NO, + INPUT_CURSOR_HAND, + + INPUT_CURSOR_COUNT +}; + +//----------------------------------------------------------------------------- +// Main interface for input. This is a low-level interface +//----------------------------------------------------------------------------- +#define INPUTSYSTEM_INTERFACE_VERSION "InputSystemVersion001" +abstract_class IInputSystem : public IAppSystem +{ +public: + /// Attach, detach input system from a particular window + /// This window should be the root window for the application + /// Only 1 window should be attached at any given time. + virtual void AttachToWindow( const void* const hWnd ) = 0; + virtual void DetachFromWindow( ) = 0; + + /// Enables/disables input. PollInputState will not update current + /// button/analog states when it is called if the system is disabled. + virtual void EnableInput( const bool bEnable ) = 0; + + /// Enables/disables the windows message pump. PollInputState will not. + /// Peek/Dispatch messages if this is disabled. + virtual void EnableMessagePump( const bool bEnable ) = 0; + + /// Gets the time of the last polling in ms. + virtual int GetPollTick() const = 0; + + /// Is a button down? "Buttons" are binary-state input devices (mouse buttons, keyboard keys). + virtual bool IsButtonDown( const ButtonCode_t code ) const = 0; + + /// Returns the tick at which the button was pressed and released + virtual int GetButtonPressedTick( const ButtonCode_t code ) const = 0; + + /// TODO[ AMOS ]: reverse this further ( returns an enum ? )... + virtual int GetJoystickDeadzoneIndex( ) const = 0; + + /// DoNothing; VFTable padding. + virtual bool ReturnFalse( ) const = 0; + + /// Polls the current input state. + virtual void PollInputState( const void* const eventCallback ) = 0; + + /// Posts a user-defined event into the event queue; this is expected + /// to be called in overridden wndprocs connected to the root panel. + virtual void PostUserEvent( const InputEvent_t &event ) = 0; + virtual void PostUserEvent( const InputEventType_t type ) = 0; + + /// Returns the number of joysticks + virtual int GetJoystickCount( ) const = 0; + + /// Sample the joystick and append events to the input queue. + virtual void SampleDevices( void ) = 0; + + virtual void SetRumble( const float fLeftMainMotor, const float fRightMainMotor, const float fLeftTriggerMotor, const float fRightTriggerMotor, const int userId = INVALID_USER_ID ) = 0; + virtual void StopRumble( const int userId = INVALID_USER_ID ) = 0; + + /// Resets the input state. + virtual void ResetInputState() = 0; + + /// Convert back + forth between ButtonCode/AnalogCode + strings. + virtual const char* ButtonCodeToString( const ButtonCode_t code ) const = 0; + virtual ButtonCode_t StringToButtonCode( const char* const pString ) const = 0; + + /// Sleeps until input happens. Pass a negative number to sleep infinitely. + virtual void SleepUntilInput( const int nMaxSleepTimeMS = -1 ) = 0; + + /// Convert back + forth between virtual codes + button codes + virtual ButtonCode_t VirtualKeyToButtonCode( const int nVirtualKey ) const = 0; + virtual int ButtonCodeToVirtualKey( const ButtonCode_t code ) const = 0; + + /// Sets the cursor position. + virtual void SetCursorPosition( const int x, const int y ) = 0; + + /// Tells the input system to generate UI-related events, defined + /// in inputsystem/inputenums.h (see IE_FirstUIEvent) + /// We could have multiple clients that care about UI-related events + /// so we refcount the clients with an Add/Remove strategy. If there + /// are no interested clients, the UI events are not generated. + virtual void AddUIEventListener() = 0; + virtual void RemoveUIEventListener() = 0; + + /// Creates a cursor using one of the well-known cursor icons. + virtual InputCursorHandle_t GetStandardCursor( const InputStandardCursor_t id ) = 0; + + /// Loads a cursor defined in a file. + virtual InputCursorHandle_t LoadCursorFromFile( const char* const pFileName, const char* const pPathID = NULL ) = 0; + + /// Sets the cursor icon. + virtual void SetCursorIcon( const InputCursorHandle_t hCursor ) = 0; + + /// Gets the cursor position. + virtual void GetCursorPosition( const int* const pX, const int* const pY ) = 0; + + /// Mouse capture. + virtual void EnableMouseCapture( const PlatWindow_t hWnd ) = 0; + virtual void DisableMouseCapture( ) = 0; + + // Mouse/Joystick cursor visibility, tell inputsystem when we hide stuff rather than querying the OS which is expensive on OSX. + virtual void SetMouseCursorVisible( const bool bVisible ) = 0; + virtual void SetJoystickCursorVisible( const bool bVisible ) = 0; + + /// Reset the current cursor icon. Used to reset the icon in the case of alt+tabs where the cursor has been forced to a different + /// icon because it was outside of the client rect during the reload. + virtual void ResetCursorIcon() = 0; + + // read and clear accumulated raw input values. + virtual void GetRawMouseAccumulators( int& accumX, int& accumY ) = 0; +}; + +#endif // IINPUTSYSTEM_H From 01b805f801c466dfb8a3b7a5e56c8a1430193882 Mon Sep 17 00:00:00 2001 From: Kawe Mazidjatari <48657826+Mauler125@users.noreply.github.com> Date: Sat, 23 Dec 2023 19:37:39 +0100 Subject: [PATCH 07/24] InputSystem: joystick deadzone indices and event input callback types Adjust iface accordingly. --- src/public/inputsystem/InputEnums.h | 8 +++++--- src/public/inputsystem/iinputsystem.h | 12 ++++++++---- 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/src/public/inputsystem/InputEnums.h b/src/public/inputsystem/InputEnums.h index 7f7c5f99..6895d74d 100644 --- a/src/public/inputsystem/InputEnums.h +++ b/src/public/inputsystem/InputEnums.h @@ -37,10 +37,12 @@ enum JoystickAxis_t MAX_JOYSTICK_AXES, }; -enum JoystickDeadzoneMode_t +enum JoystickDeadzoneIndex_t { - JOYSTICK_DEADZONE_CROSS = 0, - JOYSTICK_DEADZONE_SQUARE = 1, + JOYSTICK_DEADZONE_NONE = 0, + JOYSTICK_DEADZONE_XBOX360, + JOYSTICK_DEADZONE_XBOX1, + JOYSTICK_DEADZONE_OTHER }; //----------------------------------------------------------------------------- diff --git a/src/public/inputsystem/iinputsystem.h b/src/public/inputsystem/iinputsystem.h index 578ef757..29949574 100644 --- a/src/public/inputsystem/iinputsystem.h +++ b/src/public/inputsystem/iinputsystem.h @@ -16,6 +16,10 @@ DECLARE_POINTER_HANDLE( InputCursorHandle_t ); #define INPUT_CURSOR_HANDLE_INVALID ( (InputCursorHandle_t)0 ) +///----------------------------------------------------------------------------- +/// Input event callback +///----------------------------------------------------------------------------- +typedef void ( *InputEventCallback_t ) ( const InputEvent_t& eventCallback ); ///----------------------------------------------------------------------------- /// An enumeration describing well-known cursor icons @@ -67,17 +71,17 @@ public: /// Is a button down? "Buttons" are binary-state input devices (mouse buttons, keyboard keys). virtual bool IsButtonDown( const ButtonCode_t code ) const = 0; - /// Returns the tick at which the button was pressed and released + /// Returns the tick at which the button was pressed and released. virtual int GetButtonPressedTick( const ButtonCode_t code ) const = 0; - /// TODO[ AMOS ]: reverse this further ( returns an enum ? )... - virtual int GetJoystickDeadzoneIndex( ) const = 0; + /// Returns the joystick deadzone index for connected hardware. + virtual JoystickDeadzoneIndex_t GetJoystickDeadzoneIndex( ) const = 0; /// DoNothing; VFTable padding. virtual bool ReturnFalse( ) const = 0; /// Polls the current input state. - virtual void PollInputState( const void* const eventCallback ) = 0; + virtual void PollInputState( const InputEventCallback_t eventCallback ) = 0; /// Posts a user-defined event into the event queue; this is expected /// to be called in overridden wndprocs connected to the root panel. From e8f480bba46120c28a991459d3b981317c113e61 Mon Sep 17 00:00:00 2001 From: Kawe Mazidjatari <48657826+Mauler125@users.noreply.github.com> Date: Sun, 24 Dec 2023 02:48:49 +0100 Subject: [PATCH 08/24] Tier1: make CTier1AppSystem iface public --- src/public/tier1/tier1.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/public/tier1/tier1.h b/src/public/tier1/tier1.h index 47b69b90..177e8de0 100644 --- a/src/public/tier1/tier1.h +++ b/src/public/tier1/tier1.h @@ -13,6 +13,7 @@ template< class IInterface, int ConVarFlag = 0 > class CTier1AppSystem : public CTier0AppSystem< IInterface > { +public: virtual bool Connect( const CreateInterfaceFn factory ) = 0; virtual void Disconnect( ) = 0; virtual void* QueryInterface( const char* const pInterfaceName ) = 0; From ccfef821b01b9e43a661b3880ab0c065097a03b3 Mon Sep 17 00:00:00 2001 From: Kawe Mazidjatari <48657826+Mauler125@users.noreply.github.com> Date: Sun, 24 Dec 2023 02:58:11 +0100 Subject: [PATCH 09/24] InputSystem: fixup enumerants and controller structs Enumerants: * ButtonCode_t::JOYSTICK_MAX_BUTTON_COUNT = 32 (previously 26, incorrect...). * AnalogCode_t::JOYSTICK_FIRST_AXIS = 2 (previously 4, incorrect...). * Added: ButtonCode_t::KEY_CREDITSIGN (k104, last key). * Fixed up Xbox controller enums. Structs xdevice_t: * Added partially reversed unkownhiddevice_t structure (used for non-xbox hardware). General: * Added static assertions for structure sizes. --- src/common/xbox/xboxstubs.h | 3 ++ src/inputsystem/inputsystem.h | 37 ++++++++++++++---- src/public/inputsystem/AnalogCode.h | 4 +- src/public/inputsystem/ButtonCode.h | 59 +++++++++++++++++------------ 4 files changed, 67 insertions(+), 36 deletions(-) diff --git a/src/common/xbox/xboxstubs.h b/src/common/xbox/xboxstubs.h index cfef77cf..c86f5ab6 100644 --- a/src/common/xbox/xboxstubs.h +++ b/src/common/xbox/xboxstubs.h @@ -43,6 +43,9 @@ typedef enum XK_STICK2_LEFT, XK_STICK2_RIGHT, + XK_UP_DOWN, + XK_LEFT_RIGHT, + XK_MAX_KEYS, } xKey_t; diff --git a/src/inputsystem/inputsystem.h b/src/inputsystem/inputsystem.h index a24a4c70..dd266b07 100644 --- a/src/inputsystem/inputsystem.h +++ b/src/inputsystem/inputsystem.h @@ -19,6 +19,8 @@ private: INPUT_STATE_CURRENT, INPUT_STATE_COUNT, + + BUTTON_EVENT_COUNT = 128 }; struct xdevice_t @@ -31,20 +33,38 @@ private: float rightTriggerMotor; }; + struct unkownhiddevice_t + { + struct state_t + { + SRWLOCK lock; + char unk0[56]; + xvibration_t vibration; + char unk1[48]; + }; + + // Name might be incorrect! + state_t states[INPUT_STATE_COUNT]; + HANDLE hThread0; + HANDLE hthread1; + }; + int userId; char active; XINPUT_STATE states[INPUT_STATE_COUNT]; int newState; - _BYTE gap6[20]; + xKey_t lastStickKeys[MAX_JOYSTICK_AXES-2]; // -2 as U and V aren't polled. + int unk0; bool pendingRumbleUpdate; _BYTE gap41[3]; xvibration_t vibration; - bool bUnk0; - char field_55; + bool isXbox360Gamepad; + bool nonXboxDevice; // uses unknownHidDevice when set _BYTE gap56[42]; - int field_80; - _BYTE gap84[316]; + unkownhiddevice_t unknownHidDevice; + _BYTE gap190[42]; }; + static_assert(sizeof(xdevice_t) == 0x1C0); struct appKey_t { @@ -56,7 +76,7 @@ private: { // Analog states CBitVec m_ButtonState; - int m_pAnalogValue[JOYSTICK_MAX_BUTTON_COUNT]; + int m_pAnalogValue[ANALOG_CODE_LAST]; }; @@ -90,7 +110,7 @@ private: int m_AnalogEventTypes[JOYSTICK_AXIS_BUTTON_COUNT]; // Button events - InputEvent_t m_Events[128]; + InputEvent_t m_Events[BUTTON_EVENT_COUNT]; InputEvent_t m_CurrentEvent; DWORD m_StartupTimeTick; @@ -104,7 +124,7 @@ private: // Xbox controller info int m_nJoystickCount; - appKey_t m_appXKeys[XUSER_MAX_COUNT][XK_MAX_KEYS+2]; + appKey_t m_appXKeys[XUSER_MAX_COUNT][XK_MAX_KEYS]; char pad_unk[16]; xdevice_t m_XDevices[XUSER_MAX_COUNT]; @@ -137,6 +157,7 @@ private: bool m_bIgnoreLocalJoystick; InputCursorHandle_t m_hCursor; }; +static_assert(sizeof(CInputSystem) == 0x18E8); /////////////////////////////////////////////////////////////////////////////// extern CInputSystem* g_pInputSystem; diff --git a/src/public/inputsystem/AnalogCode.h b/src/public/inputsystem/AnalogCode.h index cb439583..ce59433e 100644 --- a/src/public/inputsystem/AnalogCode.h +++ b/src/public/inputsystem/AnalogCode.h @@ -23,9 +23,7 @@ enum AnalogCode_t { ANALOG_CODE_INVALID = -1, - MOUSE_X = 0, - MOUSE_Y, - MOUSE_XY, // Invoked when either x or y changes + MOUSE_XY = 0, // Invoked when either x or y changes MOUSE_WHEEL, JOYSTICK_FIRST_AXIS, diff --git a/src/public/inputsystem/ButtonCode.h b/src/public/inputsystem/ButtonCode.h index 0f9c2df1..87f3618b 100644 --- a/src/public/inputsystem/ButtonCode.h +++ b/src/public/inputsystem/ButtonCode.h @@ -12,7 +12,7 @@ enum { - JOYSTICK_MAX_BUTTON_COUNT = XK_MAX_KEYS, + JOYSTICK_MAX_BUTTON_COUNT = 32, JOYSTICK_POV_BUTTON_COUNT = 4, JOYSTICK_AXIS_BUTTON_COUNT = MAX_JOYSTICK_AXES * 2, }; @@ -134,8 +134,9 @@ enum ButtonCode_t KEY_CAPSLOCKTOGGLE, KEY_NUMLOCKTOGGLE, KEY_SCROLLLOCKTOGGLE, + KEY_CREDITSIGN, - KEY_LAST = KEY_SCROLLLOCKTOGGLE, + KEY_LAST = KEY_CREDITSIGN, KEY_COUNT = KEY_LAST - KEY_FIRST + 1, // Mouse @@ -162,40 +163,48 @@ enum ButtonCode_t JOYSTICK_FIRST_AXIS_BUTTON, JOYSTICK_LAST_AXIS_BUTTON = JOYSTICK_AXIS_BUTTON_INTERNAL(MAX_JOYSTICKS - 1, JOYSTICK_AXIS_BUTTON_COUNT - 1), - JOYSTICK_LAST = JOYSTICK_LAST_AXIS_BUTTON, + // New in R5 + JOYSTICK_UP_DOWN, + JOYSTICK_LEFT_RIGHT, + + JOYSTICK_LAST = JOYSTICK_LEFT_RIGHT, BUTTON_CODE_LAST, BUTTON_CODE_COUNT = BUTTON_CODE_LAST - KEY_FIRST + 1, - // Helpers for XBox - KEY_XBUTTON_UP = JOYSTICK_FIRST_POV_BUTTON, // POV buttons - KEY_XBUTTON_DOWN, - KEY_XBUTTON_LEFT, - KEY_XBUTTON_RIGHT, - KEY_XBUTTON_START, - KEY_XBUTTON_BACK, - KEY_XBUTTON_STICK1, - KEY_XBUTTON_STICK2, - - KEY_XBUTTON_A = JOYSTICK_FIRST_BUTTON, // Buttons + // Helpers for XBox 360 + KEY_XBUTTON_A = JOYSTICK_FIRST_BUTTON, // Buttons KEY_XBUTTON_B, KEY_XBUTTON_X, KEY_XBUTTON_Y, KEY_XBUTTON_LEFT_SHOULDER, KEY_XBUTTON_RIGHT_SHOULDER, - - KEY_XBUTTON_LTRIGGER_PARTIAL, + KEY_XBUTTON_BACK, + KEY_XBUTTON_START, + KEY_XBUTTON_STICK1, + KEY_XBUTTON_STICK2, + KEY_XBUTTON_INACTIVE_START, KEY_XBUTTON_LTRIGGER_FULL, - KEY_XBUTTON_RTRIGGER_PARTIAL, KEY_XBUTTON_RTRIGGER_FULL, + KEY_XBUTTON_RELOAD, + KEY_XBUTTON_TRIGGER, + KEY_XBUTTON_PUMP_ACTION, + KEY_XBUTTON_ROLL_RIGHT, + KEY_XBUTTON_ROLL_LEFT, - KEY_XSTICK1_UP = JOYSTICK_FIRST_AXIS_BUTTON, // YAXIS NEGATIVE - KEY_XSTICK1_DOWN, // YAXIS POSITIVE - KEY_XSTICK1_LEFT, // XAXIS NEGATIVE - KEY_XSTICK1_RIGHT, // XAXIS POSITIVE + KEY_XBUTTON_UP = JOYSTICK_FIRST_POV_BUTTON, // POV buttons + KEY_XBUTTON_RIGHT, + KEY_XBUTTON_DOWN, + KEY_XBUTTON_LEFT, - KEY_XSTICK2_UP, // VAXIS NEGATIVE - KEY_XSTICK2_DOWN, // VAXIS POSITIVE - KEY_XSTICK2_LEFT, // UAXIS NEGATIVE - KEY_XSTICK2_RIGHT, // UAXIS POSITIVE + KEY_XSTICK1_RIGHT = JOYSTICK_FIRST_AXIS_BUTTON, // XAXIS POSITIVE + KEY_XSTICK1_LEFT, // XAXIS NEGATIVE + KEY_XSTICK1_DOWN, // YAXIS POSITIVE + KEY_XSTICK1_UP, // YAXIS NEGATIVE + KEY_XBUTTON_LTRIGGER, // ZAXIS POSITIVE + KEY_XBUTTON_RTRIGGER, // ZAXIS NEGATIVE + KEY_XSTICK2_RIGHT, // UAXIS POSITIVE + KEY_XSTICK2_LEFT, // UAXIS NEGATIVE + KEY_XSTICK2_DOWN, // VAXIS POSITIVE + KEY_XSTICK2_UP, // VAXIS NEGATIVE }; From 00622ec9689709445197b3177b4dbec395d2a0c2 Mon Sep 17 00:00:00 2001 From: Kawe Mazidjatari <48657826+Mauler125@users.noreply.github.com> Date: Sun, 24 Dec 2023 03:05:29 +0100 Subject: [PATCH 10/24] InputSystem: add inline helpers --- src/public/inputsystem/ButtonCode.h | 135 ++++++++++++++++++++++++++++ 1 file changed, 135 insertions(+) diff --git a/src/public/inputsystem/ButtonCode.h b/src/public/inputsystem/ButtonCode.h index 87f3618b..9d9f188b 100644 --- a/src/public/inputsystem/ButtonCode.h +++ b/src/public/inputsystem/ButtonCode.h @@ -208,3 +208,138 @@ enum ButtonCode_t KEY_XSTICK2_DOWN, // VAXIS POSITIVE KEY_XSTICK2_UP, // VAXIS NEGATIVE }; + +//----------------------------------------------------------------------------- +// Inline helpers +//----------------------------------------------------------------------------- +inline bool IsAlpha( const ButtonCode_t code ) +{ + return ( code >= KEY_A ) && ( code <= KEY_Z ); +} + +inline bool IsAlphaNumeric( const ButtonCode_t code ) +{ + return ( code >= KEY_0 ) && ( code <= KEY_Z ); +} + +inline bool IsSpace( const ButtonCode_t code ) +{ + return ( code == KEY_ENTER ) || ( code == KEY_TAB ) || ( code == KEY_SPACE ); +} + +inline bool IsKeypad( const ButtonCode_t code ) +{ + return ( code >= MOUSE_FIRST ) && ( code <= KEY_PAD_DECIMAL ); +} + +inline bool IsPunctuation( const ButtonCode_t code ) +{ + return ( code >= KEY_0 ) && ( code <= KEY_SPACE ) && !IsAlphaNumeric( code ) && !IsSpace( code ) && !IsKeypad( code ); +} + +inline bool IsKeyCode( const ButtonCode_t code ) +{ + return ( code >= KEY_FIRST ) && ( code <= KEY_LAST ); +} + +inline bool IsMouseCode( const ButtonCode_t code ) +{ + return ( code >= MOUSE_FIRST ) && ( code <= MOUSE_LAST ); +} + +inline bool IsJoystickCode( const ButtonCode_t code ) +{ + return ( ( code >= JOYSTICK_FIRST ) && ( code <= JOYSTICK_LAST ) ); +} + +inline bool IsJoystickButtonCode( const ButtonCode_t code ) +{ + return ( code >= JOYSTICK_FIRST_BUTTON ) && ( code <= JOYSTICK_LAST_BUTTON ); +} + +inline bool IsJoystickPOVCode( const ButtonCode_t code ) +{ + return ( code >= JOYSTICK_FIRST_POV_BUTTON ) && ( code <= JOYSTICK_LAST_POV_BUTTON ); +} + +inline bool IsJoystickAxisCode( const ButtonCode_t code ) +{ + return ( code >= JOYSTICK_FIRST_AXIS_BUTTON ) && ( code <= JOYSTICK_LAST_AXIS_BUTTON ); +} + +inline ButtonCode_t GetBaseButtonCode( const ButtonCode_t code ) +{ + if ( IsJoystickButtonCode( code ) ) + { + const int offset = ( code - JOYSTICK_FIRST_BUTTON ) % JOYSTICK_MAX_BUTTON_COUNT; + return (ButtonCode_t)( JOYSTICK_FIRST_BUTTON + offset ); + } + + if ( IsJoystickPOVCode( code ) ) + { + const int offset = ( code - JOYSTICK_FIRST_POV_BUTTON ) % JOYSTICK_POV_BUTTON_COUNT; + return (ButtonCode_t)( JOYSTICK_FIRST_POV_BUTTON + offset ); + } + + if ( IsJoystickAxisCode( code ) ) + { + const int offset = ( code - JOYSTICK_FIRST_AXIS_BUTTON ) % JOYSTICK_AXIS_BUTTON_COUNT; + return (ButtonCode_t)( JOYSTICK_FIRST_AXIS_BUTTON + offset ); + } + + return code; +} + +inline int GetJoystickForCode( const ButtonCode_t code ) +{ + if ( !IsJoystickCode( code ) ) + return 0; + + if ( IsJoystickButtonCode( code ) ) + { + const int offset = ( code - JOYSTICK_FIRST_BUTTON ) / JOYSTICK_MAX_BUTTON_COUNT; + return offset; + } + if ( IsJoystickPOVCode( code ) ) + { + const int offset = ( code - JOYSTICK_FIRST_POV_BUTTON ) / JOYSTICK_POV_BUTTON_COUNT; + return offset; + } + if ( IsJoystickAxisCode( code ) ) + { + const int offset = ( code - JOYSTICK_FIRST_AXIS_BUTTON ) / JOYSTICK_AXIS_BUTTON_COUNT; + return offset; + } + + return 0; +} + +inline ButtonCode_t ButtonCodeToJoystickButtonCode( ButtonCode_t code, int nDesiredJoystick ) +{ + if ( !IsJoystickCode( code ) || nDesiredJoystick == 0 ) + return code; + + nDesiredJoystick = clamp( nDesiredJoystick, 0, MAX_JOYSTICKS - 1 ); + code = GetBaseButtonCode( code ); + + // Now upsample it + if ( IsJoystickButtonCode( code ) ) + { + const int nOffset = code - JOYSTICK_FIRST_BUTTON; + return JOYSTICK_BUTTON( nDesiredJoystick, nOffset ); + } + + if ( IsJoystickPOVCode( code ) ) + { + const int nOffset = code - JOYSTICK_FIRST_POV_BUTTON; + return JOYSTICK_POV_BUTTON( nDesiredJoystick, nOffset ); + } + + if ( IsJoystickAxisCode( code ) ) + { + const int nOffset = code - JOYSTICK_FIRST_AXIS_BUTTON; + return JOYSTICK_AXIS_BUTTON( nDesiredJoystick, nOffset ); + } + + return code; +} From fc668bb7f5a06f14429b08f6e495a5ea1ae8c8db Mon Sep 17 00:00:00 2001 From: Kawe Mazidjatari <48657826+Mauler125@users.noreply.github.com> Date: Sun, 24 Dec 2023 15:15:17 +0100 Subject: [PATCH 11/24] InputSystem: add comment to field --- src/inputsystem/inputsystem.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/inputsystem/inputsystem.h b/src/inputsystem/inputsystem.h index dd266b07..16bbaf30 100644 --- a/src/inputsystem/inputsystem.h +++ b/src/inputsystem/inputsystem.h @@ -111,6 +111,8 @@ private: // Button events InputEvent_t m_Events[BUTTON_EVENT_COUNT]; + + // Current event InputEvent_t m_CurrentEvent; DWORD m_StartupTimeTick; From 98d47ce8ed991bce6846b585ea962e1d256093be Mon Sep 17 00:00:00 2001 From: Kawe Mazidjatari <48657826+Mauler125@users.noreply.github.com> Date: Sun, 24 Dec 2023 15:17:08 +0100 Subject: [PATCH 12/24] InputSystem: add reversed KeyInfo_t and KeyEvent_t struct Almost fully mapped out, the unknown fields seem to be unused or padding. --- src/core/init.cpp | 4 ++- src/engine/CMakeLists.txt | 6 ++++ src/engine/keys.cpp | 5 +++ src/engine/keys.h | 72 +++++++++++++++++++++++++++++++++++++++ 4 files changed, 86 insertions(+), 1 deletion(-) create mode 100644 src/engine/keys.cpp create mode 100644 src/engine/keys.h diff --git a/src/core/init.cpp b/src/core/init.cpp index 61c80dee..e231ef81 100644 --- a/src/core/init.cpp +++ b/src/core/init.cpp @@ -96,14 +96,15 @@ #include "engine/sys_utils.h" #ifndef DEDICATED #include "engine/sys_getmodes.h" -#include "engine/gl_rmain.h" #include "engine/sys_mainwind.h" #include "engine/matsys_interface.h" +#include "engine/gl_rmain.h" #include "engine/gl_matsysiface.h" #include "engine/gl_drawlights.h" #include "engine/gl_screen.h" #include "engine/gl_rsurf.h" #include "engine/debugoverlay.h" +#include "engine/keys.h" #endif // !DEDICATED #include "vscript/languages/squirrel_re/include/squirrel.h" #include "vscript/languages/squirrel_re/include/sqvm.h" @@ -593,6 +594,7 @@ void DetourRegister() // Register detour classes to be searched and hooked. REGISTER(VGL_RSurf); REGISTER(VDebugOverlay); // !TODO: This also needs to be exposed to server dll!!! + REGISTER(VKeys); #endif // !DEDICATED // VScript diff --git a/src/engine/CMakeLists.txt b/src/engine/CMakeLists.txt index a27fa06f..acd19043 100644 --- a/src/engine/CMakeLists.txt +++ b/src/engine/CMakeLists.txt @@ -26,6 +26,11 @@ add_sources( SOURCE_GROUP "Debug" "debugoverlay.h" ) +add_sources( SOURCE_GROUP "Input" + "keys.cpp" + "keys.h" +) + add_sources( SOURCE_GROUP "Render" "framelimit.cpp" "framelimit.h" @@ -189,6 +194,7 @@ add_sources( SOURCE_GROUP "Common" "${ENGINE_SOURCE_DIR}/common/qlimits.h" "${ENGINE_SOURCE_DIR}/common/sdkdefs.h" "${ENGINE_SOURCE_DIR}/common/x86defs.h" + "${ENGINE_SOURCE_DIR}/common/xbox/xboxstubs.h" ) file( GLOB ENGINE_PUBLIC_HEADERS diff --git a/src/engine/keys.cpp b/src/engine/keys.cpp new file mode 100644 index 00000000..84fad325 --- /dev/null +++ b/src/engine/keys.cpp @@ -0,0 +1,5 @@ +#include "keys.h" + +KeyInfo_t* g_pKeyInfo = nullptr; +ButtonCode_t* g_pKeyEventTicks = nullptr; +short* g_nKeyEventCount = nullptr; \ No newline at end of file diff --git a/src/engine/keys.h b/src/engine/keys.h new file mode 100644 index 00000000..317eadef --- /dev/null +++ b/src/engine/keys.h @@ -0,0 +1,72 @@ +#ifndef ENGINE_KEYS_H +#define ENGINE_KEYS_H +#include "inputsystem/ButtonCode.h" + +//----------------------------------------------------------------------------- +// Keypress event +//----------------------------------------------------------------------------- +struct KeyEvent_t +{ + const char* m_pCommand; + int m_nTick; + bool m_bDown; +}; + +//----------------------------------------------------------------------------- +// Current keypress state +//----------------------------------------------------------------------------- +struct KeyInfo_t +{ + enum + { + KEY_TAPPED_BIND = 0, + KEY_HELD_BIND, + + KEY_BIND_COUNT + }; + + const char* m_pKeyBinding[KEY_BIND_COUNT]; + int m_nKeyUpTarget; + int m_nKeyDownTarget; + + uint32_t m_nEventTick; // When was the event issued? + int unknown; + short m_nEventNumber; // The event number. + + bool m_bKeyDown; + bool m_bEventIsButtonKey; // Is the event a button key (< ButtonCode_t::KEY_LAST) + bool m_bBoundKeyDown; + bool m_bBoundSecondKey; // Is the key bound to the second row? + + short paddingMaybe; +}; + +extern KeyInfo_t* g_pKeyInfo; // ARRAYSIZE = ButtonCode_t::BUTTON_CODE_LAST +extern ButtonCode_t* g_pKeyEventTicks; // ARRAYSIZE = ButtonCode_t::BUTTON_CODE_LAST +extern short* g_nKeyEventCount; + +class VKeys : public IDetour +{ + virtual void GetAdr(void) const + { + LogVarAdr("g_pKeyInfo", reinterpret_cast(g_pKeyInfo)); + LogVarAdr("g_pKeyEventTicks", reinterpret_cast(g_pKeyEventTicks)); + LogVarAdr("g_nKeyEventCount", reinterpret_cast(g_nKeyEventCount)); + } + virtual void GetFun(void) const { } + virtual void GetVar(void) const + { + g_pKeyInfo = g_GameDll.FindPatternSIMD("48 83 EC 28 33 D2 48 8D 0D ?? ?? ?? ?? 41 B8 ?? ?? ?? ?? E8 ?? ?? ?? ?? 33 C0 C6 05 ?? ?? ?? ?? ??") + .FindPatternSelf("48 8D 0D", CMemory::Direction::DOWN, 40).ResolveRelativeAddressSelf(3, 7).RCast(); + + CMemory l_EngineApi_PumpMessages = g_GameDll.FindPatternSIMD("48 89 5C 24 ?? 55 48 81 EC ?? ?? ?? ?? 45 33 C9"); + + // NOTE: g_nKeyEventCount's pattern is found earlier, thus searched for earlier to offset base for g_pKeyEventTicks. + g_nKeyEventCount = l_EngineApi_PumpMessages.FindPatternSelf("0F B7 15").ResolveRelativeAddressSelf(3, 7).RCast(); + g_pKeyEventTicks = l_EngineApi_PumpMessages.FindPatternSelf("48 8D 35").ResolveRelativeAddressSelf(3, 7).RCast(); + } + virtual void GetCon(void) const { } + virtual void Detour(const bool bAttach) const { } +}; + +#endif // ENGINE_KEYS_H From 30518e1f64d2d84edb62aec1403d6ac065d51bcd Mon Sep 17 00:00:00 2001 From: Kawe Mazidjatari <48657826+Mauler125@users.noreply.github.com> Date: Sun, 24 Dec 2023 15:23:05 +0100 Subject: [PATCH 13/24] InputSystem: make InputEventCallback_t return type bool --- src/public/inputsystem/iinputsystem.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/public/inputsystem/iinputsystem.h b/src/public/inputsystem/iinputsystem.h index 29949574..857808e8 100644 --- a/src/public/inputsystem/iinputsystem.h +++ b/src/public/inputsystem/iinputsystem.h @@ -19,7 +19,7 @@ DECLARE_POINTER_HANDLE( InputCursorHandle_t ); ///----------------------------------------------------------------------------- /// Input event callback ///----------------------------------------------------------------------------- -typedef void ( *InputEventCallback_t ) ( const InputEvent_t& eventCallback ); +typedef bool ( *InputEventCallback_t ) ( const InputEvent_t& eventCallback ); ///----------------------------------------------------------------------------- /// An enumeration describing well-known cursor icons From d42ca04e8cd2b749a0db44a56b8aff8b8bdf06a5 Mon Sep 17 00:00:00 2001 From: Kawe Mazidjatari <48657826+Mauler125@users.noreply.github.com> Date: Sun, 24 Dec 2023 16:29:42 +0100 Subject: [PATCH 14/24] EngineAPI: key event dispatcher rebuild --- src/common/global.cpp | 3 +++ src/common/global.h | 2 ++ src/engine/keys.h | 8 ++++++- src/engine/sys_dll2.cpp | 15 ++++++++++++- src/engine/sys_mainwind.cpp | 38 +++++++++++++++++++++++++++++++- src/engine/sys_mainwind.h | 6 ++++- src/inputsystem/inputsystem.cpp | 3 ++- src/inputsystem/inputsystem.h | 5 +++++ src/vgui/vgui_baseui_interface.h | 5 +++++ 9 files changed, 80 insertions(+), 5 deletions(-) diff --git a/src/common/global.cpp b/src/common/global.cpp index 850ba453..c538eaef 100644 --- a/src/common/global.cpp +++ b/src/common/global.cpp @@ -28,6 +28,8 @@ ConVar* fps_max_rt = nullptr; ConVar* fps_max_rt_tolerance = nullptr; ConVar* fps_max_rt_sleep_threshold = nullptr; ConVar* fps_max_gfx = nullptr; + +ConVar* in_syncRT = nullptr; #endif // !DEDICATED ConVar* base_tickinterval_sp = nullptr; @@ -565,6 +567,7 @@ void ConVar_InitShipped(void) #ifndef DEDICATED miles_language = g_pCVar->FindVar("miles_language"); rui_defaultDebugFontFace = g_pCVar->FindVar("rui_defaultDebugFontFace"); + in_syncRT = g_pCVar->FindVar("in_syncRT"); r_visualizetraces = g_pCVar->FindVar("r_visualizetraces"); r_visualizetraces_duration = g_pCVar->FindVar("r_visualizetraces_duration"); #endif // !DEDICATED diff --git a/src/common/global.h b/src/common/global.h index 3d546b56..3ae5c83e 100644 --- a/src/common/global.h +++ b/src/common/global.h @@ -19,6 +19,8 @@ extern ConVar* fps_max_rt; extern ConVar* fps_max_rt_tolerance; extern ConVar* fps_max_rt_sleep_threshold; extern ConVar* fps_max_gfx; + +extern ConVar* in_syncRT; #endif // !DEDICATED extern ConVar* base_tickinterval_sp; diff --git a/src/engine/keys.h b/src/engine/keys.h index 317eadef..c4b7e829 100644 --- a/src/engine/keys.h +++ b/src/engine/keys.h @@ -41,6 +41,8 @@ struct KeyInfo_t short paddingMaybe; }; +inline bool(*Key_Event)(const KeyEvent_t& keyEvent); + extern KeyInfo_t* g_pKeyInfo; // ARRAYSIZE = ButtonCode_t::BUTTON_CODE_LAST extern ButtonCode_t* g_pKeyEventTicks; // ARRAYSIZE = ButtonCode_t::BUTTON_CODE_LAST extern short* g_nKeyEventCount; @@ -49,11 +51,15 @@ class VKeys : public IDetour { virtual void GetAdr(void) const { + LogFunAdr("Key_Event", reinterpret_cast(Key_Event)); LogVarAdr("g_pKeyInfo", reinterpret_cast(g_pKeyInfo)); LogVarAdr("g_pKeyEventTicks", reinterpret_cast(g_pKeyEventTicks)); LogVarAdr("g_nKeyEventCount", reinterpret_cast(g_nKeyEventCount)); } - virtual void GetFun(void) const { } + virtual void GetFun(void) const + { + Key_Event = g_GameDll.FindPatternSIMD("48 89 5C 24 ?? 48 89 74 24 ?? 57 48 83 EC 20 4C 63 41 08").RCast(); + } virtual void GetVar(void) const { g_pKeyInfo = g_GameDll.FindPatternSIMD("48 83 EC 28 33 D2 48 8D 0D ?? ?? ?? ?? 41 B8 ?? ?? ?? ?? E8 ?? ?? ?? ?? 33 C0 C6 05 ?? ?? ?? ?? ??") diff --git a/src/engine/sys_dll2.cpp b/src/engine/sys_dll2.cpp index d9dc35c2..9abae8d9 100644 --- a/src/engine/sys_dll2.cpp +++ b/src/engine/sys_dll2.cpp @@ -17,6 +17,8 @@ #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" @@ -162,7 +164,18 @@ void CEngineAPI::VSetStartupInfo(CEngineAPI* pEngineAPI, StartupInfo_t* pStartup void CEngineAPI::PumpMessages() { #ifndef DEDICATED - CEngineAPI_PumpMessages(); + MSG msg; + while (PeekMessageW(&msg, NULL, 0, 0, PM_REMOVE)) + { + TranslateMessage(&msg); + DispatchMessageW(&msg); + } + + if (in_syncRT->GetBool()) + (*g_fnSyncRTWithIn)(); + + g_pInputSystem->PollInputState(UIInputEventHandler); + g_pGame->DispatchAllStoredGameMessages(); #endif // !DEDICATED } diff --git a/src/engine/sys_mainwind.cpp b/src/engine/sys_mainwind.cpp index 43407dc3..e963a551 100644 --- a/src/engine/sys_mainwind.cpp +++ b/src/engine/sys_mainwind.cpp @@ -9,6 +9,7 @@ #include "windows/input.h" #include "engine/sys_mainwind.h" #include "engine/sys_engine.h" +#include "engine/keys.h" #include "gameui/IConsole.h" #include "gameui/IBrowser.h" @@ -97,7 +98,7 @@ int CGame::WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) //----------------------------------------------------------------------------- // Purpose: gets the window rect //----------------------------------------------------------------------------- -void CGame::GetWindowRect(int* x, int* y, int* w, int* h) +void CGame::GetWindowRect(int* const x, int* const y, int* const w, int* const h) const { if (x) { @@ -117,6 +118,41 @@ void CGame::GetWindowRect(int* x, int* y, int* w, int* h) } } +//----------------------------------------------------------------------------- +// Purpose: dispatch key event +//----------------------------------------------------------------------------- +void CGame::DispatchKeyEvent(const uint64_t msTime, const ButtonCode_t buttonCode) const +{ + const float duration = buttonCode == KEY_XBUTTON_BACK ? 1.0f : 0.2f; + KeyInfo_t& keyInfo = g_pKeyInfo[buttonCode]; + + if (keyInfo.m_bKeyDown && ((msTime - keyInfo.m_nEventTick) * 0.001f) >= duration) + { + KeyEvent_t keyEvent; + + keyEvent.m_pCommand = keyInfo.m_pKeyBinding[KeyInfo_t::KEY_HELD_BIND]; + keyEvent.m_nTick = buttonCode; + keyEvent.m_bDown = true; + + Key_Event(keyEvent); + keyInfo.m_bKeyDown = true; + } +} + +//----------------------------------------------------------------------------- +// Purpose: dispatch all the queued up messages +//----------------------------------------------------------------------------- +void CGame::DispatchAllStoredGameMessages() const +{ + const uint64_t ticks = Plat_MSTime(); + const short eventCount = *g_nKeyEventCount; + + for (short i = 0; i < eventCount; i++) + { + DispatchKeyEvent(ticks, g_pKeyEventTicks[i]); + } +} + /////////////////////////////////////////////////////////////////////////////// void VGame::Detour(const bool bAttach) const { diff --git a/src/engine/sys_mainwind.h b/src/engine/sys_mainwind.h index 4c44b56e..9ed5a2ac 100644 --- a/src/engine/sys_mainwind.h +++ b/src/engine/sys_mainwind.h @@ -5,6 +5,7 @@ //===========================================================================// #ifndef SYS_MAINWIND_H #define SYS_MAINWIND_H +#include "inputsystem/iinputsystem.h" inline CMemory p_CGame__AttachToWindow; inline void (*v_CGame__AttachToWindow)(void); @@ -25,7 +26,7 @@ public: inline HWND GetWindow() const { return m_hWindow; } - void GetWindowRect(int* x, int* y, int* w, int* h); + void GetWindowRect(int* const x, int* const y, int* const w, int* const h) const; inline int GetDesktopWidth() const { return m_iDesktopWidth; } inline int GetDesktopHeight() const { return m_iDesktopHeight; } @@ -33,6 +34,9 @@ public: inline float GetTVRefreshRate() const // Avoid stutter on TV's running on broadcast frame rates. { return ((float)m_iDesktopRefreshRate == 59.0f || (float)m_iDesktopRefreshRate == 60.0f) ? 59.939999f : (float)m_iDesktopRefreshRate; } + void DispatchKeyEvent(const uint64_t msTime, const ButtonCode_t buttonCode) const; + void DispatchAllStoredGameMessages() const; + private: HWND m_hWindow; HINSTANCE m_hInstance; diff --git a/src/inputsystem/inputsystem.cpp b/src/inputsystem/inputsystem.cpp index 256fc8b0..f181d0ca 100644 --- a/src/inputsystem/inputsystem.cpp +++ b/src/inputsystem/inputsystem.cpp @@ -50,4 +50,5 @@ //} /////////////////////////////////////////////////////////////////////////////// -CInputSystem* g_pInputSystem = nullptr; \ No newline at end of file +CInputSystem* g_pInputSystem = nullptr; +bool(**g_fnSyncRTWithIn)(void) = nullptr; diff --git a/src/inputsystem/inputsystem.h b/src/inputsystem/inputsystem.h index 16bbaf30..52b666b5 100644 --- a/src/inputsystem/inputsystem.h +++ b/src/inputsystem/inputsystem.h @@ -163,6 +163,7 @@ static_assert(sizeof(CInputSystem) == 0x18E8); /////////////////////////////////////////////////////////////////////////////// extern CInputSystem* g_pInputSystem; +extern bool(**g_fnSyncRTWithIn)(void); // Belongs to an array of callbacks, see CMaterialSystem::MatsysMode_Init(). /////////////////////////////////////////////////////////////////////////////// class VInputSystem : public IDetour @@ -170,12 +171,16 @@ class VInputSystem : public IDetour virtual void GetAdr(void) const { LogVarAdr("g_pInputSystem", reinterpret_cast(g_pInputSystem)); + LogVarAdr("g_fnSyncRTWithIn", reinterpret_cast(g_fnSyncRTWithIn)); } virtual void GetFun(void) const { } virtual void GetVar(void) const { g_pInputSystem = g_GameDll.FindPatternSIMD("48 83 EC 28 48 8B 0D ?? ?? ?? ?? 48 8D 05 ?? ?? ?? ?? 48 89 05 ?? ?? ?? ?? 48 85 C9 74 11") .FindPatternSelf("48 89 05", CMemory::Direction::DOWN, 40).ResolveRelativeAddressSelf(0x3, 0x7).RCast(); + + const CMemory l_EngineApi_PumpMessages = g_GameDll.FindPatternSIMD("48 89 5C 24 ?? 55 48 81 EC ?? ?? ?? ?? 45 33 C9"); + g_fnSyncRTWithIn = l_EngineApi_PumpMessages.FindPattern("74 06").FindPatternSelf("FF 15").ResolveRelativeAddressSelf(2, 6).RCast(); } virtual void GetCon(void) const { } virtual void Detour(const bool bAttach) const { } diff --git a/src/vgui/vgui_baseui_interface.h b/src/vgui/vgui_baseui_interface.h index 3801cf2c..d4a5b4ea 100644 --- a/src/vgui/vgui_baseui_interface.h +++ b/src/vgui/vgui_baseui_interface.h @@ -1,6 +1,7 @@ #pragma once #include #include +#include "inputsystem/iinputsystem.h" enum class PaintMode_t { @@ -85,6 +86,7 @@ inline void*(*CEngineVGui_RenderStart)(CMatSystemSurface* pMatSystemSurface); inline CMemory p_CEngineVGui_RenderEnd; inline void*(*CEngineVGui_RenderEnd)(void); +inline InputEventCallback_t UIInputEventHandler = nullptr; inline CEngineVGui* g_pEngineVGui = nullptr; /////////////////////////////////////////////////////////////////////////////// @@ -95,6 +97,7 @@ class VEngineVGui : public IDetour LogFunAdr("CEngineVGui::Paint", p_CEngineVGui_Paint.GetPtr()); LogFunAdr("CEngineVGui::RenderStart", p_CEngineVGui_RenderStart.GetPtr()); LogFunAdr("CEngineVGui::RenderEnd", p_CEngineVGui_RenderEnd.GetPtr()); + LogFunAdr("UIInputEventHandler", reinterpret_cast(UIInputEventHandler)); LogVarAdr("g_pEngineVGui", reinterpret_cast(g_pEngineVGui)); } virtual void GetFun(void) const @@ -114,6 +117,8 @@ class VEngineVGui : public IDetour #endif p_CEngineVGui_RenderEnd = g_GameDll.FindPatternSIMD("40 53 48 83 EC 20 48 8B 0D ?? ?? ?? ?? C6 05 ?? ?? ?? ?? ?? 48 8B 01"); CEngineVGui_RenderEnd = p_CEngineVGui_RenderEnd.RCast(); /*40 53 48 83 EC 20 48 8B 0D ?? ?? ?? ?? C6 05 ?? ?? ?? ?? ?? 48 8B 01*/ + + UIInputEventHandler = g_GameDll.FindPatternSIMD("40 53 48 83 EC 40 48 63 01").RCast(); } virtual void GetVar(void) const { From 76b927e3b0298e8e41ca3026a07e2f3257be8d75 Mon Sep 17 00:00:00 2001 From: Kawe Mazidjatari <48657826+Mauler125@users.noreply.github.com> Date: Sun, 24 Dec 2023 16:33:20 +0100 Subject: [PATCH 15/24] Tier1: temporarily comment Unused and causes errors due to unimplemented mutex class (needs to be reversed still). --- src/public/tier1/utlstringmap.h | 2 +- src/public/tier1/utlsymbol.h | 231 ++++++++++++++++---------------- 2 files changed, 119 insertions(+), 114 deletions(-) diff --git a/src/public/tier1/utlstringmap.h b/src/public/tier1/utlstringmap.h index 82c2e975..7bc46b16 100644 --- a/src/public/tier1/utlstringmap.h +++ b/src/public/tier1/utlstringmap.h @@ -96,7 +96,7 @@ public: else // ( m_Vector.Count() < index ) { // this is a strange shouldn't-happen case. - AssertMsg( false, "CUtlStringMap insert unexpected entries." ); + //AssertMsg( false, "CUtlStringMap insert unexpected entries." ); m_Vector.EnsureCount( index + 1 ); m_Vector[index] = item; } diff --git a/src/public/tier1/utlsymbol.h b/src/public/tier1/utlsymbol.h index 3133559d..70a3308e 100644 --- a/src/public/tier1/utlsymbol.h +++ b/src/public/tier1/utlsymbol.h @@ -196,60 +196,62 @@ private: }; -class CUtlSymbolTableMT : public CUtlSymbolTable -{ -public: - CUtlSymbolTableMT( int growSize = 0, int initSize = 32, bool caseInsensitive = false ) - : CUtlSymbolTable( growSize, initSize, caseInsensitive ) - { - } +// TODO[ AMOS ]: implement CThreadSpinRWLock - CUtlSymbol AddString( const char* pString ) - { - m_lock.LockForWrite(); - CUtlSymbol result = CUtlSymbolTable::AddString( pString ); - m_lock.UnlockWrite(); - return result; - } - - CUtlSymbol Find( const char* pString ) const - { - m_lock.LockForWrite(); - CUtlSymbol result = CUtlSymbolTable::Find( pString ); - m_lock.UnlockWrite(); - return result; - } - - const char* String( CUtlSymbol id ) const - { - m_lock.LockForRead(); - const char *pszResult = CUtlSymbolTable::String( id ); - m_lock.UnlockRead(); - return pszResult; - } - - const char * StringNoLock( CUtlSymbol id ) const - { - return CUtlSymbolTable::String( id ); - } - - void LockForRead() - { - m_lock.LockForRead(); - } - - void UnlockForRead() - { - m_lock.UnlockRead(); - } - -private: -#ifdef WIN32 - mutable CThreadSpinRWLock m_lock; -#else - mutable CThreadRWLock m_lock; -#endif -}; +//class CUtlSymbolTableMT : public CUtlSymbolTable +//{ +//public: +// CUtlSymbolTableMT( int growSize = 0, int initSize = 32, bool caseInsensitive = false ) +// : CUtlSymbolTable( growSize, initSize, caseInsensitive ) +// { +// } +// +// CUtlSymbol AddString( const char* pString ) +// { +// m_lock.LockForWrite(); +// CUtlSymbol result = CUtlSymbolTable::AddString( pString ); +// m_lock.UnlockWrite(); +// return result; +// } +// +// CUtlSymbol Find( const char* pString ) const +// { +// m_lock.LockForWrite(); +// CUtlSymbol result = CUtlSymbolTable::Find( pString ); +// m_lock.UnlockWrite(); +// return result; +// } +// +// const char* String( CUtlSymbol id ) const +// { +// m_lock.LockForRead(); +// const char *pszResult = CUtlSymbolTable::String( id ); +// m_lock.UnlockRead(); +// return pszResult; +// } +// +// const char * StringNoLock( CUtlSymbol id ) const +// { +// return CUtlSymbolTable::String( id ); +// } +// +// void LockForRead() +// { +// m_lock.LockForRead(); +// } +// +// void UnlockForRead() +// { +// m_lock.UnlockRead(); +// } +// +//private: +//#ifdef WIN32 +// mutable CThreadSpinRWLock m_lock; +//#else +// mutable CThreadRWLock m_lock; +//#endif +//}; @@ -268,68 +270,71 @@ typedef void* FileNameHandle_t; // Symbol table for more efficiently storing filenames by breaking paths and filenames apart. // Refactored from BaseFileSystem.h -class CUtlFilenameSymbolTable -{ - // Internal representation of a FileHandle_t - // If we get more than 64K filenames, we'll have to revisit... - // Right now CUtlSymbol is a short, so this packs into an int/void * pointer size... - struct FileNameHandleInternal_t - { - FileNameHandleInternal_t() - { - COMPILE_TIME_ASSERT( sizeof( *this ) == sizeof( FileNameHandle_t ) ); - COMPILE_TIME_ASSERT( sizeof( value ) == 4 ); - value = 0; -#ifdef PLATFORM_64BITS - pad = 0; -#endif - } +// TODO[ AMOS ]: implement CThreadSpinRWLock - // We pack the path and file values into a single 32 bit value. We were running - // out of space with the two 16 bit values (more than 64k files) so instead of increasing - // the total size we split the underlying pool into two (paths and files) and - // use a smaller path string pool and a larger file string pool. - unsigned int value; - -#ifdef PLATFORM_64BITS - // some padding to make sure we are the same size as FileNameHandle_t on 64 bit. - unsigned int pad; -#endif - - static const unsigned int cNumBitsInPath = 12; - static const unsigned int cNumBitsInFile = 32 - cNumBitsInPath; - - static const unsigned int cMaxPathValue = 1 << cNumBitsInPath; - static const unsigned int cMaxFileValue = 1 << cNumBitsInFile; - - static const unsigned int cPathBitMask = cMaxPathValue - 1; - static const unsigned int cFileBitMask = cMaxFileValue - 1; - - // Part before the final '/' character - unsigned int GetPath() const { return ((value >> cNumBitsInFile) & cPathBitMask); } - void SetPath( unsigned int path ) { Assert( path < cMaxPathValue ); value = ((value & cFileBitMask) | ((path & cPathBitMask) << cNumBitsInFile)); } - - // Part after the final '/', including extension - unsigned int GetFile() const { return (value & cFileBitMask); } - void SetFile( unsigned int file ) { Assert( file < cMaxFileValue ); value = ((value & (cPathBitMask << cNumBitsInFile)) | (file & cFileBitMask)); } - }; - -public: - FileNameHandle_t FindOrAddFileName( const char *pFileName ); - FileNameHandle_t FindFileName( const char *pFileName ); - int PathIndex( const FileNameHandle_t &handle ) { return (( const FileNameHandleInternal_t * )&handle)->GetPath(); } - bool String( const FileNameHandle_t& handle, char *buf, int buflen ); - void RemoveAll(); - void SpewStrings(); - bool SaveToBuffer( CUtlBuffer &buffer ); - bool RestoreFromBuffer( CUtlBuffer &buffer ); - -private: - CCountedStringPoolBase m_PathStringPool; - CCountedStringPoolBase m_FileStringPool; - mutable CThreadSpinRWLock m_lock; -}; +//class CUtlFilenameSymbolTable +//{ +// // Internal representation of a FileHandle_t +// // If we get more than 64K filenames, we'll have to revisit... +// // Right now CUtlSymbol is a short, so this packs into an int/void * pointer size... +// struct FileNameHandleInternal_t +// { +// FileNameHandleInternal_t() +// { +// COMPILE_TIME_ASSERT( sizeof( *this ) == sizeof( FileNameHandle_t ) ); +// COMPILE_TIME_ASSERT( sizeof( value ) == 4 ); +// value = 0; +// +//#ifdef PLATFORM_64BITS +// pad = 0; +//#endif +// } +// +// // We pack the path and file values into a single 32 bit value. We were running +// // out of space with the two 16 bit values (more than 64k files) so instead of increasing +// // the total size we split the underlying pool into two (paths and files) and +// // use a smaller path string pool and a larger file string pool. +// unsigned int value; +// +//#ifdef PLATFORM_64BITS +// // some padding to make sure we are the same size as FileNameHandle_t on 64 bit. +// unsigned int pad; +//#endif +// +// static const unsigned int cNumBitsInPath = 12; +// static const unsigned int cNumBitsInFile = 32 - cNumBitsInPath; +// +// static const unsigned int cMaxPathValue = 1 << cNumBitsInPath; +// static const unsigned int cMaxFileValue = 1 << cNumBitsInFile; +// +// static const unsigned int cPathBitMask = cMaxPathValue - 1; +// static const unsigned int cFileBitMask = cMaxFileValue - 1; +// +// // Part before the final '/' character +// unsigned int GetPath() const { return ((value >> cNumBitsInFile) & cPathBitMask); } +// void SetPath( unsigned int path ) { Assert( path < cMaxPathValue ); value = ((value & cFileBitMask) | ((path & cPathBitMask) << cNumBitsInFile)); } +// +// // Part after the final '/', including extension +// unsigned int GetFile() const { return (value & cFileBitMask); } +// void SetFile( unsigned int file ) { Assert( file < cMaxFileValue ); value = ((value & (cPathBitMask << cNumBitsInFile)) | (file & cFileBitMask)); } +// }; +// +//public: +// FileNameHandle_t FindOrAddFileName( const char *pFileName ); +// FileNameHandle_t FindFileName( const char *pFileName ); +// int PathIndex( const FileNameHandle_t &handle ) { return (( const FileNameHandleInternal_t * )&handle)->GetPath(); } +// bool String( const FileNameHandle_t& handle, char *buf, int buflen ); +// void RemoveAll(); +// void SpewStrings(); +// bool SaveToBuffer( CUtlBuffer &buffer ); +// bool RestoreFromBuffer( CUtlBuffer &buffer ); +// +//private: +// CCountedStringPoolBase m_PathStringPool; +// CCountedStringPoolBase m_FileStringPool; +// mutable CThreadSpinRWLock m_lock; +//}; // This creates a simple class that includes the underlying CUtlSymbol // as a private member and then instances a private symbol table to From aa1a43ac4f61d1e2c379e3b32d8b460dfa5a66b6 Mon Sep 17 00:00:00 2001 From: Kawe Mazidjatari <48657826+Mauler125@users.noreply.github.com> Date: Sun, 24 Dec 2023 20:38:07 +0100 Subject: [PATCH 16/24] Tier0: add template inline for FindPatternSIMD This allows for directly setting a function pointer without double casting it, and significantly reduce code verbosity. --- src/public/tier0/module.h | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/public/tier0/module.h b/src/public/tier0/module.h index 299b3662..3bbe0cdc 100644 --- a/src/public/tier0/module.h +++ b/src/public/tier0/module.h @@ -28,6 +28,15 @@ public: void LoadSections(); CMemory FindPatternSIMD(const char* szPattern, const ModuleSections_t* moduleSection = nullptr) const; + + template + inline void FindPatternSIMD(const char* szPattern, + T*& pMemPtrOut, const ModuleSections_t* moduleSection = nullptr) const + { + CMemory mem = FindPatternSIMD(szPattern, moduleSection); + pMemPtrOut = mem.RCast(); + } + CMemory FindString(const char* szString, const ptrdiff_t occurrence = 1, bool nullTerminator = false) const; CMemory FindStringReadOnly(const char* szString, bool nullTerminator) const; CMemory FindFreeDataPage(const size_t nSize) const; From 0e62280896ec2a243283366205fb8313d6e29a14 Mon Sep 17 00:00:00 2001 From: Kawe Mazidjatari <48657826+Mauler125@users.noreply.github.com> Date: Sun, 24 Dec 2023 20:38:50 +0100 Subject: [PATCH 17/24] NVIDIA: add PC_LATENCY_PING marker to msg pump --- src/inputsystem/inputsystem.cpp | 23 +++++++++++++++++++++++ src/inputsystem/inputsystem.h | 15 ++++++++++++--- 2 files changed, 35 insertions(+), 3 deletions(-) diff --git a/src/inputsystem/inputsystem.cpp b/src/inputsystem/inputsystem.cpp index f181d0ca..01f2a39a 100644 --- a/src/inputsystem/inputsystem.cpp +++ b/src/inputsystem/inputsystem.cpp @@ -6,6 +6,8 @@ #include "core/stdafx.h" #include "vpc/IAppSystem.h" +#include "windows/id3dx.h" +#include "geforce/reflex.h" #include "inputsystem/inputsystem.h" ////----------------------------------------------------------------------------- @@ -49,6 +51,27 @@ // return CallVFunc(index, this, pString); //} +LRESULT CInputSystem::WindowProc(void* unused, HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + if (g_pInputSystem->m_bEnabled && + ((hwnd == g_pInputSystem->m_hAttachedHWnd) || (uMsg == WM_ACTIVATEAPP)) && + (uMsg != WM_CLOSE)) + { + if (PCLSTATS_IS_PING_MSG_ID(uMsg)) + { + GFX_SetLatencyMarker(D3D11Device(), PC_LATENCY_PING); + } + } + + return v_CInputSystem__WindowProc(unused, hwnd, uMsg, wParam, lParam); +} + + +void VInputSystem::Detour(const bool bAttach) const +{ + DetourSetup(&v_CInputSystem__WindowProc, &CInputSystem::WindowProc, bAttach); +} + /////////////////////////////////////////////////////////////////////////////// CInputSystem* g_pInputSystem = nullptr; bool(**g_fnSyncRTWithIn)(void) = nullptr; diff --git a/src/inputsystem/inputsystem.h b/src/inputsystem/inputsystem.h index 52b666b5..ed667267 100644 --- a/src/inputsystem/inputsystem.h +++ b/src/inputsystem/inputsystem.h @@ -11,6 +11,9 @@ class CInputSystem : public CTier1AppSystem< IInputSystem > { public: // !!!interface implemented in engine!!! +public: + // Hook statics: + static LRESULT WindowProc(void* unused, HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam); private: enum @@ -162,18 +165,24 @@ private: static_assert(sizeof(CInputSystem) == 0x18E8); /////////////////////////////////////////////////////////////////////////////// +inline LRESULT (*v_CInputSystem__WindowProc)(void* thisptr, HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam); + extern CInputSystem* g_pInputSystem; -extern bool(**g_fnSyncRTWithIn)(void); // Belongs to an array of callbacks, see CMaterialSystem::MatsysMode_Init(). +extern bool(**g_fnSyncRTWithIn)(void); // Belongs to an array of functions, see CMaterialSystem::MatsysMode_Init(). /////////////////////////////////////////////////////////////////////////////// class VInputSystem : public IDetour { virtual void GetAdr(void) const { + LogFunAdr("CInputSystem::WindowProc", reinterpret_cast(v_CInputSystem__WindowProc)); LogVarAdr("g_pInputSystem", reinterpret_cast(g_pInputSystem)); LogVarAdr("g_fnSyncRTWithIn", reinterpret_cast(g_fnSyncRTWithIn)); } - virtual void GetFun(void) const { } + virtual void GetFun(void) const + { + g_GameDll.FindPatternSIMD("48 89 4C 24 ?? 55 56 41 54 41 55 48 83 EC 48", v_CInputSystem__WindowProc); + } virtual void GetVar(void) const { g_pInputSystem = g_GameDll.FindPatternSIMD("48 83 EC 28 48 8B 0D ?? ?? ?? ?? 48 8D 05 ?? ?? ?? ?? 48 89 05 ?? ?? ?? ?? 48 85 C9 74 11") @@ -183,6 +192,6 @@ class VInputSystem : public IDetour g_fnSyncRTWithIn = l_EngineApi_PumpMessages.FindPattern("74 06").FindPatternSelf("FF 15").ResolveRelativeAddressSelf(2, 6).RCast(); } virtual void GetCon(void) const { } - virtual void Detour(const bool bAttach) const { } + virtual void Detour(const bool bAttach) const; }; /////////////////////////////////////////////////////////////////////////////// From 6575f80447e3205578a21b079d271d9c2f4ad80d Mon Sep 17 00:00:00 2001 From: Kawe Mazidjatari <48657826+Mauler125@users.noreply.github.com> Date: Sun, 24 Dec 2023 22:32:58 +0100 Subject: [PATCH 18/24] NVIDIA: add TRIGGER_FLASH marker to input event handler --- src/engine/keys.cpp | 32 +++++++++++++++++++++++++++++++- src/engine/keys.h | 13 ++++++++----- src/engine/sys_dll2.cpp | 2 +- src/engine/sys_mainwind.cpp | 2 +- src/vgui/vgui_baseui_interface.h | 6 +++--- 5 files changed, 44 insertions(+), 11 deletions(-) diff --git a/src/engine/keys.cpp b/src/engine/keys.cpp index 84fad325..ea120c6e 100644 --- a/src/engine/keys.cpp +++ b/src/engine/keys.cpp @@ -1,5 +1,35 @@ #include "keys.h" +#include "windows/id3dx.h" +#include "geforce/reflex.h" KeyInfo_t* g_pKeyInfo = nullptr; ButtonCode_t* g_pKeyEventTicks = nullptr; -short* g_nKeyEventCount = nullptr; \ No newline at end of file +short* g_nKeyEventCount = nullptr; + + +bool Input_Event(const InputEvent_t& inputEvent, const int noKeyUpCheck) +{ + bool runTriggerMarker = inputEvent.m_nData == ButtonCode_t::MOUSE_LEFT; + const KeyInfo_t& keyInfo = g_pKeyInfo[inputEvent.m_nData]; + + if (noKeyUpCheck) + { + const int v = (inputEvent.m_nType & 0xFFFFFFFD) == 0; + + if (keyInfo.m_nKeyDownTarget == v) + runTriggerMarker = false; + } + + if (runTriggerMarker && (inputEvent.m_nType != IE_ButtonReleased || keyInfo.m_bTrapKeyUp)) + { + GFX_SetLatencyMarker(D3D11Device(), TRIGGER_FLASH); + } + + return v_Input_Event(inputEvent, noKeyUpCheck); +} + +/////////////////////////////////////////////////////////////////////////////// +void VKeys::Detour(const bool bAttach) const +{ + DetourSetup(&v_Input_Event, &Input_Event, bAttach); +} diff --git a/src/engine/keys.h b/src/engine/keys.h index c4b7e829..431ab29d 100644 --- a/src/engine/keys.h +++ b/src/engine/keys.h @@ -35,13 +35,14 @@ struct KeyInfo_t bool m_bKeyDown; bool m_bEventIsButtonKey; // Is the event a button key (< ButtonCode_t::KEY_LAST) - bool m_bBoundKeyDown; + bool m_bTrapKeyUp; bool m_bBoundSecondKey; // Is the key bound to the second row? short paddingMaybe; }; -inline bool(*Key_Event)(const KeyEvent_t& keyEvent); +inline bool (*v_Input_Event)(const InputEvent_t& inputEvent, const int noKeyUpCheck); +inline bool(*v_Key_Event)(const KeyEvent_t& keyEvent); extern KeyInfo_t* g_pKeyInfo; // ARRAYSIZE = ButtonCode_t::BUTTON_CODE_LAST extern ButtonCode_t* g_pKeyEventTicks; // ARRAYSIZE = ButtonCode_t::BUTTON_CODE_LAST @@ -51,14 +52,16 @@ class VKeys : public IDetour { virtual void GetAdr(void) const { - LogFunAdr("Key_Event", reinterpret_cast(Key_Event)); + LogFunAdr("Input_Event", reinterpret_cast(v_Input_Event)); + LogFunAdr("Key_Event", reinterpret_cast(v_Key_Event)); LogVarAdr("g_pKeyInfo", reinterpret_cast(g_pKeyInfo)); LogVarAdr("g_pKeyEventTicks", reinterpret_cast(g_pKeyEventTicks)); LogVarAdr("g_nKeyEventCount", reinterpret_cast(g_nKeyEventCount)); } virtual void GetFun(void) const { - Key_Event = g_GameDll.FindPatternSIMD("48 89 5C 24 ?? 48 89 74 24 ?? 57 48 83 EC 20 4C 63 41 08").RCast(); + g_GameDll.FindPatternSIMD("48 89 5C 24 ?? 48 89 74 24 ?? 48 89 7C 24 ?? 55 41 54 41 56", v_Input_Event); + g_GameDll.FindPatternSIMD("48 89 5C 24 ?? 48 89 74 24 ?? 57 48 83 EC 20 4C 63 41 08", v_Key_Event); } virtual void GetVar(void) const { @@ -72,7 +75,7 @@ class VKeys : public IDetour g_pKeyEventTicks = l_EngineApi_PumpMessages.FindPatternSelf("48 8D 35").ResolveRelativeAddressSelf(3, 7).RCast(); } virtual void GetCon(void) const { } - virtual void Detour(const bool bAttach) const { } + virtual void Detour(const bool bAttach) const; }; #endif // ENGINE_KEYS_H diff --git a/src/engine/sys_dll2.cpp b/src/engine/sys_dll2.cpp index 9abae8d9..32cb51e8 100644 --- a/src/engine/sys_dll2.cpp +++ b/src/engine/sys_dll2.cpp @@ -174,7 +174,7 @@ void CEngineAPI::PumpMessages() if (in_syncRT->GetBool()) (*g_fnSyncRTWithIn)(); - g_pInputSystem->PollInputState(UIInputEventHandler); + g_pInputSystem->PollInputState(v_UIInputEventHandler); g_pGame->DispatchAllStoredGameMessages(); #endif // !DEDICATED } diff --git a/src/engine/sys_mainwind.cpp b/src/engine/sys_mainwind.cpp index e963a551..b08353e2 100644 --- a/src/engine/sys_mainwind.cpp +++ b/src/engine/sys_mainwind.cpp @@ -134,7 +134,7 @@ void CGame::DispatchKeyEvent(const uint64_t msTime, const ButtonCode_t buttonCod keyEvent.m_nTick = buttonCode; keyEvent.m_bDown = true; - Key_Event(keyEvent); + v_Key_Event(keyEvent); keyInfo.m_bKeyDown = true; } } diff --git a/src/vgui/vgui_baseui_interface.h b/src/vgui/vgui_baseui_interface.h index d4a5b4ea..035f0ffd 100644 --- a/src/vgui/vgui_baseui_interface.h +++ b/src/vgui/vgui_baseui_interface.h @@ -86,7 +86,7 @@ inline void*(*CEngineVGui_RenderStart)(CMatSystemSurface* pMatSystemSurface); inline CMemory p_CEngineVGui_RenderEnd; inline void*(*CEngineVGui_RenderEnd)(void); -inline InputEventCallback_t UIInputEventHandler = nullptr; +inline InputEventCallback_t v_UIInputEventHandler = nullptr; inline CEngineVGui* g_pEngineVGui = nullptr; /////////////////////////////////////////////////////////////////////////////// @@ -97,7 +97,7 @@ class VEngineVGui : public IDetour LogFunAdr("CEngineVGui::Paint", p_CEngineVGui_Paint.GetPtr()); LogFunAdr("CEngineVGui::RenderStart", p_CEngineVGui_RenderStart.GetPtr()); LogFunAdr("CEngineVGui::RenderEnd", p_CEngineVGui_RenderEnd.GetPtr()); - LogFunAdr("UIInputEventHandler", reinterpret_cast(UIInputEventHandler)); + LogFunAdr("UIInputEventHandler", reinterpret_cast(v_UIInputEventHandler)); LogVarAdr("g_pEngineVGui", reinterpret_cast(g_pEngineVGui)); } virtual void GetFun(void) const @@ -118,7 +118,7 @@ class VEngineVGui : public IDetour p_CEngineVGui_RenderEnd = g_GameDll.FindPatternSIMD("40 53 48 83 EC 20 48 8B 0D ?? ?? ?? ?? C6 05 ?? ?? ?? ?? ?? 48 8B 01"); CEngineVGui_RenderEnd = p_CEngineVGui_RenderEnd.RCast(); /*40 53 48 83 EC 20 48 8B 0D ?? ?? ?? ?? C6 05 ?? ?? ?? ?? ?? 48 8B 01*/ - UIInputEventHandler = g_GameDll.FindPatternSIMD("40 53 48 83 EC 40 48 63 01").RCast(); + g_GameDll.FindPatternSIMD("40 53 48 83 EC 40 48 63 01", v_UIInputEventHandler); } virtual void GetVar(void) const { From f08f9dd4cb45283b01e8e9b499c7c7e24665ea0d Mon Sep 17 00:00:00 2001 From: Kawe Mazidjatari <48657826+Mauler125@users.noreply.github.com> Date: Mon, 25 Dec 2023 01:46:39 +0100 Subject: [PATCH 19/24] NVIDIA: low latency code decouple --- src/engine/sys_dll2.cpp | 75 ++++++++++++++++++++++++----------------- src/engine/sys_dll2.h | 3 ++ 2 files changed, 47 insertions(+), 31 deletions(-) diff --git a/src/engine/sys_dll2.cpp b/src/engine/sys_dll2.cpp index 32cb51e8..b9937ada 100644 --- a/src/engine/sys_dll2.cpp +++ b/src/engine/sys_dll2.cpp @@ -179,6 +179,49 @@ void CEngineAPI::PumpMessages() #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: //----------------------------------------------------------------------------- @@ -197,37 +240,7 @@ bool CEngineAPI::MainLoop() } #ifndef DEDICATED - if (GFX_IsLowLatencySDKEnabled()) - { - if (GFX_HasPendingLowLatencyParameterUpdates()) - { - 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); - } - - GFX_RunLowLatencyFrame(D3D11Device()); - } - + CEngineAPI::RunLowLatencyFrame(); CEngineAPI::PumpMessages(); #endif // !DEDICATED diff --git a/src/engine/sys_dll2.h b/src/engine/sys_dll2.h index bdf7b0b6..9153bcf5 100644 --- a/src/engine/sys_dll2.h +++ b/src/engine/sys_dll2.h @@ -35,6 +35,9 @@ public: static void VSetStartupInfo(CEngineAPI* pEngineAPI, StartupInfo_t* pStartupInfo); static void PumpMessages(); + static void RunLowLatencyFrame(); + static void UpdateLowLatencyParameters(); + static bool MainLoop(); //private: void* m_hEditorHWnd; From bbb5811bbf926d9f704bc042099e8ffdadc2202b Mon Sep 17 00:00:00 2001 From: Kawe Mazidjatari <48657826+Mauler125@users.noreply.github.com> Date: Mon, 25 Dec 2023 02:24:23 +0100 Subject: [PATCH 20/24] Engine: fix incorrect function names Was actually pointing to Host_Init_DuringVideo, not Host_Init. Added all Host_Init functions to avoid confusion in the future. --- src/engine/host_cmd.h | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/src/engine/host_cmd.h b/src/engine/host_cmd.h index c80393df..d7c8b3d3 100644 --- a/src/engine/host_cmd.h +++ b/src/engine/host_cmd.h @@ -19,7 +19,13 @@ extern EngineParms_t* g_pEngineParms; /* ==== HOST ============================================================================================================================================================ */ inline CMemory p_Host_Init; -inline void*(*v_Host_Init)(bool* bDedicated); +inline void(*v_Host_Init)(); + +inline CMemory p_Host_Init_DuringVideo; +inline void(*v_Host_Init_DuringVideo)(bool* bDedicated); + +inline CMemory p_Host_Init_PostVideo; +inline void(*v_Host_Init_PostVideo)(bool* bDedicated); inline CMemory p_Host_Shutdown; inline void(*v_Host_Shutdown)(); @@ -52,6 +58,8 @@ class VHostCmd : public IDetour virtual void GetAdr(void) const { LogFunAdr("Host_Init", p_Host_Init.GetPtr()); + LogFunAdr("Host_Init_DuringVideo", p_Host_Init_DuringVideo.GetPtr()); + LogFunAdr("Host_Init_PostVideo", p_Host_Init_PostVideo.GetPtr()); LogFunAdr("Host_Shutdown", p_Host_Shutdown.GetPtr()); LogFunAdr("Host_Disconnect", p_Host_Disconnect.GetPtr()); LogFunAdr("Host_NewGame", p_Host_NewGame.GetPtr()); @@ -65,26 +73,30 @@ class VHostCmd : public IDetour } virtual void GetFun(void) const { + p_Host_Init = g_GameDll.FindPatternSIMD("88 4C 24 08 53 55 56 57 48 83 EC 68"); #if defined (GAMEDLL_S0) || defined (GAMEDLL_S1) - p_Host_Init = g_GameDll.FindPatternSIMD("48 89 5C 24 ?? 48 89 6C 24 ?? 48 89 74 24 ?? 57 41 54 41 55 41 56 41 57 48 81 EC ?? ?? ?? ?? 48 8B D9 FF 15 ?? ?? ?? ??"); + p_Host_Init_DuringVideo = g_GameDll.FindPatternSIMD("48 89 5C 24 ?? 48 89 6C 24 ?? 48 89 74 24 ?? 57 41 54 41 55 41 56 41 57 48 81 EC ?? ?? ?? ?? 48 8B D9 FF 15 ?? ?? ?? ??"); p_Host_NewGame = g_GameDll.FindPatternSIMD("48 8B C4 56 41 54 41 57 48 81 EC ?? ?? ?? ?? F2 0F 10 05 ?? ?? ?? ??"); p_Host_Disconnect = g_GameDll.FindPatternSIMD("48 83 EC 38 48 89 7C 24 ?? 0F B6 F9"); p_Host_ChangeLevel = g_GameDll.FindPatternSIMD("40 53 56 41 56 48 81 EC ?? ?? ?? ?? 49 8B D8"); p_SetLaunchOptions = g_GameDll.FindPatternSIMD("48 89 6C 24 ?? 57 48 83 EC 20 48 8B E9 48 8B 0D ?? ?? ?? ??"); #elif defined (GAMEDLL_S2) || defined (GAMEDLL_S3) - p_Host_Init = g_GameDll.FindPatternSIMD("48 89 5C 24 ?? 48 89 74 24 ?? 48 89 7C 24 ?? 55 41 54 41 55 41 56 41 57 48 8D AC 24 ?? ?? ?? ?? B8 ?? ?? ?? ?? E8 ?? ?? ?? ?? 48 2B E0 48 8B D9"); + p_Host_Init_DuringVideo = g_GameDll.FindPatternSIMD("48 89 5C 24 ?? 48 89 74 24 ?? 48 89 7C 24 ?? 55 41 54 41 55 41 56 41 57 48 8D AC 24 ?? ?? ?? ?? B8 ?? ?? ?? ?? E8 ?? ?? ?? ?? 48 2B E0 48 8B D9"); p_Host_NewGame = g_GameDll.FindPatternSIMD("48 8B C4 ?? 41 54 41 55 48 81 EC 70 04 ?? ?? F2 0F 10 05 ?? ?? ?? 0B"); p_Host_Disconnect = g_GameDll.FindPatternSIMD("40 53 48 83 EC 30 0F B6 D9"); p_Host_ChangeLevel = g_GameDll.FindPatternSIMD("40 56 57 41 56 48 81 EC ?? ?? ?? ??"); p_SetLaunchOptions = g_GameDll.FindPatternSIMD("48 89 5C 24 ?? 48 89 6C 24 ?? 57 48 83 EC 20 48 8B 1D ?? ?? ?? ?? 48 8B E9 48 85 DB"); #endif + p_Host_Init_PostVideo = g_GameDll.FindPatternSIMD("48 8B C4 41 56 48 81 EC ?? ?? ?? ?? 45 33 F6"); p_Host_Shutdown = g_GameDll.FindPatternSIMD("48 8B C4 48 83 EC ?? 80 3D ?? ?? ?? ?? ?? 0F 85 ?? ?? ?? ?? 8B 15 ?? ?? ?? ??"); p_Host_Status_PrintClient = g_GameDll.FindPatternSIMD("48 89 5C 24 ?? 48 89 6C 24 ?? 56 57 41 56 48 83 EC 60 48 8B A9 ?? ?? ?? ??"); #if !defined (GAMEDLL_S0) && !defined (GAMEDLL_S1) && !defined (GAMEDLL_S2) p_DFS_InitializeFeatureFlagDefinitions = g_GameDll.FindPatternSIMD("E8 ?? ?? ?? ?? 40 38 3D ?? ?? ?? ?? 48 8D 15 ?? ?? ?? ?? 48 8B CE").FollowNearCallSelf(); v_DFS_InitializeFeatureFlagDefinitions = p_DFS_InitializeFeatureFlagDefinitions.RCast(); /*48 8B C4 55 53 48 8D 68 E8*/ #endif // !(GAMEDLL_S0) || !(GAMEDLL_S1) || !(GAMEDLL_S2) - v_Host_Init = p_Host_Init.RCast(); /*48 89 5C 24 ?? 48 89 74 24 ?? 48 89 7C 24 ?? 55 41 54 41 55 41 56 41 57 48 8D AC 24 ?? ?? ?? ?? B8 ?? ?? ?? ?? E8 ?? ?? ?? ?? 48 2B E0 48 8B D9*/ + v_Host_Init = p_Host_Init.RCast(); + v_Host_Init_DuringVideo = p_Host_Init_DuringVideo.RCast(); /*48 89 5C 24 ?? 48 89 74 24 ?? 48 89 7C 24 ?? 55 41 54 41 55 41 56 41 57 48 8D AC 24 ?? ?? ?? ?? B8 ?? ?? ?? ?? E8 ?? ?? ?? ?? 48 2B E0 48 8B D9*/ + v_Host_Init_PostVideo = p_Host_Init_PostVideo.RCast(); v_Host_Shutdown = p_Host_Shutdown.RCast(); v_Host_NewGame = p_Host_NewGame.RCast(); /*48 8B C4 ?? 41 54 41 55 48 81 EC 70 04 00 00 F2 0F 10 05 ?? ?? ?? 0B*/ v_Host_Disconnect = p_Host_Disconnect.RCast(); From c3fed1dc2a337c773f9336c3423aa42e8740363e Mon Sep 17 00:00:00 2001 From: Kawe Mazidjatari <48657826+Mauler125@users.noreply.github.com> Date: Mon, 25 Dec 2023 18:47:05 +0100 Subject: [PATCH 21/24] MaterialSystem: Expose the proper pointer The first pointer was a pointing to a pointer to g_MaterialSystem. The new pointer points directly to g_MaterialSystem. Also added CMaterialSystem::GetCurrentFrameCount() for g_FrameNum. --- src/materialsystem/cmaterialsystem.h | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/src/materialsystem/cmaterialsystem.h b/src/materialsystem/cmaterialsystem.h index 1058ca96..59b94aef 100644 --- a/src/materialsystem/cmaterialsystem.h +++ b/src/materialsystem/cmaterialsystem.h @@ -14,6 +14,13 @@ public: static CMaterialGlue* FindMaterialEx(CMaterialSystem* pMatSys, const char* pMaterialName, uint8_t nMaterialType, int nUnk, bool bComplain); static Vector2D GetScreenSize(CMaterialSystem* pMatSys = nullptr); #endif // !MATERIALSYSTEM_NODX + + // TODO: reverse the vftable! + inline int GetCurrentFrameCount() + { + const static int index = 74; + return CallVFunc(index, this); + } }; #ifndef MATERIALSYSTEM_NODX @@ -91,6 +98,13 @@ inline int* g_nUnfreeStreamingTextureMemory = nullptr; inline int* g_nUnusableStreamingTextureMemory = nullptr; #endif // !MATERIALSYSTEM_NODX +// TODO: move to materialsystem_global.h! +// TODO: reverse the vftable! +inline CMaterialSystem* MaterialSystem() +{ + return g_pMaterialSystem; +} + /////////////////////////////////////////////////////////////////////////////// class VMaterialSystem : public IDetour { @@ -158,7 +172,7 @@ class VMaterialSystem : public IDetour s_pRenderContext = p_DispatchDrawCall.FindPattern("48 8B ?? ?? ?? ?? 01").ResolveRelativeAddressSelf(0x3, 0x7); g_pMaterialAdapterMgr = p_CMaterialSystem__Disconnect.FindPattern("48 8D").ResolveRelativeAddressSelf(0x3, 0x7).RCast(); #endif // !MATERIALSYSTEM_NODX - g_pMaterialSystem = g_GameDll.FindPatternSIMD("48 8B 0D ?? ?? ?? ?? 48 85 C9 74 11 48 8B 01 48 8D 15 ?? ?? ?? ??").ResolveRelativeAddressSelf(0x3, 0x7).RCast(); + g_pMaterialSystem = g_GameDll.FindPatternSIMD("8B 41 28 85 C0 7F 18").FindPatternSelf("48 8D 0D").ResolveRelativeAddressSelf(3, 7).RCast(); } virtual void GetCon(void) const { From 0251c59227d4e6229ab4c5ea2183e202165ae176 Mon Sep 17 00:00:00 2001 From: Kawe Mazidjatari <48657826+Mauler125@users.noreply.github.com> Date: Mon, 25 Dec 2023 19:23:01 +0100 Subject: [PATCH 22/24] NVIDIA: properly enqueue frame ID Sync Frame ID between main thread and render thread, this changes makes the integration PASS the reflex test utility. --- src/engine/client/cdll_engine_int.cpp | 3 +- src/engine/gl_rsurf.cpp | 4 ++- src/engine/host.cpp | 3 +- src/engine/keys.cpp | 3 +- src/engine/sys_dll2.cpp | 15 +++++++--- src/geforce/reflex.cpp | 39 ++++---------------------- src/geforce/reflex.h | 5 +--- src/inputsystem/inputsystem.cpp | 3 +- src/materialsystem/cmaterialsystem.cpp | 14 +++++++-- 9 files changed, 40 insertions(+), 49 deletions(-) diff --git a/src/engine/client/cdll_engine_int.cpp b/src/engine/client/cdll_engine_int.cpp index c6acb0e4..a412d110 100644 --- a/src/engine/client/cdll_engine_int.cpp +++ b/src/engine/client/cdll_engine_int.cpp @@ -15,6 +15,7 @@ #include "geforce/reflex.h" #include "vengineclient_impl.h" #include "cdll_engine_int.h" +#include "materialsystem/cmaterialsystem.h" /*****************************************************************************/ #ifndef DEDICATED @@ -64,7 +65,7 @@ void FrameStageNotify_Post(const ClientFrameStage_t frameStage) case ClientFrameStage_t::FRAME_RENDER_START: break; case ClientFrameStage_t::FRAME_RENDER_END: - GFX_SetLatencyMarker(D3D11Device(), SIMULATION_END); + GFX_SetLatencyMarker(D3D11Device(), SIMULATION_END, MaterialSystem()->GetCurrentFrameCount()); break; case ClientFrameStage_t::FRAME_NET_FULL_FRAME_UPDATE_ON_REMOVE: break; diff --git a/src/engine/gl_rsurf.cpp b/src/engine/gl_rsurf.cpp index 695526b5..0bfd7beb 100644 --- a/src/engine/gl_rsurf.cpp +++ b/src/engine/gl_rsurf.cpp @@ -9,10 +9,12 @@ #include "windows/id3dx.h" #include "geforce/reflex.h" #include "engine/gl_rsurf.h" +#include void* R_DrawDepthOfField(const float a1) { - GFX_SetLatencyMarker(D3D11Device(), RENDERSUBMIT_START); + GFX_SetLatencyMarker(D3D11Device(), RENDERSUBMIT_START, MaterialSystem()->GetCurrentFrameCount()); + return V_DrawDepthOfField(a1); } diff --git a/src/engine/host.cpp b/src/engine/host.cpp index f605ce81..e1b83133 100644 --- a/src/engine/host.cpp +++ b/src/engine/host.cpp @@ -12,6 +12,7 @@ #include "windows/id3dx.h" #include "geforce/reflex.h" #include "vgui/vgui_debugpanel.h" +#include #endif // !DEDICATED CCommonHostState* g_pCommonHostState = nullptr; @@ -46,7 +47,7 @@ Services environments) void Host_CountRealTimePackets() { v_Host_CountRealTimePackets(); - GFX_SetLatencyMarker(D3D11Device(), SIMULATION_START); + GFX_SetLatencyMarker(D3D11Device(), SIMULATION_START, MaterialSystem()->GetCurrentFrameCount()); } /* diff --git a/src/engine/keys.cpp b/src/engine/keys.cpp index ea120c6e..92d4b43e 100644 --- a/src/engine/keys.cpp +++ b/src/engine/keys.cpp @@ -1,6 +1,7 @@ #include "keys.h" #include "windows/id3dx.h" #include "geforce/reflex.h" +#include KeyInfo_t* g_pKeyInfo = nullptr; ButtonCode_t* g_pKeyEventTicks = nullptr; @@ -22,7 +23,7 @@ bool Input_Event(const InputEvent_t& inputEvent, const int noKeyUpCheck) if (runTriggerMarker && (inputEvent.m_nType != IE_ButtonReleased || keyInfo.m_bTrapKeyUp)) { - GFX_SetLatencyMarker(D3D11Device(), TRIGGER_FLASH); + GFX_SetLatencyMarker(D3D11Device(), TRIGGER_FLASH, MaterialSystem()->GetCurrentFrameCount()); } return v_Input_Event(inputEvent, noKeyUpCheck); diff --git a/src/engine/sys_dll2.cpp b/src/engine/sys_dll2.cpp index b9937ada..1911b1f7 100644 --- a/src/engine/sys_dll2.cpp +++ b/src/engine/sys_dll2.cpp @@ -227,28 +227,35 @@ void CEngineAPI::RunLowLatencyFrame() //----------------------------------------------------------------------------- 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) + if (g_pEngine->GetQuitting() != IEngine::QUIT_TODESKTOP) { return true; + } return false; } #ifndef DEDICATED - CEngineAPI::RunLowLatencyFrame(); + if (bRunLowLatency) { + CEngineAPI::RunLowLatencyFrame(); + } CEngineAPI::PumpMessages(); #endif // !DEDICATED if (g_pEngine->Frame()) { #ifndef DEDICATED - // Only increment frame number if we ran an actual engine frame. - GFX_IncrementFrameNumber(); + // Only run reflex if we ran an actual engine frame. + bRunLowLatency = true; #endif // !DEDICATED } } diff --git a/src/geforce/reflex.cpp b/src/geforce/reflex.cpp index 824c4fde..56947b5a 100644 --- a/src/geforce/reflex.cpp +++ b/src/geforce/reflex.cpp @@ -16,10 +16,6 @@ bool s_ReflexModeInfoUpToDate = false; // If not, the Low Latency SDK will not run. NvAPI_Status s_ReflexModeUpdateStatus = NvAPI_Status::NVAPI_OK; -// Static frame number counter for latency markers. -NvU64 s_ReflexFrameNumber = 0; -NvU64 s_ReflexLastFrameNumber = 0; - //----------------------------------------------------------------------------- // Purpose: enable/disable low latency SDK // Input : enable - @@ -75,23 +71,6 @@ bool GFX_ParameterUpdateWasSuccessful(void) return s_ReflexModeUpdateStatus == NvAPI_Status::NVAPI_OK; } -//----------------------------------------------------------------------------- -// Purpose: gets the reflex frame number -// Output : int -//----------------------------------------------------------------------------- -NvU64 GFX_GetFrameNumber(void) -{ - return s_ReflexFrameNumber; -} - -//----------------------------------------------------------------------------- -// Purpose: increments the reflex frame number -//----------------------------------------------------------------------------- -void GFX_IncrementFrameNumber(void) -{ - ++s_ReflexFrameNumber; -} - //----------------------------------------------------------------------------- // Purpose: updates the low latency parameters // Input : *device - @@ -100,7 +79,7 @@ void GFX_IncrementFrameNumber(void) // useMarkersToOptimize - // maxFramesPerSecond - //----------------------------------------------------------------------------- -void GFX_UpdateLowLatencyParameters(IUnknown* device, const bool useLowLatencyMode, +void GFX_UpdateLowLatencyParameters(IUnknown* const device, const bool useLowLatencyMode, const bool useLowLatencyBoost, const bool useMarkersToOptimize, const float maxFramesPerSecond) { @@ -125,18 +104,12 @@ void GFX_UpdateLowLatencyParameters(IUnknown* device, const bool useLowLatencyMo // Purpose: runs a frame of the low latency sdk // Input : *device - //----------------------------------------------------------------------------- -void GFX_RunLowLatencyFrame(IUnknown* device) +void GFX_RunLowLatencyFrame(IUnknown* const device) { Assert(device); - const NvU64 currentFrameNumber = GFX_GetFrameNumber(); - - if (s_ReflexLastFrameNumber == currentFrameNumber) - return; if (GFX_ParameterUpdateWasSuccessful()) NvAPI_D3D_Sleep(device); - - s_ReflexLastFrameNumber = currentFrameNumber; } //----------------------------------------------------------------------------- @@ -145,8 +118,8 @@ void GFX_RunLowLatencyFrame(IUnknown* device) // frameNumber - // markerType - //----------------------------------------------------------------------------- -void GFX_SetLatencyMarker(IUnknown* device, - const NV_LATENCY_MARKER_TYPE markerType) +void GFX_SetLatencyMarker(IUnknown* const device, + const NV_LATENCY_MARKER_TYPE markerType, const NvU64 frameID) { Assert(device); @@ -155,9 +128,9 @@ void GFX_SetLatencyMarker(IUnknown* device, NV_LATENCY_MARKER_PARAMS params = {}; params.version = NV_LATENCY_MARKER_PARAMS_VER1; - params.frameID = s_ReflexFrameNumber; + params.frameID = frameID; params.markerType = markerType; NvAPI_D3D_SetLatencyMarker(device, ¶ms); - PCLSTATS_MARKER(markerType, s_ReflexFrameNumber); + PCLSTATS_MARKER(markerType, frameID); } diff --git a/src/geforce/reflex.h b/src/geforce/reflex.h index 3244629f..acef73b4 100644 --- a/src/geforce/reflex.h +++ b/src/geforce/reflex.h @@ -7,9 +7,6 @@ bool GFX_IsLowLatencySDKEnabled(void); void GFX_MarkLowLatencyParametersOutOfDate(void); bool GFX_HasPendingLowLatencyParameterUpdates(void); -NvU64 GFX_GetFrameNumber(void); -void GFX_IncrementFrameNumber(void); - void GFX_UpdateLowLatencyParameters(IUnknown* device, const bool useLowLatencyMode, const bool useLowLatencyBoost, const bool useMarkersToOptimize, const float maxFramesPerSecond); @@ -17,6 +14,6 @@ void GFX_UpdateLowLatencyParameters(IUnknown* device, const bool useLowLatencyMo void GFX_RunLowLatencyFrame(IUnknown* device); void GFX_SetLatencyMarker(IUnknown* device, - const NV_LATENCY_MARKER_TYPE markerType); + const NV_LATENCY_MARKER_TYPE markerType, const NvU64 frameID); #endif // GFSDK_REFLEX_H diff --git a/src/inputsystem/inputsystem.cpp b/src/inputsystem/inputsystem.cpp index 01f2a39a..caefb8ec 100644 --- a/src/inputsystem/inputsystem.cpp +++ b/src/inputsystem/inputsystem.cpp @@ -9,6 +9,7 @@ #include "windows/id3dx.h" #include "geforce/reflex.h" #include "inputsystem/inputsystem.h" +#include ////----------------------------------------------------------------------------- //// Enables/disables input @@ -59,7 +60,7 @@ LRESULT CInputSystem::WindowProc(void* unused, HWND hwnd, UINT uMsg, WPARAM wPar { if (PCLSTATS_IS_PING_MSG_ID(uMsg)) { - GFX_SetLatencyMarker(D3D11Device(), PC_LATENCY_PING); + GFX_SetLatencyMarker(D3D11Device(), PC_LATENCY_PING, MaterialSystem()->GetCurrentFrameCount()); } } diff --git a/src/materialsystem/cmaterialsystem.cpp b/src/materialsystem/cmaterialsystem.cpp index 851fcd79..0f466392 100644 --- a/src/materialsystem/cmaterialsystem.cpp +++ b/src/materialsystem/cmaterialsystem.cpp @@ -115,11 +115,19 @@ void* __fastcall DispatchDrawCall(int64_t a1, uint64_t a2, int a3, int a4, int64 //--------------------------------------------------------------------------------- ssize_t SpinPresent(void) { - GFX_SetLatencyMarker(D3D11Device(), RENDERSUBMIT_END); + // NOTE: -1 since we need to sync this with its corresponding frame, g_FrameNum + // gets incremented in CMaterialSystem::SwapBuffers, which is after the markers + // for simulation start/end and render submit start. The render thread (here) + // continues after to finish the frame. + const NvU64 frameID = (NvU64)MaterialSystem()->GetCurrentFrameCount() -1; - GFX_SetLatencyMarker(D3D11Device(), PRESENT_START); + GFX_SetLatencyMarker(D3D11Device(), RENDERSUBMIT_END, frameID); + + // TODO[ AMOS ]: move to actual Present runtime call? SpinPresent calls some + // other DX buffer copy API's before the actual Present calls is being made. + GFX_SetLatencyMarker(D3D11Device(), PRESENT_START, frameID); const ssize_t val = v_SpinPresent(); - GFX_SetLatencyMarker(D3D11Device(), PRESENT_END); + GFX_SetLatencyMarker(D3D11Device(), PRESENT_END, frameID); return val; } From acbf0352daafb6aab28c912e7e02852edebea78e Mon Sep 17 00:00:00 2001 From: Kawe Mazidjatari <48657826+Mauler125@users.noreply.github.com> Date: Mon, 25 Dec 2023 19:24:42 +0100 Subject: [PATCH 23/24] NVIDIA: always run PC Latency stats PCLStats is not NVIDIA hardware bound as per Reflex's documentation, and runs separately from the NVIDIA Reflex code. Always enable! --- src/geforce/reflex.cpp | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/src/geforce/reflex.cpp b/src/geforce/reflex.cpp index 56947b5a..cbb4c041 100644 --- a/src/geforce/reflex.cpp +++ b/src/geforce/reflex.cpp @@ -123,14 +123,16 @@ void GFX_SetLatencyMarker(IUnknown* const device, { Assert(device); - if (!GFX_IsLowLatencySDKEnabled()) - return; + if (GFX_IsLowLatencySDKEnabled()) + { + NV_LATENCY_MARKER_PARAMS params = {}; + params.version = NV_LATENCY_MARKER_PARAMS_VER1; + params.frameID = frameID; + params.markerType = markerType; - NV_LATENCY_MARKER_PARAMS params = {}; - params.version = NV_LATENCY_MARKER_PARAMS_VER1; - params.frameID = frameID; - params.markerType = markerType; + NvAPI_D3D_SetLatencyMarker(device, ¶ms); + } - NvAPI_D3D_SetLatencyMarker(device, ¶ms); + // PCLStats is supported on non-NVIDIA hardware. PCLSTATS_MARKER(markerType, frameID); } From 3873cc81c2e159ea82b8741710507af0068e00a7 Mon Sep 17 00:00:00 2001 From: Kawe Mazidjatari <48657826+Mauler125@users.noreply.github.com> Date: Mon, 25 Dec 2023 19:36:59 +0100 Subject: [PATCH 24/24] InputSystem: rename function parameter --- src/engine/gl_rsurf.cpp | 5 ++--- src/engine/gl_rsurf.h | 2 +- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/src/engine/gl_rsurf.cpp b/src/engine/gl_rsurf.cpp index 0bfd7beb..7c387b6d 100644 --- a/src/engine/gl_rsurf.cpp +++ b/src/engine/gl_rsurf.cpp @@ -11,11 +11,10 @@ #include "engine/gl_rsurf.h" #include -void* R_DrawDepthOfField(const float a1) +void* R_DrawDepthOfField(const float scalar) { GFX_SetLatencyMarker(D3D11Device(), RENDERSUBMIT_START, MaterialSystem()->GetCurrentFrameCount()); - - return V_DrawDepthOfField(a1); + return V_DrawDepthOfField(scalar); } void* R_DrawWorldMeshes(void* baseEntity, void* renderContext, DrawWorldLists_t worldLists) diff --git a/src/engine/gl_rsurf.h b/src/engine/gl_rsurf.h index 902477e2..cf21bd7e 100644 --- a/src/engine/gl_rsurf.h +++ b/src/engine/gl_rsurf.h @@ -2,7 +2,7 @@ #include "public/ivrenderview.h" inline CMemory P_DrawDepthOfField; -inline void*(*V_DrawDepthOfField)(const float a1); +inline void*(*V_DrawDepthOfField)(const float scalar); inline CMemory P_DrawWorldMeshes; inline void*(*V_DrawWorldMeshes)(void* baseEntity, void* renderContext, DrawWorldLists_t worldLists);