From 827641b9b112797482e0eba04db2c516d35703b0 Mon Sep 17 00:00:00 2001 From: Kawe Mazidjatari <48657826+Mauler125@users.noreply.github.com> Date: Fri, 29 Apr 2022 18:25:54 +0200 Subject: [PATCH] Early working implementation of the 'mdl/error.rmdl' fallback Only works for prop_static (for the time being) Only works for the S3 game_dll. In order to get this to work: you must set 'old_gather_props' to nun-null and (for certain maps) perform the patch to prevent the frustum culling code to deref a bad pointer (see command 'opcodes test'). --- r5dev/datacache/mdlcache.cpp | 57 ++++++++++++++++++++++++++++++--- r5dev/datacache/mdlcache.h | 58 +++++++++++++++++++++++++++------- r5dev/public/include/memaddr.h | 4 +-- 3 files changed, 101 insertions(+), 18 deletions(-) diff --git a/r5dev/datacache/mdlcache.cpp b/r5dev/datacache/mdlcache.cpp index 2a7c77e6..afe6ee0a 100644 --- a/r5dev/datacache/mdlcache.cpp +++ b/r5dev/datacache/mdlcache.cpp @@ -161,7 +161,15 @@ studiohdr_t* CMDLCache::FindUncachedMDL(CMDLCache* cache, MDLHandle_t handle, vo return v17; } -studiohdr_t* CMDLCache::GetStudioHdr(CMDLCache* pMDLCache, MDLHandle_t handle) +//----------------------------------------------------------------------------- +// Purpose: gets the studiohdr from cache pool by handle +// Input : *this - +// handle - +// *a3 - +// *a4 +// Output : a pointer to the studiohdr_t object +//----------------------------------------------------------------------------- +studiohdr_t* CMDLCache::GetStudioHDR(CMDLCache* pMDLCache, MDLHandle_t handle) { __int64 v2; // rbx __int64 v3; // rbx @@ -183,20 +191,61 @@ studiohdr_t* CMDLCache::GetStudioHdr(CMDLCache* pMDLCache, MDLHandle_t handle) v4 = *(_QWORD*)(*(_QWORD*)(*(_QWORD*)v3 + 8i64) + 24i64); result = (studiohdr_t*)(v4 + 16); if (!v4) - result = nullptr;; + result = nullptr; return result; } +//----------------------------------------------------------------------------- +// Purpose: gets the studio hardware data reference from cache pool by handle +// Input : *this - +// handle - +// *a3 - +// *a4 +// Output : a pointer to the CStudioHWDataRef object +//----------------------------------------------------------------------------- +CStudioHWDataRef* CMDLCache::GetStudioHardwareRef(CMDLCache* cache, MDLHandle_t handle) +{ + __int64 v2; // rbx + __int64 v3; // rdi + __int64 v4; // rbx + __int64 result; // rax + + v2 = handle; + EnterCriticalSection(reinterpret_cast(&*m_MDLMutex)); + v3 = *(_QWORD*)(m_MDLDict.Deref().GetPtr() + 24 * v2 + 16); + LeaveCriticalSection(reinterpret_cast(&*m_MDLMutex)); + + if (!v3) + { + return nullptr; + } + + if (*(_QWORD*)v3) + { + v4 = *(_QWORD*)(*(_QWORD*)v3 + 8i64); + AcquireSRWLockExclusive(reinterpret_cast(&*m_MDLLock)); + v_CStudioHWDataRef__SetFlags(reinterpret_cast(v4), 1i64); // !!! DECLARED INLINE IN < S3 !!! + ReleaseSRWLockExclusive(reinterpret_cast(&*m_MDLLock)); + } + if ((*(_BYTE*)(v3 + 18) & 1) != 0) + result = *(_QWORD*)(v3 + 0x20) + 16i64; + else + result = 0i64; + return reinterpret_cast(result); +} + void MDLCache_Attach() { DetourAttach((LPVOID*)&v_CMDLCache__FindMDL, &CMDLCache::FindMDL); DetourAttach((LPVOID*)&v_CMDLCache__FindUncachedMDL, &CMDLCache::FindUncachedMDL); - //DetourAttach((LPVOID*)&v_CMDLCache__GetStudioHdr, &CMDLCache::GetStudioHdr); + DetourAttach((LPVOID*)&v_CMDLCache__GetStudioHardwareRef, &CMDLCache::GetStudioHardwareRef); + //DetourAttach((LPVOID*)&v_CMDLCache__GetStudioHdr, &CMDLCache::GetStudioHDR); } void MDLCache_Detach() { DetourDetach((LPVOID*)&v_CMDLCache__FindMDL, &CMDLCache::FindMDL); DetourDetach((LPVOID*)&v_CMDLCache__FindUncachedMDL, &CMDLCache::FindUncachedMDL); - //DetourDetach((LPVOID*)&v_CMDLCache__GetStudioHdr, &CMDLCache::GetStudioHdr); + DetourDetach((LPVOID*)&v_CMDLCache__GetStudioHardwareRef, &CMDLCache::GetStudioHardwareRef); + //DetourDetach((LPVOID*)&v_CMDLCache__GetStudioHdr, &CMDLCache::GetStudioHDR); } \ No newline at end of file diff --git a/r5dev/datacache/mdlcache.h b/r5dev/datacache/mdlcache.h index 5069e9fd..f34ae819 100644 --- a/r5dev/datacache/mdlcache.h +++ b/r5dev/datacache/mdlcache.h @@ -3,6 +3,21 @@ #include "public/include/studio.h" #include "datacache/imdlcache.h" +class CStudioHWDataRef +{ +public: + bool IsDataRef(void) const { return true; } + uint8_t m_pUnknown[0x90]{}; +}; + +struct RStaticProp_t +{ + studiohdr_t* m_pStudioHDR{}; + CStudioHWDataRef* m_pHardWareData{}; + const char* m_szPropName{}; + uint8_t m_pUnknown[0x62]{}; +}; + struct CMDLFallBack { studiohdr_t* m_pErrorHDR{}; @@ -24,10 +39,11 @@ inline CMDLFallBack* g_pMDLFallback = new CMDLFallBack(); class CMDLCache { public: - static studiohdr_t* FindMDL(CMDLCache* pMDLCache, MDLHandle_t handle, void* a3); - static void FindCachedMDL(CMDLCache* pMDLCache, void* a2, void* a3); - static studiohdr_t* FindUncachedMDL(CMDLCache* pMDLCache, MDLHandle_t handle, void* a3, void* a4); - static studiohdr_t* GetStudioHdr(CMDLCache* pMDLCache, MDLHandle_t handle); + static studiohdr_t* FindMDL(CMDLCache* cache, MDLHandle_t handle, void* a3); + static void FindCachedMDL(CMDLCache* cache, void* a2, void* a3); + static studiohdr_t* FindUncachedMDL(CMDLCache* cache, MDLHandle_t handle, void* a3, void* a4); + static studiohdr_t* GetStudioHDR(CMDLCache* cache, MDLHandle_t handle); + static CStudioHWDataRef* GetStudioHardwareRef(CMDLCache* cache, MDLHandle_t handle); CMDLCache* m_pVTable; void* m_pStrCmp; // string compare func; @@ -48,11 +64,18 @@ inline auto v_CMDLCache__FindCachedMDL = p_CMDLCache__FindCachedMDL.RCast(); -inline CMemory p_CMDLCache__GetStudioHdr; -inline auto v_CMDLCache__GetStudioHdr = p_CMDLCache__GetStudioHdr.RCast(); +inline CMemory p_CMDLCache__GetStudioHDR; +inline auto v_CMDLCache__GetStudioHDR = p_CMDLCache__GetStudioHDR.RCast(); + +inline CMemory p_CMDLCache__GetStudioHardwareRef; +inline auto v_CMDLCache__GetStudioHardwareRef = p_CMDLCache__GetStudioHardwareRef.RCast(); + +inline CMemory p_CStudioHWDataRef__SetFlags; // Probably incorrect. +inline auto v_CStudioHWDataRef__SetFlags = p_CStudioHWDataRef__SetFlags.RCast(); inline CMemory m_MDLDict; inline LPCRITICAL_SECTION* m_MDLMutex = nullptr; +inline PSRWLOCK* m_MDLLock = nullptr; inline CMDLCache* g_MDLCache = nullptr; @@ -66,8 +89,9 @@ class HMDLCache : public IDetour std::cout << "| FUN: CMDLCache::FindMDL : 0x" << std::hex << std::uppercase << p_CMDLCache__FindMDL.GetPtr() << std::setw(nPad) << " |" << std::endl; std::cout << "| FUN: CMDLCache::FindCachedMDL : 0x" << std::hex << std::uppercase << p_CMDLCache__FindCachedMDL.GetPtr() << std::setw(nPad) << " |" << std::endl; std::cout << "| FUN: CMDLCache::FindUncachedMDL : 0x" << std::hex << std::uppercase << p_CMDLCache__FindUncachedMDL.GetPtr() << std::setw(nPad) << " |" << std::endl; - std::cout << "| FUN: CMDLCache::GetStudioHdr : 0x" << std::hex << std::uppercase << p_CMDLCache__GetStudioHdr.GetPtr() << std::setw(nPad) << " |" << std::endl; + std::cout << "| FUN: CMDLCache::GetStudioHdr : 0x" << std::hex << std::uppercase << p_CMDLCache__GetStudioHDR.GetPtr() << std::setw(nPad) << " |" << std::endl; std::cout << "| VAR: m_MDLMutex : 0x" << std::hex << std::uppercase << m_MDLMutex << std::setw(nPad) << " |" << std::endl; + std::cout << "| VAR: m_MDLLock : 0x" << std::hex << std::uppercase << m_MDLLock << std::setw(nPad) << " |" << std::endl; std::cout << "| VAR: m_MDLDict : 0x" << std::hex << std::uppercase << m_MDLDict.GetPtr() << std::setw(nPad) << " |" << std::endl; std::cout << "| VAR: g_MDLCache : 0x" << std::hex << std::uppercase << g_MDLCache << std::setw(0) << " |" << std::endl; std::cout << "+----------------------------------------------------------------+" << std::endl; @@ -81,17 +105,25 @@ class HMDLCache : public IDetour v_CMDLCache__FindCachedMDL = p_CMDLCache__FindCachedMDL.RCast(); /*4D 85 C0 74 7A 48 89 6C 24 ?*/ p_CMDLCache__FindUncachedMDL = g_mGameDll.FindPatternSIMD(reinterpret_cast("\x48\x89\x5C\x24\x00\x48\x89\x6C\x24\x00\x48\x89\x74\x24\x00\x48\x89\x7C\x24\x00\x41\x56\x48\x83\xEC\x20\x48\x8B\xE9\x0F\xB7\xFA"), "xxxx?xxxx?xxxx?xxxx?xxxxxxxxxxxx"); - v_CMDLCache__FindUncachedMDL = p_CMDLCache__FindUncachedMDL.RCast(); + v_CMDLCache__FindUncachedMDL = p_CMDLCache__FindUncachedMDL.RCast(); /*48 89 5C 24 ? 48 89 6C 24 ? 48 89 74 24 ? 48 89 7C 24 ? 41 56 48 83 EC 20 48 8B E9 0F B7 FA*/ - p_CMDLCache__GetStudioHdr = g_mGameDll.FindPatternSIMD(reinterpret_cast("\x40\x53\x48\x83\xEC\x20\x48\x8D\x0D\x00\x00\x00\x00\x0F\xB7\xDA\xFF\x15\x00\x00\x00\x00\x48\x8B\x05\x00\x00\x00\x00\x48\x8D\x14\x5B\x48\x8D\x0D\x00\x00\x00\x00\x48\x8B\x5C\xD0\x00\xFF\x15\x00\x00\x00\x00\x48\x8B\x03\x48\x8B\x48\x08"), "xxxxxxxxx????xxxxx????xxx????xxxxxxx????xxxx?xx????xxxxxxx");; - v_CMDLCache__GetStudioHdr = p_CMDLCache__GetStudioHdr.RCast(); + p_CMDLCache__GetStudioHDR = g_mGameDll.FindPatternSIMD(reinterpret_cast("\x40\x53\x48\x83\xEC\x20\x48\x8D\x0D\x00\x00\x00\x00\x0F\xB7\xDA\xFF\x15\x00\x00\x00\x00\x48\x8B\x05\x00\x00\x00\x00\x48\x8D\x14\x5B\x48\x8D\x0D\x00\x00\x00\x00\x48\x8B\x5C\xD0\x00\xFF\x15\x00\x00\x00\x00\x48\x8B\x03\x48\x8B\x48\x08"), "xxxxxxxxx????xxxxx????xxx????xxxxxxx????xxxx?xx????xxxxxxx"); + v_CMDLCache__GetStudioHDR = p_CMDLCache__GetStudioHDR.RCast(); /*40 53 48 83 EC 20 48 8D 0D ? ? ? ? 0F B7 DA FF 15 ? ? ? ? 48 8B 05 ? ? ? ? 48 8D 14 5B 48 8D 0D ? ? ? ? 48 8B 5C D0 ? FF 15 ? ? ? ? 48 8B 03 48 8B 48 08*/ + + p_CMDLCache__GetStudioHardwareRef = g_mGameDll.FindPatternSIMD(reinterpret_cast("\x48\x89\x5C\x24\x00\x57\x48\x83\xEC\x20\x48\x8D\x0D\x00\x00\x00\x00\x0F\xB7\xDA\xFF\x15\x00\x00\x00\x00\x48\x8B\x05\x00\x00\x00\x00\x48\x8D\x14\x5B\x48\x8D\x0D\x00\x00\x00\x00\x48\x8B\x7C\xD0\x00\xFF\x15\x00\x00\x00\x00\x48\x8B\x1F"), "xxxx?xxxxxxxx????xxxxx????xxx????xxxxxxx????xxxx?xx????xxx"); + v_CMDLCache__GetStudioHardwareRef = p_CMDLCache__GetStudioHardwareRef.RCast(); /*48 89 5C 24 ? 57 48 83 EC 20 48 8D 0D ? ? ? ? 0F B7 DA FF 15 ? ? ? ? 48 8B 05 ? ? ? ? 48 8D 14 5B 48 8D 0D ? ? ? ? 48 8B 7C D0 ? FF 15 ? ? ? ? 48 8B 1F*/ + + p_CStudioHWDataRef__SetFlags = g_mGameDll.FindPatternSIMD(reinterpret_cast("\x48\x83\xEC\x08\x4C\x8D\x14\x12"), "xxxxxxxx"); + v_CStudioHWDataRef__SetFlags = p_CStudioHWDataRef__SetFlags.RCast(); /*48 83 EC 08 4C 8D 14 12*/ } virtual void GetVar(void) const { m_MDLMutex = g_mGameDll.FindPatternSIMD(reinterpret_cast("\x48\x83\xEC\x28\xBA\x00\x00\x00\x00\x48\x8D\x0D\x00\x00\x00\x00\xFF\x15\x00\x00\x00\x00\x0F\xB6\x05\x00\x00\x00\x00"), "xxxxx????xxx????xx????xxx????") - .FindPatternSelf("48 8D 0D", CMemory::Direction::DOWN).ResolveRelativeAddressSelf(0x3, 0x7).RCast(); + .FindPatternSelf("48 8D 0D").ResolveRelativeAddressSelf(0x3, 0x7).RCast(); - m_MDLDict = p_CMDLCache__FindMDL.FindPattern("48 8B 05", CMemory::Direction::DOWN).ResolveRelativeAddressSelf(0x3, 0x7); + m_MDLLock = p_CMDLCache__GetStudioHardwareRef.Offset(0x35).FindPatternSelf("48 8D").ResolveRelativeAddressSelf(0x2, 0x7).RCast(); + + m_MDLDict = p_CMDLCache__FindMDL.FindPattern("48 8B 05").ResolveRelativeAddressSelf(0x3, 0x7); g_MDLCache = g_mGameDll.FindPatternSIMD(reinterpret_cast("\x48\x8B\x0D\x00\x00\x00\x00\x44\x0F\xB7\x82\x00\x00\x00\x00\x48\x8B\x01\x48\xFF\xA0\x30\x01\x00\x00"), "xxx????xxxx????xxxxxxxxxx") .ResolveRelativeAddressSelf(0x3, 0x7).RCast(); @@ -102,5 +134,7 @@ class HMDLCache : public IDetour }; /////////////////////////////////////////////////////////////////////////////// +#ifdef GAMEDLL_S3 REGISTER(HMDLCache); +#endif // GAMEDLL_S3 #endif // MDLCACHE_H diff --git a/r5dev/public/include/memaddr.h b/r5dev/public/include/memaddr.h index 919d6a67..bb6cb7e8 100644 --- a/r5dev/public/include/memaddr.h +++ b/r5dev/public/include/memaddr.h @@ -106,8 +106,8 @@ public: bool CheckOpCodes(const vector vOpcodeArray) const; void Patch(vector vOpcodes) const; void PatchString(const string& svString) const; - CMemory FindPattern(const string& svPattern, const Direction searchDirect, const int opCodesToScan = 512, const ptrdiff_t occurence = 1) const; - CMemory FindPatternSelf(const string& svPattern, const Direction searchDirect, const int opCodesToScan = 512, const ptrdiff_t occurence = 1); + CMemory FindPattern(const string& svPattern, const Direction searchDirect = Direction::DOWN, const int opCodesToScan = 512, const ptrdiff_t occurence = 1) const; + CMemory FindPatternSelf(const string& svPattern, const Direction searchDirect = Direction::DOWN, const int opCodesToScan = 512, const ptrdiff_t occurence = 1); CMemory FollowNearCall(ptrdiff_t opcodeOffset = 0x1, ptrdiff_t nextInstructionOffset = 0x5) const; CMemory FollowNearCallSelf(ptrdiff_t opcodeOffset = 0x1, ptrdiff_t nextInstructionOffset = 0x5); CMemory ResolveRelativeAddress(ptrdiff_t registerOffset = 0x0, ptrdiff_t nextInstructionOffset = 0x4) const;