diff --git a/src/control/Bridge.cpp b/src/control/Bridge.cpp index 81f43f32..dacb7aab 100644 --- a/src/control/Bridge.cpp +++ b/src/control/Bridge.cpp @@ -123,8 +123,7 @@ void CBridge::FindBridgeEntities() pLiftRoad = nil; pLiftPart = nil; - for (int i = 1; i < CPools::GetBuildingPool()->GetSize(); ++i) - { + for (int i = CPools::GetBuildingPool()->GetSize()-1; i >= 0; i--) { CBuilding* entry = CPools::GetBuildingPool()->GetSlot(i); if (entry) { diff --git a/src/control/CarAI.cpp b/src/control/CarAI.cpp index bb0c1ec3..b4dd8777 100644 --- a/src/control/CarAI.cpp +++ b/src/control/CarAI.cpp @@ -588,7 +588,7 @@ void CCarAI::MakeWayForCarWithSiren(CVehicle *pVehicle) CVector2D forward = pVehicle->GetMoveSpeed() / flatSpeed; float projection = flatSpeed * 45 + 20; int i = CPools::GetVehiclePool()->GetSize(); - while (i--) { + while (--i >= 0) { CVehicle* vehicle = CPools::GetVehiclePool()->GetSlot(i); if (!vehicle) continue; diff --git a/src/control/CarCtrl.cpp b/src/control/CarCtrl.cpp index fd6d8057..cf77b5a4 100644 --- a/src/control/CarCtrl.cpp +++ b/src/control/CarCtrl.cpp @@ -648,8 +648,7 @@ CCarCtrl::AddToCarArray(int32 id, int32 vehclass) void CCarCtrl::RemoveDistantCars() { - uint32 i = CPools::GetVehiclePool()->GetSize(); - while (--i){ + for (int i = CPools::GetVehiclePool()->GetSize()-1; i >= 0; i--) { CVehicle* pVehicle = CPools::GetVehiclePool()->GetSlot(i); if (!pVehicle) continue; @@ -733,8 +732,7 @@ int32 CCarCtrl::CountCarsOfType(int32 mi) { int32 total = 0; - uint32 i = CPools::GetVehiclePool()->GetSize(); - while (i--){ + for (int i = CPools::GetVehiclePool()->GetSize()-1; i >= 0; i--) { CVehicle* pVehicle = CPools::GetVehiclePool()->GetSlot(i); if (!pVehicle) continue; diff --git a/src/control/Phones.cpp b/src/control/Phones.cpp index f8005899..074718db 100644 --- a/src/control/Phones.cpp +++ b/src/control/Phones.cpp @@ -151,8 +151,8 @@ CPhoneInfo::Initialise(void) pickedUpPhone = nil; m_nMax = 0; m_nNum = 0; - for (int v5 = pool->GetSize() - 1; v5 >= 0; v5--) { - CBuilding *building = pool->GetSlot(v5); + for (int i = pool->GetSize() - 1; i >= 0; i--) { + CBuilding *building = pool->GetSlot(i); if (building) { if (building->m_modelIndex == MI_PHONEBOOTH1) { CPhone *maxPhone = &m_aPhones[m_nMax]; diff --git a/src/control/Pickups.cpp b/src/control/Pickups.cpp index 3ba01e46..c1a85af4 100644 --- a/src/control/Pickups.cpp +++ b/src/control/Pickups.cpp @@ -296,7 +296,7 @@ CPickup::Update(CPlayerPed *player, CVehicle *vehicle, int playerId) m_pObject->UpdateRwFrame(); bool touched = false; - for (int32 i = CPools::GetVehiclePool()->GetSize(); i > 0; i--) { // TODO: check if i > 0 is not a R* mistake + for (int32 i = CPools::GetVehiclePool()->GetSize()-1; i >= 0; i--) { CVehicle *vehicle = CPools::GetVehiclePool()->GetSlot(i); if (vehicle != nil && vehicle->IsSphereTouchingVehicle(m_pObject->GetPosition().x, m_pObject->GetPosition().y, m_pObject->GetPosition().z, 1.5f)) { touched = true; @@ -323,7 +323,7 @@ CPickup::Update(CPlayerPed *player, CVehicle *vehicle, int playerId) if (CTimer::GetTimeInMilliseconds() > m_nTimer) explode = true; else {// added else here since vehicle lookup is useless - for (int32 i = CPools::GetVehiclePool()->GetSize(); i > 0; i--) { // TODO: check if i > 0 is not a R* mistake + for (int32 i = CPools::GetVehiclePool()->GetSize()-1; i >= 0; i--) { CVehicle *vehicle = CPools::GetVehiclePool()->GetSlot(i); if (vehicle != nil && vehicle->IsSphereTouchingVehicle(m_pObject->GetPosition().x, m_pObject->GetPosition().y, m_pObject->GetPosition().z, 1.5f)) { explode = true; diff --git a/src/control/Replay.cpp b/src/control/Replay.cpp index 65ee2840..473b13d3 100644 --- a/src/control/Replay.cpp +++ b/src/control/Replay.cpp @@ -1156,7 +1156,7 @@ void CReplay::RestoreStuffFromMem(void) FindPlayerPed()->m_pWanted = new CWanted(PlayerWanted); /* Nice memory leak */ CWorld::Players[0] = PlayerInfo; int i = CPools::GetPedPool()->GetSize(); - while (i--){ + while (--i >= 0) { CPed* ped = CPools::GetPedPool()->GetSlot(i); if (!ped) continue; @@ -1174,7 +1174,7 @@ void CReplay::RestoreStuffFromMem(void) ped->AddWeaponModel(ped->m_wepModelID); } i = CPools::GetVehiclePool()->GetSize(); - while (i--){ + while (--i >= 0) { CVehicle* vehicle = CPools::GetVehiclePool()->GetSlot(i); if (!vehicle) continue; @@ -1233,7 +1233,7 @@ void CReplay::RestoreStuffFromMem(void) } PrintElementsInPtrList(); i = CPools::GetObjectPool()->GetSize(); - while (i--){ + while (--i >= 0) { CObject* object = CPools::GetObjectPool()->GetSlot(i); if (!object) continue; @@ -1248,7 +1248,7 @@ void CReplay::RestoreStuffFromMem(void) object->GetMatrix().AttachRW(RwFrameGetMatrix(RpAtomicGetFrame(object->m_rwObject)), false); } i = CPools::GetDummyPool()->GetSize(); - while (i--){ + while (--i >= 0) { CDummy* dummy = CPools::GetDummyPool()->GetSlot(i); if (!dummy) continue; @@ -1294,7 +1294,7 @@ WRAPPER void CReplay::EmptyPedsAndVehiclePools(void) { EAXJMP(0x5970E0); } void CReplay::EmptyPedsAndVehiclePools(void) { int i = CPools::GetVehiclePool()->GetSize(); - while (i--) { + while (--i >= 0) { CVehicle* v = CPools::GetVehiclePool()->GetSlot(i); if (!v) continue; @@ -1302,7 +1302,7 @@ void CReplay::EmptyPedsAndVehiclePools(void) delete v; } i = CPools::GetPedPool()->GetSize(); - while (i--) { + while (--i >= 0) { CPed* p = CPools::GetPedPool()->GetSlot(i); if (!p) continue; @@ -1319,7 +1319,7 @@ void CReplay::EmptyAllPools(void) { EmptyPedsAndVehiclePools(); int i = CPools::GetObjectPool()->GetSize(); - while (i--) { + while (--i >= 0) { CObject* o = CPools::GetObjectPool()->GetSlot(i); if (!o) continue; @@ -1327,7 +1327,7 @@ void CReplay::EmptyAllPools(void) delete o; } i = CPools::GetDummyPool()->GetSize(); - while (i--) { + while (--i >= 0) { CDummy* d = CPools::GetDummyPool()->GetSlot(i); if (!d) continue; @@ -1343,14 +1343,14 @@ WRAPPER void CReplay::MarkEverythingAsNew(void) { EAXJMP(0x597280); } void CReplay::MarkEverythingAsNew(void) { int i = CPools::GetVehiclePool()->GetSize(); - while (i--) { + while (--i >= 0) { CVehicle* v = CPools::GetVehiclePool()->GetSlot(i); if (!v) continue; v->bHasAlreadyBeenRecorded = false; } i = CPools::GetPedPool()->GetSize(); - while (i--) { + while (--i >= 0) { CPed* p = CPools::GetPedPool()->GetSlot(i); if (!p) continue; diff --git a/src/core/Pools.cpp b/src/core/Pools.cpp index 847fa753..8e66b049 100644 --- a/src/core/Pools.cpp +++ b/src/core/Pools.cpp @@ -1,6 +1,8 @@ #include "common.h" #include "patcher.h" #include "Pools.h" +#include "World.h" +#include "ProjectileInfo.h" CCPtrNodePool *&CPools::ms_pPtrNodePool = *(CCPtrNodePool**)0x943044; CEntryInfoNodePool *&CPools::ms_pEntryInfoNodePool = *(CEntryInfoNodePool**)0x941448; @@ -12,15 +14,9 @@ CObjectPool *&CPools::ms_pObjectPool = *(CObjectPool**)0x880E28; CDummyPool *&CPools::ms_pDummyPool = *(CDummyPool**)0x8F2C18; CAudioScriptObjectPool *&CPools::ms_pAudioScriptObjectPool = *(CAudioScriptObjectPool**)0x8F1B6C; -WRAPPER void CPools::Initialise(void) { EAXJMP(0x4A1770); } -WRAPPER void CPools::MakeSureSlotInObjectPoolIsEmpty(int32 handle) { EAXJMP(0x4A2DB0); } - -#if 0 void CPools::Initialise(void) { - // TODO: unused right now - assert(0); ms_pPtrNodePool = new CCPtrNodePool(NUMPTRNODES); ms_pEntryInfoNodePool = new CEntryInfoNodePool(NUMENTRYINFOS); ms_pPedPool = new CPedPool(NUMPEDS); @@ -31,7 +27,33 @@ CPools::Initialise(void) ms_pDummyPool = new CDummyPool(NUMDUMMIES); ms_pAudioScriptObjectPool = new CAudioScriptObjectPool(NUMAUDIOSCRIPTOBJECTS); } -#endif + +void +CPools::ShutDown(void) +{ + debug("PtrNodes left %d\n", ms_pPtrNodePool->GetNoOfUsedSpaces()); + debug("EntryInfoNodes left %d\n", ms_pEntryInfoNodePool->GetNoOfUsedSpaces()); + debug("Peds left %d\n", ms_pPedPool->GetNoOfUsedSpaces()); + debug("Vehicles left %d\n", ms_pVehiclePool->GetNoOfUsedSpaces()); + debug("Buildings left %d\n", ms_pBuildingPool->GetNoOfUsedSpaces()); + debug("Treadables left %d\n", ms_pTreadablePool->GetNoOfUsedSpaces()); + debug("Objects left %d\n", ms_pObjectPool->GetNoOfUsedSpaces()); + debug("Dummys left %d\n", ms_pDummyPool->GetNoOfUsedSpaces()); + debug("AudioScriptObjects left %d\n", ms_pAudioScriptObjectPool->GetNoOfUsedSpaces()); + printf("Shutdown pool started\n"); + + delete ms_pPtrNodePool; + delete ms_pEntryInfoNodePool; + delete ms_pPedPool; + delete ms_pVehiclePool; + delete ms_pBuildingPool; + delete ms_pTreadablePool; + delete ms_pObjectPool; + delete ms_pDummyPool; + delete ms_pAudioScriptObjectPool; + + printf("Shutdown pool done\n"); +} int32 CPools::GetPedRef(CPed *ped) { return ms_pPedPool->GetIndex(ped); } CPed *CPools::GetPed(int32 handle) { return ms_pPedPool->GetAt(handle); } @@ -39,3 +61,47 @@ int32 CPools::GetVehicleRef(CVehicle *vehicle) { return ms_pVehiclePool->GetInde CVehicle *CPools::GetVehicle(int32 handle) { return ms_pVehiclePool->GetAt(handle); } int32 CPools::GetObjectRef(CObject *object) { return ms_pObjectPool->GetIndex(object); } CObject *CPools::GetObject(int32 handle) { return ms_pObjectPool->GetAt(handle); } + +void +CPools::CheckPoolsEmpty() +{ + assert(ms_pPedPool->GetNoOfUsedSpaces() == 0); + assert(ms_pVehiclePool->GetNoOfUsedSpaces() == 0); + printf("pools have beem cleared \n"); +} + + +void +CPools::MakeSureSlotInObjectPoolIsEmpty(int32 slot) +{ + if (ms_pObjectPool->IsFreeSlot(slot)) return; + + CObject *object = ms_pObjectPool->GetSlot(slot); + if (object->ObjectCreatedBy == TEMP_OBJECT) { + CWorld::Remove(object); + delete object; + } else if (!CProjectileInfo::RemoveIfThisIsAProjectile(object)) { + // relocate to another slot?? + CObject *newObject = new CObject(); + CWorld::Remove(object); + memcpy(newObject, object, ms_pObjectPool->GetMaxEntrySize()); + CWorld::Add(newObject); + object->m_rwObject = nil; + delete object; + newObject->m_pFirstReference = nil; + } +} + + +STARTPATCHES + InjectHook(0x4A1770, CPools::Initialise, PATCH_JUMP); + InjectHook(0x4A1880, CPools::ShutDown, PATCH_JUMP); + InjectHook(0x4A1A50, CPools::CheckPoolsEmpty, PATCH_JUMP); + InjectHook(0x4A1A80, CPools::GetPedRef, PATCH_JUMP); + InjectHook(0x4A1AA0, CPools::GetPed, PATCH_JUMP); + InjectHook(0x4A1AC0, CPools::GetVehicleRef, PATCH_JUMP); + InjectHook(0x4A1AE0, CPools::GetVehicle, PATCH_JUMP); + InjectHook(0x4A1B00, CPools::GetObjectRef, PATCH_JUMP); + InjectHook(0x4A1B20, CPools::GetObject, PATCH_JUMP); + InjectHook(0x4A2DB0, CPools::MakeSureSlotInObjectPoolIsEmpty, PATCH_JUMP); +ENDPATCHES diff --git a/src/core/Pools.h b/src/core/Pools.h index 4e6bd547..770a1de1 100644 --- a/src/core/Pools.h +++ b/src/core/Pools.h @@ -43,11 +43,13 @@ public: static CAudioScriptObjectPool *GetAudioScriptObjectPool(void) { return ms_pAudioScriptObjectPool; } static void Initialise(void); + static void ShutDown(void); static int32 GetPedRef(CPed *ped); static CPed *GetPed(int32 handle); static int32 GetVehicleRef(CVehicle *vehicle); static CVehicle *GetVehicle(int32 handle); static int32 GetObjectRef(CObject *object); static CObject *GetObject(int32 handle); - static void MakeSureSlotInObjectPoolIsEmpty(int32 handle); + static void CheckPoolsEmpty(); + static void MakeSureSlotInObjectPoolIsEmpty(int32 slot); }; diff --git a/src/core/Streaming.cpp b/src/core/Streaming.cpp index d9dc8628..69e14869 100644 --- a/src/core/Streaming.cpp +++ b/src/core/Streaming.cpp @@ -226,7 +226,7 @@ CStreaming::Init(void) CModelInfo::GetModelInfo("IslandLODsubIND", &islandLODsubInd); CModelInfo::GetModelInfo("IslandLODsubCOM", &islandLODsubCom); - for(i = 0; i < CPools::GetBuildingPool()->GetSize(); i++){ + for(i = CPools::GetBuildingPool()->GetSize()-1; i >= 0; i--){ CBuilding *building = CPools::GetBuildingPool()->GetSlot(i); if(building == nil) continue; @@ -682,8 +682,8 @@ CStreaming::RequestBigBuildings(eLevelName level) int i, n; CBuilding *b; - n = CPools::GetBuildingPool()->GetSize(); - for(i = 0; i < n; i++){ + n = CPools::GetBuildingPool()->GetSize()-1; + for(i = n; i >= 0; i--){ b = CPools::GetBuildingPool()->GetSlot(i); if(b && b->bIsBIGBuilding && b->m_level == level) RequestModel(b->GetModelIndex(), STREAMFLAGS_DONT_REMOVE|STREAMFLAGS_PRIORITY); @@ -837,8 +837,8 @@ CStreaming::RemoveBuildings(eLevelName level) CEntity *e; CBaseModelInfo *mi; - n = CPools::GetBuildingPool()->GetSize(); - for(i = 0; i < n; i++){ + n = CPools::GetBuildingPool()->GetSize()-1; + for(i = n; i >= 0; i--){ e = CPools::GetBuildingPool()->GetSlot(i); if(e && e->m_level == level){ mi = CModelInfo::GetModelInfo(e->GetModelIndex()); @@ -850,8 +850,8 @@ CStreaming::RemoveBuildings(eLevelName level) } } - n = CPools::GetTreadablePool()->GetSize(); - for(i = 0; i < n; i++){ + n = CPools::GetTreadablePool()->GetSize()-1; + for(i = n; i >= 0; i--){ e = CPools::GetTreadablePool()->GetSlot(i); if(e && e->m_level == level){ mi = CModelInfo::GetModelInfo(e->GetModelIndex()); @@ -863,8 +863,8 @@ CStreaming::RemoveBuildings(eLevelName level) } } - n = CPools::GetObjectPool()->GetSize(); - for(i = 0; i < n; i++){ + n = CPools::GetObjectPool()->GetSize()-1; + for(i = n; i >= 0; i--){ e = CPools::GetObjectPool()->GetSlot(i); if(e && e->m_level == level){ mi = CModelInfo::GetModelInfo(e->GetModelIndex()); @@ -876,8 +876,8 @@ CStreaming::RemoveBuildings(eLevelName level) } } - n = CPools::GetDummyPool()->GetSize(); - for(i = 0; i < n; i++){ + n = CPools::GetDummyPool()->GetSize()-1; + for(i = n; i >= 0; i--){ e = CPools::GetDummyPool()->GetSlot(i); if(e && e->m_level == level){ mi = CModelInfo::GetModelInfo(e->GetModelIndex()); @@ -951,8 +951,8 @@ CStreaming::RemoveBigBuildings(eLevelName level) CEntity *e; CBaseModelInfo *mi; - n = CPools::GetBuildingPool()->GetSize(); - for(i = 0; i < n; i++){ + n = CPools::GetBuildingPool()->GetSize()-1; + for(i = n; i >= 0; i--){ e = CPools::GetBuildingPool()->GetSlot(i); if(e && e->bIsBIGBuilding && e->m_level == level){ mi = CModelInfo::GetModelInfo(e->GetModelIndex()); @@ -1172,8 +1172,8 @@ CStreaming::HaveAllBigBuildingsLoaded(eLevelName level) return; } - n = CPools::GetBuildingPool()->GetSize(); - for(i = 0; i < n; i++){ + n = CPools::GetBuildingPool()->GetSize()-1; + for(i = n; i >= 0; i--){ e = CPools::GetBuildingPool()->GetSlot(i); if(e && e->bIsBIGBuilding && e->m_level == level && ms_aInfoForModel[e->GetModelIndex()].m_loadState != STREAMSTATE_LOADED) diff --git a/src/core/ZoneCull.cpp b/src/core/ZoneCull.cpp index dc162147..6d33a1cf 100644 --- a/src/core/ZoneCull.cpp +++ b/src/core/ZoneCull.cpp @@ -169,22 +169,22 @@ CCullZones::MarkSubwayAsInvisible(bool visible) CEntity *e; CVehicle *v; - n = CPools::GetBuildingPool()->GetSize(); - for(i = 0; i < n; i++){ + n = CPools::GetBuildingPool()->GetSize()-1; + for(i = n; i >= 0; i--){ e = CPools::GetBuildingPool()->GetSlot(i); if(e && e->bIsSubway) e->bIsVisible = visible; } - n = CPools::GetTreadablePool()->GetSize(); - for(i = 0; i < n; i++){ + n = CPools::GetTreadablePool()->GetSize()-1; + for(i = n; i >= 0; i--){ e = CPools::GetTreadablePool()->GetSlot(i); if(e && e->bIsSubway) e->bIsVisible = visible; } - n = CPools::GetVehiclePool()->GetSize(); - for(i = 0; i < n; i++){ + n = CPools::GetVehiclePool()->GetSize()-1; + for(i = n; i >= 0; i--){ v = CPools::GetVehiclePool()->GetSlot(i); if(v && v->IsTrain() && ((CTrain*)v)->m_nTrackId != TRACK_ELTRAIN) v->bIsVisible = visible; diff --git a/src/core/templates.h b/src/core/templates.h index ef2db33a..f785d647 100644 --- a/src/core/templates.h +++ b/src/core/templates.h @@ -44,7 +44,20 @@ public: m_flags[i].free = 1; } } - int GetSize(void) { return m_size; } + ~CPool() { + Flush(); + } + void Flush() { + if (m_size > 0) { + free(m_entries); + free(m_flags); + m_entries = nil; + m_flags = nil; + m_size = 0; + m_allocPtr = 0; + } + } + int GetSize(void) const { return m_size; } T *New(void){ bool wrapped = false; do @@ -101,12 +114,14 @@ public: n++; return n; } + bool IsFreeSlot(int i) { return !!m_flags[i].free; } void ClearStorage(uint8 *&flags, U *&entries){ free(flags); free(entries); flags = nil; entries = nil; } + uint32 GetMaxEntrySize() const { return sizeof(U); } void CopyBack(uint8 *&flags, U *&entries){ memcpy(m_flags, flags, sizeof(uint8)*m_size); memcpy(m_entries, entries, sizeof(U)*m_size); diff --git a/src/weapons/ProjectileInfo.cpp b/src/weapons/ProjectileInfo.cpp new file mode 100644 index 00000000..50d75516 --- /dev/null +++ b/src/weapons/ProjectileInfo.cpp @@ -0,0 +1,7 @@ +#include "common.h" +#include "patcher.h" +#include "ProjectileInfo.h" +#include "Projectile.h" + + +WRAPPER bool CProjectileInfo::RemoveIfThisIsAProjectile(CObject *pObject) { EAXJMP(0x55BBD0); } \ No newline at end of file diff --git a/src/weapons/ProjectileInfo.h b/src/weapons/ProjectileInfo.h new file mode 100644 index 00000000..f4753b28 --- /dev/null +++ b/src/weapons/ProjectileInfo.h @@ -0,0 +1,9 @@ +#pragma once + +class CObject; + +class CProjectileInfo +{ +public: + static bool RemoveIfThisIsAProjectile(CObject *pObject); +}; \ No newline at end of file