From 72289f9f334281c36d74b4930a58ed356b4ccbd5 Mon Sep 17 00:00:00 2001 From: Kawe Mazidjatari <48657826+Mauler125@users.noreply.github.com> Date: Fri, 6 May 2022 00:51:49 +0200 Subject: [PATCH] CMDLCache::GetStudioHardware improvements Slightly mapped out the structure more. The function should now be compatible with earlier game dll's. CStudioHWDataRef::SetFlags has to be rebuild as these are declared inline for earlier game dll's. --- r5dev/datacache/idatacache.h | 11 +++++++++ r5dev/datacache/mdlcache.cpp | 41 ++++++++++++++++---------------- r5dev/datacache/mdlcache.h | 37 +++++++++++++++-------------- r5dev/public/include/studio.h | 44 ++++++++++++++++++++++++++++++++++- r5dev/tier0/basetypes.h | 2 ++ 5 files changed, 95 insertions(+), 40 deletions(-) create mode 100644 r5dev/datacache/idatacache.h diff --git a/r5dev/datacache/idatacache.h b/r5dev/datacache/idatacache.h new file mode 100644 index 00000000..1e0f372b --- /dev/null +++ b/r5dev/datacache/idatacache.h @@ -0,0 +1,11 @@ +#ifndef IDATACACHE_H +#define IDATACACHE_H + +//--------------------------------------------------------- +// Cache-defined handle for a cache item +//--------------------------------------------------------- +FORWARD_DECLARE_HANDLE(memhandle_t); +typedef memhandle_t DataCacheHandle_t; +#define DC_INVALID_HANDLE ((DataCacheHandle_t)0) + +#endif // IDATACACHE_H diff --git a/r5dev/datacache/mdlcache.cpp b/r5dev/datacache/mdlcache.cpp index cdbf830c..e0e2607a 100644 --- a/r5dev/datacache/mdlcache.cpp +++ b/r5dev/datacache/mdlcache.cpp @@ -10,6 +10,7 @@ #include "tier1/cvar.h" #include "datacache/mdlcache.h" #include "datacache/imdlcache.h" +#include "datacache/idatacache.h" #include "engine/sys_utils.h" #include "rtech/rtech_utils.h" #include "public/include/studio.h" @@ -238,48 +239,46 @@ studiohdr_t* CMDLCache::GetStudioHDR(CMDLCache* pMDLCache, MDLHandle_t handle) } //----------------------------------------------------------------------------- -// Purpose: gets the studio hardware data reference from cache pool by handle +// Purpose: gets the studio hardware data from cache pool by handle // Input : *this - // handle - -// Output : a pointer to the CStudioHWDataRef object +// Output : a pointer to the studiohwdata_t object //----------------------------------------------------------------------------- -CStudioHWDataRef* CMDLCache::GetStudioHardwareRef(CMDLCache* cache, MDLHandle_t handle) +studiohwdata_t* CMDLCache::GetStudioHardware(CMDLCache* cache, MDLHandle_t handle) { - __int64 v2; // rbx - __int64 v3; // rdi - __int64 v4; // rbx - __int64 result; // rax + studiodata_t* pStudioData; // rdi + void* pAnimData; // rbx + studiohwdata_t* result; // rax - v2 = handle; EnterCriticalSection(reinterpret_cast(&*m_MDLMutex)); - v3 = *(_QWORD*)(m_MDLDict.Deref().GetPtr() + 24 * v2 + 16); + pStudioData = *(studiodata_t**)(m_MDLDict.Deref().GetPtr() + 24 * static_cast(handle) + 16); LeaveCriticalSection(reinterpret_cast(&*m_MDLMutex)); - if (!v3) + if (!pStudioData) { if (!g_pMDLFallback->m_hErrorMDL) { Error(eDLL_T::ENGINE, "Studio hardware with handle \"%hu\" not found and \"%s\" couldn't be loaded.\n", handle, ERROR_MODEL); return nullptr; } - v3 = *(_QWORD*)(m_MDLDict.Deref().GetPtr() + 24i64 * g_pMDLFallback->m_hErrorMDL + 16); + pStudioData = *(studiodata_t**)(m_MDLDict.Deref().GetPtr() + 24i64 * g_pMDLFallback->m_hErrorMDL + 16); } - if (*(_QWORD*)v3) + if (pStudioData->m_MDLCache) { - if (*(_QWORD*)v3 == 0xDEADFEEDDEADFEED) + if (reinterpret_cast(pStudioData->m_MDLCache) == 0xDEADFEEDDEADFEED) return nullptr; - v4 = *(_QWORD*)(*(_QWORD*)v3 + 8i64); + pAnimData = (void*)*((_QWORD*)pStudioData->m_MDLCache + 1); AcquireSRWLockExclusive(reinterpret_cast(&*m_MDLLock)); - v_CStudioHWDataRef__SetFlags(reinterpret_cast(v4), 1i64); // !!! DECLARED INLINE IN < S3 !!! + v_CStudioHWDataRef__SetFlags(reinterpret_cast(pAnimData), 1i64); // !!! DECLARED INLINE IN < S3 !!! ReleaseSRWLockExclusive(reinterpret_cast(&*m_MDLLock)); } - if ((*(_BYTE*)(v3 + 18) & 1) != 0) - result = *(_QWORD*)(v3 + 0x20) + 16i64; + if ((pStudioData->m_nFlags & STUDIODATA_FLAGS_STUDIOMESH_LOADED)) + result = &pStudioData->m_pHardwareRef->m_HardwareData; else - result = 0i64; - return reinterpret_cast(result); + result = nullptr; + return result; } //----------------------------------------------------------------------------- @@ -305,7 +304,7 @@ void MDLCache_Attach() DetourAttach((LPVOID*)&v_CMDLCache__FindMDL, &CMDLCache::FindMDL); DetourAttach((LPVOID*)&v_CMDLCache__FindCachedMDL, &CMDLCache::FindCachedMDL); DetourAttach((LPVOID*)&v_CMDLCache__FindUncachedMDL, &CMDLCache::FindUncachedMDL); - DetourAttach((LPVOID*)&v_CMDLCache__GetStudioHardwareRef, &CMDLCache::GetStudioHardwareRef); + DetourAttach((LPVOID*)&v_CMDLCache__GetStudioHardware, &CMDLCache::GetStudioHardware); DetourAttach((LPVOID*)&v_CMDLCache__GetStudioHDR, &CMDLCache::GetStudioHDR); } @@ -314,6 +313,6 @@ void MDLCache_Detach() DetourDetach((LPVOID*)&v_CMDLCache__FindMDL, &CMDLCache::FindMDL); DetourDetach((LPVOID*)&v_CMDLCache__FindCachedMDL, &CMDLCache::FindCachedMDL); DetourDetach((LPVOID*)&v_CMDLCache__FindUncachedMDL, &CMDLCache::FindUncachedMDL); - DetourDetach((LPVOID*)&v_CMDLCache__GetStudioHardwareRef, &CMDLCache::GetStudioHardwareRef); + DetourDetach((LPVOID*)&v_CMDLCache__GetStudioHardware, &CMDLCache::GetStudioHardware); 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 670448de..0a7555d8 100644 --- a/r5dev/datacache/mdlcache.h +++ b/r5dev/datacache/mdlcache.h @@ -1,6 +1,7 @@ #ifndef MDLCACHE_H #define MDLCACHE_H #include "public/include/studio.h" +#include "datacache/idatacache.h" #include "datacache/imdlcache.h" #include "tier0/threadtools.h" @@ -32,7 +33,7 @@ struct CMDLFallBack // only models with type "mod_studio" have this data struct studiodata_t { - void* m_MDLCache; + DataCacheHandle_t m_MDLCache; void* m_pAnimData; // !TODO: reverse struct. unsigned short m_nRefCount; unsigned short m_nFlags; @@ -42,7 +43,7 @@ struct studiodata_t void* Unk2; // TODO: unverified! #endif // !GAMEDLL_S3 void* Unk3; // ptr to flags and model string. - CStudioHWDataRef* m_HardwareData; + CStudioHWDataRef* m_pHardwareRef; void* Unk4; // contains material stuff (CMaterialGlue). int Unk5; char pad[72]; @@ -60,7 +61,7 @@ public: static void FindCachedMDL(CMDLCache* cache, studiodata_t* pStudioData, void* a3); static studiohdr_t* FindUncachedMDL(CMDLCache* cache, MDLHandle_t handle, studiodata_t* pStudioData, void* a4); static studiohdr_t* GetStudioHDR(CMDLCache* cache, MDLHandle_t handle); - static CStudioHWDataRef* GetStudioHardwareRef(CMDLCache* cache, MDLHandle_t handle); + static studiohwdata_t* GetStudioHardware(CMDLCache* cache, MDLHandle_t handle); static void* GetStudioMaterialGlue(CMDLCache* cache, MDLHandle_t handle); CMDLCache* m_pVTable; @@ -82,8 +83,8 @@ inline auto v_CMDLCache__FindUncachedMDL = p_CMDLCache__FindUncachedMDL.RCast(); -inline CMemory p_CMDLCache__GetStudioHardwareRef; -inline auto v_CMDLCache__GetStudioHardwareRef = p_CMDLCache__GetStudioHardwareRef.RCast(); +inline CMemory p_CMDLCache__GetStudioHardware; +inline auto v_CMDLCache__GetStudioHardware = p_CMDLCache__GetStudioHardware.RCast(); inline CMemory p_CStudioHWDataRef__SetFlags; // Probably incorrect. inline auto v_CStudioHWDataRef__SetFlags = p_CStudioHWDataRef__SetFlags.RCast(); @@ -101,16 +102,16 @@ class HMDLCache : public IDetour { virtual void GetAdr(void) const { - 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::GetStudioHardwareRef : 0x" << std::hex << std::uppercase << p_CMDLCache__GetStudioHardwareRef.GetPtr() << std::setw(nPad) << " |" << std::endl; - std::cout << "| FUN: CStudioHWDataRef::SetFlags : 0x" << std::hex << std::uppercase << p_CStudioHWDataRef__SetFlags.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 << "| 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::GetStudioHardware : 0x" << std::hex << std::uppercase << p_CMDLCache__GetStudioHardware.GetPtr() << std::setw(nPad) << " |" << std::endl; + std::cout << "| FUN: CStudioHWDataRef::SetFlags : 0x" << std::hex << std::uppercase << p_CStudioHWDataRef__SetFlags.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; } virtual void GetFun(void) const @@ -127,8 +128,8 @@ class HMDLCache : public IDetour 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_CMDLCache__GetStudioHardware = 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__GetStudioHardware = p_CMDLCache__GetStudioHardware.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*/ @@ -138,7 +139,7 @@ class HMDLCache : public IDetour 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").ResolveRelativeAddressSelf(0x3, 0x7).RCast(); - m_MDLLock = p_CMDLCache__GetStudioHardwareRef.Offset(0x35).FindPatternSelf("48 8D 0D").ResolveRelativeAddressSelf(0x3, 0x7).RCast(); + m_MDLLock = p_CMDLCache__GetStudioHardware.Offset(0x35).FindPatternSelf("48 8D 0D").ResolveRelativeAddressSelf(0x3, 0x7).RCast(); m_MDLDict = p_CMDLCache__FindMDL.FindPattern("48 8B 05").ResolveRelativeAddressSelf(0x3, 0x7); diff --git a/r5dev/public/include/studio.h b/r5dev/public/include/studio.h index 6bbe0d5d..58b7c6c1 100644 --- a/r5dev/public/include/studio.h +++ b/r5dev/public/include/studio.h @@ -102,6 +102,23 @@ // models when we change materials. #define STUDIOHDR_BAKED_VERTEX_LIGHTING_IS_INDIRECT_ONLY ( 1 << 27 ) +enum +{ + STUDIODATA_FLAGS_STUDIOMESH_LOADED = 0x0001, + STUDIODATA_FLAGS_VCOLLISION_LOADED = 0x0002, + STUDIODATA_ERROR_MODEL = 0x0004, + STUDIODATA_FLAGS_NO_STUDIOMESH = 0x0008, + STUDIODATA_FLAGS_NO_VERTEX_DATA = 0x0010, + // = 0x0020, // unused + STUDIODATA_FLAGS_PHYSICS2COLLISION_LOADED = 0x0040, + STUDIODATA_FLAGS_VCOLLISION_SCANNED = 0x0080, + + STUDIODATA_FLAGS_COMBINED_PLACEHOLDER = 0x0100, + STUDIODATA_FLAGS_COMBINED = 0x0200, + STUDIODATA_FLAGS_COMBINED_UNAVAILABLE = 0x0400, + STUDIODATA_FLAGS_COMBINED_ASSET = 0x0800, +}; + #pragma pack(push, 1) struct studiohdr_t { @@ -170,6 +187,28 @@ struct studiohdr_t }; #pragma pack(pop) +// studio model data +struct studiomeshdata_t +{ + int m_NumGroup; + void* m_pMeshGroup; // studiomeshgroup_t +}; + +struct studioloddata_t +{ + studiomeshdata_t* m_pMeshData; + // !TODO: +}; + +struct studiohwdata_t +{ + int m_RootLOD; // calced and clamped, nonzero for lod culling + int m_NumLODs; + studioloddata_t* m_pLODs; + int m_NumStudioMeshes; + // !TODO: +}; + class CStudioHdr { public: @@ -185,7 +224,10 @@ class CStudioHWDataRef { public: bool IsDataRef(void) const { return true; } - uint8_t m_pUnknown[0x90]{}; + + CStudioHWDataRef* m_pVTable; + uint8_t pad0[0x8]; + studiohwdata_t m_HardwareData; }; #endif // STUDIO_H diff --git a/r5dev/tier0/basetypes.h b/r5dev/tier0/basetypes.h index f1ca6e81..dcbda55a 100644 --- a/r5dev/tier0/basetypes.h +++ b/r5dev/tier0/basetypes.h @@ -35,6 +35,8 @@ #define MAX( a, b ) ( ( ( a ) > ( b ) ) ? ( a ) : ( b ) ) #endif +#define FORWARD_DECLARE_HANDLE(name) typedef struct name##__ *name + struct vrect_t { int x, y, width, height;