102 Patches: Detours to the Rescue
C reference for DttR maintainers and modders.
Loading...
Searching...
No Matches
hooks.c
Go to the documentation of this file.
1#include <dttr_pcdogs.h>
2
3#include <stdlib.h>
4#include <windows.h>
5
6#include <dttr_config.h>
7
9#include "graphics_private.h"
10#include "hooks_private.h"
11#include "sidecar_private.h"
12#include <dttr_log.h>
13
16
19 true,
20 "83 F8 ?? 7C ?? D9 43 ?? D8 1D ?? ?? ?? ?? DF E0 F6 C4 41 0F ?? ?? ?? ??",
21 19,
22 0xE9,
23 0xBA,
24 0x00,
25 0x00,
26 0x00,
27 0x90
28 ),
30 true,
31 "8B 08 EB ?? A1 ?? ?? ?? ?? 8B 0D ?? ?? ?? ?? 3B C1",
32 17,
33 0x90,
34 0x90
35 ),
37 true,
38 "83 C1 14 4E 75 ?? A1 ?? ?? ?? ?? 8B 0D ?? ?? ?? ?? 3B C1",
39 19,
40 0x90,
41 0x90
42 ),
44 true,
45 "DB 44 24 30 D9 1F",
46 -15,
47 0xD9,
48 0x1F,
49 0x90,
50 0x90,
51 0x90
52 ),
54 true,
55 "DB 44 24 30 D9 1F",
56 -10,
57 0x90,
58 0x90,
59 0x90,
60 0x90
61 ),
63 true,
64 "8D AE ?? ?? ?? ?? DB 44 24 30 D9 1F",
65 10,
66 0x90,
67 0x90
68 ),
70 true,
71 "8D AE ?? ?? ?? ?? DB 44 24 30",
72 6,
73 0x90,
74 0x90,
75 0x90,
76 0x90
77 ),
79 true,
80 "8B 54 24 18 89 44 24 30",
81 -5,
82 0xD9,
83 0x5D,
84 0x00,
85 0x90,
86 0x90
87 ),
89 true,
90 "8B 54 24 18 89 44 24 30",
91 4,
92 0x90,
93 0x90,
94 0x90,
95 0x90
96 ),
97 DTTR_PCDOGS_PATCH_SPEC_AOB_BYTES(true, "83 C0 14 50 55 D9 5D 00", 5, 0x90, 0x90, 0x90),
98 DTTR_PCDOGS_PATCH_SPEC_AOB_BYTES(true, "52 DB 44 24 34", 1, 0x90, 0x90, 0x90, 0x90),
99 DTTR_PCDOGS_PATCH_SPEC_AOB_BYTES(false, "53 8B 5C 24 14 55 33 C9 56 57 85 DB", 0, 0xC3),
100};
101
104
105// Lazily creates the DirectDraw 7 facade that satisfies the game's renderer bootstrap.
113
114// Temporarily relaxes page protection so the DirectDraw callback can publish the facade
115// pointer through the game-provided slot.
116static void store_pointer(void **slot, void *value) {
117 DWORD old = 0;
118 const SIZE_T slot_size = sizeof(*slot);
119
120 if (!VirtualProtect(slot, slot_size, PAGE_READWRITE, &old)) {
122 "VirtualProtect failed for slot=%p error=%lu",
123 slot,
124 GetLastError()
125 );
126 return;
127 }
128
129 *slot = value;
130 VirtualProtect(slot, slot_size, old, &old);
131}
132
133// Replaces DirectDrawCreateEx with the sidecar facade so the game renders through the
134// selected backend.
137 void **ddraw_out,
140) {
142
143 if (!ddraw7) {
144 return E_OUTOFMEMORY;
145 }
146
149 );
150 if (!DTTR_ResultOK(result)) {
152 "Failed to publish DirectDraw object: %s",
154 );
155 return E_FAIL;
156 }
157
158 if (ddraw_out) {
159 store_pointer(ddraw_out, ddraw7);
160 }
161
162 DTTR_LOG_DEBUG("DirectDrawCreateEx returning S_OK, vtbl=%p", ddraw7->vtbl);
163 return S_OK;
164}
165
166// Reports a single compatible DirectDraw device to keep the game enumeration path on
167// the sidecar renderer.
169 DDraw_EnumCallbackExA lpCallback,
170 LPVOID lpContext,
171 DWORD dwFlags
172) {
174 "DirectDrawEnumerateExA intercepted - callback=%p context=%p flags=0x%x",
175 lpCallback,
176 lpContext,
177 dwFlags
178 );
179
180 if (!lpCallback) {
181 return S_OK;
182 }
183
184 lpCallback(NULL, "DTTR Virtual Display", "display", lpContext, NULL);
185
186 return S_OK;
187}
188
189// Initializes the sidecar renderer before DirectDraw callbacks hand it to the game.
192
193 if (!graphics_hook_hwnd) {
194 DTTR_LOG_ERROR("Failed to initialize backend");
195 return false;
196 }
197
198 if (!get_or_create_ddraw7()) {
199 DTTR_LOG_ERROR("Failed to create DirectDraw translator");
200 return false;
201 }
202
203 const DTTR_PCDOGS_T_Patch_Spec graphics_import_thunk_patches[] = {
208 };
209
211 ctx,
212 "sidecar/graphics-import-thunk",
213 graphics_import_thunk_patches,
214 DTTR_ARRAY_COUNT(graphics_import_thunk_patches),
216 )) {
217 return false;
218 }
219
220 if (dttr_config.vertex_precision == DTTR_VERTEX_PRECISION_SUBPIXEL) {
222 ctx,
223 "sidecar/graphics-byte-patch",
227 )) {
228 return false;
229 }
230 }
231
232 return true;
233}
234
235// Releases DirectDraw facade state after graphics patches are removed.
return S_OK
void void * ctx
DTTR_Graphics_COM_DirectDraw7 * dttr_graphics_com_create_directdraw7()
void DWORD DWORD * free
DTTR_Graphics_COM_DirectDrawSurface7 DWORD flags void NULL
@ DTTR_VERTEX_PRECISION_SUBPIXEL
Definition dttr_config.h:45
DTTR_Config dttr_config
Definition defaults.c:53
DTTR_Result DTTR_Core_PatchGroupRelease(DTTR_Core_PatchGroup **group)
Definition core.c:657
#define DTTR_ARRAY_COUNT(array_)
Definition dttr_core.h:18
struct DTTR_Core_PatchGroup DTTR_Core_PatchGroup
Definition dttr_core.h:25
#define DTTR_LOG_DEBUG(...)
Definition dttr_log.h:28
#define DTTR_LOG_ERROR(...)
Definition dttr_log.h:31
DTTR_PCDOGS_API const struct dttr_pcdogs_function_accessor_DDraw_CreateEx *const DTTR_PCDOGS_F_DDraw_CreateEx
Accessor object for DDraw_CreateEx.
DTTR_PCDOGS_API const struct DTTR_PCDOGS_D_D3D_CreateTextureSurface_DDrawObject_type *const DTTR_PCDOGS_D_D3D_CreateTextureSurface_DDrawObject
DTTR_PCDOGS_API const struct dttr_pcdogs_function_accessor_DDraw_EnumerateExA *const DTTR_PCDOGS_F_DDraw_EnumerateExA
Accessor object for DDraw_EnumerateExA.
GUID DTTR_PCDOGS_T_Win32_GUID
Win32 GUID value used by DirectDraw import entries.
struct DTTR_PCDOGS_T_DDraw_IDirectDraw7 DTTR_PCDOGS_T_DDraw_IDirectDraw7
#define DTTR_PCDOGS_PATCH_SPEC_AOB_BYTES(required_, aob_, offset_,...)
struct DTTR_PCDOGS_T_COM_IUnknown DTTR_PCDOGS_T_COM_IUnknown
bool DTTR_ResultOK(DTTR_Result result)
Definition core.c:78
static HWND graphics_hook_hwnd
Definition hooks.c:15
HRESULT dttr_hook_directdraw_create_ex_callback(DTTR_PCDOGS_T_Win32_GUID *guid, void **ddraw_out, DTTR_PCDOGS_T_Win32_GUID *iid, DTTR_PCDOGS_T_COM_IUnknown *outer)
Definition hooks.c:135
static DTTR_Graphics_COM_DirectDraw7 * graphics_hook_ddraw7
Definition hooks.c:14
static DTTR_Core_PatchGroup * graphics_import_thunk_patch_group
Definition hooks.c:102
static const DTTR_PCDOGS_T_Patch_Spec graphics_byte_patches[]
Definition hooks.c:17
static void store_pointer(void **slot, void *value)
Definition hooks.c:116
static DTTR_Core_PatchGroup * graphics_byte_patch_group
Definition hooks.c:103
static DTTR_Graphics_COM_DirectDraw7 * get_or_create_ddraw7()
Definition hooks.c:106
void dttr_graphics_hooks_cleanup(const DTTR_Mods_Context *ctx)
Definition hooks.c:236
bool dttr_graphics_hooks_init(const DTTR_Mods_Context *ctx)
Definition hooks.c:190
HRESULT dttr_hook_directdraw_enumerate_ex_a_callback(DDraw_EnumCallbackExA lpCallback, LPVOID lpContext, DWORD dwFlags)
Definition hooks.c:168
BOOL(* DDraw_EnumCallbackExA)(GUID *lpGUID, LPSTR lpDriverDescription, LPSTR lpDriverName, LPVOID lpContext, HMONITOR hm)
HWND dttr_graphics_init()
Definition graphics.c:482
static const char * dttr_sidecar_result_detail(DTTR_Result result)
static bool dttr_sidecar_install_pcdogs_patch_group(const DTTR_Mods_Context *ctx, const char *label, const DTTR_PCDOGS_T_Patch_Spec *patches, size_t patch_count, DTTR_Core_PatchGroup **group)
DTTR_Graphics_COM_DirectDraw7_VT * vtbl