Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feature: hook r_shadows cvar to restore shadows in pre-25th anniversary versions #545

Draft
wants to merge 2 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion BunnymodXT/cvars.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@
X(skill) \
X(host_framerate) \
X(sensitivity) \
X(coop)
X(coop) \
X(r_shadows)

#define DEFINE_CVARS(X) \
X(_bxt_taslog, "0") \
Expand Down
108 changes: 107 additions & 1 deletion BunnymodXT/modules/HwDLL.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
#include <boost/algorithm/string/replace.hpp>
#include <boost/algorithm/string/predicate.hpp>
#include <cerrno>
#include <GL/gl.h>
#include "../sptlib-wrapper.hpp"
#include <SPTLib/MemUtils.hpp>
#include <SPTLib/Hooks.hpp>
Expand Down Expand Up @@ -314,6 +313,11 @@ extern "C" void __cdecl R_SetFrustum()
HwDLL::HOOKED_R_SetFrustum();
}

extern "C" void __cdecl studioapi_GL_StudioDrawShadow()
{
HwDLL::HOOKED_studioapi_GL_StudioDrawShadow();
}

extern "C" void __cdecl SPR_Set(HSPRITE_HL hSprite, int r, int g, int b)
{
HwDLL::HOOKED_SPR_Set(hSprite, r, g, b);
Expand Down Expand Up @@ -466,6 +470,7 @@ void HwDLL::Hook(const std::wstring& moduleName, void* moduleHandle, void* modul
MemUtils::MarkAsExecutable(ORIG_BUsesSDLInput);
MemUtils::MarkAsExecutable(ORIG_R_StudioRenderModel);
MemUtils::MarkAsExecutable(ORIG_R_SetFrustum);
MemUtils::MarkAsExecutable(ORIG_studioapi_GL_StudioDrawShadow);
MemUtils::MarkAsExecutable(ORIG_SPR_Set);
MemUtils::MarkAsExecutable(ORIG_DrawCrosshair);
MemUtils::MarkAsExecutable(ORIG_Draw_FillRGBA);
Expand Down Expand Up @@ -535,6 +540,7 @@ void HwDLL::Hook(const std::wstring& moduleName, void* moduleHandle, void* modul
ORIG_BUsesSDLInput, HOOKED_BUsesSDLInput,
ORIG_R_StudioRenderModel, HOOKED_R_StudioRenderModel,
ORIG_R_SetFrustum, HOOKED_R_SetFrustum,
ORIG_studioapi_GL_StudioDrawShadow, HOOKED_studioapi_GL_StudioDrawShadow,
ORIG_SPR_Set, HOOKED_SPR_Set,
ORIG_DrawCrosshair, HOOKED_DrawCrosshair,
ORIG_Draw_FillRGBA, HOOKED_Draw_FillRGBA,
Expand Down Expand Up @@ -630,6 +636,7 @@ void HwDLL::Unhook()
ORIG_BUsesSDLInput,
ORIG_R_StudioRenderModel,
ORIG_R_SetFrustum,
ORIG_studioapi_GL_StudioDrawShadow,
ORIG_SPR_Set,
ORIG_DrawCrosshair,
ORIG_Draw_FillRGBA,
Expand Down Expand Up @@ -729,6 +736,7 @@ void HwDLL::Clear()
ORIG_BUsesSDLInput = nullptr;
ORIG_R_StudioRenderModel = nullptr;
ORIG_R_SetFrustum = nullptr;
ORIG_studioapi_GL_StudioDrawShadow = nullptr;
ORIG_SPR_Set = nullptr;
ORIG_DrawCrosshair = nullptr;
ORIG_Draw_FillRGBA = nullptr;
Expand Down Expand Up @@ -788,6 +796,8 @@ void HwDLL::Clear()
frametime_remainder = nullptr;
pstudiohdr = nullptr;
scr_fov_value = nullptr;
r_shadows = nullptr;
qglDepthMask = nullptr;
framesTillExecuting = 0;
executing = false;
insideCbuf_Execute = false;
Expand Down Expand Up @@ -1330,6 +1340,27 @@ void HwDLL::FindStuff()
EngineDevWarning("[hw dll] Could not find R_SetFrustum.\n");
}

ORIG_studioapi_GL_StudioDrawShadow = reinterpret_cast<_studioapi_GL_StudioDrawShadow>(MemUtils::GetSymbolAddress(m_Handle, "studioapi_GL_StudioDrawShadow"));
if (ORIG_studioapi_GL_StudioDrawShadow) {
EngineDevMsg("[hw dll] Found studioapi_GL_StudioDrawShadow at %p.\n", ORIG_studioapi_GL_StudioDrawShadow);
} else {
EngineDevWarning("[hw dll] Could not find studioapi_GL_StudioDrawShadow.\n");
}

r_shadows = reinterpret_cast<cvar_t*>(MemUtils::GetSymbolAddress(m_Handle, "r_shadows"));
if (r_shadows) {
EngineDevMsg("[hw dll] Found r_shadows at %p.\n", r_shadows);
} else {
EngineDevWarning("[hw dll] Could not find r_shadows.\n");
}

qglDepthMask = reinterpret_cast<qglDepthMask_def*>(MemUtils::GetSymbolAddress(m_Handle, "qglDepthMask"));
if (qglDepthMask) {
EngineDevMsg("[hw dll] Found qglDepthMask at %p.\n", qglDepthMask);
} else {
EngineDevWarning("[hw dll] Could not find qglDepthMask.\n");
}

g_sv_delta = reinterpret_cast<void**>(MemUtils::GetSymbolAddress(m_Handle, "g_sv_delta"));
if (g_sv_delta)
EngineDevMsg("[hw dll] Found g_sv_delta at %p.\n", g_sv_delta);
Expand Down Expand Up @@ -1590,6 +1621,19 @@ void HwDLL::FindStuff()
}
});

auto fstudioapi_GL_StudioDrawShadow = FindAsync(
ORIG_studioapi_GL_StudioDrawShadow,
patterns::engine::studioapi_GL_StudioDrawShadow,
[&](auto pattern) {
switch (pattern - patterns::engine::studioapi_GL_StudioDrawShadow.cbegin())
{
case 0: // HL-SteamPipe
r_shadows = reinterpret_cast<cvar_t*>(*reinterpret_cast<uintptr_t*>(reinterpret_cast<uintptr_t>(ORIG_studioapi_GL_StudioDrawShadow) + 0xE) - offsetof(cvar_t, value));
qglDepthMask = reinterpret_cast<qglDepthMask_def*>(*reinterpret_cast<uintptr_t*>(reinterpret_cast<uintptr_t>(ORIG_studioapi_GL_StudioDrawShadow) + 0x8));
break;
}
});

auto fSeedRandomNumberGenerator = FindAsync(
ORIG_SeedRandomNumberGenerator,
patterns::engine::SeedRandomNumberGenerator,
Expand Down Expand Up @@ -2125,6 +2169,17 @@ void HwDLL::FindStuff()
}
}

{
auto pattern = fstudioapi_GL_StudioDrawShadow.get();
if (ORIG_studioapi_GL_StudioDrawShadow) {
EngineDevMsg("[hw dll] Found studioapi_GL_StudioDrawShadow at %p (using the %s pattern).\n", ORIG_studioapi_GL_StudioDrawShadow, pattern->name());
EngineDevMsg("[hw dll] Found r_shadows at %p.\n", r_shadows);
EngineDevMsg("[hw dll] Found qglDepthMask at %p.\n", qglDepthMask);
} else {
EngineDevWarning("[hw dll] Could not find studioapi_GL_StudioDrawShadow.\n");
}
}

{
auto pattern = fHost_ValidSave.get();
if (ORIG_Host_ValidSave) {
Expand Down Expand Up @@ -5706,6 +5761,13 @@ void HwDLL::RegisterCVarsAndCommandsIfNeeded()
return;

registeredVarsAndCmds = true;

if (r_shadows)
{
ORIG_Cvar_RegisterVariable(r_shadows);
CVars::r_shadows.Assign(r_shadows);
}

RegisterCVar(CVars::_bxt_taslog);
RegisterCVar(CVars::_bxt_min_frametime);
RegisterCVar(CVars::_bxt_tas_script_generation);
Expand Down Expand Up @@ -8355,3 +8417,47 @@ HOOK_DEF_1(HwDLL, void, __cdecl, LoadThisDll, const char*, szDllFilename)

ORIG_LoadThisDll(szDllFilename);
}

/*
_Smiley:

The original shadows have a issue with depth fighting.
Well in the beginning of original function, glDepthMask(GL_TRUE) is called.
I found that if we change it to GL_FALSE and return GL_TRUE at the end of the function, then we can get rid of this issue.

I preferred to hook the QGL pointer for this, because accessing glDepthMask from system libraries will be more environment dependent, although of course it does not require finding with patterns/offsets.
QGL pointer functions are engine wrappers for GL functions made with the development of Quake 2.

Of course, we could also use byte patching instead, but this is a dubious solution and generally more limited in actions, although it is simpler to implement.

The logic behind all this code is so simple: we redirect the QGL pointer to our own wrapper, in which we do what we want, and at the end of the function we return everything back to original state.
*/

void APIENTRY_HL DepthMask(GLboolean flag)
{
auto& hw = HwDLL::GetInstance();

if (hw.inside_studioapi_GL_StudioDrawShadow)
flag = GL_FALSE;

hw.orig_qglDepthMask(flag);
}

HOOK_DEF_0(HwDLL, void, __cdecl, studioapi_GL_StudioDrawShadow)
{
if (!qglDepthMask || !r_shadows || !CVars::r_shadows.GetBool())
{
ORIG_studioapi_GL_StudioDrawShadow();
return;
}

orig_qglDepthMask = *qglDepthMask; // Save the original pointer.
*qglDepthMask = DepthMask; // Redirect to our own wrapper.

inside_studioapi_GL_StudioDrawShadow = true;
ORIG_studioapi_GL_StudioDrawShadow();
inside_studioapi_GL_StudioDrawShadow = false;

*qglDepthMask = orig_qglDepthMask; // Restore the original pointer.
orig_qglDepthMask(GL_TRUE); // We call qglDepthMask(GL_TRUE) back, since we changed it to GL_FALSE only for the duration of this function.
}
10 changes: 10 additions & 0 deletions BunnymodXT/modules/HwDLL.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@
#include "taslogger/writer.hpp"
#include "../input_editor.hpp"
#include "../shared.hpp"
#include <GL/gl.h>

typedef void (APIENTRY_HL *qglDepthMask_def)(GLboolean flag);

enum class TASEditorMode {
DISABLED,
Expand Down Expand Up @@ -87,6 +90,7 @@ class HwDLL : public IHookableNameFilterOrdered
HOOK_DECL(qboolean, __cdecl, ValidStuffText, char* buf)
HOOK_DECL(qboolean, __cdecl, CL_ReadDemoMessage_OLD)
HOOK_DECL(void, __cdecl, LoadThisDll, const char* szDllFilename)
HOOK_DECL(void, __cdecl, studioapi_GL_StudioDrawShadow)

#ifdef HLSDK10_BUILD
struct server_static_t
Expand Down Expand Up @@ -555,7 +559,13 @@ class HwDLL : public IHookableNameFilterOrdered

bool ducktap;
edict_t **sv_player;

bool inside_studioapi_GL_StudioDrawShadow = false;
qglDepthMask_def orig_qglDepthMask;
protected:
cvar_t *r_shadows;
qglDepthMask_def *qglDepthMask;

void KeyDown(Key& btn);
void KeyUp(Key& btn);
void SaveInitialDataToDemo();
Expand Down
5 changes: 5 additions & 0 deletions BunnymodXT/patterns.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,11 @@ namespace patterns
{
namespace engine
{
PATTERNS(studioapi_GL_StudioDrawShadow,
"HL-SteamPipe",
"55 8B EC 51 6A 01 FF 15 ?? ?? ?? ?? D9 05 ?? ?? ?? ?? D8 1D ?? ?? ?? ?? DF E0 F6 C4 44 0F 8B ?? ?? ?? ?? 83 3D ?? ?? ?? ?? 05" // + 0x8 = qglDepthMask, + 0xE = r_shadows.value
);

PATTERNS(LoadAndDecryptHwDLL,
"HL-NGHL",
"8B 0D ?? ?? ?? ?? 53 56 33 DB 8B 01 57 53 68 ?? ?? ?? ?? FF 74 24 18 FF 50 28 8B 0D ?? ?? ?? ?? 8B F0 6A 02 53 8B 01 56 FF 50 30 8B 0D",
Expand Down
8 changes: 8 additions & 0 deletions BunnymodXT/shared.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,3 +45,11 @@ constexpr int kRenderFxTrigger = 241; // DO NOT CHANGE THIS VALUE OR YOU WILL BR

// - Other constants
constexpr steamid_t STEAMID64_CONST = 76561197960265728; // 0x110000100000000

// - Custom macros

#ifdef _WIN32
#define APIENTRY_HL APIENTRY
#else
#define APIENTRY_HL
#endif