Skip to content

Commit 5ffc79d

Browse files
committed
HooksNvngxDlss: add DLSS hud override hook for dlssd
OverrideDlssHud should now apply to dlssd too
1 parent 6c3e1a4 commit 5ffc79d

File tree

4 files changed

+147
-1
lines changed

4 files changed

+147
-1
lines changed

src/DLSSTweaks.hpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,10 @@ namespace nvngx_dlssg
102102
void settings_changed();
103103
void init(HMODULE ngx_module);
104104
};
105+
namespace nvngx_dlssd
106+
{
107+
void init(HMODULE ngx_module);
108+
};
105109

106110
// wrapper struct on top of SafetyHookInline
107111
// can either call the hook trampoline via SafetyHookInline, or call a specified function if dest_proc is set

src/DllMain.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ const wchar_t* DlssFileName = L"nvngx_dlss.dll";
2222
const char* DlssFileNameA = "nvngx_dlss.dll";
2323
const wchar_t* DlssgFileName = L"nvngx_dlssg.dll";
2424
const char* DlssgFileNameA = "nvngx_dlssg.dll";
25+
const wchar_t* DlssdFileName = L"nvngx_dlssd.dll";
26+
const char* DlssdFileNameA = "nvngx_dlssd.dll";
2527

2628
const wchar_t* LogFileName = L"dlsstweaks.log";
2729
const wchar_t* IniFileName = L"dlsstweaks.ini";
@@ -171,11 +173,14 @@ void __stdcall LoaderNotificationCallback(unsigned long notification_reason, con
171173
// If user has overridden the nvngx_dlss path, use the filename they specified in our comparisons below
172174
std::wstring dlssName = DlssFileName;
173175
std::wstring dlssgName = DlssgFileName;
176+
std::wstring dlssdName = DlssdFileName;
174177

175178
if (settings.dllPathOverrides.count(DlssFileNameA))
176179
dlssName = settings.dllPathOverrides[DlssFileNameA].filename().wstring();
177180
if (settings.dllPathOverrides.count(DlssgFileNameA))
178181
dlssgName = settings.dllPathOverrides[DlssgFileNameA].filename().wstring();
182+
if (settings.dllPathOverrides.count(DlssdFileNameA))
183+
dlssdName = settings.dllPathOverrides[DlssdFileNameA].filename().wstring();
179184

180185
// A module was loaded in, check if NGX/DLSS and apply hooks if so
181186
std::wstring dllName(notification_data->Loaded.BaseDllName->Buffer, notification_data->Loaded.BaseDllName->Length / sizeof(WCHAR));
@@ -191,6 +196,10 @@ void __stdcall LoaderNotificationCallback(unsigned long notification_reason, con
191196
{
192197
nvngx_dlssg::init((HMODULE)notification_data->Loaded.DllBase);
193198
}
199+
else if (!_wcsicmp(dllName.c_str(), dlssdName.c_str()))
200+
{
201+
nvngx_dlssd::init((HMODULE)notification_data->Loaded.DllBase);
202+
}
194203
}
195204
}
196205

src/HooksNvngxDlss.cpp

Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ namespace nvngx_dlss
4545
{
4646
// Allow force enabling/disabling the DLSS debug display via RegQueryValueExW hook
4747
// (fallback method if we couldn't find the indicator value check pattern in the DLL)
48+
// NOTE: copy any changes to the nvngx_dlssd::RegQueryValueExW_Hook below!
4849
LSTATUS(__stdcall* RegQueryValueExW_Orig)(HKEY hKey, LPCWSTR lpValueName, LPDWORD lpReserved, LPDWORD lpType, LPBYTE lpData, LPDWORD lpcbData);
4950
LSTATUS __stdcall RegQueryValueExW_Hook(HKEY hKey, LPCWSTR lpValueName, LPDWORD lpReserved, LPDWORD lpType, LPBYTE lpData, LPDWORD lpcbData)
5051
{
@@ -66,6 +67,7 @@ LSTATUS __stdcall RegQueryValueExW_Hook(HKEY hKey, LPCWSTR lpValueName, LPDWORD
6667
}
6768

6869
SafetyHookInline DLSS_GetIndicatorValue_Hook;
70+
// NOTE: copy any changes to the nvngx_dlssd::DLSS_GetIndicatorValue below!
6971
uint32_t __fastcall DLSS_GetIndicatorValue(void* thisptr, uint32_t* OutValue)
7072
{
7173
auto ret = DLSS_GetIndicatorValue_Hook.thiscall<uint32_t>(thisptr, OutValue);
@@ -223,6 +225,7 @@ void CreateDlssInstance_PresetSelection(SafetyHookContext& ctx)
223225
}
224226

225227
SafetyHookMid dlssIndicatorHudHook{};
228+
// NOTE: copy any changes to the nvngx_dlssd::hook below!
226229
bool hook(HMODULE ngx_module)
227230
{
228231
// Search for & hook the function that overrides the DLSS presets with ones set by NV
@@ -486,3 +489,133 @@ void init(HMODULE ngx_module)
486489
dllmain = safetyhook::create_inline(utility::ModuleEntryPoint(ngx_module), hooked_dllmain);
487490
}
488491
};
492+
493+
// NOTE: nvngx_dlssd namespace is pretty much a copy of nvngx_dlss atm...
494+
// Ideally we would reuse the same code between them, but since both DLLs are usually loaded at the same time it wouldn't be possible to use the same SafetyHookInline instance between them
495+
// our hook code also has no way to know which DLL we were called from, so wouldn't be able to add seperate instances for each DLL...
496+
// only solution I can see requires us to include seperate functions for both dlss & dlssd
497+
// unfortunately I don't know a good way of making them both share the same code yet, so would need to share changes between them manually :/
498+
namespace nvngx_dlssd
499+
{
500+
// Allow force enabling/disabling the DLSS debug display via RegQueryValueExW hook
501+
// (fallback method if we couldn't find the indicator value check pattern in the DLL)
502+
// NOTE: copy any changes to the nvngx_dlss::RegQueryValueExW_Hook above!
503+
LSTATUS(__stdcall* RegQueryValueExW_Orig)(HKEY hKey, LPCWSTR lpValueName, LPDWORD lpReserved, LPDWORD lpType, LPBYTE lpData, LPDWORD lpcbData);
504+
LSTATUS __stdcall RegQueryValueExW_Hook(HKEY hKey, LPCWSTR lpValueName, LPDWORD lpReserved, LPDWORD lpType, LPBYTE lpData, LPDWORD lpcbData)
505+
{
506+
LSTATUS ret = RegQueryValueExW_Orig(hKey, lpValueName, lpReserved, lpType, lpData, lpcbData);
507+
if (settings.overrideDlssHud == 0 || _wcsicmp(lpValueName, L"ShowDlssIndicator") != 0)
508+
return ret;
509+
510+
if (lpcbData && *lpcbData >= 4 && lpData)
511+
{
512+
DWORD* outData = (DWORD*)lpData;
513+
if (settings.overrideDlssHud >= 1)
514+
*outData = 0x400;
515+
else if (settings.overrideDlssHud < 0)
516+
*outData = 0;
517+
return ERROR_SUCCESS; // always return success for DLSS to accept the result
518+
}
519+
520+
return ret;
521+
}
522+
523+
SafetyHookInline DLSS_GetIndicatorValue_Hook;
524+
// NOTE: copy any changes to the nvngx_dlss::DLSS_GetIndicatorValue above!
525+
uint32_t __fastcall DLSS_GetIndicatorValue(void* thisptr, uint32_t* OutValue)
526+
{
527+
auto ret = DLSS_GetIndicatorValue_Hook.thiscall<uint32_t>(thisptr, OutValue);
528+
if (settings.overrideDlssHud == 0)
529+
return ret;
530+
*OutValue = settings.overrideDlssHud > 0 ? 0x400 : 0;
531+
return ret;
532+
}
533+
534+
SafetyHookMid dlssIndicatorHudHook{};
535+
// NOTE: copy any changes to the nvngx_dlss::hook above!
536+
bool hook(HMODULE ngx_module)
537+
{
538+
// OverrideDlssHud hooks
539+
// This pattern finds 2 matches in latest DLSS, but only 1 in older ones
540+
// The one we're trying to find seems to always be first match
541+
// TODO: scan for RegQueryValue call and grab the offset from that, use offset instead of wildcards below
542+
auto indicatorValueCheck = hook::pattern((void*)ngx_module, "8B 81 ? ? ? ? 89 02 33 C0 C3");
543+
if ((!settings.disableIniMonitoring || settings.overrideDlssHud == 2) && indicatorValueCheck.size())
544+
{
545+
if (!settings.disableIniMonitoring)
546+
spdlog::debug("nvngx_dlssd: applying hud hook via vftable hook...");
547+
else if (settings.overrideDlssHud == 2)
548+
spdlog::debug("nvngx_dlssd: OverrideDlssHud == 2, applying hud hook via vftable hook...");
549+
550+
auto indicatorValueCheck_addr = indicatorValueCheck.get(0).get<void>();
551+
DLSS_GetIndicatorValue_Hook = safetyhook::create_inline(indicatorValueCheck_addr, DLSS_GetIndicatorValue);
552+
553+
// Unfortunately it's not enough to just hook the function, HUD render code seems to have an optimization where it checks funcptr and inlines code if it matches
554+
// So we also need to search for the address of the function, find vftable that holds it, and overwrite entry to point at our hook
555+
556+
// Ugly way of converting our address to a pattern string...
557+
uint8_t* p = (uint8_t*)&indicatorValueCheck_addr;
558+
559+
std::stringstream ss;
560+
ss << std::hex << std::setw(2) << std::setfill('0') << (int)p[0];
561+
for (int i = 1; i < 8; ++i)
562+
ss << " " << std::setw(2) << std::setfill('0') << (int)p[i];
563+
564+
auto pattern = ss.str();
565+
566+
auto indicatorValueCheckMemberVf = hook::pattern((void*)ngx_module, pattern);
567+
for (int i = 0; i < indicatorValueCheckMemberVf.size(); i++)
568+
{
569+
auto vfAddr = indicatorValueCheckMemberVf.get(i).get<uintptr_t>(0);
570+
UnprotectMemory unprotect{ (uintptr_t)vfAddr, sizeof(uintptr_t) };
571+
*vfAddr = (uintptr_t)&DLSS_GetIndicatorValue;
572+
}
573+
574+
spdlog::info("nvngx_dlssd: applied debug hud overlay hook via vftable hook");
575+
}
576+
else
577+
{
578+
// Failed to locate indicator value check inside DLSS
579+
// Fallback to RegQueryValueExW hook so we can override the ShowDlssIndicator value
580+
HMODULE advapi = GetModuleHandleA("advapi32.dll");
581+
RegQueryValueExW_Orig = advapi ? (decltype(RegQueryValueExW_Orig))GetProcAddress(advapi, "RegQueryValueExW") : nullptr;
582+
if (!RegQueryValueExW_Orig || !utility::HookIAT(ngx_module, "advapi32.dll", RegQueryValueExW_Orig, RegQueryValueExW_Hook))
583+
spdlog::warn("nvngx_dlssd: failed to hook DLSS HUD functions, OverrideDlssHud might not be available.");
584+
else
585+
spdlog::info("nvngx_dlssd: applied debug hud overlay hook via registry");
586+
}
587+
588+
return true;
589+
}
590+
591+
void unhook(HMODULE ngx_module)
592+
{
593+
dlssIndicatorHudHook.reset();
594+
595+
spdlog::debug("nvngx_dlssd: finished unhook");
596+
}
597+
598+
SafetyHookInline dllmain;
599+
BOOL APIENTRY hooked_dllmain(HMODULE hModule, int ul_reason_for_call, LPVOID lpReserved)
600+
{
601+
BOOL res = dllmain.stdcall<BOOL>(hModule, ul_reason_for_call, lpReserved);
602+
603+
if (ul_reason_for_call == DLL_PROCESS_DETACH)
604+
{
605+
unhook(hModule);
606+
dllmain.reset();
607+
}
608+
609+
return res;
610+
}
611+
612+
// Installs DllMain hook onto nvngx_dlssd
613+
void init(HMODULE ngx_module)
614+
{
615+
if (settings.disableAllTweaks)
616+
return;
617+
618+
hook(ngx_module);
619+
dllmain = safetyhook::create_inline(utility::ModuleEntryPoint(ngx_module), hooked_dllmain);
620+
}
621+
};

src/resource.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
#define TWEAKS_VER_MAJOR 0
1717
#define TWEAKS_VER_MINOR 200
1818
#define TWEAKS_VER_BUILD 8
19-
#define TWEAKS_VER_REVISION 0
19+
#define TWEAKS_VER_REVISION 1
2020

2121
#define STR(value) #value
2222
#define STRINGIZE(value) STR(value)

0 commit comments

Comments
 (0)