diff --git a/SilentPatchSA/ModelInfoSA.cpp b/SilentPatchSA/ModelInfoSA.cpp index 1e2b563..85400a2 100644 --- a/SilentPatchSA/ModelInfoSA.cpp +++ b/SilentPatchSA/ModelInfoSA.cpp @@ -1,6 +1,8 @@ #include "StdAfxSA.h" #include "ModelInfoSA.h" +#include + static void* BaseModelInfoShutdown = AddressByVersion(0x4C4D50, 0x4C4DD0, 0x4CF590); WRAPPER void CBaseModelInfo::Shutdown() { VARJMP(BaseModelInfoShutdown); } @@ -12,17 +14,32 @@ void (*CCustomCarPlateMgr::SetupMaterialPlatebackTexture)(RpMaterial* pMaterial, CBaseModelInfo** const ms_modelInfoPtrs = *AddressByVersion(0x509CB1, 0x4C0C96, 0x403DB7); const uint32_t m_numModelInfoPtrs = *AddressByVersion(0x4C5956+2, 0, 0); + +static RwTexture** const ms_aDirtTextures = *AddressByVersion( 0x5D5DCC + 3, 0, 0 /*TODO*/); +void RemapDirt( CVehicleModelInfo* modelInfo, uint32_t dirtID ) +{ + RpMaterial** materials = modelInfo->m_numDirtMaterials > CVehicleModelInfo::IN_PLACE_BUFFER_DIRT_SIZE ? modelInfo->m_dirtMaterials : modelInfo->m_staticDirtMaterials; + + for ( size_t i = 0; i < modelInfo->m_numDirtMaterials; i++ ) + { + RpMaterialSetTexture( materials[i], ms_aDirtTextures[dirtID] ); + } +} + void CVehicleModelInfo::Shutdown() { CBaseModelInfo::Shutdown(); + delete m_dirtMaterials; + m_dirtMaterials = nullptr; + delete m_apPlateMaterials; m_apPlateMaterials = nullptr; } void CVehicleModelInfo::FindEditableMaterialList() { - size_t materialCount = 0; + std::vector editableMaterials; auto GetEditableMaterialListCB = [&]( RpAtomic* atomic ) -> RpAtomic* { RpGeometryForAllMaterials( RpAtomicGetGeometry(atomic), [&]( RpMaterial* material ) -> RpMaterial* { @@ -32,8 +49,7 @@ void CVehicleModelInfo::FindEditableMaterialList() { if ( _stricmp(texName, "vehiclegrunge256") == 0 ) { - if ( materialCount < _countof(m_apDirtMaterials) ) - m_apDirtMaterials[materialCount++] = material; + editableMaterials.push_back( material ); } } } @@ -47,6 +63,20 @@ void CVehicleModelInfo::FindEditableMaterialList() for ( uint32_t i = 0; i < m_pVehicleStruct->m_nNumExtras; i++ ) GetEditableMaterialListCB(m_pVehicleStruct->m_apExtras[i]); + m_numDirtMaterials = editableMaterials.size(); + if ( m_numDirtMaterials > IN_PLACE_BUFFER_DIRT_SIZE ) + { + m_dirtMaterials = new RpMaterial* [m_numDirtMaterials]; + std::copy( editableMaterials.begin(), editableMaterials.end(), stdext::checked_array_iterator(m_dirtMaterials, m_numDirtMaterials) ); + } + else + { + m_dirtMaterials = nullptr; + + // Use existing space instead of allocating new space + std::copy( editableMaterials.begin(), editableMaterials.end(), m_staticDirtMaterials ); + } + m_nPrimaryColor = -1; m_nSecondaryColor = -1; m_nTertiaryColor = -1; @@ -59,9 +89,8 @@ void CVehicleModelInfo::SetCarCustomPlate() m_nPlateType = -1; m_apPlateMaterials = new RpMaterial* [2*CCustomCarPlateMgr::NUM_MAX_PLATES]; + std::fill_n( m_apPlateMaterials, 2*CCustomCarPlateMgr::NUM_MAX_PLATES, nullptr ); - for ( int i = 0; i < 2*CCustomCarPlateMgr::NUM_MAX_PLATES; i++ ) - m_apPlateMaterials[i] = nullptr; CCustomCarPlateMgr::SetupClump(reinterpret_cast(pRwObject), m_apPlateMaterials); } diff --git a/SilentPatchSA/ModelInfoSA.h b/SilentPatchSA/ModelInfoSA.h index 6e49607..6643fa0 100644 --- a/SilentPatchSA/ModelInfoSA.h +++ b/SilentPatchSA/ModelInfoSA.h @@ -268,7 +268,16 @@ public: } *m_pVehicleStruct; char field_60[464]; - RpMaterial* m_apDirtMaterials[32]; + + static const size_t IN_PLACE_BUFFER_DIRT_SIZE = 30; + union{ + struct{; + RpMaterial** m_dirtMaterials; + size_t m_numDirtMaterials; + RpMaterial* m_staticDirtMaterials[IN_PLACE_BUFFER_DIRT_SIZE]; + }; + RpMaterial* __oldDirtMaterials[32]; // Unused with SilentPatch + }; unsigned char m_anPrimaryColors[8]; unsigned char m_anSecondaryColors[8]; unsigned char m_anTertiaryColors[8]; @@ -299,6 +308,8 @@ public: extern CBaseModelInfo** const ms_modelInfoPtrs; extern const uint32_t m_numModelInfoPtrs; +void RemapDirt( CVehicleModelInfo* modelInfo, uint32_t dirtID ); + class CCustomCarPlateMgr { // Pretty much rewritten for SilentPatch diff --git a/SilentPatchSA/SilentPatchSA.cpp b/SilentPatchSA/SilentPatchSA.cpp index 545babd..7cf6ffb 100644 --- a/SilentPatchSA/SilentPatchSA.cpp +++ b/SilentPatchSA/SilentPatchSA.cpp @@ -1120,7 +1120,9 @@ CVehicleModelInfo* __fastcall VehicleModelInfoCtor(CVehicleModelInfo* me) { orgVehicleModelInfoCtor(me); me->m_apPlateMaterials = nullptr; - std::fill( std::begin(me->m_apDirtMaterials), std::end(me->m_apDirtMaterials), nullptr ); + me->m_dirtMaterials = nullptr; + me->m_numDirtMaterials = 0; + std::fill( std::begin( me->m_staticDirtMaterials ), std::end( me->m_staticDirtMaterials ), nullptr ); return me; } @@ -2438,9 +2440,9 @@ BOOL InjectDelayedPatches_10() // Cars getting dirty // Only 1.0 and Steam + InjectHook( 0x5D5DB0, RemapDirt, PATCH_JUMP ); InjectHook(0x4C9648, &CVehicleModelInfo::FindEditableMaterialList, PATCH_CALL); Patch(0x4C964D, 0x0FEBCE8B); - Patch(0x5D5DC2, 32); // 1.0 ONLY } if ( !bHasImVehFt && !bSAMP )