Add DebugOverlay implementation

This commit is contained in:
Kawe Mazidjatari 2022-06-15 01:24:29 +02:00
parent a1331d2b8b
commit e70e4d1a8c
10 changed files with 302 additions and 22 deletions

View File

@ -202,7 +202,7 @@ void Systems_Init()
#ifndef DEDICATED
HCVideoMode_Common_Attach();
//DebugOverlays_Attach();
DebugOverlays_Attach();
RSurf_Attach();
#endif // !DEDICATED
@ -319,7 +319,7 @@ void Systems_Shutdown()
#ifndef DEDICATED
HCVideoMode_Common_Detach();
//DebugOverlays_Detach();
DebugOverlays_Detach();
RSurf_Detach();
#endif // !DEDICATED

View File

@ -0,0 +1,259 @@
//============================================================================//
//
// Purpose: Debug interface functions
//
//============================================================================//
#include "core/stdafx.h"
#include "tier0/tslist.h"
#include "tier0/basetypes.h"
#include "tier1/cvar.h"
#include "common/pseudodefs.h"
#include "engine/client/clientstate.h"
#include "engine/host_cmd.h"
#include "engine/debugoverlay.h"
#include "materialsystem/cmaterialsystem.h"
//------------------------------------------------------------------------------
// Purpose: checks if overlay should be decayed
//------------------------------------------------------------------------------
bool OverlayBase_t::IsDead() const
{
if (r_debug_overlay_nodecay->GetBool())
{
// Keep rendering the overlay if nodecay is set.
return false;
}
if (g_pClientState->IsPaused())
{
// Keep rendering the overlay if the client simulation is paused.
return false;
}
if (m_nCreationTick == -1)
{
if (m_nOverlayTick == -1)
{
if (m_flEndTime == NDEBUG_PERSIST_TILL_NEXT_SERVER)
{
return false;
}
return g_pClientState->GetClientTime() >= m_flEndTime;
}
else
{
return m_nOverlayTick < *overlay_tickcount;
}
return false;
}
else
{
return m_nCreationTick < *render_tickcount;
}
return g_pClientState->GetClientTime() >= m_flEndTime;
}
//------------------------------------------------------------------------------
// Purpose: destroys the overlay
//------------------------------------------------------------------------------
void HDestroyOverlay(OverlayBase_t* pOverlay)
{
std::int64_t pOverlayType;
EnterCriticalSection(&*s_OverlayMutex);
switch (pOverlay->m_Type)
{
case OverlayType_t::OVERLAY_BOX:
pOverlayType = 128i64;
goto LABEL_MALLOC;
case OverlayType_t::OVERLAY_SPHERE:
pOverlayType = 72i64;
goto LABEL_MALLOC;
case OverlayType_t::OVERLAY_LINE:
pOverlayType = 80i64;
goto LABEL_MALLOC;
case OverlayType_t::OVERLAY_TRIANGLE:
pOverlayType = 6200i64;
goto LABEL_MALLOC;
case OverlayType_t::OVERLAY_SWEPT_BOX:
pOverlay->m_Type = OverlayType_t::OVERLAY_UNK1;
LeaveCriticalSection(&*s_OverlayMutex);
return;
case OverlayType_t::OVERLAY_BOX2:
break;
case OverlayType_t::OVERLAY_CAPSULE:
pOverlayType = 112i64;
break;
case OverlayType_t::OVERLAY_UNK0:
pOverlayType = 88i64;
goto LABEL_MALLOC;
LABEL_MALLOC:
pOverlay->m_Type = OverlayType_t::OVERLAY_UNK1;
v_MemAlloc_Internal(pOverlay, pOverlayType);
break;
default:
break;
}
LeaveCriticalSection(&*s_OverlayMutex);
}
//------------------------------------------------------------------------------
// Purpose: draws a generic overlay
//------------------------------------------------------------------------------
void DrawOverlay(OverlayBase_t* pOverlay)
{
//void* pRenderContext = nullptr; // ptr to CMatQueuedRenderContext vtable.
EnterCriticalSection(&*s_OverlayMutex);
//pRenderContext = (*(void*(__fastcall**)(void*))(**(std::int64_t**)g_pMaterialSystem + MATERIALSYSTEM_VCALL_OFF_0))((void*)g_pMaterialSystem);
//(*(void(__fastcall**)(void*, std::int64_t))(*(std::int64_t*)pRenderContext + CMATQUEUEDRENDERCONTEXT_VCALL_OFS_0))((void*)pRenderContext, 0x1);
switch (pOverlay->m_Type)
{
case OverlayType_t::OVERLAY_BOX:
{
OverlayBox_t* pBox = static_cast<OverlayBox_t*>(pOverlay); // TODO: debug this since it doesn't work but does compute something..
// for testing, since RenderWireframeBox doesn't seem to work properly
//RenderWireframeSphere({ pBox->origin_X, pBox->origin_Y, pBox->origin_Z }, pBox->maxs.x, 8, 8, Color(pBox->r, pBox->g, pBox->b, 255), false);
//RenderLine({ pBox->origin_X, pBox->origin_Y, pBox->origin_Z }, { pBox->origin_X, pBox->origin_Y, pBox->origin_Z+pBox->maxs.z }, Color(pBox->r, pBox->g, pBox->b, 255), false);
//if (pBox->a < 255)
//{
// RenderWireframeBox({ pBox->origin_X, pBox->origin_Y, pBox->origin_Z }, pBox->angles, pBox->maxs, Color(pBox->r, pBox->g, pBox->b, 255), false);
//}
//else {
// RenderBox({ pBox->origin_X, pBox->origin_Y, pBox->origin_Z }, pBox->angles, pBox->mins, pBox->maxs, Color(pBox->r, pBox->g, pBox->b, pBox->a), false);
//}
break;
}
case OverlayType_t::OVERLAY_SPHERE:
{
OverlaySphere_t* pSphere = static_cast<OverlaySphere_t*>(pOverlay);
v_RenderWireframeSphere(pSphere->vOrigin, pSphere->flRadius, pSphere->nTheta, pSphere->nPhi, Color(pSphere->r, pSphere->g, pSphere->b, pSphere->a), false);
break;
}
case OverlayType_t::OVERLAY_LINE:
{
OverlayLine_t* pLine = static_cast<OverlayLine_t*>(pOverlay);
v_RenderLine(pLine->origin, pLine->dest, Color(pLine->r, pLine->g, pLine->b, pLine->a), pLine->noDepthTest);
break;
}
case OverlayType_t::OVERLAY_TRIANGLE:
{
break;
}
case OverlayType_t::OVERLAY_SWEPT_BOX:
{
break;
}
case OverlayType_t::OVERLAY_BOX2:
{
break;
}
case OverlayType_t::OVERLAY_CAPSULE:
{
break;
}
case OverlayType_t::OVERLAY_UNK0:
{
break;
}
case OverlayType_t::OVERLAY_UNK1:
{
break;
}
}
//(*(void(__fastcall**)(void*))(*(_QWORD*)pRenderContext + CMATQUEUEDRENDERCONTEXT_VCALL_OFS_1))(pRenderContext);
//(*(void(__fastcall**)(void*))(*(_QWORD*)pRenderContext + CMATQUEUEDRENDERCONTEXT_VCALL_OFS_2))(pRenderContext);
LeaveCriticalSection(&*s_OverlayMutex);
}
//------------------------------------------------------------------------------
// Purpose : overlay drawing entrypoint
//------------------------------------------------------------------------------
void DrawAllOverlays(char pOverlay)
{
if (!enable_debug_overlays->GetBool())
{
return;
}
EnterCriticalSection(&*s_OverlayMutex);
OverlayBase_t* pCurrOverlay = *s_pOverlays; // rdi
OverlayBase_t* pPrevOverlay = nullptr; // rsi
OverlayBase_t* pNextOverlay = nullptr; // rbx
while (pCurrOverlay)
{
if (pCurrOverlay->IsDead())
{
if (pPrevOverlay)
{
// If I had a last overlay reset it's next pointer
pPrevOverlay->m_pNextOverlay = pCurrOverlay->m_pNextOverlay;
}
else
{
// If the first line, reset the s_pOverlays pointer
*s_pOverlays = pCurrOverlay->m_pNextOverlay;
}
pNextOverlay = pCurrOverlay->m_pNextOverlay;
v_DestroyOverlay(pCurrOverlay);
pCurrOverlay = pNextOverlay;
}
else
{
bool bDraw{ };
if (pCurrOverlay->m_nCreationTick == -1)
{
if (pCurrOverlay->m_nOverlayTick == *overlay_tickcount)
{
// Draw overlay if unk0 == *overlay_tickcount
bDraw = true;
}
if (pCurrOverlay->m_nOverlayTick == -1)
{
// Draw overlay if unk0 == -1
bDraw = true;
}
}
else
{
bDraw = pCurrOverlay->m_nCreationTick == *render_tickcount;
}
if (bDraw)
{
if (pOverlay)
{
DrawOverlay(pCurrOverlay);
}
}
pPrevOverlay = pCurrOverlay;
pCurrOverlay = pCurrOverlay->m_pNextOverlay;
}
}
LeaveCriticalSection(&*s_OverlayMutex);
}
///////////////////////////////////////////////////////////////////////////////
void DebugOverlays_Attach()
{
//#if defined (GAMEDLL_S0) || defined (GAMEDLL_S1)
// p_DrawAllOverlays.Offset(0x189).Patch({ 0x83, 0x3F, 0x02 }); // Default value in memory is 0x2, condition is 0x4. Patch to fullfill condition.
//#elif defined (GAMEDLL_S2) || defined (GAMEDLL_S3)
// p_DrawAllOverlays.Offset(0x188).Patch({ 0x83, 0x3F, 0x02 }); // Default value in memory is 0x2, condition is 0x4. Patch to fullfill condition.
//#endif
DetourAttach((LPVOID*)&v_DrawAllOverlays, &DrawAllOverlays);
}
void DebugOverlays_Detach()
{
DetourDetach((LPVOID*)&v_DrawAllOverlays, &DrawAllOverlays);
}

View File

@ -37,20 +37,20 @@ struct OverlayBase_t
OverlayBase_t(void)
{
m_Type = OverlayType_t::OVERLAY_BOX;
m_nServerCount = -1;
m_nCreationTick = -1;
m_flEndTime = 0.0f;
m_nServerCount = -1;
m_pNextOverlay = NULL;
unk0 = NULL;
m_nOverlayTick = NULL;
}
bool IsDead(void) const;
OverlayType_t m_Type {}; // What type of overlay is it?
int m_nCreationTick{}; // Duration -1 means go away after this frame #
float m_nServerCount {}; // Latch server count, too
float m_flEndTime {}; // When does this box go away
int m_nServerCount {}; // Latch server count, too
OverlayBase_t* m_pNextOverlay {}; // 16
int64_t unk0 {}; // 24
int m_nOverlayTick {}; // 24
};
struct OverlayLine_t : public OverlayBase_t
@ -70,10 +70,14 @@ struct OverlayBox_t : public OverlayBase_t
{
OverlayBox_t(void) { m_Type = OverlayType_t::OVERLAY_BOX; }
Vector3 origin{};
Vector3 mins{};
Vector3 maxs{};
QAngle angles{};
QAngle angles{}; //0x0020 - this isn't angles but idrk where it is
float origin_X{}; //0x002C
Vector3 unk30{}; //0x0030
float origin_Y{}; //0x003C
Vector3 unk40{}; //0x0040
float origin_Z{}; //0x004C
Vector3 mins{}; //0x0050
Vector3 maxs{}; //0x005C
int r{};
int g{};
int b{};
@ -100,16 +104,19 @@ void DebugOverlays_Attach();
void DebugOverlays_Detach();
inline CMemory p_DrawAllOverlays;
inline auto DrawAllOverlays = p_DrawAllOverlays.RCast<void (*)(char a1)>();
inline auto v_DrawAllOverlays = p_DrawAllOverlays.RCast<void (*)(char a1)>();
inline CMemory p_RenderBox;
inline auto RenderBox = p_RenderBox.RCast<void* (*)(Vector3 origin, QAngle angles, Vector3 vMins, Vector3 vMaxs, Color color, bool bZBuffer)>();
inline CMemory p_RenderWireframeBox;
inline auto v_RenderWireframeBox = p_RenderWireframeBox.RCast<void* (*)(Vector3 origin, QAngle angles, Vector3 vMins, Vector3 vMaxs, Color color, bool bZBuffer)>();
inline CMemory p_RenderLine;
inline auto RenderLine = p_RenderLine.RCast<void* (*)(Vector3 origin, Vector3 dest, Color color, bool bZBuffer)>();
inline auto v_RenderLine = p_RenderLine.RCast<void* (*)(Vector3 origin, Vector3 dest, Color color, bool bZBuffer)>();
inline CMemory p_RenderWireframeSphere;
inline auto v_RenderWireframeSphere = p_RenderWireframeSphere.RCast<void* (*)(Vector3 vCenter, float flRadius, int nTheta, int nPhi, Color c, bool bZBuffer)>();
inline CMemory p_DestroyOverlay;
inline auto DestroyOverlay = p_DestroyOverlay.RCast<void (*)(OverlayBase_t* pOverlay)>();
inline auto v_DestroyOverlay = p_DestroyOverlay.RCast<void (*)(OverlayBase_t* pOverlay)>();
inline int* client_debugdraw_int_unk = nullptr;
inline float* client_debugdraw_float_unk = nullptr;
@ -126,7 +133,8 @@ class VDebugOverlay : public IDetour
virtual void GetAdr(void) const
{
spdlog::debug("| FUN: DrawAllOverlays : {:#18x} |\n", p_DrawAllOverlays.GetPtr());
spdlog::debug("| FUN: RenderBox : {:#18x} |\n", p_RenderBox.GetPtr());
spdlog::debug("| FUN: RenderWireframeBox : {:#18x} |\n", p_RenderWireframeBox.GetPtr());
spdlog::debug("| FUN: RenderWireframeSphere : {:#18x} |\n", p_RenderWireframeSphere.GetPtr());
spdlog::debug("| FUN: RenderLine : {:#18x} |\n", p_RenderLine.GetPtr());
spdlog::debug("| FUN: DestroyOverlay : {:#18x} |\n", p_DestroyOverlay.GetPtr());
spdlog::debug("| VAR: s_pOverlays : {:#18x} |\n", reinterpret_cast<uintptr_t>(s_pOverlays));
@ -144,15 +152,17 @@ class VDebugOverlay : public IDetour
p_RenderBox = g_mGameDll.FindPatternSIMD(reinterpret_cast<rsig_t>("\x48\x89\x5C\x24\x00\x48\x89\x6C\x24\x00\x44\x89\x4C\x24\x00"), "xxxx?xxxx?xxxx?");
#elif defined (GAMEDLL_S2) || defined (GAMEDLL_S3)
p_DrawAllOverlays = g_mGameDll.FindPatternSIMD(reinterpret_cast<rsig_t>("\x40\x55\x48\x83\xEC\x30\x48\x8B\x05\x00\x00\x00\x00\x0F\xB6\xE9"), "xxxxxxxxx????xxx");
p_RenderBox = g_mGameDll.FindPatternSIMD(reinterpret_cast<rsig_t>("\x48\x89\x5C\x24\x00\x48\x89\x6C\x24\x00\x44\x89\x4C\x24\x00"), "xxxx?xxxx?xxxx?");
p_RenderWireframeBox = g_mGameDll.FindPatternSIMD(reinterpret_cast<rsig_t>("\x48\x89\x5C\x24\x00\x48\x89\x6C\x24\x00\x44\x89\x4C\x24\x00"), "xxxx?xxxx?xxxx?");
#endif
p_RenderLine = g_mGameDll.FindPatternSIMD(reinterpret_cast<rsig_t>("\x48\x89\x74\x24\x00\x44\x89\x44\x24\x00\x57\x41\x56"), "xxxx?xxxx?xxx");
p_DestroyOverlay = g_mGameDll.FindPatternSIMD(reinterpret_cast<rsig_t>("\x40\x53\x48\x83\xEC\x20\x48\x8B\xD9\x48\x8D\x0D\x00\x00\x00\x00\xFF\x15\x00\x00\x00\x00\x48\x63\x03"), "xxxxxxxxxxxx????xx????xxx");
p_RenderWireframeSphere = g_mGameDll.FindPatternSIMD(reinterpret_cast<rsig_t>("\x40\x56\x41\x54\x41\x55\x48\x81\xEC\x00\x00\x00\x00"), "xxxxxxxxx????");
p_RenderLine = g_mGameDll.FindPatternSIMD(reinterpret_cast<rsig_t>("\x48\x89\x74\x24\x00\x44\x89\x44\x24\x00\x57\x41\x56"), "xxxx?xxxx?xxx");
DrawAllOverlays = p_DrawAllOverlays.RCast<void (*)(char)>(); /*40 55 48 83 EC 30 48 8B 05 ?? ?? ?? ?? 0F B6 E9*/
DestroyOverlay = p_DestroyOverlay.RCast<void (*)(OverlayBase_t*)>(); /*40 53 48 83 EC 20 48 8B D9 48 8D 0D ?? ?? ?? ?? FF 15 ?? ?? ?? ?? 48 63 03 */
RenderBox = p_RenderBox.RCast<void* (*)(Vector3, QAngle, Vector3, Vector3, Color, bool)>(); /*48 89 5C 24 ?? 48 89 6C 24 ?? 44 89 4C 24 ??*/
RenderLine = p_RenderLine.RCast<void* (*)(Vector3, Vector3, Color, bool)>(); /*48 89 74 24 ?? 44 89 44 24 ?? 57 41 56*/
v_DrawAllOverlays = p_DrawAllOverlays.RCast<void (*)(char)>(); /*40 55 48 83 EC 30 48 8B 05 ?? ?? ?? ?? 0F B6 E9*/
v_DestroyOverlay = p_DestroyOverlay.RCast<void (*)(OverlayBase_t*)>(); /*40 53 48 83 EC 20 48 8B D9 48 8D 0D ?? ?? ?? ?? FF 15 ?? ?? ?? ?? 48 63 03 */
v_RenderWireframeBox = p_RenderWireframeBox.RCast<void* (*)(Vector3, QAngle, Vector3, Vector3, Color, bool)>(); /*48 89 5C 24 ?? 48 89 6C 24 ?? 44 89 4C 24 ??*/
v_RenderWireframeSphere = p_RenderWireframeSphere.RCast<void* (*)(Vector3, float, int, int, Color, bool)>(); /*40 56 41 54 41 55 48 81 EC ?? ?? ?? ??*/
v_RenderLine = p_RenderLine.RCast<void* (*)(Vector3, Vector3, Color, bool)>(); /*48 89 74 24 ?? 44 89 44 24 ?? 57 41 56*/
}
virtual void GetVar(void) const
{

View File

@ -169,6 +169,7 @@ void ConVar::Init(void) const
void ConVar::InitShipped(void) const
{
single_frame_shutdown_for_reload = g_pCVar->FindVar("single_frame_shutdown_for_reload");
enable_debug_overlays = g_pCVar->FindVar("enable_debug_overlays");
model_defaultFadeDistScale = g_pCVar->FindVar("model_defaultFadeDistScale");
model_defaultFadeDistMin = g_pCVar->FindVar("model_defaultFadeDistMin");
staticProp_no_fade_scalar = g_pCVar->FindVar("staticProp_no_fade_scalar");

View File

@ -7,6 +7,7 @@
// ENGINE |
ConVar* single_frame_shutdown_for_reload = nullptr;
ConVar* old_gather_props = nullptr;
ConVar* enable_debug_overlays = nullptr;
ConVar* staticProp_defaultBuildFrustum = nullptr;
ConVar* staticProp_no_fade_scalar = nullptr;

View File

@ -5,6 +5,7 @@
// ENGINE |
extern ConVar* single_frame_shutdown_for_reload;
extern ConVar* old_gather_props;
extern ConVar* enable_debug_overlays;
extern ConVar* staticProp_defaultBuildFrustum;
extern ConVar* staticProp_no_fade_scalar;

View File

@ -32,6 +32,7 @@
<ClCompile Include="..\engine\clockdriftmgr.cpp" />
<ClCompile Include="..\engine\cmodel_bsp.cpp" />
<ClCompile Include="..\engine\common.cpp" />
<ClCompile Include="..\engine\debugoverlay.cpp" />
<ClCompile Include="..\engine\gl_rsurf.cpp" />
<ClCompile Include="..\engine\gl_screen.cpp" />
<ClCompile Include="..\engine\host_cmd.cpp" />

View File

@ -507,6 +507,9 @@
<ClCompile Include="..\mathlib\sha1.cpp">
<Filter>sdk\mathlib</Filter>
</ClCompile>
<ClCompile Include="..\engine\debugoverlay.cpp">
<Filter>sdk\engine</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\client\cdll_engine_int.h">

View File

@ -32,6 +32,7 @@
<ClCompile Include="..\engine\clockdriftmgr.cpp" />
<ClCompile Include="..\engine\cmodel_bsp.cpp" />
<ClCompile Include="..\engine\common.cpp" />
<ClCompile Include="..\engine\debugoverlay.cpp" />
<ClCompile Include="..\engine\gl_rsurf.cpp" />
<ClCompile Include="..\engine\gl_screen.cpp" />
<ClCompile Include="..\engine\host_cmd.cpp" />

View File

@ -537,6 +537,9 @@
<ClCompile Include="..\mathlib\sha1.cpp">
<Filter>sdk\mathlib</Filter>
</ClCompile>
<ClCompile Include="..\engine\debugoverlay.cpp">
<Filter>sdk\engine</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\client\cdll_engine_int.h">