1
+ #pragma once
2
+
3
+ #include " ../pch.h"
4
+ #include " NvApiTypes.h"
5
+ #include " ReflexHooks.h"
6
+ #include " fakenvapi.h"
7
+
8
+ class NvApiHooks {
9
+ public:
10
+ // NvAPI_GPU_GetArchInfo hooking based on Nukem's spoofing code here
11
+ // https://github.com/Nukem9/dlssg-to-fsr3/blob/89ddc8c1cce4593fb420e633a06605c3c4b9c3cf/source/wrapper_generic/nvapi.cpp#L50
12
+
13
+ inline static NvApiTypes::PFN_NvApi_QueryInterface OriginalNvAPI_QueryInterface = nullptr ;
14
+ inline static NvApiTypes::PfnNvAPI_GPU_GetArchInfo OriginalNvAPI_GPU_GetArchInfo = nullptr ;
15
+
16
+ inline static uint32_t __stdcall HookedNvAPI_GPU_GetArchInfo (void * GPUHandle, NV_GPU_ARCH_INFO* ArchInfo)
17
+ {
18
+ if (OriginalNvAPI_GPU_GetArchInfo)
19
+ {
20
+ const auto status = OriginalNvAPI_GPU_GetArchInfo (GPUHandle, ArchInfo);
21
+
22
+ if (status == 0 && ArchInfo)
23
+ {
24
+ LOG_DEBUG (" From api arch: {0:X} impl: {1:X} rev: {2:X}!" , ArchInfo->architecture , ArchInfo->implementation , ArchInfo->revision );
25
+
26
+ // for 16xx cards
27
+ if (ArchInfo->architecture == NV_GPU_ARCHITECTURE_TU100 && ArchInfo->implementation > NV_GPU_ARCH_IMPLEMENTATION_TU106)
28
+ {
29
+ ArchInfo->implementation = NV_GPU_ARCH_IMPLEMENTATION_TU106;
30
+ ArchInfo->implementation_id = NV_GPU_ARCH_IMPLEMENTATION_TU106;
31
+
32
+ LOG_INFO (" Spoofed arch: {0:X} impl: {1:X} rev: {2:X}!" , ArchInfo->architecture , ArchInfo->implementation , ArchInfo->revision );
33
+ }
34
+ // else if (ArchInfo->architecture < NV_GPU_ARCHITECTURE_TU100 && ArchInfo->architecture >= NV_GPU_ARCHITECTURE_GP100)
35
+ // {
36
+ // LOG_INFO("Spoofing below 16xx arch: {0:X} impl: {1:X} rev: {2:X}!", ArchInfo->architecture, ArchInfo->implementation, ArchInfo->revision);
37
+
38
+ // ArchInfo->architecture = NV_GPU_ARCHITECTURE_TU100;
39
+ // ArchInfo->architecture_id = NV_GPU_ARCHITECTURE_TU100;
40
+ // ArchInfo->implementation = NV_GPU_ARCH_IMPLEMENTATION_TU106;
41
+ // ArchInfo->implementation_id = NV_GPU_ARCH_IMPLEMENTATION_TU106;
42
+
43
+ // LOG_INFO("Spoofed arch: {0:X} impl: {1:X} rev: {2:X}!", ArchInfo->architecture, ArchInfo->implementation, ArchInfo->revision);
44
+ // }
45
+ }
46
+
47
+ return status;
48
+ }
49
+
50
+ return 0xFFFFFFFF ;
51
+ }
52
+
53
+ inline static void * __stdcall HookedNvAPI_QueryInterface (NvApiTypes::NV_INTERFACE InterfaceId)
54
+ {
55
+ switch (InterfaceId) {
56
+ case NvApiTypes::NV_INTERFACE::D3D_SetSleepMode:
57
+ case NvApiTypes::NV_INTERFACE::D3D_Sleep:
58
+ case NvApiTypes::NV_INTERFACE::D3D_GetLatency:
59
+ case NvApiTypes::NV_INTERFACE::D3D_SetLatencyMarker:
60
+ case NvApiTypes::NV_INTERFACE::D3D12_SetAsyncFrameMarker:
61
+ return ReflexHooks::hookReflex (OriginalNvAPI_QueryInterface, InterfaceId);
62
+ default :
63
+ ReflexHooks::hookReflex (OriginalNvAPI_QueryInterface, InterfaceId);
64
+ }
65
+
66
+ const auto functionPointer = OriginalNvAPI_QueryInterface (InterfaceId);
67
+
68
+ if (functionPointer)
69
+ {
70
+ switch (InterfaceId) {
71
+ case NvApiTypes::NV_INTERFACE::GPU_GetArchInfo:
72
+ if (!Config::Instance ()->DE_Available ) {
73
+ OriginalNvAPI_GPU_GetArchInfo = static_cast <NvApiTypes::PfnNvAPI_GPU_GetArchInfo>(functionPointer);
74
+ return &HookedNvAPI_GPU_GetArchInfo;
75
+ }
76
+ break ;
77
+ }
78
+ }
79
+
80
+ return functionPointer;
81
+ }
82
+
83
+ // Requires HMODULE to make sure nvapi is loaded before calling this function
84
+ inline static void Hook (HMODULE nvapiModule)
85
+ {
86
+ if (OriginalNvAPI_QueryInterface != nullptr )
87
+ return ;
88
+
89
+ if (nvapiModule == nullptr ) {
90
+ LOG_ERROR (" Hook called with a nullptr nvapi module" );
91
+ return ;
92
+ }
93
+
94
+ LOG_DEBUG (" Trying to hook NvApi" );
95
+
96
+ OriginalNvAPI_QueryInterface = (NvApiTypes::PFN_NvApi_QueryInterface)GetProcAddress (nvapiModule, " nvapi_QueryInterface" );
97
+
98
+ LOG_DEBUG (" OriginalNvAPI_QueryInterface = {0:X}" , (unsigned long long )OriginalNvAPI_QueryInterface);
99
+
100
+ if (OriginalNvAPI_QueryInterface != nullptr )
101
+ {
102
+ LOG_INFO (" NvAPI_QueryInterface found, hooking!" );
103
+ fakenvapi::Init ((fakenvapi::PFN_Fake_QueryInterface&)OriginalNvAPI_QueryInterface);
104
+
105
+ DetourTransactionBegin ();
106
+ DetourUpdateThread (GetCurrentThread ());
107
+ DetourAttach (&(PVOID&)OriginalNvAPI_QueryInterface, HookedNvAPI_QueryInterface);
108
+ DetourTransactionCommit ();
109
+ }
110
+ }
111
+
112
+ inline static void Unhook () {
113
+ DetourTransactionBegin ();
114
+ DetourUpdateThread (GetCurrentThread ());
115
+
116
+ if (OriginalNvAPI_QueryInterface != nullptr )
117
+ {
118
+ DetourDetach (&(PVOID&)OriginalNvAPI_QueryInterface, HookedNvAPI_QueryInterface);
119
+ OriginalNvAPI_QueryInterface = nullptr ;
120
+ }
121
+
122
+ DetourTransactionCommit ();
123
+ }
124
+ };
0 commit comments