@@ -67,33 +67,37 @@ void Memory::Free(void* apData) noexcept
6767 TiltedPhoques::ThisCall (RealFormFree, GameHeap::Get (), apData, false );
6868}
6969
70- bool Memory:: IsFormAllocateReplacedByEF () noexcept
70+ static bool IsFormAllocateReplacedByEF (TFormAllocate** appOutEngineFixesAlloc ) noexcept
7171{
7272 POINTER_SKYRIMSE (TFormAllocate, s_formAllocate, 68115 );
7373 TFormAllocate* pFormAllocate = s_formAllocate.Get ();
7474
75- // 6-byte sequence of 'FF 25 00 00 00 00' comes before the virtual address we're after; so, +6
76- auto possibleEfAllocAddr = *reinterpret_cast <uintptr_t *>(reinterpret_cast <uint8_t *>(*pFormAllocate) + 6 );
75+ auto opcodeBytes = reinterpret_cast <uint16_t *>(*pFormAllocate);
76+ uint8_t shift = 0 ;
77+
78+ if (*opcodeBytes == 0x25FF ) // 'jmp' opcode 'FF 25' and the 4-byte displacement bytes come before the virtual address we're after
79+ shift = 6 ;
80+ else if (*opcodeBytes == 0xB848 ) // 'mov' opcode '48 B8' comes before the virtual address we're after
81+ shift = 2 ;
82+
83+ auto possibleEfAllocAddress = *reinterpret_cast <uintptr_t *>(reinterpret_cast <uint8_t *>(*pFormAllocate) + shift);
7784
7885 MEMORY_BASIC_INFORMATION mbi;
79- if (VirtualQuery ((void *)possibleEfAllocAddr , &mbi, sizeof (mbi)) != 0 )
86+ if (VirtualQuery ((void *)possibleEfAllocAddress , &mbi, sizeof (mbi)) != 0 )
8087 {
81- return mbi.AllocationBase == GetModuleHandleW (L" EngineFixes.dll" );
88+ if (mbi.AllocationBase == GetModuleHandleW (L" EngineFixes.dll" ))
89+ {
90+ *appOutEngineFixesAlloc = reinterpret_cast <TFormAllocate*>(possibleEfAllocAddress);
91+ return true ;
92+ }
8293 }
8394 return false ;
8495}
8596
86- bool Memory::RehookMemoryFunctions ( ) noexcept
97+ static void RehookFormAllocate (TFormAllocate* apEngineFixesAllocate ) noexcept
8798{
88- POINTER_SKYRIMSE (TFormAllocate, s_formAllocate, 68115 );
89- TFormAllocate* pFormAllocate = s_formAllocate.Get ();
90-
91- uintptr_t efAllocAddr = *reinterpret_cast <uintptr_t *>(reinterpret_cast <uint8_t *>(*pFormAllocate) + 6 );
92- auto pEngineFixesAllocate = reinterpret_cast <decltype (&HookFormAllocate)>(efAllocAddr);
93-
94- RealFormAllocate = pEngineFixesAllocate;
99+ RealFormAllocate = apEngineFixesAllocate;
95100 TP_HOOK_IMMEDIATE (&RealFormAllocate, HookFormAllocate);
96- return true ; // TODO when to return false?
97101}
98102
99103size_t Hook_msize (void * apData)
@@ -171,10 +175,10 @@ int __cdecl Hook_initterm_e(_PIFV* apFirst, _PIFV* apLast)
171175 // We want to run last, so pre-chain.
172176 auto retval = Real_initterm_e (apFirst, apLast);
173177
174- // Check if anyone messed with STR's moddified allocator hook,
175- // which changes the size of some allocations.
176- if (GetModuleHandleW (L" EngineFixes.dll" ) && Memory:: IsFormAllocateReplacedByEF ())
177- Memory::RehookMemoryFunctions ( );
178+ // Check if EngineFixes messed with STR's modified alloc hook; if it did, treat EF as truth and rehook
179+ TFormAllocate* pEngineFixesAllocate = nullptr ;
180+ if (GetModuleHandleW (L" EngineFixes.dll" ) && IsFormAllocateReplacedByEF (&pEngineFixesAllocate ))
181+ RehookFormAllocate (pEngineFixesAllocate );
178182
179183 return retval;
180184}
0 commit comments