CMDLCache code improvements

Slightly mapped out the CMDLCache class, to the point the pointers to its members are no longer needed. Also fixed a bug were the studiodata pointer was dereferenced before checking if its not null, this check did exist, but was performed too late. Fully implemented the CUtlDict class for m_MDLDict. Slightly optimized the initialization of the error model handles.
This commit is contained in:
Kawe Mazidjatari 2023-06-19 13:53:56 +02:00
parent 2cfed900d0
commit abe68def03
5 changed files with 87 additions and 82 deletions

View File

@ -29,25 +29,31 @@ std::unordered_set<MDLHandle_t> g_vBadMDLHandles;
studiohdr_t* CMDLCache::FindMDL(CMDLCache* cache, MDLHandle_t handle, void* a3)
{
studiohdr_t* pStudioHdr; // rax
studiodata_t* pStudioData = cache->GetStudioData(handle);
EnterCriticalSection(reinterpret_cast<LPCRITICAL_SECTION>(&*m_MDLMutex));
studiodata_t* pStudioData = m_MDLDict->Find(handle);
LeaveCriticalSection(reinterpret_cast<LPCRITICAL_SECTION>(&*m_MDLMutex));
if (!g_pMDLFallback->m_hErrorMDL || !g_pMDLFallback->m_hEmptyMDL)
if (pStudioData)
{
if (pStudioData->m_MDLCache)
{
studiohdr_t* pStudioHDR = **reinterpret_cast<studiohdr_t***>(pStudioData);
if (pStudioHDR)
if (!g_pMDLFallback->m_hErrorMDL)
{
const string svStudio = ConvertToUnixPath(pStudioHDR->name);
if (svStudio.compare(ERROR_MODEL) == NULL)
CUtlString studioPathFixed(pStudioHDR->name);
studioPathFixed.FixSlashes(INCORRECT_PATH_SEPARATOR);
if (studioPathFixed.IsEqual_CaseInsensitive(ERROR_MODEL))
{
g_pMDLFallback->m_pErrorHDR = pStudioHDR;
g_pMDLFallback->m_hErrorMDL = handle;
}
else if (svStudio.compare(EMPTY_MODEL) == NULL)
}
else if (!g_pMDLFallback->m_hEmptyMDL)
{
CUtlString studioPathFixed(pStudioHDR->name);
studioPathFixed.FixSlashes(INCORRECT_PATH_SEPARATOR);
if (studioPathFixed.IsEqual_CaseInsensitive(EMPTY_MODEL))
{
g_pMDLFallback->m_pEmptyHDR = pStudioHDR;
g_pMDLFallback->m_hEmptyMDL = handle;
@ -55,8 +61,7 @@ studiohdr_t* CMDLCache::FindMDL(CMDLCache* cache, MDLHandle_t handle, void* a3)
}
}
}
if (!pStudioData)
else
{
pStudioHdr = GetErrorModel();
@ -136,27 +141,20 @@ studiohdr_t* CMDLCache::FindUncachedMDL(CMDLCache* cache, MDLHandle_t handle, st
studiohdr_t** ppStudioHdr; // rax
pStudioData->m_Mutex.WaitForLock();
const char* szModelName = cache->GetModelName(handle);
EnterCriticalSection(reinterpret_cast<LPCRITICAL_SECTION>(&*m_MDLMutex));
void* pModelCache = cache->m_pModelCacheSection;
char* szModelName = (char*)(*(_QWORD*)((int64)pModelCache + 24 * static_cast<int64>(handle) + 8));
LeaveCriticalSection(reinterpret_cast<LPCRITICAL_SECTION>(&*m_MDLMutex));
if (IsBadReadPtrV2(reinterpret_cast<void*>(szModelName)))
pStudioHdr = GetErrorModel();
if (!IsKnownBadModel(handle))
{
pStudioHdr = GetErrorModel();
if (!IsKnownBadModel(handle))
{
if (!pStudioHdr)
Error(eDLL_T::ENGINE, EXIT_FAILURE, "Model with handle \"%hu\" not found and \"%s\" couldn't be loaded.\n", handle, ERROR_MODEL);
else
Error(eDLL_T::ENGINE, NO_ERROR, "Model with handle \"%hu\" not found; replacing with \"%s\".\n", handle, ERROR_MODEL);
}
pStudioData->m_Mutex.ReleaseWaiter();
return pStudioHdr;
if (!pStudioHdr)
Error(eDLL_T::ENGINE, EXIT_FAILURE, "Model with handle \"%hu\" not found and \"%s\" couldn't be loaded.\n", handle, ERROR_MODEL);
else
Error(eDLL_T::ENGINE, NO_ERROR, "Model with handle \"%hu\" not found; replacing with \"%s\".\n", handle, ERROR_MODEL);
}
pStudioData->m_Mutex.ReleaseWaiter();
return pStudioHdr;
size_t nFileNameLen = strlen(szModelName);
if (nFileNameLen < 5 ||
@ -208,7 +206,7 @@ studiohdr_t* CMDLCache::FindUncachedMDL(CMDLCache* cache, MDLHandle_t handle, st
FindCachedMDL(cache, pStudioData, a4);
if ((__int64)*(studiohdr_t**)pStudioData)
{
if ((__int64)*(studiohdr_t**)pStudioData == 0xDEADFEEDDEADFEED)
if ((DataCacheHandle_t)*(studiohdr_t**)pStudioData == DC_INVALID_HANDLE)
{
pStudioHdr = GetErrorModel();
if (!IsKnownBadModel(handle))
@ -244,7 +242,7 @@ studiohdr_t* CMDLCache::FindUncachedMDL(CMDLCache* cache, MDLHandle_t handle, st
// handle -
// Output : a pointer to the studiohdr_t object
//-----------------------------------------------------------------------------
studiohdr_t* CMDLCache::GetStudioHDR(CMDLCache* pMDLCache, MDLHandle_t handle)
studiohdr_t* CMDLCache::GetStudioHDR(CMDLCache* cache, MDLHandle_t handle)
{
studiohdr_t* pStudioHdr = nullptr; // rax
@ -257,12 +255,11 @@ studiohdr_t* CMDLCache::GetStudioHDR(CMDLCache* pMDLCache, MDLHandle_t handle)
return pStudioHdr;
}
EnterCriticalSection(reinterpret_cast<LPCRITICAL_SECTION>(&*m_MDLMutex));
studiodata_t* pStudioData = m_MDLDict->Find(handle);
LeaveCriticalSection(reinterpret_cast<LPCRITICAL_SECTION>(&*m_MDLMutex));
studiodata_t* pStudioData = cache->GetStudioData(handle);
if (*(_QWORD*)(pStudioData))
{
if (reinterpret_cast<int64_t>(pStudioData->m_MDLCache) != 0xDEADFEEDDEADFEED)
if (pStudioData->m_MDLCache != DC_INVALID_HANDLE)
{
void* v4 = *(void**)(*((_QWORD*)pStudioData->m_MDLCache + 1) + 24i64);
if (v4)
@ -280,9 +277,7 @@ studiohdr_t* CMDLCache::GetStudioHDR(CMDLCache* pMDLCache, MDLHandle_t handle)
//-----------------------------------------------------------------------------
studiohwdata_t* CMDLCache::GetHardwareData(CMDLCache* cache, MDLHandle_t handle)
{
EnterCriticalSection(reinterpret_cast<LPCRITICAL_SECTION>(&*m_MDLMutex));
studiodata_t* pStudioData = m_MDLDict->Find(handle);
LeaveCriticalSection(reinterpret_cast<LPCRITICAL_SECTION>(&*m_MDLMutex));
studiodata_t* pStudioData = cache->GetStudioData(handle);
if (!pStudioData)
{
@ -291,21 +286,21 @@ studiohwdata_t* CMDLCache::GetHardwareData(CMDLCache* cache, MDLHandle_t handle)
Error(eDLL_T::ENGINE, EXIT_FAILURE, "Studio hardware with handle \"%hu\" not found and \"%s\" couldn't be loaded.\n", handle, ERROR_MODEL);
return nullptr;
}
pStudioData = m_MDLDict->Find(g_pMDLFallback->m_hErrorMDL);
pStudioData = cache->GetStudioData(g_pMDLFallback->m_hErrorMDL);
}
if (pStudioData->m_MDLCache)
{
if (reinterpret_cast<int64_t>(pStudioData->m_MDLCache) == 0xDEADFEEDDEADFEED)
if (pStudioData->m_MDLCache == DC_INVALID_HANDLE)
return nullptr;
void* pAnimData = (void*)*((_QWORD*)pStudioData->m_MDLCache + 1);
AcquireSRWLockExclusive(reinterpret_cast<PSRWLOCK>(&*m_MDLLock));
AcquireSRWLockExclusive(reinterpret_cast<PSRWLOCK>(&*g_pMDLLock));
#if !defined (GAMEDLL_S0) && !defined (GAMEDLL_S1) && !defined (GAMEDLL_S2)
v_CStudioHWDataRef__SetFlags(reinterpret_cast<CStudioHWDataRef*>(pAnimData), 1i64); // !!! DECLARED INLINE IN < S3 !!!
#endif
ReleaseSRWLockExclusive(reinterpret_cast<PSRWLOCK>(&*m_MDLLock));
ReleaseSRWLockExclusive(reinterpret_cast<PSRWLOCK>(&*g_pMDLLock));
}
if ((pStudioData->m_nFlags & STUDIODATA_FLAGS_STUDIOMESH_LOADED))
return &pStudioData->m_pHardwareRef->m_HardwareData;
@ -313,21 +308,6 @@ studiohwdata_t* CMDLCache::GetHardwareData(CMDLCache* cache, MDLHandle_t handle)
return nullptr;
}
//-----------------------------------------------------------------------------
// Purpose: gets the studio material glue from cache pool by handle
// Input : *this -
// handle -
// Output : a pointer to the CMaterialGlue object
//-----------------------------------------------------------------------------
void* CMDLCache::GetMaterialTable(CMDLCache* cache, MDLHandle_t handle)
{
EnterCriticalSection(reinterpret_cast<LPCRITICAL_SECTION>(&*m_MDLMutex));
studiodata_t* pStudioData = m_MDLDict->Find(handle);
LeaveCriticalSection(reinterpret_cast<LPCRITICAL_SECTION>(&*m_MDLMutex));
return &pStudioData->m_pMaterialTable;
}
//-----------------------------------------------------------------------------
// Purpose: gets the error model
// Output : *studiohdr_t

View File

@ -63,7 +63,7 @@ struct studiodata_t
extern RMDLFallBack_t* g_pMDLFallback;
extern std::unordered_set<MDLHandle_t> g_vBadMDLHandles;
class CMDLCache
class CMDLCache : public IMDLCache
{
public:
static studiohdr_t* FindMDL(CMDLCache* cache, MDLHandle_t handle, void* a3);
@ -71,15 +71,41 @@ public:
static studiohdr_t* FindUncachedMDL(CMDLCache* cache, MDLHandle_t handle, studiodata_t* pStudioData, void* a4);
static studiohdr_t* GetStudioHDR(CMDLCache* cache, MDLHandle_t handle);
static studiohwdata_t* GetHardwareData(CMDLCache* cache, MDLHandle_t handle);
static void* GetMaterialTable(CMDLCache* cache, MDLHandle_t handle);
static studiohdr_t* GetErrorModel(void);
static bool IsKnownBadModel(MDLHandle_t handle);
CMDLCache* m_pVTable;
void* m_pStrCmp; // string compare func;
void* m_pModelCacheSection; // IDataCacheSection*
int m_nModelCacheFrameLocks; //
// TODO..
studiodata_t* GetStudioData(MDLHandle_t handle)
{
EnterCriticalSection(reinterpret_cast<LPCRITICAL_SECTION>(&m_MDLMutex));
studiodata_t* pStudioData = m_MDLDict.Element(handle);
LeaveCriticalSection(reinterpret_cast<LPCRITICAL_SECTION>(&m_MDLMutex));
return pStudioData;
}
const char* GetModelName(MDLHandle_t handle)
{
EnterCriticalSection(reinterpret_cast<LPCRITICAL_SECTION>(&m_MDLMutex));
const char* szModelName = m_MDLDict.GetElementName(handle);
LeaveCriticalSection(reinterpret_cast<LPCRITICAL_SECTION>(&m_MDLMutex));
return szModelName;
}
void* GetMaterialTable(MDLHandle_t handle)
{
EnterCriticalSection(reinterpret_cast<LPCRITICAL_SECTION>(&m_MDLMutex));
studiodata_t* pStudioData = m_MDLDict.Element(handle);
LeaveCriticalSection(reinterpret_cast<LPCRITICAL_SECTION>(&m_MDLMutex));
return &pStudioData->m_pMaterialTable;
}
private:
CUtlDict<studiodata_t*, MDLHandle_t> m_MDLDict;
LPCRITICAL_SECTION m_MDLMutex;
// !TODO: reverse the rest
};
inline CMemory p_CMDLCache__FindMDL;
@ -100,10 +126,8 @@ inline auto v_CMDLCache__GetHardwareData = p_CMDLCache__GetHardwareData.RCast<st
inline CMemory p_CStudioHWDataRef__SetFlags; // Probably incorrect.
inline auto v_CStudioHWDataRef__SetFlags = p_CStudioHWDataRef__SetFlags.RCast<bool (*)(CStudioHWDataRef* ref, int64_t flags)>();
#endif
inline CUtlDict<studiodata_t*, MDLHandle_t>* m_MDLDict;
inline LPCRITICAL_SECTION* m_MDLMutex = nullptr;
inline PSRWLOCK* m_MDLLock = nullptr;
inline CMDLCache* g_MDLCache = nullptr;
inline CMDLCache* g_pMDLCache = nullptr;
inline PSRWLOCK* g_pMDLLock = nullptr; // Possibly a member? research required.
///////////////////////////////////////////////////////////////////////////////
class VMDLCache : public IDetour
@ -120,10 +144,8 @@ class VMDLCache : public IDetour
#if !defined (GAMEDLL_S0) && !defined (GAMEDLL_S1) && !defined (GAMEDLL_S2)
LogFunAdr("CStudioHWDataRef::SetFlags", p_CStudioHWDataRef__SetFlags.GetPtr());
#endif
LogVarAdr("m_MDLMutex", reinterpret_cast<uintptr_t>(m_MDLMutex));
LogVarAdr("m_MDLLock", reinterpret_cast<uintptr_t>(m_MDLLock));
LogVarAdr("m_MDLDict", reinterpret_cast<uintptr_t>(m_MDLDict));
LogVarAdr("g_MDLCache", reinterpret_cast<uintptr_t>(g_MDLCache));
LogVarAdr("g_MDLCache", reinterpret_cast<uintptr_t>(g_pMDLCache));
LogVarAdr("g_MDLLock", reinterpret_cast<uintptr_t>(g_pMDLLock));
}
virtual void GetFun(void) const
{
@ -163,15 +185,11 @@ class VMDLCache : public IDetour
}
virtual void GetVar(void) const
{
m_MDLMutex = g_GameDll.FindPatternSIMD("48 83 EC 28 BA ?? ?? ?? ?? 48 8D 0D ?? ?? ?? ?? FF 15 ?? ?? ?? ?? 0F B6 05 ?? ?? ?? ??")
.FindPatternSelf("48 8D 0D").ResolveRelativeAddressSelf(0x3, 0x7).RCast<LPCRITICAL_SECTION*>();
// Get MDLCache singleton from CStudioRenderContext::Connect
g_pMDLCache = g_GameDll.FindPatternSIMD("48 83 EC 28 48 8B 05 ?? ?? ?? ?? 48 8D 0D ?? ?? ?? ?? 48 85 C0 48 0F 45 C8 FF 05 ?? ?? ?? ?? 48 83 3D ?? ?? ?? ?? ?? 48 8D 05 ?? ?? ?? ??")
.FindPatternSelf("48 8D 05").ResolveRelativeAddressSelf(0x3, 0x7).RCast<CMDLCache*>();
m_MDLLock = p_CMDLCache__GetHardwareData.Offset(0x35).FindPatternSelf("48 8D 0D").ResolveRelativeAddressSelf(0x3, 0x7).RCast<PSRWLOCK*>();
m_MDLDict = p_CMDLCache__FindMDL.FindPattern("48 8B 05").ResolveRelativeAddressSelf(0x3, 0x7).RCast<CUtlDict<studiodata_t*, MDLHandle_t>*>();
g_MDLCache = g_GameDll.FindPatternSIMD("48 8B 0D ?? ?? ?? ?? 44 0F B7 82 ?? ?? ?? ?? 48 8B 01 48 FF A0")
.ResolveRelativeAddressSelf(0x3, 0x7).RCast<CMDLCache*>();
g_pMDLLock = p_CMDLCache__GetHardwareData.Offset(0x35).FindPatternSelf("48 8D 0D").ResolveRelativeAddressSelf(0x3, 0x7).RCast<PSRWLOCK*>();
}
virtual void GetCon(void) const { }
virtual void Attach(void) const;

View File

@ -8,12 +8,12 @@
void* __fastcall CStaticProp_Init(int64_t thisptr, int64_t a2, unsigned int idx, unsigned int a4, StaticPropLump_t* lump, int64_t a6, int64_t a7)
{
MDLHandle_t handle = *reinterpret_cast<uint16_t*>(a7 + 0x140);
studiohdr_t* pStudioHdr = g_MDLCache->FindMDL(g_MDLCache, handle, nullptr);
studiohdr_t* pStudioHdr = g_pMDLCache->FindMDL(g_pMDLCache, handle, nullptr);
if (lump->m_Skin >= pStudioHdr->numskinfamilies)
{
Error(eDLL_T::ENGINE, NO_ERROR,
"Invalid skin index for static prop %i with model '%s' (got %i, max %i)\n",
"Invalid skin index for static prop #%i with model '%s' (got %i, max %i)\n",
idx, pStudioHdr->name, lump->m_Skin, pStudioHdr->numskinfamilies-1);
lump->m_Skin = 0;

View File

@ -6,6 +6,6 @@
//---------------------------------------------------------
FORWARD_DECLARE_HANDLE(memhandle_t);
typedef memhandle_t DataCacheHandle_t;
#define DC_INVALID_HANDLE ((DataCacheHandle_t)0)
#define DC_INVALID_HANDLE ((DataCacheHandle_t)0xDEADFEEDDEADFEED)
#endif // IDATACACHE_H

View File

@ -43,4 +43,11 @@ enum MDLCacheDataType_t
MDLCACHE_VERTEXES,
MDLCACHE_DECODEDANIMBLOCK
};
abstract_class IMDLCache : public IAppSystem
{
// !TODO: map this out.
};
#endif // !IMDLCACHE_H