@@ -32,6 +32,10 @@ namespace {
3232 // --- IDirect3D*Texture9 (IUnknown layout) ---------------------------
3333 constexpr int kResource_Release = 2 ;
3434
35+ // Bytes to flush from a hook target / trampoline so the x86-on-ARM64 emulator re-JITs
36+ // it. Covers MinHook's max prologue patch and its 64-byte trampoline slot.
37+ constexpr SIZE_T kFlushSpan = 64 ;
38+
3539 void ** GetVTable (void * com_object)
3640 {
3741 return *static_cast <void ***>(com_object);
@@ -98,6 +102,13 @@ namespace {
98102 Warning (" D3D9Hooks: MH_EnableHook failed for %p\n " , target);
99103 return false ;
100104 }
105+ // Under the x86-on-ARM64 emulator, patched code is only re-translated when its
106+ // instruction cache is flushed. MinHook flushes just the 5 patched bytes, which can
107+ // leave a stale/guarded JIT block and trap; flush the whole prologue and the freshly
108+ // built trampoline so the emulator re-JITs both. No-op on native x86.
109+ const HANDLE proc = GetCurrentProcess ();
110+ FlushInstructionCache (proc, target, kFlushSpan );
111+ if (original && *original) FlushInstructionCache (proc, *original, kFlushSpan );
101112 g_hooked_targets.push_back (target);
102113 return true ;
103114 }
@@ -361,9 +372,11 @@ void RemoveAllD3D9Hooks()
361372 // Signal first: a detour reached after this (e.g. a surviving patch) falls through.
362373 g_unhooked = true ;
363374
375+ const HANDLE proc = GetCurrentProcess ();
364376 for (void * target : g_hooked_targets) {
365377 MH_DisableHook (target);
366378 MH_RemoveHook (target);
379+ FlushInstructionCache (proc, target, kFlushSpan ); // re-JIT the restored prologue under emulation
367380 }
368381 g_hooked_targets.clear ();
369382
0 commit comments