diff --git a/Client/game_sa/CModelInfoSA.h b/Client/game_sa/CModelInfoSA.h index 48c3b544f3..6f90a75591 100644 --- a/Client/game_sa/CModelInfoSA.h +++ b/Client/game_sa/CModelInfoSA.h @@ -46,6 +46,7 @@ static void* ARRAY_ModelInfo = *(void**)(0x403DA4 + 3); #define FUNC_CText_Get 0x6A0050 #define FUNC_GetBoundingBox 0x4082F0 +#define FUNC_AddRef 0x4C4BA0 #define FUNC_RemoveRef 0x4C4BB0 #define FUNC_IsBoatModel 0x4c5a70 #define FUNC_IsCarModel 0x4c5aa0 @@ -154,6 +155,9 @@ enum class eModelSpecialType : unsigned char class CBaseModelInfoSAInterface { public: + void AddRef() { ((void(__thiscall*)(CBaseModelInfoSAInterface*))FUNC_AddRef)(this); } + void RemoveRef() { ((void(__thiscall*)(CBaseModelInfoSAInterface*))FUNC_RemoveRef)(this); } + CBaseModelInfo_SA_VTBL* VFTBL; // +0 unsigned long ulHashKey; // +4 Generated by CKeyGen::GetUppercaseKey(char const *) called by CBaseModelInfo::SetModelName(char const *) diff --git a/Client/game_sa/CRendererSA.cpp b/Client/game_sa/CRendererSA.cpp index eed6fe73ff..f80b2d8a59 100644 --- a/Client/game_sa/CRendererSA.cpp +++ b/Client/game_sa/CRendererSA.cpp @@ -32,25 +32,17 @@ void CRendererSA::RenderModel(CModelInfo* pModelInfo, const CMatrix& matrix, flo if (!pModelInfoSAInterface) return; - // Prevent GC from freeing RwObject during rendering - pModelInfo->ModelAddRef(NON_BLOCKING, "CRendererSA::RenderModel"); - - // Revalidate interface after AddRef - pModelInfoSAInterface = pModelInfo->GetInterface(); - if (!pModelInfoSAInterface) - { - pModelInfo->RemoveRef(); - return; - } - - // Check and cache pRwObject RwObject* pRwObject = pModelInfoSAInterface->pRwObject; if (!pRwObject) - { - // Release reference before early return to prevent leak - pModelInfo->RemoveRef(); return; - } + + // Prevent GC from freeing RwObject/TXD during rendering by calling GTA's + // native CBaseModelInfo::AddRef/RemoveRef. These manage usNumberOfRefs and + // texture dictionary refs without going through MTA's ref-counting (which + // triggers Remove() when m_dwReferences drops to 0, unloading the model + // every frame for dxDrawModel3D models with no persistent MTA-side reference + // -- causing visible flickering). + pModelInfoSAInterface->AddRef(); RwFrame* pFrame = RpGetFrame(pRwObject); @@ -61,7 +53,6 @@ void CRendererSA::RenderModel(CModelInfo* pModelInfo, const CMatrix& matrix, flo rwMatrix.pos = (RwV3d&)matrix.vPos; RwFrameTransform(pFrame, &rwMatrix, rwCOMBINEREPLACE); - // Ensure reference released on exception try { // Setup ambient light multiplier @@ -83,9 +74,9 @@ void CRendererSA::RenderModel(CModelInfo* pModelInfo, const CMatrix& matrix, flo } catch (...) { - // Release reference on rendering exception - pModelInfo->RemoveRef(); + pModelInfoSAInterface->RemoveRef(); throw; - } // Release reference - allow GC - pModelInfo->RemoveRef(); + } + + pModelInfoSAInterface->RemoveRef(); }