diff --git a/r5dev/datacache/mdlcache.cpp b/r5dev/datacache/mdlcache.cpp index 2250e8c8..91936ca5 100644 --- a/r5dev/datacache/mdlcache.cpp +++ b/r5dev/datacache/mdlcache.cpp @@ -29,30 +29,10 @@ std::unordered_set<MDLHandle_t> g_vBadMDLHandles; studiohdr_t* CMDLCache::FindMDL(CMDLCache* cache, MDLHandle_t handle, void* a3) { studiodata_t* pStudioData = cache->GetStudioData(handle); - studiohdr_t* pStudioHdr; - if (pStudioData) + if (!pStudioData) { - if (pStudioData->m_MDLCache && - pStudioData->m_MDLCache != DC_INVALID_HANDLE) - { - studiohdr_t* pStudioHDR = **reinterpret_cast<studiohdr_t***>(pStudioData); - - if (!g_pMDLFallback->m_hErrorMDL && V_ComparePath(pStudioHDR->name, ERROR_MODEL)) - { - g_pMDLFallback->m_pErrorHDR = pStudioHDR; - g_pMDLFallback->m_hErrorMDL = handle; - } - else if (!g_pMDLFallback->m_hEmptyMDL && V_ComparePath(pStudioHDR->name, EMPTY_MODEL)) - { - g_pMDLFallback->m_pEmptyHDR = pStudioHDR; - g_pMDLFallback->m_hEmptyMDL = handle; - } - } - } - else - { - pStudioHdr = GetErrorModel(); + studiohdr_t* const pStudioHdr = GetErrorModel(); if (!IsKnownBadModel(handle)) { @@ -65,28 +45,54 @@ studiohdr_t* CMDLCache::FindMDL(CMDLCache* cache, MDLHandle_t handle, void* a3) return pStudioHdr; } - int nFlags = STUDIOHDR_FLAGS_NEEDS_DEFERRED_ADDITIVE | STUDIOHDR_FLAGS_OBSOLETE; + studiocache_t* studioCache = pStudioData->GetStudioCache(); + + // Store error and empty fallback models. + if (studioCache && studioCache != DC_INVALID_HANDLE) + { + studiohdr_t* const pStudioHDR = pStudioData->GetStudioCache()->GetStudioHdr(); + + if (pStudioHDR) + { + if (!g_pMDLFallback->m_hErrorMDL && V_ComparePath(pStudioHDR->name, ERROR_MODEL)) + { + g_pMDLFallback->m_pErrorHDR = pStudioHDR; + g_pMDLFallback->m_hErrorMDL = handle; + } + else if (!g_pMDLFallback->m_hEmptyMDL && V_ComparePath(pStudioHDR->name, EMPTY_MODEL)) + { + g_pMDLFallback->m_pEmptyHDR = pStudioHDR; + g_pMDLFallback->m_hEmptyMDL = handle; + } + } + } + + const int nFlags = STUDIOHDR_FLAGS_NEEDS_DEFERRED_ADDITIVE | STUDIOHDR_FLAGS_OBSOLETE; + if ((pStudioData->m_nFlags & nFlags)) { - void* pMDLCache = *reinterpret_cast<void**>(pStudioData); - if (pStudioData->m_MDLCache) + if (studioCache) { if (a3) { FindCachedMDL(cache, pStudioData, a3); - pMDLCache = *reinterpret_cast<void**>(pStudioData); + studioCache = pStudioData->m_pStudioCache; } - pStudioHdr = *reinterpret_cast<studiohdr_t**>(pMDLCache); + studiohdr_t* const pStudioHdr = studioCache->GetStudioHdr(); + if (pStudioHdr) return pStudioHdr; return FindUncachedMDL(cache, handle, pStudioData, a3); } - pMDLCache = pStudioData->m_pAnimData; - if (pMDLCache) + + studioanimcache_t* const animCache = pStudioData->m_pAnimCache; + + if (animCache) { - pStudioHdr = *reinterpret_cast<studiohdr_t**>(pMDLCache); + studiohdr_t* const pStudioHdr = animCache->GetStudioHdr(); + if (pStudioHdr) return pStudioHdr; } @@ -129,9 +135,9 @@ studiohdr_t* CMDLCache::FindUncachedMDL(CMDLCache* cache, MDLHandle_t handle, st AUTO_LOCK(pStudioData->m_Mutex); const char* szModelName = cache->GetModelName(handle); - size_t nFileNameLen = strlen(szModelName); + const size_t nFileNameLen = strlen(szModelName); - studiohdr_t* pStudioHdr; + studiohdr_t* pStudioHdr = nullptr; if (nFileNameLen < 5 || (Q_stricmp(&szModelName[nFileNameLen - 5], ".rmdl") != 0) && @@ -150,16 +156,16 @@ studiohdr_t* CMDLCache::FindUncachedMDL(CMDLCache* cache, MDLHandle_t handle, st return pStudioHdr; } - LOBYTE(pStudioData->m_nGuidLock) = 1; + pStudioData->m_bSearchingModelName = true; g_pRTech->StringToGuid(szModelName); - LOBYTE(pStudioData->m_nGuidLock) = 0; + pStudioData->m_bSearchingModelName = false; - if (!pStudioData->m_MDLCache) + if (!pStudioData->m_pStudioCache) { - studiohdr_t** pAnimData = (studiohdr_t**)pStudioData->m_pAnimData; - if (pAnimData) + studioanimcache_t* const animCache = pStudioData->GetAnimCache(); + if (animCache) { - pStudioHdr = *pAnimData; + pStudioHdr = animCache->GetStudioHdr(); } else { @@ -178,11 +184,11 @@ studiohdr_t* CMDLCache::FindUncachedMDL(CMDLCache* cache, MDLHandle_t handle, st else { FindCachedMDL(cache, pStudioData, a4); - DataCacheHandle_t dataHandle = pStudioData->m_MDLCache; + studiocache_t* const dataCache = pStudioData->GetStudioCache(); - if (dataHandle) + if (dataCache) { - if (dataHandle == DC_INVALID_HANDLE) + if (dataCache == DC_INVALID_HANDLE) { pStudioHdr = GetErrorModel(); if (!IsKnownBadModel(handle)) @@ -194,11 +200,12 @@ studiohdr_t* CMDLCache::FindUncachedMDL(CMDLCache* cache, MDLHandle_t handle, st } } else - pStudioHdr = *(studiohdr_t**)dataHandle; + pStudioHdr = dataCache->GetStudioHdr(); } else { pStudioHdr = GetErrorModel(); + if (!IsKnownBadModel(handle)) { if (!pStudioHdr) @@ -209,6 +216,7 @@ studiohdr_t* CMDLCache::FindUncachedMDL(CMDLCache* cache, MDLHandle_t handle, st } } + assert(pStudioHdr); return pStudioHdr; } @@ -218,30 +226,28 @@ studiohdr_t* CMDLCache::FindUncachedMDL(CMDLCache* cache, MDLHandle_t handle, st // handle - // Output : a pointer to the studiohdr_t object //----------------------------------------------------------------------------- -studiohdr_t* CMDLCache::GetStudioHDR(CMDLCache* cache, MDLHandle_t handle) +vcollide_t* CMDLCache::GetVCollide(CMDLCache* cache, MDLHandle_t handle) { - studiohdr_t* pStudioHdr = nullptr; // rax - if (!handle) { - pStudioHdr = GetErrorModel(); - if (!pStudioHdr) - Error(eDLL_T::ENGINE, EXIT_FAILURE, "Attempted to load model with no handle and \"%s\" couldn't be loaded.\n", ERROR_MODEL); - - return pStudioHdr; + Error(eDLL_T::ENGINE, NO_ERROR, "Attempted to get vcollide with no handle.\n"); + return nullptr; } - studiodata_t* pStudioData = cache->GetStudioData(handle); - DataCacheHandle_t dataCache = pStudioData->m_MDLCache; + const studiodata_t* const pStudioData = cache->GetStudioData(handle); + const studiocache_t* const dataCache = pStudioData->GetStudioCache(); - if (dataCache && - dataCache != DC_INVALID_HANDLE) + if (dataCache && dataCache != DC_INVALID_HANDLE) { - void* v4 = *(void**)(*((_QWORD*)dataCache + 1) + 24i64); - if (v4) - pStudioHdr = (studiohdr_t*)((char*)v4 + 0x10); + CStudioVCollide* const pVCollide = dataCache->GetPhysicsCache()->GetStudioVCollide(); + + if (pVCollide) + { + return pVCollide->GetVCollide(); + } } - return pStudioHdr; + + return nullptr; } //----------------------------------------------------------------------------- @@ -252,7 +258,7 @@ studiohdr_t* CMDLCache::GetStudioHDR(CMDLCache* cache, MDLHandle_t handle) //----------------------------------------------------------------------------- studiohwdata_t* CMDLCache::GetHardwareData(CMDLCache* cache, MDLHandle_t handle) { - studiodata_t* pStudioData = cache->GetStudioData(handle); + const studiodata_t* pStudioData = cache->GetStudioData(handle); if (!pStudioData) { @@ -264,21 +270,22 @@ studiohwdata_t* CMDLCache::GetHardwareData(CMDLCache* cache, MDLHandle_t handle) pStudioData = cache->GetStudioData(g_pMDLFallback->m_hErrorMDL); } - DataCacheHandle_t dataCache = pStudioData->m_MDLCache; + const studiocache_t* const dataCache = pStudioData->GetStudioCache(); if (dataCache) { if (dataCache == DC_INVALID_HANDLE) return nullptr; - void* pAnimData = (void*)*((_QWORD*)dataCache + 1); + studiophysicscache_t* const physicsCache = dataCache->GetPhysicsCache(); AcquireSRWLockExclusive(g_pMDLLock); - CStudioHWDataRef__SetFlags(reinterpret_cast<CStudioHWDataRef*>(pAnimData), 1i64); // !!! DECLARED INLINE IN < S3 !!! + CStudioHWDataRef__SetFlags(reinterpret_cast<CStudioHWDataRef*>(physicsCache), 1i64); // !!! DECLARED INLINE IN < S3 !!! ReleaseSRWLockExclusive(g_pMDLLock); } + if ((pStudioData->m_nFlags & STUDIODATA_FLAGS_STUDIOMESH_LOADED)) - return &pStudioData->m_pHardwareRef->m_HardwareData; + return pStudioData->GetHardwareDataRef()->GetHardwareData(); else return nullptr; } @@ -313,5 +320,5 @@ void VMDLCache::Detour(const bool bAttach) const DetourSetup(&CMDLCache__FindCachedMDL, &CMDLCache::FindCachedMDL, bAttach); DetourSetup(&CMDLCache__FindUncachedMDL, &CMDLCache::FindUncachedMDL, bAttach); DetourSetup(&CMDLCache__GetHardwareData, &CMDLCache::GetHardwareData, bAttach); - DetourSetup(&CMDLCache__GetStudioHDR, &CMDLCache::GetStudioHDR, bAttach); + DetourSetup(&CMDLCache__GetVCollide, &CMDLCache::GetVCollide, bAttach); } diff --git a/r5dev/datacache/mdlcache.h b/r5dev/datacache/mdlcache.h index e204bb49..cd22535a 100644 --- a/r5dev/datacache/mdlcache.h +++ b/r5dev/datacache/mdlcache.h @@ -2,17 +2,12 @@ #define MDLCACHE_H #include "tier0/threadtools.h" #include "tier1/utldict.h" +#include "tier1/refcount.h" #include "datacache/idatacache.h" #include "datacache/imdlcache.h" #include "public/studio.h" - -struct RStaticProp_t -{ - studiohdr_t* m_pStudioHDR{}; - CStudioHWDataRef* m_pHardWareData{}; - const char* m_szPropName{}; - uint8_t m_pUnknown[0x62]{}; -}; +#include "public/vphysics/vcollide.h" +#include "public/rtech/ipakfile.h" struct RMDLFallBack_t { @@ -39,11 +34,78 @@ struct RMDLFallBack_t } }; + +struct CStudioVCollide : public CRefCounted<> +{ +public: + //~CStudioVCollide() // TODO: add g_PhysicsCollision to SDK + //{ + // g_pPhysicsCollision->VCollideUnload(&m_vcollide); + //} + vcollide_t* GetVCollide() + { + return &m_vcollide; + } +private: + vcollide_t m_vcollide; +}; + +class CStudioPhysicsGeoms : public CRefCounted<> +{ + int unk1; + void* m_pGeomDataDesc; + int unk2; + __int16 unk3; + __int16 unk4; +}; + +struct studiophysicscache_t +{ + inline CStudioVCollide* GetStudioVCollide() const { return m_pVCollide; } + inline CStudioPhysicsGeoms* GetPhysicsGeoms() const { return m_pPhysicsGeoms; } + + int unk0; + int unk1; + int unk2; + int unk3; + int unk4; + int unk5; + CStudioVCollide* m_pVCollide; + CStudioPhysicsGeoms* m_pPhysicsGeoms; +}; + +struct studiocache_t +{ + inline studiohdr_t* GetStudioHdr() const { return m_pStudioHdr; } + inline studiophysicscache_t* GetPhysicsCache() const { return m_pPhysicsCache; } + + studiohdr_t* m_pStudioHdr; + studiophysicscache_t* m_pPhysicsCache; + const char* m_szPropName; + uint8_t m_pUnknown[98]; +}; + +struct studioanimcache_t +{ + inline studiohdr_t* GetStudioHdr() const { return m_pStudioHdr; } + + studiohdr_t* m_pStudioHdr; + const char* m_pszRigName; + int unk0; + int m_nSequenceCount; + void** m_pAnimSequences; + // TODO reverse the rest +}; + // only models with type "mod_studio" have this data struct studiodata_t { - DataCacheHandle_t m_MDLCache; - void* m_pAnimData; // !TODO: reverse struct. + inline studiocache_t* GetStudioCache() const { return m_pStudioCache; } + inline studioanimcache_t* GetAnimCache() const { return m_pAnimCache; } + inline CStudioHWDataRef* GetHardwareDataRef() const { return m_pHardwareRef; } + + studiocache_t* m_pStudioCache; + studioanimcache_t* m_pAnimCache; // !TODO: reverse struct. unsigned short m_nRefCount; unsigned short m_nFlags; MDLHandle_t m_Handle; @@ -53,7 +115,8 @@ struct studiodata_t int Unk5; char pad[72]; CThreadFastMutex m_Mutex; - int m_nGuidLock; // always -1, set to 1 and 0 in CMDLCache::FindUncachedMDL. + bool m_bSearchingModelName; + PakHandle_t m_PakHandle; }; extern RMDLFallBack_t* g_pMDLFallback; @@ -65,13 +128,14 @@ public: static studiohdr_t* FindMDL(CMDLCache* cache, MDLHandle_t handle, void* a3); 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 vcollide_t* GetVCollide(CMDLCache* cache, MDLHandle_t handle); static studiohwdata_t* GetHardwareData(CMDLCache* cache, MDLHandle_t handle); static studiohdr_t* GetErrorModel(void); static bool IsKnownBadModel(MDLHandle_t handle); - studiodata_t* GetStudioData(MDLHandle_t handle) + inline studiodata_t* GetStudioData(MDLHandle_t handle) { EnterCriticalSection(&m_MDLMutex); studiodata_t* pStudioData = m_MDLDict.Element(handle); @@ -80,7 +144,7 @@ public: return pStudioData; } - const char* GetModelName(MDLHandle_t handle) + inline const char* GetModelName(MDLHandle_t handle) { EnterCriticalSection(&m_MDLMutex); const char* szModelName = m_MDLDict.GetElementName(handle); @@ -89,7 +153,7 @@ public: return szModelName; } - void* GetMaterialTable(MDLHandle_t handle) + inline void* GetMaterialTable(MDLHandle_t handle) { EnterCriticalSection(&m_MDLMutex); studiodata_t* pStudioData = m_MDLDict.Element(handle); @@ -108,7 +172,7 @@ inline studiohdr_t*(*CMDLCache__FindMDL)(CMDLCache* pCache, MDLHandle_t handle, inline void(*CMDLCache__FindCachedMDL)(CMDLCache* pCache, studiodata_t* pStudioData, void* a3); inline studiohdr_t*(*CMDLCache__FindUncachedMDL)(CMDLCache* pCache, MDLHandle_t handle, studiodata_t* pStudioData, void* a4); -inline studiohdr_t*(*CMDLCache__GetStudioHDR)(CMDLCache* pCache, MDLHandle_t handle); +inline vcollide_t*(*CMDLCache__GetVCollide)(CMDLCache* pCache, MDLHandle_t handle); inline studiohwdata_t*(*CMDLCache__GetHardwareData)(CMDLCache* pCache, MDLHandle_t handle); inline bool(*CStudioHWDataRef__SetFlags)(CStudioHWDataRef* ref, int64_t flags); // Probably incorrect name. @@ -124,7 +188,7 @@ class VMDLCache : public IDetour LogFunAdr("CMDLCache::FindMDL", CMDLCache__FindMDL); LogFunAdr("CMDLCache::FindCachedMDL", CMDLCache__FindCachedMDL); LogFunAdr("CMDLCache::FindUncachedMDL", CMDLCache__FindUncachedMDL); - LogFunAdr("CMDLCache::GetStudioHDR", CMDLCache__GetStudioHDR); + LogFunAdr("CMDLCache::GetVCollide", CMDLCache__GetVCollide); LogFunAdr("CMDLCache::GetHardwareData", CMDLCache__GetHardwareData); LogFunAdr("CStudioHWDataRef::SetFlags", CStudioHWDataRef__SetFlags); @@ -136,7 +200,7 @@ class VMDLCache : public IDetour g_GameDll.FindPatternSIMD("48 89 5C 24 ?? 48 89 6C 24 ?? 48 89 74 24 ?? 57 48 83 EC 20 48 8B F1 0F B7 EA").GetPtr(CMDLCache__FindMDL); g_GameDll.FindPatternSIMD("4D 85 C0 74 7A 48 89 6C 24 ??").GetPtr(CMDLCache__FindCachedMDL); g_GameDll.FindPatternSIMD("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").GetPtr(CMDLCache__FindUncachedMDL); - g_GameDll.FindPatternSIMD("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").GetPtr(CMDLCache__GetStudioHDR); + g_GameDll.FindPatternSIMD("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").GetPtr(CMDLCache__GetVCollide); g_GameDll.FindPatternSIMD("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").GetPtr(CMDLCache__GetHardwareData); g_GameDll.FindPatternSIMD("48 83 EC 08 4C 8D 14 12").GetPtr(CStudioHWDataRef__SetFlags); } diff --git a/r5dev/public/datacache/idatacache.h b/r5dev/public/datacache/idatacache.h index 0ff683c2..2469ee7d 100644 --- a/r5dev/public/datacache/idatacache.h +++ b/r5dev/public/datacache/idatacache.h @@ -6,6 +6,6 @@ //--------------------------------------------------------- FORWARD_DECLARE_HANDLE(memhandle_t); typedef memhandle_t DataCacheHandle_t; -#define DC_INVALID_HANDLE ((DataCacheHandle_t)0xDEADFEEDDEADFEED) +#define DC_INVALID_HANDLE ((void*)0xDEADFEEDDEADFEED) #endif // IDATACACHE_H diff --git a/r5dev/public/studio.h b/r5dev/public/studio.h index e75146d3..e42bd03e 100644 --- a/r5dev/public/studio.h +++ b/r5dev/public/studio.h @@ -1066,14 +1066,17 @@ private: CMDLCache* m_pMDLCache; }; -class CStudioHWDataRef +template<class T> +class CStudioAssetEmbeddedRef : public CRefCounted<> +{ +protected: + T m_Embedded; +}; + +class CStudioHWDataRef : public CStudioAssetEmbeddedRef<studiohwdata_t> { public: - bool IsDataRef(void) const { return true; } - - CStudioHWDataRef* m_pVTable; - uint8_t pad0[0x8]; - studiohwdata_t m_HardwareData; + studiohwdata_t* GetHardwareData() { return &m_Embedded; } }; #endif // STUDIO_H