From 076f10f7a130ac22f6e92100a818db22b314c96a Mon Sep 17 00:00:00 2001 From: xezon <4720891+xezon@users.noreply.github.com> Date: Sat, 2 Aug 2025 14:51:55 +0200 Subject: [PATCH 1/3] unify(memory): Merge GameMemory code (#1408) --- Core/GameEngine/CMakeLists.txt | 4 +- Core/GameEngine/Include/Common/GameDefines.h | 8 +++ .../GameEngine/Include/Common/GameMemory.h | 5 +- .../Source/Common/System/GameMemory.cpp | 53 +++++++--------- .../Source/Common/System/MemoryInit.cpp | 60 ++++++++++++++++++- .../Source/Common/System/MemoryInit.cpp | 2 +- 6 files changed, 91 insertions(+), 41 deletions(-) diff --git a/Core/GameEngine/CMakeLists.txt b/Core/GameEngine/CMakeLists.txt index 0c91e47cc5d..0ebd34e5b80 100644 --- a/Core/GameEngine/CMakeLists.txt +++ b/Core/GameEngine/CMakeLists.txt @@ -646,13 +646,13 @@ set(GAMEENGINE_SRC # Source/Common/System/FunctionLexicon.cpp # Source/Common/System/GameCommon.cpp #Source/Common/System/GameMemory.cpp # is conditionally appended + #Source/Common/System/GameMemoryInit.cpp # is conditionally appended # Source/Common/System/GameType.cpp # Source/Common/System/Geometry.cpp # Source/Common/System/KindOf.cpp # Source/Common/System/List.cpp Source/Common/System/LocalFile.cpp Source/Common/System/LocalFileSystem.cpp - #Source/Common/System/MemoryInit.cpp # is conditionally appended # Source/Common/System/ObjectStatusTypes.cpp # Source/Common/System/QuotedPrintable.cpp # Source/Common/System/Radar.cpp @@ -1140,7 +1140,7 @@ if(RTS_GAMEMEMORY_ENABLE) # Uses the original Game Memory implementation. list(APPEND GAMEENGINE_SRC # Source/Common/System/GameMemory.cpp -# Source/Common/System/MemoryInit.cpp +# Source/Common/System/GameMemoryInit.cpp ) else() # Uses the null implementation when disabled. diff --git a/Core/GameEngine/Include/Common/GameDefines.h b/Core/GameEngine/Include/Common/GameDefines.h index 8a9f5158c85..3df8fb30903 100644 --- a/Core/GameEngine/Include/Common/GameDefines.h +++ b/Core/GameEngine/Include/Common/GameDefines.h @@ -59,3 +59,11 @@ #ifndef ENABLE_FILESYSTEM_EXISTENCE_CACHE #define ENABLE_FILESYSTEM_EXISTENCE_CACHE (1) #endif + +// Enable obsolete code. This mainly refers to code that existed in Generals but was removed in GeneralsMD. +// Disable and remove this when Generals and GeneralsMD are merged. +#if RTS_GENERALS +#ifndef USE_OBSOLETE_GENERALS_CODE +#define USE_OBSOLETE_GENERALS_CODE (1) +#endif +#endif diff --git a/Generals/Code/GameEngine/Include/Common/GameMemory.h b/Generals/Code/GameEngine/Include/Common/GameMemory.h index b069822943d..e43af713441 100644 --- a/Generals/Code/GameEngine/Include/Common/GameMemory.h +++ b/Generals/Code/GameEngine/Include/Common/GameMemory.h @@ -730,7 +730,6 @@ private: \ public: /* include this line at the end to reset visibility to 'public' */ - // ---------------------------------------------------------------------------- /** This class is provided as a simple and safe way to integrate C++ object allocation @@ -894,10 +893,9 @@ class STLSpecialAlloc static void deallocate(void* __p, size_t); }; -#endif //DISABLE_GAMEMEMORY +#endif // DISABLE_GAMEMEMORY -// ---------------------------------------------------------------------------- /** A simple utility class to ensure exception safety; this holds a MemoryPoolObject and deletes it in its destructor. Especially useful for iterators! @@ -916,4 +914,5 @@ class MemoryPoolObjectHolder #define EMPTY_DTOR(CLASS) inline CLASS::~CLASS() { } + #endif // _GAME_MEMORY_H_ diff --git a/Generals/Code/GameEngine/Source/Common/System/GameMemory.cpp b/Generals/Code/GameEngine/Source/Common/System/GameMemory.cpp index f760d6f470f..8275aa0db16 100644 --- a/Generals/Code/GameEngine/Source/Common/System/GameMemory.cpp +++ b/Generals/Code/GameEngine/Source/Common/System/GameMemory.cpp @@ -75,7 +75,9 @@ DECLARE_PERF_TIMER(MemoryPoolInitFilling) faster to free raw DMA blocks. @todo verify this speedup is enough to be worth the extra space */ -#define MPSB_DLINK +#ifndef DISABLE_MEMORYPOOL_MPSB_DLINK + #define MPSB_DLINK +#endif #ifdef MEMORYPOOL_DEBUG @@ -201,7 +203,6 @@ static Bool theMainInitFlag = false; #define MEM_BOUND_ALIGNMENT 4 static Int roundUpMemBound(Int i); -static void *sysAllocate(Int numBytes); static void *sysAllocateDoNotZero(Int numBytes); static void sysFree(void* p); static void memset32(void* ptr, Int value, Int bytesToFill); @@ -222,27 +223,6 @@ static Int roundUpMemBound(Int i) return (i + (MEM_BOUND_ALIGNMENT-1)) & ~(MEM_BOUND_ALIGNMENT-1); } -//----------------------------------------------------------------------------- -/** - identical to sysAllocateDoNotZero, except that the memory block returned - is filled to all-zero-bytes. -*/ -static void* sysAllocate(Int numBytes) -{ - void* p = ::GlobalAlloc(GMEM_FIXED | GMEM_ZEROINIT, numBytes); - if (!p) - throw ERROR_OUT_OF_MEMORY; -#ifdef MEMORYPOOL_DEBUG - { - USE_PERF_TIMER(MemoryPoolDebugging) - theTotalSystemAllocationInBytes += ::GlobalSize(p); - if (thePeakSystemAllocationInBytes < theTotalSystemAllocationInBytes) - thePeakSystemAllocationInBytes = theTotalSystemAllocationInBytes; - } -#endif - return p; -} - //----------------------------------------------------------------------------- /** this is the low-level allocator that we use to request memory from the OS. @@ -837,7 +817,7 @@ Bool BlockCheckpointInfo::shouldBeInReport(Int flags, Int startCheckpoint, Int e BlockCheckpointInfo *freed = NULL; try { - freed = (BlockCheckpointInfo *)::sysAllocate(sizeof(BlockCheckpointInfo)); + freed = (BlockCheckpointInfo *)::sysAllocateDoNotZero(sizeof(BlockCheckpointInfo)); } catch (...) { freed = NULL; } @@ -896,6 +876,7 @@ void MemoryPoolSingleBlock::initBlock(Int logicalSize, MemoryPoolBlob *owningBlo #endif } #endif // MEMORYPOOL_DEBUG + #ifdef MEMORYPOOL_CHECKPOINTING m_checkpointInfo = NULL; #endif @@ -1204,7 +1185,7 @@ void MemoryPoolBlob::initBlob(MemoryPool *owningPool, Int allocationCount) m_usedBlocksInBlob = 0; Int rawBlockSize = MemoryPoolSingleBlock::calcRawBlockSize(m_owningPool->getAllocationSize()); - m_blockData = (char *)::sysAllocate(rawBlockSize * m_totalBlocksInBlob); // throws on failure + m_blockData = (char *)::sysAllocateDoNotZero(rawBlockSize * m_totalBlocksInBlob); // throws on failure // set up the list of free blocks in the blob (namely, all of 'em) MemoryPoolSingleBlock *block = (MemoryPoolSingleBlock *)m_blockData; @@ -1577,7 +1558,7 @@ MemoryPoolBlob* MemoryPool::createBlob(Int allocationCount) { DEBUG_ASSERTCRASH(allocationCount > 0 && allocationCount%MEM_BOUND_ALIGNMENT==0, ("bad allocationCount (must be >0 and evenly divisible by %d)",MEM_BOUND_ALIGNMENT)); - MemoryPoolBlob* blob = new (::sysAllocate(sizeof(MemoryPoolBlob))) MemoryPoolBlob; // will throw on failure + MemoryPoolBlob* blob = new (::sysAllocateDoNotZero(sizeof(MemoryPoolBlob))) MemoryPoolBlob; // will throw on failure blob->initBlob(this, allocationCount); // will throw on failure @@ -2175,6 +2156,8 @@ void DynamicMemoryAllocator::debugIgnoreLeaksForThisBlock(void* pBlockPtr) allocate a chunk-o-bytes from this DMA and return it, but don't bother zeroing out the block. if unable to allocate, throw ERROR_OUT_OF_MEMORY. this function will never return null. + + added code to make sure we're on a DWord boundary, throw exception if not */ void *DynamicMemoryAllocator::allocateBytesDoNotZeroImplementation(Int numBytes DECLARE_LITERALSTRING_ARG2) { @@ -2262,6 +2245,13 @@ void *DynamicMemoryAllocator::allocateBytesDoNotZeroImplementation(Int numBytes } #endif #endif + +#if defined(RTS_DEBUG) + // check alignment + if (unsigned(result)&3) + throw ERROR_OUT_OF_MEMORY; +#endif + return result; } @@ -2673,7 +2663,7 @@ MemoryPool *MemoryPoolFactory::createMemoryPool(const char *poolName, Int alloca throw ERROR_OUT_OF_MEMORY; } - pool = new (::sysAllocate(sizeof(MemoryPool))) MemoryPool; // will throw on failure + pool = new (::sysAllocateDoNotZero(sizeof(MemoryPool))) MemoryPool; // will throw on failure pool->init(this, poolName, allocationSize, initialAllocationCount, overflowAllocationCount); // will throw on failure pool->addToList(&m_firstPoolInFactory); @@ -2689,8 +2679,7 @@ MemoryPool *MemoryPoolFactory::createMemoryPool(const char *poolName, Int alloca */ MemoryPool *MemoryPoolFactory::findMemoryPool(const char *poolName) { - MemoryPool *pool = m_firstPoolInFactory; - for (; pool; pool = pool->getNextPoolInList()) + for (MemoryPool *pool = m_firstPoolInFactory; pool; pool = pool->getNextPoolInList()) { if (!strcmp(poolName, pool->getPoolName())) { @@ -2729,7 +2718,7 @@ DynamicMemoryAllocator *MemoryPoolFactory::createDynamicMemoryAllocator(Int numS { DynamicMemoryAllocator *dma; - dma = new (::sysAllocate(sizeof(DynamicMemoryAllocator))) DynamicMemoryAllocator; // will throw on failure + dma = new (::sysAllocateDoNotZero(sizeof(DynamicMemoryAllocator))) DynamicMemoryAllocator; // will throw on failure dma->init(this, numSubPools, pParms); // will throw on failure dma->addToList(&m_firstDmaInFactory); @@ -3424,7 +3413,7 @@ void initMemoryManager() Int numSubPools; const PoolInitRec *pParms; userMemoryManagerGetDmaParms(&numSubPools, &pParms); - TheMemoryPoolFactory = new (::sysAllocate(sizeof(MemoryPoolFactory))) MemoryPoolFactory; // will throw on failure + TheMemoryPoolFactory = new (::sysAllocateDoNotZero(sizeof(MemoryPoolFactory))) MemoryPoolFactory; // will throw on failure TheMemoryPoolFactory->init(); // will throw on failure TheDynamicMemoryAllocator = TheMemoryPoolFactory->createDynamicMemoryAllocator(numSubPools, pParms); // will throw on failure userMemoryManagerInitPools(); @@ -3499,7 +3488,7 @@ static void preMainInitMemoryManager() Int numSubPools; const PoolInitRec *pParms; userMemoryManagerGetDmaParms(&numSubPools, &pParms); - TheMemoryPoolFactory = new (::sysAllocate(sizeof(MemoryPoolFactory))) MemoryPoolFactory; // will throw on failure + TheMemoryPoolFactory = new (::sysAllocateDoNotZero(sizeof(MemoryPoolFactory))) MemoryPoolFactory; // will throw on failure TheMemoryPoolFactory->init(); // will throw on failure TheDynamicMemoryAllocator = TheMemoryPoolFactory->createDynamicMemoryAllocator(numSubPools, pParms); // will throw on failure diff --git a/Generals/Code/GameEngine/Source/Common/System/MemoryInit.cpp b/Generals/Code/GameEngine/Source/Common/System/MemoryInit.cpp index 0b0c7ee9539..3c2f00837f0 100644 --- a/Generals/Code/GameEngine/Source/Common/System/MemoryInit.cpp +++ b/Generals/Code/GameEngine/Source/Common/System/MemoryInit.cpp @@ -123,6 +123,7 @@ static PoolSizeRec sizes[] = { "AIGroupPool", 64, 32 }, { "AIDockMachinePool", 256, 32 }, { "AIGuardMachinePool", 32, 32 }, + { "AIGuardRetaliateMachinePool", 32, 32 }, { "AITNGuardMachinePool", 32, 32 }, { "PathNodePool", 8192, 1024 }, { "PathPool", 256, 16 }, @@ -143,6 +144,9 @@ static PoolSizeRec sizes[] = { "ObjectSMCHelperPool", 4096, 256 }, { "ObjectWeaponStatusHelperPool", 4096, 256 }, { "ObjectDefectionHelperPool", 4096, 256 }, + { "StatusDamageHelper", 1500, 256 }, + { "SubdualDamageHelper", 1500, 256 }, + { "TempWeaponBonusHelper", 4096, 256 }, { "Locomotor", 2048, 32 }, { "LocomotorTemplate", 128, 32 }, { "ObjectPool", 4096, 32 }, @@ -159,6 +163,10 @@ static PoolSizeRec sizes[] = { "AudioEventInfo", 1200, 64 }, { "AudioRequest", 256, 8 }, { "AutoHealBehavior", 4096, 32 }, + { "WeaponBonusUpdate", 16, 16 }, + { "GrantStealthBehavior", 4096, 32 }, + { "NeutronBlastBehavior", 4096, 32 }, + { "CountermeasuresBehavior", 256, 32 }, { "BaseRegenerateUpdate", 64, 32 }, { "BoneFXDamage", 64, 32 }, { "BoneFXUpdate", 64, 32 }, @@ -172,11 +180,15 @@ static PoolSizeRec sizes[] = { "EjectPilotDie", 1024, 32 }, { "CrushDie", 1024, 32 }, { "DamDie", 8, 8 }, +#if USE_OBSOLETE_GENERALS_CODE { "DelayedUpgrade", 32, 32 }, { "DelayedWeaponSetUpgradeUpdate", 32, 32 }, +#endif { "DeliverPayloadStateMachine", 32, 32 }, { "DeliverPayloadAIUpdate", 32, 32 }, { "DeletionUpdate", 128, 32 }, + { "SmartBombTargetHomingUpdate", 8, 8 }, + { "DynamicAudioEventInfo", 16, 256 }, // Note: some levels have none, some have lots. Since all are allocated at level load time, we can set this low for the levels with none. { "HackInternetStateMachine", 32, 32 }, { "HackInternetAIUpdate", 32, 32 }, { "MissileAIUpdate", 512, 32 }, @@ -203,6 +215,7 @@ static PoolSizeRec sizes[] = { "GenerateMinefieldBehavior", 32, 32 }, { "HelicopterSlowDeathBehavior", 64, 32 }, { "ParkingPlaceBehavior", 32, 32 }, + { "FlightDeckBehavior", 8, 8 }, #ifdef ALLOW_SURRENDER { "POWTruckAIUpdate", 32, 32, }, { "POWTruckBehavior", 32, 32, }, @@ -211,10 +224,12 @@ static PoolSizeRec sizes[] = { "PropagandaCenterBehavior", 16, 16 }, #endif { "PropagandaTowerBehavior", 16, 16 }, + { "BunkerBusterBehavior", 16, 16 }, { "ObjectTracker", 128, 32 }, { "OCLUpdate", 16, 16 }, { "BodyParticleSystem", 128, 64 }, { "HighlanderBody", 2048, 128 }, + { "UndeadBody", 32, 32 }, { "HordeUpdate", 128, 32 }, { "ImmortalBody", 2048, 128 }, { "InactiveBody", 2048, 32 }, @@ -227,11 +242,14 @@ static PoolSizeRec sizes[] = { "PilotFindVehicleUpdate", 256, 32 }, { "DemoTrapUpdate", 32, 32 }, { "ParticleUplinkCannonUpdate", 16, 16 }, + { "SpectreGunshipUpdate", 8, 8 }, + { "SpectreGunshipDeploymentUpdate", 8, 8 }, { "BaikonurLaunchPower", 4, 4 }, { "RadiusDecalUpdate", 16, 16 }, { "BattlePlanUpdate", 32, 32 }, { "LifetimeUpdate", 256, 32 }, { "LocomotorSetUpgrade", 512, 128 }, + { "LockWeaponCreate", 64, 128 }, { "AutoDepositUpdate", 256, 32 }, { "NeutronMissileUpdate", 512, 32 }, { "MoneyCrateCollide", 32, 32 }, @@ -239,6 +257,7 @@ static PoolSizeRec sizes[] = { "OpenContain", 128, 32 }, { "OverchargeBehavior", 32, 32 }, { "OverlordContain", 32, 32 }, + { "HelixContain", 32, 32 }, { "ParachuteContain", 128, 32 }, { "PhysicsBehavior", 600, 32 }, { "PoisonedBehavior", 512, 64 }, @@ -249,6 +268,7 @@ static PoolSizeRec sizes[] = { "QueueProductionExitUpdate", 32, 32 }, { "RadarUpdate", 16, 16 }, { "RadarUpgrade", 16, 16 }, + { "AnimationSteeringUpdate", 1024, 32 }, { "SupplyWarehouseCripplingBehavior", 16, 16 }, { "CostModifierUpgrade", 32, 32 }, { "CashBountyPower", 32, 32 }, @@ -256,6 +276,7 @@ static PoolSizeRec sizes[] = { "ObjectCreationUpgrade", 128, 32 }, { "MinefieldBehavior", 256, 32 }, { "JetSlowDeathBehavior", 64, 32 }, + { "BattleBusSlowDeathBehavior", 64, 32 }, { "RebuildHoleBehavior", 64, 32 }, { "RebuildHoleExposeDie", 64, 32 }, { "RepairDockUpdate", 32, 32 }, @@ -298,6 +319,8 @@ static PoolSizeRec sizes[] = { "TransitionDamageFX", 256, 32 }, { "TransportAIUpdate", 64, 32 }, { "TransportContain", 128, 32 }, + { "RiderChangeContain", 128, 32 }, + { "InternetHackContain", 16, 16 }, { "TunnelContain", 16, 16 }, { "TunnelContainDie", 32, 32 }, { "TunnelCreate", 32, 32 }, @@ -310,6 +333,14 @@ static PoolSizeRec sizes[] = { "VeterancyGainCreate", 512, 128 }, { "ConvertToCarBombCrateCollide", 32, 32 }, { "ConvertToHijackedVehicleCrateCollide", 32, 32 }, + { "SabotageCommandCenterCrateCollide", 256, 128 }, + { "SabotageFakeBuildingCrateCollide", 256, 128 }, + { "SabotageInternetCenterCrateCollide", 256, 128 }, + { "SabotageMilitaryFactoryCrateCollide", 256, 128 }, + { "SabotagePowerPlantCrateCollide", 256, 128 }, + { "SabotageSuperweaponCrateCollide", 256, 128 }, + { "SabotageSupplyCenterCrateCollide", 256, 128 }, + { "SabotageSupplyDropzoneCrateCollide", 256, 128 }, { "JetAIUpdate", 64, 32 }, { "ChinookAIUpdate", 32, 32 }, { "WanderAIUpdate", 32, 32 }, @@ -333,23 +364,33 @@ static PoolSizeRec sizes[] = { "W3DLaserDraw", 32, 32 }, { "W3DModelDraw", 4096, 128 }, { "W3DOverlordTankDraw", 64, 64 }, + { "W3DOverlordTruckDraw", 64, 64 }, + { "W3DOverlordAircraftDraw", 64, 64 }, { "W3DPoliceCarDraw", 32, 32 }, { "W3DProjectileStreamDraw", 32, 32 }, { "W3DRopeDraw", 32, 32 }, { "W3DScienceModelDraw", 32, 32 }, { "W3DSupplyDraw", 32, 32 }, { "W3DTankDraw", 256, 32 }, + { "W3DTreeDraw", 16, 16 }, + { "W3DPropDraw", 16, 16 }, { "W3DTracerDraw", 64, 32 }, { "W3DTruckDraw", 128, 32 }, { "W3DTankTruckDraw", 32, 16 }, + { "W3DTreeTextureClass", 4, 4 }, { "DefaultSpecialPower", 32, 32 }, { "OCLSpecialPower", 32, 32 }, + { "FireWeaponPower", 32, 32 }, #ifdef ALLOW_DEMORALIZE { "DemoralizeSpecialPower", 16, 16, }, #endif { "CashHackSpecialPower", 32, 32 }, { "CommandSetUpgrade", 32, 32 }, + { "PassengersFireUpgrade", 32, 32 }, { "GrantUpgradeCreate", 256, 32 }, + { "GrantScienceUpgrade", 256, 32 }, + { "ReplaceObjectUpgrade", 32, 32 }, + { "ModelConditionUpgrade", 32, 32 }, { "SpyVisionSpecialPower", 256, 32 }, { "StealthDetectorUpdate", 256, 32 }, { "StealthUpdate", 256, 32 }, @@ -370,6 +411,7 @@ static PoolSizeRec sizes[] = { "MobNexusContain", 128, 32 }, { "MobMemberSlavedUpdate", 64, 32 }, { "EMPUpdate", 64, 32 }, + { "LeafletDropBehavior", 64, 32 }, { "Overridable", 32, 32 }, { "W3DGameWindow", 1024, 32 }, @@ -387,6 +429,12 @@ static PoolSizeRec sizes[] = { "AIGuardReturnState", 32, 32 }, { "AIGuardPickUpCrateState", 32, 32 }, { "AIGuardAttackAggressorState", 32, 32 }, + { "AIGuardRetaliateInnerState", 32, 32 }, + { "AIGuardRetaliateIdleState", 32, 32 }, + { "AIGuardRetaliateOuterState", 32, 32 }, + { "AIGuardRetaliateReturnState", 32, 32 }, + { "AIGuardRetaliatePickUpCrateState", 32, 32 }, + { "AIGuardRetaliateAttackAggressorState", 32, 32 }, { "AITNGuardInnerState", 32, 32 }, { "AITNGuardIdleState", 32, 32 }, { "AITNGuardOuterState", 32, 32 }, @@ -402,7 +450,9 @@ static PoolSizeRec sizes[] = { "AIDeadState", 600, 32 }, { "AIDockState", 600, 32 }, { "AIExitState", 600, 32 }, + { "AIExitInstantlyState", 600, 32 }, { "AIGuardState", 600, 32 }, + { "AIGuardRetaliateState", 600, 32 }, { "AITunnelNetworkGuardState", 600, 32 }, { "AIHuntState", 600, 32 }, { "AIAttackAreaState", 600, 32 }, @@ -475,6 +525,7 @@ static PoolSizeRec sizes[] = { "AIWanderState", 600, 32 }, { "AIPanicState", 600, 32 }, { "ChinookMoveToBldgState", 32, 32 }, + { "ChinookRecordCreationState", 32, 32 }, { "ScienceInfo", 64, 32 }, { "RankInfo", 32, 32 }, @@ -505,6 +556,7 @@ static PoolSizeRec sizes[] = { "AttackPriorityInfo", 32, 32 }, { "SequentialScript", 32, 32 }, { "Win32LocalFile", 1024, 256 }, + { "StdLocalFile", 1024, 256 }, { "RAMFile", 32, 32 }, { "BattlePlanBonuses", 32, 32 }, { "KindOfPercentProductionChange", 32, 32 }, @@ -579,7 +631,7 @@ static PoolSizeRec sizes[] = { "W3DPrototypeClass", 2048, 32 }, { "EnumeratedIP", 32, 32 }, { "WaterTransparencySetting", 4, 4 }, - + { "WeatherSetting", 4, 4 }, // W3D pools! { "BoxPrototypeClass", 512, 32 }, @@ -591,6 +643,7 @@ static PoolSizeRec sizes[] = { "ParticleEmitterPrototypeClass", 32, 32 }, { "NullPrototypeClass", 32, 32 }, { "HLodPrototypeClass", 512, 32 }, + { "HLodDefClass", 512, 32 }, { "DistLODPrototypeClass", 32, 32 }, { "DazzlePrototypeClass", 32, 32 }, { "CollectionPrototypeClass", 32, 32 }, @@ -608,7 +661,6 @@ static PoolSizeRec sizes[] = { "TerrainTextureClass", 32, 32 }, { "MeshClass", 16384, 1024 }, { "HTreeClass", 8192, 32 }, - { "HLodDefClass", 512, 32 }, { "HLodClass", 4096, 32 }, { "MeshModelClass", 8192, 32 }, { "ShareBufferClass", 32768, 1024 }, @@ -663,7 +715,9 @@ static PoolSizeRec sizes[] = { "DynamicMeshModel", 32, 32 }, { "GapFillerClass", 32, 32 }, { "FontCharsClass", 64, 32 }, - + { "ThumbnailManagerClass", 32, 32}, + { "SmudgeSet", 32, 32}, + { "Smudge", 128, 32}, { 0, 0, 0 } }; diff --git a/GeneralsMD/Code/GameEngine/Source/Common/System/MemoryInit.cpp b/GeneralsMD/Code/GameEngine/Source/Common/System/MemoryInit.cpp index e5e989307a1..f273e28379f 100644 --- a/GeneralsMD/Code/GameEngine/Source/Common/System/MemoryInit.cpp +++ b/GeneralsMD/Code/GameEngine/Source/Common/System/MemoryInit.cpp @@ -184,7 +184,7 @@ static PoolSizeRec sizes[] = { "DeliverPayloadAIUpdate", 32, 32 }, { "DeletionUpdate", 128, 32 }, { "SmartBombTargetHomingUpdate", 8, 8 }, - { "DynamicAudioEventInfo", 16, 256 }, // Note: some levels have none, some have lots. Since all are allocated at level load time, we can set this low for the levels with none. + { "DynamicAudioEventInfo", 16, 256 }, // Note: some levels have none, some have lots. Since all are allocated at level load time, we can set this low for the levels with none. { "HackInternetStateMachine", 32, 32 }, { "HackInternetAIUpdate", 32, 32 }, { "MissileAIUpdate", 512, 32 }, From 33581001b0ed5eb511c651ce04f2889674d34c97 Mon Sep 17 00:00:00 2001 From: xezon <4720891+xezon@users.noreply.github.com> Date: Sat, 2 Aug 2025 15:26:14 +0200 Subject: [PATCH 2/3] refactor(memory): Move memory pool size arrays into separate source files (#1408) --- Core/GameEngine/CMakeLists.txt | 4 + Generals/Code/GameEngine/CMakeLists.txt | 2 + .../System/GameMemoryInitDMA_Generals.inl | 29 + .../System/GameMemoryInitPools_Generals.inl | 660 +++++++++++++++++ .../Source/Common/System/MemoryInit.cpp | 678 +----------------- GeneralsMD/Code/GameEngine/CMakeLists.txt | 2 + .../System/GameMemoryInitDMA_GeneralsMD.inl | 29 + .../System/GameMemoryInitPools_GeneralsMD.inl | 656 +++++++++++++++++ .../Source/Common/System/MemoryInit.cpp | 674 +---------------- 9 files changed, 1410 insertions(+), 1324 deletions(-) create mode 100644 Generals/Code/GameEngine/Source/Common/System/GameMemoryInitDMA_Generals.inl create mode 100644 Generals/Code/GameEngine/Source/Common/System/GameMemoryInitPools_Generals.inl create mode 100644 GeneralsMD/Code/GameEngine/Source/Common/System/GameMemoryInitDMA_GeneralsMD.inl create mode 100644 GeneralsMD/Code/GameEngine/Source/Common/System/GameMemoryInitPools_GeneralsMD.inl diff --git a/Core/GameEngine/CMakeLists.txt b/Core/GameEngine/CMakeLists.txt index 0ebd34e5b80..15b9b827a9d 100644 --- a/Core/GameEngine/CMakeLists.txt +++ b/Core/GameEngine/CMakeLists.txt @@ -1141,6 +1141,10 @@ if(RTS_GAMEMEMORY_ENABLE) list(APPEND GAMEENGINE_SRC # Source/Common/System/GameMemory.cpp # Source/Common/System/GameMemoryInit.cpp +# Source/Common/System/GameMemoryInitDMA_Generals.inl +# Source/Common/System/GameMemoryInitDMA_GeneralsMD.inl +# Source/Common/System/GameMemoryInitPools_Generals.inl +# Source/Common/System/GameMemoryInitPools_GeneralsMD.inl ) else() # Uses the null implementation when disabled. diff --git a/Generals/Code/GameEngine/CMakeLists.txt b/Generals/Code/GameEngine/CMakeLists.txt index 41fd59b68b8..4a2bae048bc 100644 --- a/Generals/Code/GameEngine/CMakeLists.txt +++ b/Generals/Code/GameEngine/CMakeLists.txt @@ -1061,6 +1061,8 @@ if(RTS_GAMEMEMORY_ENABLE) # Uses the original Game Memory implementation. list(APPEND GAMEENGINE_SRC Source/Common/System/GameMemory.cpp + Source/Common/System/GameMemoryInitDMA_Generals.inl + Source/Common/System/GameMemoryInitPools_Generals.inl Source/Common/System/MemoryInit.cpp ) else() diff --git a/Generals/Code/GameEngine/Source/Common/System/GameMemoryInitDMA_Generals.inl b/Generals/Code/GameEngine/Source/Common/System/GameMemoryInitDMA_Generals.inl new file mode 100644 index 00000000000..98a7809fe08 --- /dev/null +++ b/Generals/Code/GameEngine/Source/Common/System/GameMemoryInitDMA_Generals.inl @@ -0,0 +1,29 @@ +/* +** Command & Conquer Generals(tm) +** Copyright 2025 TheSuperHackers +** +** This program is free software: you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation, either version 3 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program. If not, see . +*/ + +static const PoolInitRec DefaultDMA[] = +{ + // name, allocSize, initialCount, overflowCount + { "dmaPool_16", 16, 65536, 1024 }, + { "dmaPool_32", 32, 150000, 1024 }, + { "dmaPool_64", 64, 60000, 1024 }, + { "dmaPool_128", 128, 32768, 1024 }, + { "dmaPool_256", 256, 8192, 1024 }, + { "dmaPool_512", 512, 8192, 1024 }, + { "dmaPool_1024", 1024, 24000, 1024 } +}; diff --git a/Generals/Code/GameEngine/Source/Common/System/GameMemoryInitPools_Generals.inl b/Generals/Code/GameEngine/Source/Common/System/GameMemoryInitPools_Generals.inl new file mode 100644 index 00000000000..b049809df14 --- /dev/null +++ b/Generals/Code/GameEngine/Source/Common/System/GameMemoryInitPools_Generals.inl @@ -0,0 +1,660 @@ +/* +** Command & Conquer Generals(tm) +** Copyright 2025 TheSuperHackers +** +** This program is free software: you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation, either version 3 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program. If not, see . +*/ + +// And please be careful of duplicates. They are not rejected. +// not const -- we might override from INI +static PoolSizeRec PoolSizes[] = +{ + { "PartitionContactListNode", 2048, 512 }, + { "BattleshipUpdate", 32, 32 }, + { "FlyToDestAndDestroyUpdate", 32, 32 }, + { "MusicTrack", 32, 32 }, + { "PositionalSoundPool", 32, 32 }, + { "GameMessage", 2048, 32 }, + { "NameKeyBucketPool", 4096, 32 }, + { "ObjectSellInfo", 16, 16 }, + { "ProductionPrerequisitePool", 1024, 32 }, + { "RadarObject", 512, 32 }, + { "ResourceGatheringManager", 16, 16 }, + { "SightingInfo", 8192, 2048 },// Looks big, but all 3000 objects used to have 4 just built in. + { "SpecialPowerTemplate", 64, 32 }, + { "StateMachinePool", 32, 32 }, + { "TeamPool", 128, 32 }, // if you increase this, increase player/team relation map pools + { "PlayerRelationMapPool", 128, 32 }, + { "TeamRelationMapPool", 128, 32 }, + { "TeamPrototypePool", 256, 32 }, + { "TerrainType", 256, 32 }, + { "ThingTemplatePool", 1200, 32 }, + { "TunnelTracker", 16, 16 }, + { "Upgrade", 16, 16 }, + { "UpgradeTemplate", 128, 16 }, + { "Anim2D", 32, 32 }, + { "CommandButton", 300, 16 }, + { "CommandSet", 256, 16 }, + { "DisplayString", 32, 32 }, + { "WebBrowserURL", 16, 16 }, + { "Drawable", 4096, 32 }, + { "Image", 2048, 32 }, + { "ParticlePool", 4096, 256 }, + { "ParticleSystemTemplatePool", 768, 32 }, + { "ParticleSystemPool", 1024, 32 }, + { "TerrainRoadType", 64, 64, }, + { "WindowLayoutPool", 32, 32 }, + { "AnimatedParticleSysBoneClientUpdate", 16, 16 }, + { "SwayClientUpdate", 4096, 32 }, + { "BeaconClientUpdate", 64, 32 }, + { "AIGroupPool", 64, 32 }, + { "AIDockMachinePool", 256, 32 }, + { "AIGuardMachinePool", 32, 32 }, + { "AIGuardRetaliateMachinePool", 32, 32 }, + { "AITNGuardMachinePool", 32, 32 }, + { "PathNodePool", 8192, 1024 }, + { "PathPool", 256, 16 }, + { "WorkOrder", 32, 32 }, + { "TeamInQueue", 32, 32 }, + { "AIPlayer", 8, 8 }, + { "AISkirmishPlayer", 8, 8 }, + { "AIStateMachine", 600, 32 }, + { "JetAIStateMachine", 64, 32 }, + { "HeliAIStateMachine", 64, 32 }, + { "AIAttackMoveStateMachine", 2048, 32 }, + { "AIAttackThenIdleStateMachine", 512, 32 }, + { "AttackStateMachine", 512, 32 }, + { "CrateTemplate", 32, 32 }, + { "ExperienceTrackerPool", 4096, 256 }, + { "FiringTrackerPool", 4096, 256 }, + { "ObjectRepulsorHelper", 1024, 256 }, + { "ObjectSMCHelperPool", 4096, 256 }, + { "ObjectWeaponStatusHelperPool", 4096, 256 }, + { "ObjectDefectionHelperPool", 4096, 256 }, + { "StatusDamageHelper", 1500, 256 }, + { "SubdualDamageHelper", 1500, 256 }, + { "TempWeaponBonusHelper", 4096, 256 }, + { "Locomotor", 2048, 32 }, + { "LocomotorTemplate", 128, 32 }, + { "ObjectPool", 4096, 32 }, + { "SimpleObjectIteratorPool", 32, 32 }, + { "SimpleObjectIteratorClumpPool", 4096, 32 }, + { "PartitionDataPool", 4096, 32 }, + { "BuildEntry", 32, 32 }, + { "Weapon", 4096, 32 }, + { "WeaponTemplate", 192, 32 }, + { "AIUpdateInterface", 600, 32 }, + { "ActiveBody", 1024, 32 }, + { "ActiveShroudUpgrade", 32, 32 }, + { "AssistedTargetingUpdate", 32, 32 }, + { "AudioEventInfo", 1200, 64 }, + { "AudioRequest", 256, 8 }, + { "AutoHealBehavior", 4096, 32 }, + { "WeaponBonusUpdate", 16, 16 }, + { "GrantStealthBehavior", 4096, 32 }, + { "NeutronBlastBehavior", 4096, 32 }, + { "CountermeasuresBehavior", 256, 32 }, + { "BaseRegenerateUpdate", 64, 32 }, + { "BoneFXDamage", 64, 32 }, + { "BoneFXUpdate", 64, 32 }, + { "BridgeBehavior", 32, 32 }, + { "BridgeTowerBehavior", 32, 32 }, + { "BridgeScaffoldBehavior", 32, 32 }, + { "CaveContain", 16, 16 }, + { "HealContain", 32, 32 }, + { "CreateCrateDie", 256, 128 }, + { "CreateObjectDie", 1024, 32 }, + { "EjectPilotDie", 1024, 32 }, + { "CrushDie", 1024, 32 }, + { "DamDie", 8, 8 }, +#if USE_OBSOLETE_GENERALS_CODE + { "DelayedUpgrade", 32, 32 }, + { "DelayedWeaponSetUpgradeUpdate", 32, 32 }, +#endif + { "DeliverPayloadStateMachine", 32, 32 }, + { "DeliverPayloadAIUpdate", 32, 32 }, + { "DeletionUpdate", 128, 32 }, + { "SmartBombTargetHomingUpdate", 8, 8 }, + { "DynamicAudioEventInfo", 16, 256 }, // Note: some levels have none, some have lots. Since all are allocated at level load time, we can set this low for the levels with none. + { "HackInternetStateMachine", 32, 32 }, + { "HackInternetAIUpdate", 32, 32 }, + { "MissileAIUpdate", 512, 32 }, + { "DumbProjectileBehavior", 64, 32 }, + { "DestroyDie", 1024, 32 }, + { "UpgradeDie", 128, 32 }, + { "KeepObjectDie", 128, 32 }, + { "DozerAIUpdate", 32, 32 }, + { "DynamicGeometryInfoUpdate", 16, 16 }, + { "DynamicShroudClearingRangeUpdate", 128, 16 }, + { "FXListDie", 1024, 32 }, + { "FireSpreadUpdate", 2048, 128 }, + { "FirestormDynamicGeometryInfoUpdate", 16, 16 }, + { "FireWeaponCollide", 2048, 32 }, + { "FireWeaponUpdate", 32, 32 }, + { "FlammableUpdate", 4096, 256 }, + { "FloatUpdate", 512, 128 }, + { "TensileFormationUpdate", 256, 32 }, + { "GarrisonContain", 256, 32 }, + { "HealCrateCollide", 32, 32 }, + { "HeightDieUpdate", 32, 32 }, + { "FireWeaponWhenDamagedBehavior", 32, 32 }, + { "FireWeaponWhenDeadBehavior", 64, 32 }, + { "GenerateMinefieldBehavior", 32, 32 }, + { "HelicopterSlowDeathBehavior", 64, 32 }, + { "ParkingPlaceBehavior", 32, 32 }, + { "FlightDeckBehavior", 8, 8 }, +#ifdef ALLOW_SURRENDER + { "POWTruckAIUpdate", 32, 32, }, + { "POWTruckBehavior", 32, 32, }, + { "PrisonBehavior", 32, 32 }, + { "PrisonVisual", 32, 32 }, + { "PropagandaCenterBehavior", 16, 16 }, +#endif + { "PropagandaTowerBehavior", 16, 16 }, + { "BunkerBusterBehavior", 16, 16 }, + { "ObjectTracker", 128, 32 }, + { "OCLUpdate", 16, 16 }, + { "BodyParticleSystem", 128, 64 }, + { "HighlanderBody", 2048, 128 }, + { "UndeadBody", 32, 32 }, + { "HordeUpdate", 128, 32 }, + { "ImmortalBody", 2048, 128 }, + { "InactiveBody", 2048, 32 }, + { "InstantDeathBehavior", 512, 32 }, + { "LaserUpdate", 32, 32 }, + { "PointDefenseLaserUpdate", 32, 32 }, + { "CleanupHazardUpdate", 32, 32 }, + { "AutoFindHealingUpdate", 256, 32 }, + { "CommandButtonHuntUpdate", 512, 8 }, + { "PilotFindVehicleUpdate", 256, 32 }, + { "DemoTrapUpdate", 32, 32 }, + { "ParticleUplinkCannonUpdate", 16, 16 }, + { "SpectreGunshipUpdate", 8, 8 }, + { "SpectreGunshipDeploymentUpdate", 8, 8 }, + { "BaikonurLaunchPower", 4, 4 }, + { "RadiusDecalUpdate", 16, 16 }, + { "BattlePlanUpdate", 32, 32 }, + { "LifetimeUpdate", 256, 32 }, + { "LocomotorSetUpgrade", 512, 128 }, + { "LockWeaponCreate", 64, 128 }, + { "AutoDepositUpdate", 256, 32 }, + { "NeutronMissileUpdate", 512, 32 }, + { "MoneyCrateCollide", 32, 32 }, + { "NeutronMissileSlowDeathBehavior", 8, 8 }, + { "OpenContain", 128, 32 }, + { "OverchargeBehavior", 32, 32 }, + { "OverlordContain", 32, 32 }, + { "HelixContain", 32, 32 }, + { "ParachuteContain", 128, 32 }, + { "PhysicsBehavior", 600, 32 }, + { "PoisonedBehavior", 512, 64 }, + { "ProductionEntry", 32, 32 }, + { "ProductionUpdate", 256, 32 }, + { "ProjectileStreamUpdate", 32, 32 }, + { "ProneUpdate", 128, 32 }, + { "QueueProductionExitUpdate", 32, 32 }, + { "RadarUpdate", 16, 16 }, + { "RadarUpgrade", 16, 16 }, + { "AnimationSteeringUpdate", 1024, 32 }, + { "SupplyWarehouseCripplingBehavior", 16, 16 }, + { "CostModifierUpgrade", 32, 32 }, + { "CashBountyPower", 32, 32 }, + { "CleanupAreaPower", 32, 32 }, + { "ObjectCreationUpgrade", 128, 32 }, + { "MinefieldBehavior", 256, 32 }, + { "JetSlowDeathBehavior", 64, 32 }, + { "BattleBusSlowDeathBehavior", 64, 32 }, + { "RebuildHoleBehavior", 64, 32 }, + { "RebuildHoleExposeDie", 64, 32 }, + { "RepairDockUpdate", 32, 32 }, +#ifdef ALLOW_SURRENDER + { "PrisonDockUpdate", 32, 32 }, +#endif + { "RailedTransportDockUpdate", 16, 16 }, + { "RailedTransportAIUpdate", 16, 16 }, + { "RailedTransportContain", 16, 16 }, + { "RailroadBehavior", 16, 16 }, + { "SalvageCrateCollide", 32, 32 }, + { "ShroudCrateCollide", 32, 32 }, + { "SlavedUpdate", 64, 32 }, + { "SlowDeathBehavior", 4096, 32 }, + { "SpyVisionUpdate", 16, 16 }, + { "DefaultProductionExitUpdate", 32, 32 }, + { "SpawnPointProductionExitUpdate", 32, 32 }, + { "SpawnBehavior", 32, 32 }, + { "SpecialPowerCompletionDie", 32, 32 }, + { "SpecialPowerCreate", 32, 32 }, + { "PreorderCreate", 32, 32 }, + { "SpecialAbility", 512, 32 }, + { "SpecialAbilityUpdate", 512, 32 }, + { "MissileLauncherBuildingUpdate", 32, 32 }, + { "SquishCollide", 512, 32 }, + { "StructureBody", 512, 64 }, + { "HiveStructureBody", 64, 32 }, //Stinger sites + { "StructureCollapseUpdate", 32, 32 }, + { "StructureToppleUpdate", 32, 32 }, + { "SupplyCenterCreate", 32, 32 }, + { "SupplyCenterDockUpdate", 32, 32 }, + { "SupplyCenterProductionExitUpdate", 32, 32 }, + { "SupplyTruckStateMachine", 256, 32 }, + { "SupplyTruckAIUpdate", 32, 32 }, + { "SupplyWarehouseCreate", 32, 32 }, + { "SupplyWarehouseDockUpdate", 32, 32 }, + { "EnemyNearUpdate", 1024, 32 }, + { "TechBuildingBehavior", 32, 32 }, + { "ToppleUpdate", 2048, 32 }, + { "TransitionDamageFX", 256, 32 }, + { "TransportAIUpdate", 64, 32 }, + { "TransportContain", 128, 32 }, + { "RiderChangeContain", 128, 32 }, + { "InternetHackContain", 16, 16 }, + { "TunnelContain", 16, 16 }, + { "TunnelContainDie", 32, 32 }, + { "TunnelCreate", 32, 32 }, + { "TurretAI", 256, 32 }, + { "TurretStateMachine", 128, 32 }, + { "TurretSwapUpgrade", 512, 128 }, + { "UnitCrateCollide", 32, 32 }, + { "UnpauseSpecialPowerUpgrade", 32, 32 }, + { "VeterancyCrateCollide", 32, 32 }, + { "VeterancyGainCreate", 512, 128 }, + { "ConvertToCarBombCrateCollide", 32, 32 }, + { "ConvertToHijackedVehicleCrateCollide", 32, 32 }, + { "SabotageCommandCenterCrateCollide", 256, 128 }, + { "SabotageFakeBuildingCrateCollide", 256, 128 }, + { "SabotageInternetCenterCrateCollide", 256, 128 }, + { "SabotageMilitaryFactoryCrateCollide", 256, 128 }, + { "SabotagePowerPlantCrateCollide", 256, 128 }, + { "SabotageSuperweaponCrateCollide", 256, 128 }, + { "SabotageSupplyCenterCrateCollide", 256, 128 }, + { "SabotageSupplyDropzoneCrateCollide", 256, 128 }, + { "JetAIUpdate", 64, 32 }, + { "ChinookAIUpdate", 32, 32 }, + { "WanderAIUpdate", 32, 32 }, + { "WaveGuideUpdate", 16, 16 }, + { "WeaponBonusUpgrade", 512, 128 }, + { "WeaponSetUpgrade", 512, 128 }, + { "ArmorUpgrade", 512, 128 }, + { "WorkerAIUpdate", 128, 128 }, + { "WorkerStateMachine", 128, 128 }, + { "ChinookAIStateMachine", 32, 32 }, + { "DeployStyleAIUpdate", 32, 32 }, + { "AssaultTransportAIUpdate", 64, 32 }, + { "StreamingArchiveFile", 8, 8 }, + + { "DozerActionStateMachine", 256, 32 }, + { "DozerPrimaryStateMachine", 256, 32 }, + { "W3DDisplayString", 1024, 128 }, + { "W3DDefaultDraw", 1024, 128 }, + { "W3DDebrisDraw", 1024, 128 }, + { "W3DDependencyModelDraw", 64, 64 }, + { "W3DLaserDraw", 32, 32 }, + { "W3DModelDraw", 4096, 128 }, + { "W3DOverlordTankDraw", 64, 64 }, + { "W3DOverlordTruckDraw", 64, 64 }, + { "W3DOverlordAircraftDraw", 64, 64 }, + { "W3DPoliceCarDraw", 32, 32 }, + { "W3DProjectileStreamDraw", 32, 32 }, + { "W3DRopeDraw", 32, 32 }, + { "W3DScienceModelDraw", 32, 32 }, + { "W3DSupplyDraw", 32, 32 }, + { "W3DTankDraw", 256, 32 }, + { "W3DTreeDraw", 16, 16 }, + { "W3DPropDraw", 16, 16 }, + { "W3DTracerDraw", 64, 32 }, + { "W3DTruckDraw", 128, 32 }, + { "W3DTankTruckDraw", 32, 16 }, + { "W3DTreeTextureClass", 4, 4 }, + { "DefaultSpecialPower", 32, 32 }, + { "OCLSpecialPower", 32, 32 }, + { "FireWeaponPower", 32, 32 }, +#ifdef ALLOW_DEMORALIZE + { "DemoralizeSpecialPower", 16, 16, }, +#endif + { "CashHackSpecialPower", 32, 32 }, + { "CommandSetUpgrade", 32, 32 }, + { "PassengersFireUpgrade", 32, 32 }, + { "GrantUpgradeCreate", 256, 32 }, + { "GrantScienceUpgrade", 256, 32 }, + { "ReplaceObjectUpgrade", 32, 32 }, + { "ModelConditionUpgrade", 32, 32 }, + { "SpyVisionSpecialPower", 256, 32 }, + { "StealthDetectorUpdate", 256, 32 }, + { "StealthUpdate", 256, 32 }, + { "StealthUpgrade", 256, 32 }, + { "StatusBitsUpgrade", 128, 128 }, + { "SubObjectsUpgrade", 128, 128 }, + { "ExperienceScalarUpgrade", 256, 128 }, + { "MaxHealthUpgrade", 128, 128 }, + { "WeaponBonusUpgrade", 128, 64 }, + { "StickyBombUpdate", 64, 32 }, + { "FireOCLAfterWeaponCooldownUpdate", 64, 32 }, + { "HijackerUpdate", 64, 32 }, + { "ChinaMinesUpgrade", 64, 32 }, + { "PowerPlantUpdate", 16, 16 }, + { "PowerPlantUpgrade", 16, 16 }, + { "DefectorSpecialPower", 16, 16 }, + { "CheckpointUpdate", 16, 16 }, + { "MobNexusContain", 128, 32 }, + { "MobMemberSlavedUpdate", 64, 32 }, + { "EMPUpdate", 64, 32 }, + { "LeafletDropBehavior", 64, 32 }, + { "Overridable", 32, 32 }, + + { "W3DGameWindow", 1024, 32 }, + { "GameWindowDummy", 1024, 32 }, + { "SuccessState", 32, 32 }, + { "FailureState", 32, 32 }, + { "ContinueState", 32, 32 }, + { "SleepState", 32, 32 }, + + { "AIDockWaitForClearanceState", 256, 32 }, + { "AIDockProcessDockState", 256, 32 }, + { "AIGuardInnerState", 32, 32 }, + { "AIGuardIdleState", 32, 32 }, + { "AIGuardOuterState", 32, 32 }, + { "AIGuardReturnState", 32, 32 }, + { "AIGuardPickUpCrateState", 32, 32 }, + { "AIGuardAttackAggressorState", 32, 32 }, + { "AIGuardRetaliateInnerState", 32, 32 }, + { "AIGuardRetaliateIdleState", 32, 32 }, + { "AIGuardRetaliateOuterState", 32, 32 }, + { "AIGuardRetaliateReturnState", 32, 32 }, + { "AIGuardRetaliatePickUpCrateState", 32, 32 }, + { "AIGuardRetaliateAttackAggressorState", 32, 32 }, + { "AITNGuardInnerState", 32, 32 }, + { "AITNGuardIdleState", 32, 32 }, + { "AITNGuardOuterState", 32, 32 }, + { "AITNGuardReturnState", 32, 32 }, + { "AITNGuardPickUpCrateState", 32, 32 }, + { "AITNGuardAttackAggressorState", 32, 32 }, + { "AIIdleState", 2400, 32 }, + { "AIRappelState", 600, 32 }, + { "AIBusyState", 600, 32 }, + { "AIWaitState", 600, 32 }, + { "AIAttackState", 4096, 32 }, + { "AIAttackSquadState", 600, 32 }, + { "AIDeadState", 600, 32 }, + { "AIDockState", 600, 32 }, + { "AIExitState", 600, 32 }, + { "AIExitInstantlyState", 600, 32 }, + { "AIGuardState", 600, 32 }, + { "AIGuardRetaliateState", 600, 32 }, + { "AITunnelNetworkGuardState", 600, 32 }, + { "AIHuntState", 600, 32 }, + { "AIAttackAreaState", 600, 32 }, + { "AIFaceState", 1200, 32 }, + { "ApproachState", 600, 32 }, + { "DeliveringState", 600, 32 }, + { "ConsiderNewApproachState", 600, 32 }, + { "RecoverFromOffMapState", 600, 32 }, + { "HeadOffMapState", 600, 32 }, + { "CleanUpState", 600, 32 }, + { "HackInternetState", 600, 32 }, + { "PackingState", 600, 32 }, + { "UnpackingState", 600, 32 }, + { "SupplyTruckWantsToPickUpOrDeliverBoxesState", 600, 32 }, + { "RegroupingState", 600, 32 }, + { "DockingState", 600, 32 }, + { "ChinookEvacuateState", 32, 32 }, + { "ChinookHeadOffMapState", 32, 32 }, + { "ChinookTakeoffOrLandingState", 32, 32 }, + { "ChinookCombatDropState", 32, 32 }, + { "DozerActionPickActionPosState", 256, 32 }, + { "DozerActionMoveToActionPosState", 256, 32 }, + { "DozerActionDoActionState", 256, 32 }, + { "DozerPrimaryIdleState", 256, 32 }, + { "DozerActionState", 256, 32 }, + { "DozerPrimaryGoingHomeState", 256, 32 }, + { "JetAwaitingRunwayState", 64, 32 }, + { "JetOrHeliCirclingDeadAirfieldState", 64, 32 }, + { "HeliTakeoffOrLandingState", 64, 32 }, + { "JetOrHeliParkOrientState", 64, 32 }, + { "JetOrHeliReloadAmmoState", 64, 32 }, + { "SupplyTruckBusyState", 600, 32 }, + { "SupplyTruckIdleState", 600, 32 }, + { "ActAsDozerState", 600, 32 }, + { "ActAsSupplyTruckState", 600, 32 }, + { "AIDockApproachState", 256, 32 }, + { "AIDockAdvancePositionState", 256, 32 }, + { "AIDockMoveToEntryState", 256, 32 }, + { "AIDockMoveToDockState", 256, 32 }, + { "AIDockMoveToExitState", 256, 32 }, + { "AIDockMoveToRallyState", 256, 32 }, + { "AIMoveToState", 600, 32 }, + { "AIMoveOutOfTheWayState", 600, 32 }, + { "AIMoveAndTightenState", 600, 32 }, + { "AIMoveAwayFromRepulsorsState", 600, 32 }, + { "AIAttackApproachTargetState", 96, 32 }, + { "AIAttackPursueTargetState", 96, 32 }, + { "AIAttackAimAtTargetState", 96, 32 }, + { "AIAttackFireWeaponState", 256, 32 }, + { "AIPickUpCrateState", 4096, 32 }, + { "AIFollowWaypointPathState", 1200, 32 }, + { "AIFollowWaypointPathExactState", 1200, 32 }, + { "AIWanderInPlaceState", 600, 32 }, + { "AIFollowPathState", 1200, 32 }, + { "AIMoveAndEvacuateState", 1200, 32 }, + { "AIMoveAndDeleteState", 600, 32 }, + { "AIEnterState", 600, 32 }, + { "JetOrHeliReturningToDeadAirfieldState", 64, 32 }, + { "JetOrHeliReturnForLandingState", 64, 32 }, + { "TurretAIIdleState", 600, 32 }, + { "TurretAIIdleScanState", 600, 32 }, + { "TurretAIAimTurretState", 600, 32 }, + { "TurretAIRecenterTurretState", 600, 32 }, + { "TurretAIHoldTurretState", 600, 32 }, + { "JetOrHeliTaxiState", 64, 32 }, + { "JetTakeoffOrLandingState", 64, 32 }, + { "JetPauseBeforeTakeoffState", 64, 32 }, + { "AIAttackMoveToState", 600, 32 }, + { "AIAttackFollowWaypointPathState", 1200, 32 }, + { "AIWanderState", 600, 32 }, + { "AIPanicState", 600, 32 }, + { "ChinookMoveToBldgState", 32, 32 }, + { "ChinookRecordCreationState", 32, 32 }, + { "ScienceInfo", 64, 32 }, + { "RankInfo", 32, 32 }, + + { "FireWeaponNugget", 32, 32 }, + { "AttackNugget", 32, 32 }, + { "DeliverPayloadNugget", 32, 32 }, + { "ApplyRandomForceNugget", 32, 32 }, + { "GenericObjectCreationNugget", 512, 32 }, + { "SoundFXNugget", 256, 32 }, + { "TracerFXNugget", 32, 32 }, + { "RayEffectFXNugget", 32, 32 }, + { "LightPulseFXNugget", 64, 32 }, + { "ViewShakeFXNugget", 128, 32 }, + { "TerrainScorchFXNugget", 32, 32 }, + { "ParticleSystemFXNugget", 600, 32 }, + { "FXListAtBonePosFXNugget", 32, 32 }, + { "Squad", 256, 32 }, + { "BuildListInfo", 256, 32 }, + + { "ScriptGroup", 128, 32 }, + { "OrCondition", 1024, 256 }, + { "ScriptAction", 2048, 512 }, + { "Script", 1024, 256 }, + { "Parameter", 8192, 1024 }, + { "Condition", 2048, 256 }, + { "Template", 32, 32 }, + { "ScriptList", 32, 32 }, + { "AttackPriorityInfo", 32, 32 }, + { "SequentialScript", 32, 32 }, + { "Win32LocalFile", 1024, 256 }, + { "StdLocalFile", 1024, 256 }, + { "RAMFile", 32, 32 }, + { "BattlePlanBonuses", 32, 32 }, + { "KindOfPercentProductionChange", 32, 32 }, + { "UserParser", 4096, 256 }, + { "XferBlockData", 32, 32 }, + { "EvaCheckInfo", 32, 32 }, + { "SuperweaponInfo", 32, 32 }, + { "NamedTimerInfo", 32, 32 }, + { "PopupMessageData", 32, 32 }, + { "FloatingTextData", 32, 32 }, + { "MapObject", 4096, 32 }, + { "Waypoint", 1024, 32 }, + { "PolygonTrigger", 128, 32 }, + { "Bridge", 32, 32 }, + { "Mapping", 128, 32 }, + { "OutputChunk", 32, 32 }, + { "InputChunk", 32, 32 }, + { "AnimateWindow", 32, 32 }, + { "GameFont", 32, 32 }, + { "NetCommandRef", 256, 32 }, + { "GameMessageArgument", 128, 32 }, + { "GameMessageParserArgumentType", 32, 32 }, + { "GameMessageParser", 32, 32 }, + { "WeaponBonusSet", 32, 32 }, + { "Campaign", 32, 32 }, + { "Mission", 32, 32 }, + { "ModalWindow", 32, 32 }, + { "NetPacket", 32, 32 }, + { "AISideInfo", 32, 32 }, + { "AISideBuildList", 32, 32 }, + { "MetaMapRec", 256, 32 }, + { "TransportStatus", 32, 32 }, + { "Anim2DTemplate", 32, 32 }, + { "ObjectTypes", 32, 32 }, + { "NetCommandList", 512, 32 }, + { "TurretAIData", 256, 32 }, + { "NetCommandMsg", 32, 32 }, + { "NetGameCommandMsg", 64, 32 }, + { "NetAckBothCommandMsg", 32, 32 }, + { "NetAckStage1CommandMsg", 32, 32 }, + { "NetAckStage2CommandMsg", 32, 32 }, + { "NetFrameCommandMsg", 32, 32 }, + { "NetPlayerLeaveCommandMsg", 32, 32 }, + { "NetRunAheadMetricsCommandMsg", 32, 32 }, + { "NetRunAheadCommandMsg", 32, 32 }, + { "NetDestroyPlayerCommandMsg", 32, 32 }, + { "NetDisconnectFrameCommandMsg", 32, 32 }, + { "NetDisconnectScreenOffCommandMsg", 32, 32 }, + { "NetFrameResendRequestCommandMsg", 32, 32 }, + { "NetKeepAliveCommandMsg", 32, 32 }, + { "NetDisconnectKeepAliveCommandMsg", 32, 32 }, + { "NetDisconnectPlayerCommandMsg", 32, 32 }, + { "NetPacketRouterQueryCommandMsg", 32, 32 }, + { "NetPacketRouterAckCommandMsg", 32, 32 }, + { "NetDisconnectChatCommandMsg", 32, 32 }, + { "NetChatCommandMsg", 32, 32 }, + { "NetDisconnectVoteCommandMsg", 32, 32 }, + { "NetProgressCommandMsg", 32, 32 }, + { "NetWrapperCommandMsg", 32, 32 }, + { "NetFileCommandMsg", 32, 32 }, + { "NetFileAnnounceCommandMsg", 32, 32 }, + { "NetFileProgressCommandMsg", 32, 32 }, + { "NetCommandWrapperListNode", 32, 32 }, + { "NetCommandWrapperList", 32, 32 }, + { "Connection", 32, 32 }, + { "User", 32, 32 }, + { "FrameDataManager", 32, 32 }, + { "DrawableIconInfo", 32, 32 }, + { "TintEnvelope", 128, 32 }, + { "DynamicAudioEventRTS", 1024, 256 }, + { "DrawableLocoInfo", 128, 32 }, + { "W3DPrototypeClass", 2048, 32 }, + { "EnumeratedIP", 32, 32 }, + { "WaterTransparencySetting", 4, 4 }, + { "WeatherSetting", 4, 4 }, + + // W3D pools! + { "BoxPrototypeClass", 512, 32 }, + { "SpherePrototypeClass", 32, 32 }, + { "SoundRenderObjPrototypeClass", 32, 32 }, + { "RingPrototypeClass", 32, 32 }, + { "PrimitivePrototypeClass", 8192, 32 }, + { "HModelPrototypeClass", 256, 32 }, + { "ParticleEmitterPrototypeClass", 32, 32 }, + { "NullPrototypeClass", 32, 32 }, + { "HLodPrototypeClass", 512, 32 }, + { "HLodDefClass", 512, 32 }, + { "DistLODPrototypeClass", 32, 32 }, + { "DazzlePrototypeClass", 32, 32 }, + { "CollectionPrototypeClass", 32, 32 }, + { "BoxPrototypeClass", 256, 32 }, + { "AggregatePrototypeClass", 32, 32 }, + { "OBBoxRenderObjClass", 16384, 32 }, + { "AABoxRenderObjClass", 32, 32 }, + { "VertexMaterialClass", 16384, 32 }, + { "TextureClass", 1024, 32 }, + { "CloudMapTerrainTextureClass", 32, 32 }, + { "ScorchTextureClass", 32, 32 }, + { "LightMapTerrainTextureClass", 32, 32 }, + { "AlphaEdgeTextureClass", 32, 32 }, + { "AlphaTerrainTextureClass", 32, 32 }, + { "TerrainTextureClass", 32, 32 }, + { "MeshClass", 16384, 1024 }, + { "HTreeClass", 8192, 32 }, + { "HLodClass", 4096, 32 }, + { "MeshModelClass", 8192, 32 }, + { "ShareBufferClass", 32768, 1024 }, + { "AABTreeClass", 32, 32 }, + { "MotionChannelClass", 16384, 32 }, + { "BitChannelClass", 64, 32 }, + { "TimeCodedMotionChannelClass", 32, 32 }, + { "AdaptiveDeltaMotionChannelClass", 32, 32 }, + { "TimeCodedBitChannelClass", 32, 32 }, + { "UVBufferClass", 8192, 32 }, + { "TexBufferClass", 512, 32 }, + { "MatBufferClass", 512, 32 }, + { "MatrixMapperClass", 32, 32 }, + { "ScaleTextureMapperClass", 32, 32 }, + { "LinearOffsetTextureMapperClass", 32, 32 }, + { "GridTextureMapperClass", 32, 32 }, + { "RotateTextureMapperClass", 32, 32 }, + { "SineLinearOffsetTextureMapperClass", 32, 32 }, + { "StepLinearOffsetTextureMapperClass", 32, 32 }, + { "ZigZagLinearOffsetTextureMapperClass", 32, 32 }, + { "ClassicEnvironmentMapperClass", 32, 32 }, + { "EnvironmentMapperClass", 256, 32 }, + { "EdgeMapperClass", 32, 32 }, + { "WSClassicEnvironmentMapperClass", 32, 32 }, + { "WSEnvironmentMapperClass", 32, 32 }, + { "GridClassicEnvironmentMapperClass", 32, 32 }, + { "GridEnvironmentMapperClass", 32, 32 }, + { "ScreenMapperClass", 32, 32 }, + { "RandomTextureMapperClass", 32, 32 }, + { "BumpEnvTextureMapperClass", 32, 32 }, + { "MeshLoadContextClass", 32, 32 }, + { "MaterialInfoClass", 8192, 32 }, + { "MeshMatDescClass", 8192, 32 }, + { "TextureLoadTaskClass", 256, 32 }, + { "SortingNodeStruct", 256, 32 }, + { "ProxyArrayClass", 32, 32 }, + { "Line3DClass", 128, 32 }, + { "Render2DClass", 64, 32 }, + { "SurfaceClass", 128, 32 }, + { "FontCharsClassCharDataStruct", 1024, 32 }, + { "FontCharsBuffer", 16, 4 }, + { "FVFInfoClass", 128, 32 }, + { "TerrainTracksRenderObjClass", 128, 32 }, + { "DynamicIBAccessClass", 32, 32 }, + { "DX8IndexBufferClass", 128, 32 }, + { "SortingIndexBufferClass", 32, 32 }, + { "DX8VertexBufferClass", 128, 32 }, + { "SortingVertexBufferClass", 32, 32 }, + { "DynD3DMATERIAL8", 8192, 32 }, + { "DynamicMatrix3D", 512, 32 }, + { "MeshGeometryClass", 32, 32 }, + { "DynamicMeshModel", 32, 32 }, + { "GapFillerClass", 32, 32 }, + { "FontCharsClass", 64, 32 }, + { "ThumbnailManagerClass", 32, 32}, + { "SmudgeSet", 32, 32}, + { "Smudge", 128, 32}, + { 0, 0, 0 } +}; diff --git a/Generals/Code/GameEngine/Source/Common/System/MemoryInit.cpp b/Generals/Code/GameEngine/Source/Common/System/MemoryInit.cpp index 3c2f00837f0..5bb04a9d78e 100644 --- a/Generals/Code/GameEngine/Source/Common/System/MemoryInit.cpp +++ b/Generals/Code/GameEngine/Source/Common/System/MemoryInit.cpp @@ -49,27 +49,6 @@ #include "Lib/BaseType.h" #include "Common/GameMemory.h" - -//----------------------------------------------------------------------------- -void userMemoryManagerGetDmaParms(Int *numSubPools, const PoolInitRec **pParms) -{ - static const PoolInitRec defaultDMA[7] = - { - // name, allocsize, initialcount, overflowcount - { "dmaPool_16", 16, 65536, 1024 }, - { "dmaPool_32", 32, 150000, 1024 }, - { "dmaPool_64", 64, 60000, 1024 }, - { "dmaPool_128", 128, 32768, 1024 }, - { "dmaPool_256", 256, 8192, 1024 }, - { "dmaPool_512", 512, 8192, 1024 }, - { "dmaPool_1024", 1024, 24000, 1024 } - }; - - *numSubPools = 7; - *pParms = defaultDMA; -} - -//----------------------------------------------------------------------------- struct PoolSizeRec { const char* name; @@ -77,649 +56,20 @@ struct PoolSizeRec Int overflow; }; -//----------------------------------------------------------------------------- -// And please be careful of duplicates. They are not rejected. -// not const -- we might override from INI -static PoolSizeRec sizes[] = -{ - { "PartitionContactListNode", 2048, 512 }, - { "BattleshipUpdate", 32, 32 }, - { "FlyToDestAndDestroyUpdate", 32, 32 }, - { "MusicTrack", 32, 32 }, - { "PositionalSoundPool", 32, 32 }, - { "GameMessage", 2048, 32 }, - { "NameKeyBucketPool", 4096, 32 }, - { "ObjectSellInfo", 16, 16 }, - { "ProductionPrerequisitePool", 1024, 32 }, - { "RadarObject", 512, 32 }, - { "ResourceGatheringManager", 16, 16 }, - { "SightingInfo", 8192, 2048 },// Looks big, but all 3000 objects used to have 4 just built in. - { "SpecialPowerTemplate", 64, 32 }, - { "StateMachinePool", 32, 32 }, - { "TeamPool", 128, 32 }, // if you increase this, increase player/team relation map pools - { "PlayerRelationMapPool", 128, 32 }, - { "TeamRelationMapPool", 128, 32 }, - { "TeamPrototypePool", 256, 32 }, - { "TerrainType", 256, 32 }, - { "ThingTemplatePool", 1200, 32 }, - { "TunnelTracker", 16, 16 }, - { "Upgrade", 16, 16 }, - { "UpgradeTemplate", 128, 16 }, - { "Anim2D", 32, 32 }, - { "CommandButton", 300, 16 }, - { "CommandSet", 256, 16 }, - { "DisplayString", 32, 32 }, - { "WebBrowserURL", 16, 16 }, - { "Drawable", 4096, 32 }, - { "Image", 2048, 32 }, - { "ParticlePool", 4096, 256 }, - { "ParticleSystemTemplatePool", 768, 32 }, - { "ParticleSystemPool", 1024, 32 }, - { "TerrainRoadType", 64, 64, }, - { "WindowLayoutPool", 32, 32 }, - { "AnimatedParticleSysBoneClientUpdate", 16, 16 }, - { "SwayClientUpdate", 4096, 32 }, - { "BeaconClientUpdate", 64, 32 }, - { "AIGroupPool", 64, 32 }, - { "AIDockMachinePool", 256, 32 }, - { "AIGuardMachinePool", 32, 32 }, - { "AIGuardRetaliateMachinePool", 32, 32 }, - { "AITNGuardMachinePool", 32, 32 }, - { "PathNodePool", 8192, 1024 }, - { "PathPool", 256, 16 }, - { "WorkOrder", 32, 32 }, - { "TeamInQueue", 32, 32 }, - { "AIPlayer", 8, 8 }, - { "AISkirmishPlayer", 8, 8 }, - { "AIStateMachine", 600, 32 }, - { "JetAIStateMachine", 64, 32 }, - { "HeliAIStateMachine", 64, 32 }, - { "AIAttackMoveStateMachine", 2048, 32 }, - { "AIAttackThenIdleStateMachine", 512, 32 }, - { "AttackStateMachine", 512, 32 }, - { "CrateTemplate", 32, 32 }, - { "ExperienceTrackerPool", 4096, 256 }, - { "FiringTrackerPool", 4096, 256 }, - { "ObjectRepulsorHelper", 1024, 256 }, - { "ObjectSMCHelperPool", 4096, 256 }, - { "ObjectWeaponStatusHelperPool", 4096, 256 }, - { "ObjectDefectionHelperPool", 4096, 256 }, - { "StatusDamageHelper", 1500, 256 }, - { "SubdualDamageHelper", 1500, 256 }, - { "TempWeaponBonusHelper", 4096, 256 }, - { "Locomotor", 2048, 32 }, - { "LocomotorTemplate", 128, 32 }, - { "ObjectPool", 4096, 32 }, - { "SimpleObjectIteratorPool", 32, 32 }, - { "SimpleObjectIteratorClumpPool", 4096, 32 }, - { "PartitionDataPool", 4096, 32 }, - { "BuildEntry", 32, 32 }, - { "Weapon", 4096, 32 }, - { "WeaponTemplate", 192, 32 }, - { "AIUpdateInterface", 600, 32 }, - { "ActiveBody", 1024, 32 }, - { "ActiveShroudUpgrade", 32, 32 }, - { "AssistedTargetingUpdate", 32, 32 }, - { "AudioEventInfo", 1200, 64 }, - { "AudioRequest", 256, 8 }, - { "AutoHealBehavior", 4096, 32 }, - { "WeaponBonusUpdate", 16, 16 }, - { "GrantStealthBehavior", 4096, 32 }, - { "NeutronBlastBehavior", 4096, 32 }, - { "CountermeasuresBehavior", 256, 32 }, - { "BaseRegenerateUpdate", 64, 32 }, - { "BoneFXDamage", 64, 32 }, - { "BoneFXUpdate", 64, 32 }, - { "BridgeBehavior", 32, 32 }, - { "BridgeTowerBehavior", 32, 32 }, - { "BridgeScaffoldBehavior", 32, 32 }, - { "CaveContain", 16, 16 }, - { "HealContain", 32, 32 }, - { "CreateCrateDie", 256, 128 }, - { "CreateObjectDie", 1024, 32 }, - { "EjectPilotDie", 1024, 32 }, - { "CrushDie", 1024, 32 }, - { "DamDie", 8, 8 }, -#if USE_OBSOLETE_GENERALS_CODE - { "DelayedUpgrade", 32, 32 }, - { "DelayedWeaponSetUpgradeUpdate", 32, 32 }, -#endif - { "DeliverPayloadStateMachine", 32, 32 }, - { "DeliverPayloadAIUpdate", 32, 32 }, - { "DeletionUpdate", 128, 32 }, - { "SmartBombTargetHomingUpdate", 8, 8 }, - { "DynamicAudioEventInfo", 16, 256 }, // Note: some levels have none, some have lots. Since all are allocated at level load time, we can set this low for the levels with none. - { "HackInternetStateMachine", 32, 32 }, - { "HackInternetAIUpdate", 32, 32 }, - { "MissileAIUpdate", 512, 32 }, - { "DumbProjectileBehavior", 64, 32 }, - { "DestroyDie", 1024, 32 }, - { "UpgradeDie", 128, 32 }, - { "KeepObjectDie", 128, 32 }, - { "DozerAIUpdate", 32, 32 }, - { "DynamicGeometryInfoUpdate", 16, 16 }, - { "DynamicShroudClearingRangeUpdate", 128, 16 }, - { "FXListDie", 1024, 32 }, - { "FireSpreadUpdate", 2048, 128 }, - { "FirestormDynamicGeometryInfoUpdate", 16, 16 }, - { "FireWeaponCollide", 2048, 32 }, - { "FireWeaponUpdate", 32, 32 }, - { "FlammableUpdate", 4096, 256 }, - { "FloatUpdate", 512, 128 }, - { "TensileFormationUpdate", 256, 32 }, - { "GarrisonContain", 256, 32 }, - { "HealCrateCollide", 32, 32 }, - { "HeightDieUpdate", 32, 32 }, - { "FireWeaponWhenDamagedBehavior", 32, 32 }, - { "FireWeaponWhenDeadBehavior", 64, 32 }, - { "GenerateMinefieldBehavior", 32, 32 }, - { "HelicopterSlowDeathBehavior", 64, 32 }, - { "ParkingPlaceBehavior", 32, 32 }, - { "FlightDeckBehavior", 8, 8 }, -#ifdef ALLOW_SURRENDER - { "POWTruckAIUpdate", 32, 32, }, - { "POWTruckBehavior", 32, 32, }, - { "PrisonBehavior", 32, 32 }, - { "PrisonVisual", 32, 32 }, - { "PropagandaCenterBehavior", 16, 16 }, -#endif - { "PropagandaTowerBehavior", 16, 16 }, - { "BunkerBusterBehavior", 16, 16 }, - { "ObjectTracker", 128, 32 }, - { "OCLUpdate", 16, 16 }, - { "BodyParticleSystem", 128, 64 }, - { "HighlanderBody", 2048, 128 }, - { "UndeadBody", 32, 32 }, - { "HordeUpdate", 128, 32 }, - { "ImmortalBody", 2048, 128 }, - { "InactiveBody", 2048, 32 }, - { "InstantDeathBehavior", 512, 32 }, - { "LaserUpdate", 32, 32 }, - { "PointDefenseLaserUpdate", 32, 32 }, - { "CleanupHazardUpdate", 32, 32 }, - { "AutoFindHealingUpdate", 256, 32 }, - { "CommandButtonHuntUpdate", 512, 8 }, - { "PilotFindVehicleUpdate", 256, 32 }, - { "DemoTrapUpdate", 32, 32 }, - { "ParticleUplinkCannonUpdate", 16, 16 }, - { "SpectreGunshipUpdate", 8, 8 }, - { "SpectreGunshipDeploymentUpdate", 8, 8 }, - { "BaikonurLaunchPower", 4, 4 }, - { "RadiusDecalUpdate", 16, 16 }, - { "BattlePlanUpdate", 32, 32 }, - { "LifetimeUpdate", 256, 32 }, - { "LocomotorSetUpgrade", 512, 128 }, - { "LockWeaponCreate", 64, 128 }, - { "AutoDepositUpdate", 256, 32 }, - { "NeutronMissileUpdate", 512, 32 }, - { "MoneyCrateCollide", 32, 32 }, - { "NeutronMissileSlowDeathBehavior", 8, 8 }, - { "OpenContain", 128, 32 }, - { "OverchargeBehavior", 32, 32 }, - { "OverlordContain", 32, 32 }, - { "HelixContain", 32, 32 }, - { "ParachuteContain", 128, 32 }, - { "PhysicsBehavior", 600, 32 }, - { "PoisonedBehavior", 512, 64 }, - { "ProductionEntry", 32, 32 }, - { "ProductionUpdate", 256, 32 }, - { "ProjectileStreamUpdate", 32, 32 }, - { "ProneUpdate", 128, 32 }, - { "QueueProductionExitUpdate", 32, 32 }, - { "RadarUpdate", 16, 16 }, - { "RadarUpgrade", 16, 16 }, - { "AnimationSteeringUpdate", 1024, 32 }, - { "SupplyWarehouseCripplingBehavior", 16, 16 }, - { "CostModifierUpgrade", 32, 32 }, - { "CashBountyPower", 32, 32 }, - { "CleanupAreaPower", 32, 32 }, - { "ObjectCreationUpgrade", 128, 32 }, - { "MinefieldBehavior", 256, 32 }, - { "JetSlowDeathBehavior", 64, 32 }, - { "BattleBusSlowDeathBehavior", 64, 32 }, - { "RebuildHoleBehavior", 64, 32 }, - { "RebuildHoleExposeDie", 64, 32 }, - { "RepairDockUpdate", 32, 32 }, -#ifdef ALLOW_SURRENDER - { "PrisonDockUpdate", 32, 32 }, -#endif - { "RailedTransportDockUpdate", 16, 16 }, - { "RailedTransportAIUpdate", 16, 16 }, - { "RailedTransportContain", 16, 16 }, - { "RailroadBehavior", 16, 16 }, - { "SalvageCrateCollide", 32, 32 }, - { "ShroudCrateCollide", 32, 32 }, - { "SlavedUpdate", 64, 32 }, - { "SlowDeathBehavior", 4096, 32 }, - { "SpyVisionUpdate", 16, 16 }, - { "DefaultProductionExitUpdate", 32, 32 }, - { "SpawnPointProductionExitUpdate", 32, 32 }, - { "SpawnBehavior", 32, 32 }, - { "SpecialPowerCompletionDie", 32, 32 }, - { "SpecialPowerCreate", 32, 32 }, - { "PreorderCreate", 32, 32 }, - { "SpecialAbility", 512, 32 }, - { "SpecialAbilityUpdate", 512, 32 }, - { "MissileLauncherBuildingUpdate", 32, 32 }, - { "SquishCollide", 512, 32 }, - { "StructureBody", 512, 64 }, - { "HiveStructureBody", 64, 32 }, //Stinger sites - { "StructureCollapseUpdate", 32, 32 }, - { "StructureToppleUpdate", 32, 32 }, - { "SupplyCenterCreate", 32, 32 }, - { "SupplyCenterDockUpdate", 32, 32 }, - { "SupplyCenterProductionExitUpdate", 32, 32 }, - { "SupplyTruckStateMachine", 256, 32 }, - { "SupplyTruckAIUpdate", 32, 32 }, - { "SupplyWarehouseCreate", 32, 32 }, - { "SupplyWarehouseDockUpdate", 32, 32 }, - { "EnemyNearUpdate", 1024, 32 }, - { "TechBuildingBehavior", 32, 32 }, - { "ToppleUpdate", 2048, 32 }, - { "TransitionDamageFX", 256, 32 }, - { "TransportAIUpdate", 64, 32 }, - { "TransportContain", 128, 32 }, - { "RiderChangeContain", 128, 32 }, - { "InternetHackContain", 16, 16 }, - { "TunnelContain", 16, 16 }, - { "TunnelContainDie", 32, 32 }, - { "TunnelCreate", 32, 32 }, - { "TurretAI", 256, 32 }, - { "TurretStateMachine", 128, 32 }, - { "TurretSwapUpgrade", 512, 128 }, - { "UnitCrateCollide", 32, 32 }, - { "UnpauseSpecialPowerUpgrade", 32, 32 }, - { "VeterancyCrateCollide", 32, 32 }, - { "VeterancyGainCreate", 512, 128 }, - { "ConvertToCarBombCrateCollide", 32, 32 }, - { "ConvertToHijackedVehicleCrateCollide", 32, 32 }, - { "SabotageCommandCenterCrateCollide", 256, 128 }, - { "SabotageFakeBuildingCrateCollide", 256, 128 }, - { "SabotageInternetCenterCrateCollide", 256, 128 }, - { "SabotageMilitaryFactoryCrateCollide", 256, 128 }, - { "SabotagePowerPlantCrateCollide", 256, 128 }, - { "SabotageSuperweaponCrateCollide", 256, 128 }, - { "SabotageSupplyCenterCrateCollide", 256, 128 }, - { "SabotageSupplyDropzoneCrateCollide", 256, 128 }, - { "JetAIUpdate", 64, 32 }, - { "ChinookAIUpdate", 32, 32 }, - { "WanderAIUpdate", 32, 32 }, - { "WaveGuideUpdate", 16, 16 }, - { "WeaponBonusUpgrade", 512, 128 }, - { "WeaponSetUpgrade", 512, 128 }, - { "ArmorUpgrade", 512, 128 }, - { "WorkerAIUpdate", 128, 128 }, - { "WorkerStateMachine", 128, 128 }, - { "ChinookAIStateMachine", 32, 32 }, - { "DeployStyleAIUpdate", 32, 32 }, - { "AssaultTransportAIUpdate", 64, 32 }, - { "StreamingArchiveFile", 8, 8 }, - - { "DozerActionStateMachine", 256, 32 }, - { "DozerPrimaryStateMachine", 256, 32 }, - { "W3DDisplayString", 1024, 128 }, - { "W3DDefaultDraw", 1024, 128 }, - { "W3DDebrisDraw", 1024, 128 }, - { "W3DDependencyModelDraw", 64, 64 }, - { "W3DLaserDraw", 32, 32 }, - { "W3DModelDraw", 4096, 128 }, - { "W3DOverlordTankDraw", 64, 64 }, - { "W3DOverlordTruckDraw", 64, 64 }, - { "W3DOverlordAircraftDraw", 64, 64 }, - { "W3DPoliceCarDraw", 32, 32 }, - { "W3DProjectileStreamDraw", 32, 32 }, - { "W3DRopeDraw", 32, 32 }, - { "W3DScienceModelDraw", 32, 32 }, - { "W3DSupplyDraw", 32, 32 }, - { "W3DTankDraw", 256, 32 }, - { "W3DTreeDraw", 16, 16 }, - { "W3DPropDraw", 16, 16 }, - { "W3DTracerDraw", 64, 32 }, - { "W3DTruckDraw", 128, 32 }, - { "W3DTankTruckDraw", 32, 16 }, - { "W3DTreeTextureClass", 4, 4 }, - { "DefaultSpecialPower", 32, 32 }, - { "OCLSpecialPower", 32, 32 }, - { "FireWeaponPower", 32, 32 }, -#ifdef ALLOW_DEMORALIZE - { "DemoralizeSpecialPower", 16, 16, }, +#if RTS_GENERALS +#include "GameMemoryInitDMA_Generals.inl" +#include "GameMemoryInitPools_Generals.inl" +#elif RTS_ZEROHOUR +#include "GameMemoryInitDMA_GeneralsMD.inl" +#include "GameMemoryInitPools_GeneralsMD.inl" #endif - { "CashHackSpecialPower", 32, 32 }, - { "CommandSetUpgrade", 32, 32 }, - { "PassengersFireUpgrade", 32, 32 }, - { "GrantUpgradeCreate", 256, 32 }, - { "GrantScienceUpgrade", 256, 32 }, - { "ReplaceObjectUpgrade", 32, 32 }, - { "ModelConditionUpgrade", 32, 32 }, - { "SpyVisionSpecialPower", 256, 32 }, - { "StealthDetectorUpdate", 256, 32 }, - { "StealthUpdate", 256, 32 }, - { "StealthUpgrade", 256, 32 }, - { "StatusBitsUpgrade", 128, 128 }, - { "SubObjectsUpgrade", 128, 128 }, - { "ExperienceScalarUpgrade", 256, 128 }, - { "MaxHealthUpgrade", 128, 128 }, - { "WeaponBonusUpgrade", 128, 64 }, - { "StickyBombUpdate", 64, 32 }, - { "FireOCLAfterWeaponCooldownUpdate", 64, 32 }, - { "HijackerUpdate", 64, 32 }, - { "ChinaMinesUpgrade", 64, 32 }, - { "PowerPlantUpdate", 16, 16 }, - { "PowerPlantUpgrade", 16, 16 }, - { "DefectorSpecialPower", 16, 16 }, - { "CheckpointUpdate", 16, 16 }, - { "MobNexusContain", 128, 32 }, - { "MobMemberSlavedUpdate", 64, 32 }, - { "EMPUpdate", 64, 32 }, - { "LeafletDropBehavior", 64, 32 }, - { "Overridable", 32, 32 }, - - { "W3DGameWindow", 1024, 32 }, - { "GameWindowDummy", 1024, 32 }, - { "SuccessState", 32, 32 }, - { "FailureState", 32, 32 }, - { "ContinueState", 32, 32 }, - { "SleepState", 32, 32 }, - - { "AIDockWaitForClearanceState", 256, 32 }, - { "AIDockProcessDockState", 256, 32 }, - { "AIGuardInnerState", 32, 32 }, - { "AIGuardIdleState", 32, 32 }, - { "AIGuardOuterState", 32, 32 }, - { "AIGuardReturnState", 32, 32 }, - { "AIGuardPickUpCrateState", 32, 32 }, - { "AIGuardAttackAggressorState", 32, 32 }, - { "AIGuardRetaliateInnerState", 32, 32 }, - { "AIGuardRetaliateIdleState", 32, 32 }, - { "AIGuardRetaliateOuterState", 32, 32 }, - { "AIGuardRetaliateReturnState", 32, 32 }, - { "AIGuardRetaliatePickUpCrateState", 32, 32 }, - { "AIGuardRetaliateAttackAggressorState", 32, 32 }, - { "AITNGuardInnerState", 32, 32 }, - { "AITNGuardIdleState", 32, 32 }, - { "AITNGuardOuterState", 32, 32 }, - { "AITNGuardReturnState", 32, 32 }, - { "AITNGuardPickUpCrateState", 32, 32 }, - { "AITNGuardAttackAggressorState", 32, 32 }, - { "AIIdleState", 2400, 32 }, - { "AIRappelState", 600, 32 }, - { "AIBusyState", 600, 32 }, - { "AIWaitState", 600, 32 }, - { "AIAttackState", 4096, 32 }, - { "AIAttackSquadState", 600, 32 }, - { "AIDeadState", 600, 32 }, - { "AIDockState", 600, 32 }, - { "AIExitState", 600, 32 }, - { "AIExitInstantlyState", 600, 32 }, - { "AIGuardState", 600, 32 }, - { "AIGuardRetaliateState", 600, 32 }, - { "AITunnelNetworkGuardState", 600, 32 }, - { "AIHuntState", 600, 32 }, - { "AIAttackAreaState", 600, 32 }, - { "AIFaceState", 1200, 32 }, - { "ApproachState", 600, 32 }, - { "DeliveringState", 600, 32 }, - { "ConsiderNewApproachState", 600, 32 }, - { "RecoverFromOffMapState", 600, 32 }, - { "HeadOffMapState", 600, 32 }, - { "CleanUpState", 600, 32 }, - { "HackInternetState", 600, 32 }, - { "PackingState", 600, 32 }, - { "UnpackingState", 600, 32 }, - { "SupplyTruckWantsToPickUpOrDeliverBoxesState", 600, 32 }, - { "RegroupingState", 600, 32 }, - { "DockingState", 600, 32 }, - { "ChinookEvacuateState", 32, 32 }, - { "ChinookHeadOffMapState", 32, 32 }, - { "ChinookTakeoffOrLandingState", 32, 32 }, - { "ChinookCombatDropState", 32, 32 }, - { "DozerActionPickActionPosState", 256, 32 }, - { "DozerActionMoveToActionPosState", 256, 32 }, - { "DozerActionDoActionState", 256, 32 }, - { "DozerPrimaryIdleState", 256, 32 }, - { "DozerActionState", 256, 32 }, - { "DozerPrimaryGoingHomeState", 256, 32 }, - { "JetAwaitingRunwayState", 64, 32 }, - { "JetOrHeliCirclingDeadAirfieldState", 64, 32 }, - { "HeliTakeoffOrLandingState", 64, 32 }, - { "JetOrHeliParkOrientState", 64, 32 }, - { "JetOrHeliReloadAmmoState", 64, 32 }, - { "SupplyTruckBusyState", 600, 32 }, - { "SupplyTruckIdleState", 600, 32 }, - { "ActAsDozerState", 600, 32 }, - { "ActAsSupplyTruckState", 600, 32 }, - { "AIDockApproachState", 256, 32 }, - { "AIDockAdvancePositionState", 256, 32 }, - { "AIDockMoveToEntryState", 256, 32 }, - { "AIDockMoveToDockState", 256, 32 }, - { "AIDockMoveToExitState", 256, 32 }, - { "AIDockMoveToRallyState", 256, 32 }, - { "AIMoveToState", 600, 32 }, - { "AIMoveOutOfTheWayState", 600, 32 }, - { "AIMoveAndTightenState", 600, 32 }, - { "AIMoveAwayFromRepulsorsState", 600, 32 }, - { "AIAttackApproachTargetState", 96, 32 }, - { "AIAttackPursueTargetState", 96, 32 }, - { "AIAttackAimAtTargetState", 96, 32 }, - { "AIAttackFireWeaponState", 256, 32 }, - { "AIPickUpCrateState", 4096, 32 }, - { "AIFollowWaypointPathState", 1200, 32 }, - { "AIFollowWaypointPathExactState", 1200, 32 }, - { "AIWanderInPlaceState", 600, 32 }, - { "AIFollowPathState", 1200, 32 }, - { "AIMoveAndEvacuateState", 1200, 32 }, - { "AIMoveAndDeleteState", 600, 32 }, - { "AIEnterState", 600, 32 }, - { "JetOrHeliReturningToDeadAirfieldState", 64, 32 }, - { "JetOrHeliReturnForLandingState", 64, 32 }, - { "TurretAIIdleState", 600, 32 }, - { "TurretAIIdleScanState", 600, 32 }, - { "TurretAIAimTurretState", 600, 32 }, - { "TurretAIRecenterTurretState", 600, 32 }, - { "TurretAIHoldTurretState", 600, 32 }, - { "JetOrHeliTaxiState", 64, 32 }, - { "JetTakeoffOrLandingState", 64, 32 }, - { "JetPauseBeforeTakeoffState", 64, 32 }, - { "AIAttackMoveToState", 600, 32 }, - { "AIAttackFollowWaypointPathState", 1200, 32 }, - { "AIWanderState", 600, 32 }, - { "AIPanicState", 600, 32 }, - { "ChinookMoveToBldgState", 32, 32 }, - { "ChinookRecordCreationState", 32, 32 }, - { "ScienceInfo", 64, 32 }, - { "RankInfo", 32, 32 }, - - { "FireWeaponNugget", 32, 32 }, - { "AttackNugget", 32, 32 }, - { "DeliverPayloadNugget", 32, 32 }, - { "ApplyRandomForceNugget", 32, 32 }, - { "GenericObjectCreationNugget", 512, 32 }, - { "SoundFXNugget", 256, 32 }, - { "TracerFXNugget", 32, 32 }, - { "RayEffectFXNugget", 32, 32 }, - { "LightPulseFXNugget", 64, 32 }, - { "ViewShakeFXNugget", 128, 32 }, - { "TerrainScorchFXNugget", 32, 32 }, - { "ParticleSystemFXNugget", 600, 32 }, - { "FXListAtBonePosFXNugget", 32, 32 }, - { "Squad", 256, 32 }, - { "BuildListInfo", 256, 32 }, - { "ScriptGroup", 128, 32 }, - { "OrCondition", 1024, 256 }, - { "ScriptAction", 2048, 512 }, - { "Script", 1024, 256 }, - { "Parameter", 8192, 1024 }, - { "Condition", 2048, 256 }, - { "Template", 32, 32 }, - { "ScriptList", 32, 32 }, - { "AttackPriorityInfo", 32, 32 }, - { "SequentialScript", 32, 32 }, - { "Win32LocalFile", 1024, 256 }, - { "StdLocalFile", 1024, 256 }, - { "RAMFile", 32, 32 }, - { "BattlePlanBonuses", 32, 32 }, - { "KindOfPercentProductionChange", 32, 32 }, - { "UserParser", 4096, 256 }, - { "XferBlockData", 32, 32 }, - { "EvaCheckInfo", 32, 32 }, - { "SuperweaponInfo", 32, 32 }, - { "NamedTimerInfo", 32, 32 }, - { "PopupMessageData", 32, 32 }, - { "FloatingTextData", 32, 32 }, - { "MapObject", 4096, 32 }, - { "Waypoint", 1024, 32 }, - { "PolygonTrigger", 128, 32 }, - { "Bridge", 32, 32 }, - { "Mapping", 128, 32 }, - { "OutputChunk", 32, 32 }, - { "InputChunk", 32, 32 }, - { "AnimateWindow", 32, 32 }, - { "GameFont", 32, 32 }, - { "NetCommandRef", 256, 32 }, - { "GameMessageArgument", 128, 32 }, - { "GameMessageParserArgumentType", 32, 32 }, - { "GameMessageParser", 32, 32 }, - { "WeaponBonusSet", 32, 32 }, - { "Campaign", 32, 32 }, - { "Mission", 32, 32 }, - { "ModalWindow", 32, 32 }, - { "NetPacket", 32, 32 }, - { "AISideInfo", 32, 32 }, - { "AISideBuildList", 32, 32 }, - { "MetaMapRec", 256, 32 }, - { "TransportStatus", 32, 32 }, - { "Anim2DTemplate", 32, 32 }, - { "ObjectTypes", 32, 32 }, - { "NetCommandList", 512, 32 }, - { "TurretAIData", 256, 32 }, - { "NetCommandMsg", 32, 32 }, - { "NetGameCommandMsg", 64, 32 }, - { "NetAckBothCommandMsg", 32, 32 }, - { "NetAckStage1CommandMsg", 32, 32 }, - { "NetAckStage2CommandMsg", 32, 32 }, - { "NetFrameCommandMsg", 32, 32 }, - { "NetPlayerLeaveCommandMsg", 32, 32 }, - { "NetRunAheadMetricsCommandMsg", 32, 32 }, - { "NetRunAheadCommandMsg", 32, 32 }, - { "NetDestroyPlayerCommandMsg", 32, 32 }, - { "NetDisconnectFrameCommandMsg", 32, 32 }, - { "NetDisconnectScreenOffCommandMsg", 32, 32 }, - { "NetFrameResendRequestCommandMsg", 32, 32 }, - { "NetKeepAliveCommandMsg", 32, 32 }, - { "NetDisconnectKeepAliveCommandMsg", 32, 32 }, - { "NetDisconnectPlayerCommandMsg", 32, 32 }, - { "NetPacketRouterQueryCommandMsg", 32, 32 }, - { "NetPacketRouterAckCommandMsg", 32, 32 }, - { "NetDisconnectChatCommandMsg", 32, 32 }, - { "NetChatCommandMsg", 32, 32 }, - { "NetDisconnectVoteCommandMsg", 32, 32 }, - { "NetProgressCommandMsg", 32, 32 }, - { "NetWrapperCommandMsg", 32, 32 }, - { "NetFileCommandMsg", 32, 32 }, - { "NetFileAnnounceCommandMsg", 32, 32 }, - { "NetFileProgressCommandMsg", 32, 32 }, - { "NetCommandWrapperListNode", 32, 32 }, - { "NetCommandWrapperList", 32, 32 }, - { "Connection", 32, 32 }, - { "User", 32, 32 }, - { "FrameDataManager", 32, 32 }, - { "DrawableIconInfo", 32, 32 }, - { "TintEnvelope", 128, 32 }, - { "DynamicAudioEventRTS", 1024, 256 }, - { "DrawableLocoInfo", 128, 32 }, - { "W3DPrototypeClass", 2048, 32 }, - { "EnumeratedIP", 32, 32 }, - { "WaterTransparencySetting", 4, 4 }, - { "WeatherSetting", 4, 4 }, - - // W3D pools! - { "BoxPrototypeClass", 512, 32 }, - { "SpherePrototypeClass", 32, 32 }, - { "SoundRenderObjPrototypeClass", 32, 32 }, - { "RingPrototypeClass", 32, 32 }, - { "PrimitivePrototypeClass", 8192, 32 }, - { "HModelPrototypeClass", 256, 32 }, - { "ParticleEmitterPrototypeClass", 32, 32 }, - { "NullPrototypeClass", 32, 32 }, - { "HLodPrototypeClass", 512, 32 }, - { "HLodDefClass", 512, 32 }, - { "DistLODPrototypeClass", 32, 32 }, - { "DazzlePrototypeClass", 32, 32 }, - { "CollectionPrototypeClass", 32, 32 }, - { "BoxPrototypeClass", 256, 32 }, - { "AggregatePrototypeClass", 32, 32 }, - { "OBBoxRenderObjClass", 16384, 32 }, - { "AABoxRenderObjClass", 32, 32 }, - { "VertexMaterialClass", 16384, 32 }, - { "TextureClass", 1024, 32 }, - { "CloudMapTerrainTextureClass", 32, 32 }, - { "ScorchTextureClass", 32, 32 }, - { "LightMapTerrainTextureClass", 32, 32 }, - { "AlphaEdgeTextureClass", 32, 32 }, - { "AlphaTerrainTextureClass", 32, 32 }, - { "TerrainTextureClass", 32, 32 }, - { "MeshClass", 16384, 1024 }, - { "HTreeClass", 8192, 32 }, - { "HLodClass", 4096, 32 }, - { "MeshModelClass", 8192, 32 }, - { "ShareBufferClass", 32768, 1024 }, - { "AABTreeClass", 32, 32 }, - { "MotionChannelClass", 16384, 32 }, - { "BitChannelClass", 64, 32 }, - { "TimeCodedMotionChannelClass", 32, 32 }, - { "AdaptiveDeltaMotionChannelClass", 32, 32 }, - { "TimeCodedBitChannelClass", 32, 32 }, - { "UVBufferClass", 8192, 32 }, - { "TexBufferClass", 512, 32 }, - { "MatBufferClass", 512, 32 }, - { "MatrixMapperClass", 32, 32 }, - { "ScaleTextureMapperClass", 32, 32 }, - { "LinearOffsetTextureMapperClass", 32, 32 }, - { "GridTextureMapperClass", 32, 32 }, - { "RotateTextureMapperClass", 32, 32 }, - { "SineLinearOffsetTextureMapperClass", 32, 32 }, - { "StepLinearOffsetTextureMapperClass", 32, 32 }, - { "ZigZagLinearOffsetTextureMapperClass", 32, 32 }, - { "ClassicEnvironmentMapperClass", 32, 32 }, - { "EnvironmentMapperClass", 256, 32 }, - { "EdgeMapperClass", 32, 32 }, - { "WSClassicEnvironmentMapperClass", 32, 32 }, - { "WSEnvironmentMapperClass", 32, 32 }, - { "GridClassicEnvironmentMapperClass", 32, 32 }, - { "GridEnvironmentMapperClass", 32, 32 }, - { "ScreenMapperClass", 32, 32 }, - { "RandomTextureMapperClass", 32, 32 }, - { "BumpEnvTextureMapperClass", 32, 32 }, - { "MeshLoadContextClass", 32, 32 }, - { "MaterialInfoClass", 8192, 32 }, - { "MeshMatDescClass", 8192, 32 }, - { "TextureLoadTaskClass", 256, 32 }, - { "SortingNodeStruct", 256, 32 }, - { "ProxyArrayClass", 32, 32 }, - { "Line3DClass", 128, 32 }, - { "Render2DClass", 64, 32 }, - { "SurfaceClass", 128, 32 }, - { "FontCharsClassCharDataStruct", 1024, 32 }, - { "FontCharsBuffer", 16, 4 }, - { "FVFInfoClass", 128, 32 }, - { "TerrainTracksRenderObjClass", 128, 32 }, - { "DynamicIBAccessClass", 32, 32 }, - { "DX8IndexBufferClass", 128, 32 }, - { "SortingIndexBufferClass", 32, 32 }, - { "DX8VertexBufferClass", 128, 32 }, - { "SortingVertexBufferClass", 32, 32 }, - { "DynD3DMATERIAL8", 8192, 32 }, - { "DynamicMatrix3D", 512, 32 }, - { "MeshGeometryClass", 32, 32 }, - { "DynamicMeshModel", 32, 32 }, - { "GapFillerClass", 32, 32 }, - { "FontCharsClass", 64, 32 }, - { "ThumbnailManagerClass", 32, 32}, - { "SmudgeSet", 32, 32}, - { "Smudge", 128, 32}, - { 0, 0, 0 } -}; +//----------------------------------------------------------------------------- +void userMemoryManagerGetDmaParms(Int *numSubPools, const PoolInitRec **pParms) +{ + *numSubPools = ARRAY_SIZE(DefaultDMA); + *pParms = DefaultDMA; +} //----------------------------------------------------------------------------- void userMemoryAdjustPoolSize(const char *poolName, Int& initialAllocationCount, Int& overflowAllocationCount) @@ -727,7 +77,7 @@ void userMemoryAdjustPoolSize(const char *poolName, Int& initialAllocationCount, if (initialAllocationCount > 0) return; - for (const PoolSizeRec* p = sizes; p->name != NULL; ++p) + for (const PoolSizeRec* p = PoolSizes; p->name != NULL; ++p) { if (strcmp(p->name, poolName) == 0) { @@ -786,7 +136,7 @@ void userMemoryManagerInitPools() continue; if (sscanf(buf, "%s %d %d", poolName, &initial, &overflow ) == 3) { - for (PoolSizeRec* p = sizes; p->name != NULL; ++p) + for (PoolSizeRec* p = PoolSizes; p->name != NULL; ++p) { if (stricmp(p->name, poolName) == 0) { diff --git a/GeneralsMD/Code/GameEngine/CMakeLists.txt b/GeneralsMD/Code/GameEngine/CMakeLists.txt index d947c86b0ad..81b96301dac 100644 --- a/GeneralsMD/Code/GameEngine/CMakeLists.txt +++ b/GeneralsMD/Code/GameEngine/CMakeLists.txt @@ -1139,6 +1139,8 @@ if(RTS_GAMEMEMORY_ENABLE) # Uses the original Game Memory implementation. list(APPEND GAMEENGINE_SRC Source/Common/System/GameMemory.cpp + Source/Common/System/GameMemoryInitDMA_GeneralsMD.inl + Source/Common/System/GameMemoryInitPools_GeneralsMD.inl Source/Common/System/MemoryInit.cpp ) else() diff --git a/GeneralsMD/Code/GameEngine/Source/Common/System/GameMemoryInitDMA_GeneralsMD.inl b/GeneralsMD/Code/GameEngine/Source/Common/System/GameMemoryInitDMA_GeneralsMD.inl new file mode 100644 index 00000000000..91c67d3f391 --- /dev/null +++ b/GeneralsMD/Code/GameEngine/Source/Common/System/GameMemoryInitDMA_GeneralsMD.inl @@ -0,0 +1,29 @@ +/* +** Command & Conquer Generals Zero Hour(tm) +** Copyright 2025 TheSuperHackers +** +** This program is free software: you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation, either version 3 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program. If not, see . +*/ + +static const PoolInitRec DefaultDMA[] = +{ + // name, allocSize, initialCount, overflowCount + { "dmaPool_16", 16, 130000, 10000 }, + { "dmaPool_32", 32, 250000, 10000 }, + { "dmaPool_64", 64, 100000, 10000 }, + { "dmaPool_128", 128, 80000, 10000 }, + { "dmaPool_256", 256, 20000, 5000 }, + { "dmaPool_512", 512, 16000, 5000 }, + { "dmaPool_1024", 1024, 6000, 1024 } +}; diff --git a/GeneralsMD/Code/GameEngine/Source/Common/System/GameMemoryInitPools_GeneralsMD.inl b/GeneralsMD/Code/GameEngine/Source/Common/System/GameMemoryInitPools_GeneralsMD.inl new file mode 100644 index 00000000000..2bf2e64c151 --- /dev/null +++ b/GeneralsMD/Code/GameEngine/Source/Common/System/GameMemoryInitPools_GeneralsMD.inl @@ -0,0 +1,656 @@ +/* +** Command & Conquer Generals Zero Hour(tm) +** Copyright 2025 TheSuperHackers +** +** This program is free software: you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation, either version 3 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program. If not, see . +*/ + +// And please be careful of duplicates. They are not rejected. +// not const -- we might override from INI +static PoolSizeRec PoolSizes[] = +{ + { "PartitionContactListNode", 2048, 512 }, + { "BattleshipUpdate", 32, 32 }, + { "FlyToDestAndDestroyUpdate", 32, 32 }, + { "MusicTrack", 32, 32 }, + { "PositionalSoundPool", 32, 32 }, + { "GameMessage", 2048, 32 }, + { "NameKeyBucketPool", 9000, 1024 }, + { "ObjectSellInfo", 16, 16 }, + { "ProductionPrerequisitePool", 1024, 32 }, + { "RadarObject", 512, 32 }, + { "ResourceGatheringManager", 16, 16 }, + { "SightingInfo", 8192, 2048 },// Looks big, but all 3000 objects used to have 4 just built in. + { "SpecialPowerTemplate", 84, 32 }, + { "StateMachinePool", 32, 32 }, + { "TeamPool", 128, 32 }, // if you increase this, increase player/team relation map pools + { "PlayerRelationMapPool", 128, 32 }, + { "TeamRelationMapPool", 128, 32 }, + { "TeamPrototypePool", 256, 32 }, + { "TerrainType", 256, 32 }, + { "ThingTemplatePool", 2120, 32 }, + { "TunnelTracker", 16, 16 }, + { "Upgrade", 16, 16 }, + { "UpgradeTemplate", 128, 16 }, + { "Anim2D", 32, 32 }, + { "CommandButton", 1024, 256 }, + { "CommandSet", 820, 16 }, + { "DisplayString", 32, 32 }, + { "WebBrowserURL", 16, 16 }, + { "Drawable", 4096, 32 }, + { "Image", 2048, 32 }, + { "ParticlePool", 1400, 1024 }, + { "ParticleSystemTemplatePool", 1100, 32 }, + { "ParticleSystemPool", 1024, 32 }, + { "TerrainRoadType", 100, 32, }, + { "WindowLayoutPool", 32, 32 }, + { "AnimatedParticleSysBoneClientUpdate", 16, 16 }, + { "SwayClientUpdate", 32, 32 }, + { "BeaconClientUpdate", 64, 32 }, + { "AIGroupPool", 64, 32 }, + { "AIDockMachinePool", 256, 32 }, + { "AIGuardMachinePool", 32, 32 }, + { "AIGuardRetaliateMachinePool", 32, 32 }, + { "AITNGuardMachinePool", 32, 32 }, + { "PathNodePool", 8192, 1024 }, + { "PathPool", 256, 16 }, + { "WorkOrder", 32, 32 }, + { "TeamInQueue", 32, 32 }, + { "AIPlayer", 12, 4 }, + { "AISkirmishPlayer", 8, 8 }, + { "AIStateMachine", 600, 32 }, + { "JetAIStateMachine", 64, 32 }, + { "HeliAIStateMachine", 64, 32 }, + { "AIAttackMoveStateMachine", 2048, 32 }, + { "AIAttackThenIdleStateMachine", 512, 32 }, + { "AttackStateMachine", 512, 32 }, + { "CrateTemplate", 32, 32 }, + { "ExperienceTrackerPool", 2048, 512 }, + { "FiringTrackerPool", 4096, 256 }, + { "ObjectRepulsorHelper", 1024, 256 }, + { "ObjectSMCHelperPool", 2048, 256 }, + { "ObjectWeaponStatusHelperPool", 4096, 256 }, + { "ObjectDefectionHelperPool", 2048, 256 }, + { "StatusDamageHelper", 1500, 256 }, + { "SubdualDamageHelper", 1500, 256 }, + { "TempWeaponBonusHelper", 4096, 256 }, + { "Locomotor", 2048, 32 }, + { "LocomotorTemplate", 192, 32 }, + { "ObjectPool", 1500, 256 }, + { "SimpleObjectIteratorPool", 32, 32 }, + { "SimpleObjectIteratorClumpPool", 4096, 32 }, + { "PartitionDataPool", 2048, 512 }, + { "BuildEntry", 32, 32 }, + { "Weapon", 4096, 32 }, + { "WeaponTemplate", 360, 32 }, + { "AIUpdateInterface", 600, 32 }, + { "ActiveBody", 1024, 32 }, + { "ActiveShroudUpgrade", 32, 32 }, + { "AssistedTargetingUpdate", 32, 32 }, + { "AudioEventInfo", 4096, 64 }, + { "AudioRequest", 256, 8 }, + { "AutoHealBehavior", 1024, 256 }, + { "WeaponBonusUpdate", 16, 16 }, + { "GrantStealthBehavior", 4096, 32 }, + { "NeutronBlastBehavior", 4096, 32 }, + { "CountermeasuresBehavior", 256, 32 }, + { "BaseRegenerateUpdate", 128, 32 }, + { "BoneFXDamage", 64, 32 }, + { "BoneFXUpdate", 64, 32 }, + { "BridgeBehavior", 4, 4 }, + { "BridgeTowerBehavior", 32, 32 }, + { "BridgeScaffoldBehavior", 32, 32 }, + { "CaveContain", 16, 16 }, + { "HealContain", 32, 32 }, + { "CreateCrateDie", 256, 128 }, + { "CreateObjectDie", 1024, 32 }, + { "EjectPilotDie", 1024, 32 }, + { "CrushDie", 1024, 32 }, + { "DamDie", 8, 8 }, + { "DeliverPayloadStateMachine", 32, 32 }, + { "DeliverPayloadAIUpdate", 32, 32 }, + { "DeletionUpdate", 128, 32 }, + { "SmartBombTargetHomingUpdate", 8, 8 }, + { "DynamicAudioEventInfo", 16, 256 }, // Note: some levels have none, some have lots. Since all are allocated at level load time, we can set this low for the levels with none. + { "HackInternetStateMachine", 32, 32 }, + { "HackInternetAIUpdate", 32, 32 }, + { "MissileAIUpdate", 512, 32 }, + { "DumbProjectileBehavior", 64, 32 }, + { "DestroyDie", 1024, 32 }, + { "UpgradeDie", 128, 32 }, + { "KeepObjectDie", 128, 32 }, + { "DozerAIUpdate", 32, 32 }, + { "DynamicGeometryInfoUpdate", 16, 16 }, + { "DynamicShroudClearingRangeUpdate", 128, 16 }, + { "FXListDie", 1024, 32 }, + { "FireSpreadUpdate", 2048, 128 }, + { "FirestormDynamicGeometryInfoUpdate", 16, 16 }, + { "FireWeaponCollide", 2048, 32 }, + { "FireWeaponUpdate", 32, 32 }, + { "FlammableUpdate", 512, 256 }, + { "FloatUpdate", 512, 128 }, + { "TensileFormationUpdate", 256, 32 }, + { "GarrisonContain", 256, 32 }, + { "HealCrateCollide", 32, 32 }, + { "HeightDieUpdate", 32, 32 }, + { "FireWeaponWhenDamagedBehavior", 32, 32 }, + { "FireWeaponWhenDeadBehavior", 128, 64 }, + { "GenerateMinefieldBehavior", 32, 32 }, + { "HelicopterSlowDeathBehavior", 64, 32 }, + { "ParkingPlaceBehavior", 32, 32 }, + { "FlightDeckBehavior", 8, 8 }, +#ifdef ALLOW_SURRENDER + { "POWTruckAIUpdate", 32, 32, }, + { "POWTruckBehavior", 32, 32, }, + { "PrisonBehavior", 32, 32 }, + { "PrisonVisual", 32, 32 }, + { "PropagandaCenterBehavior", 16, 16 }, +#endif + { "PropagandaTowerBehavior", 16, 16 }, + { "BunkerBusterBehavior", 16, 16 }, + { "ObjectTracker", 128, 32 }, + { "OCLUpdate", 16, 16 }, + { "BodyParticleSystem", 196, 64 }, + { "HighlanderBody", 2048, 128 }, + { "UndeadBody", 32, 32 }, + { "HordeUpdate", 128, 32 }, + { "ImmortalBody", 128, 256 }, + { "InactiveBody", 2048, 32 }, + { "InstantDeathBehavior", 512, 32 }, + { "LaserUpdate", 32, 32 }, + { "PointDefenseLaserUpdate", 32, 32 }, + { "CleanupHazardUpdate", 32, 32 }, + { "AutoFindHealingUpdate", 256, 32 }, + { "CommandButtonHuntUpdate", 512, 8 }, + { "PilotFindVehicleUpdate", 256, 32 }, + { "DemoTrapUpdate", 32, 32 }, + { "ParticleUplinkCannonUpdate", 16, 16 }, + { "SpectreGunshipUpdate", 8, 8 }, + { "SpectreGunshipDeploymentUpdate", 8, 8 }, + { "BaikonurLaunchPower", 4, 4 }, + { "RadiusDecalUpdate", 16, 16 }, + { "BattlePlanUpdate", 32, 32 }, + { "LifetimeUpdate", 32, 32 }, + { "LocomotorSetUpgrade", 512, 128 }, + { "LockWeaponCreate", 64, 128 }, + { "AutoDepositUpdate", 256, 32 }, + { "NeutronMissileUpdate", 512, 32 }, + { "MoneyCrateCollide", 48, 16 }, + { "NeutronMissileSlowDeathBehavior", 8, 8 }, + { "OpenContain", 128, 32 }, + { "OverchargeBehavior", 32, 32 }, + { "OverlordContain", 32, 32 }, + { "HelixContain", 32, 32 }, + { "ParachuteContain", 128, 32 }, + { "PhysicsBehavior", 600, 32 }, + { "PoisonedBehavior", 512, 64 }, + { "ProductionEntry", 32, 32 }, + { "ProductionUpdate", 256, 32 }, + { "ProjectileStreamUpdate", 32, 32 }, + { "ProneUpdate", 128, 32 }, + { "QueueProductionExitUpdate", 32, 32 }, + { "RadarUpdate", 16, 16 }, + { "RadarUpgrade", 16, 16 }, + { "AnimationSteeringUpdate", 1024, 32 }, + { "SupplyWarehouseCripplingBehavior", 16, 16 }, + { "CostModifierUpgrade", 32, 32 }, + { "CashBountyPower", 32, 32 }, + { "CleanupAreaPower", 32, 32 }, + { "ObjectCreationUpgrade", 196, 32 }, + { "MinefieldBehavior", 256, 32 }, + { "JetSlowDeathBehavior", 64, 32 }, + { "BattleBusSlowDeathBehavior", 64, 32 }, + { "RebuildHoleBehavior", 64, 32 }, + { "RebuildHoleExposeDie", 64, 32 }, + { "RepairDockUpdate", 32, 32 }, +#ifdef ALLOW_SURRENDER + { "PrisonDockUpdate", 32, 32 }, +#endif + { "RailedTransportDockUpdate", 16, 16 }, + { "RailedTransportAIUpdate", 16, 16 }, + { "RailedTransportContain", 16, 16 }, + { "RailroadBehavior", 16, 16 }, + { "SalvageCrateCollide", 32, 32 }, + { "ShroudCrateCollide", 32, 32 }, + { "SlavedUpdate", 64, 32 }, + { "SlowDeathBehavior", 1400, 256 }, + { "SpyVisionUpdate", 16, 16 }, + { "DefaultProductionExitUpdate", 32, 32 }, + { "SpawnPointProductionExitUpdate", 32, 32 }, + { "SpawnBehavior", 32, 32 }, + { "SpecialPowerCompletionDie", 32, 32 }, + { "SpecialPowerCreate", 32, 32 }, + { "PreorderCreate", 32, 32 }, + { "SpecialAbility", 512, 32 }, + { "SpecialAbilityUpdate", 512, 32 }, + { "MissileLauncherBuildingUpdate", 32, 32 }, + { "SquishCollide", 512, 32 }, + { "StructureBody", 512, 64 }, + { "HiveStructureBody", 64, 32 }, //Stinger sites + { "StructureCollapseUpdate", 32, 32 }, + { "StructureToppleUpdate", 32, 32 }, + { "SupplyCenterCreate", 32, 32 }, + { "SupplyCenterDockUpdate", 32, 32 }, + { "SupplyCenterProductionExitUpdate", 32, 32 }, + { "SupplyTruckStateMachine", 256, 32 }, + { "SupplyTruckAIUpdate", 32, 32 }, + { "SupplyWarehouseCreate", 48, 16 }, + { "SupplyWarehouseDockUpdate", 48, 16 }, + { "EnemyNearUpdate", 1024, 32 }, + { "TechBuildingBehavior", 32, 32 }, + { "ToppleUpdate", 256, 128 }, + { "TransitionDamageFX", 384, 128 }, + { "TransportAIUpdate", 64, 32 }, + { "TransportContain", 128, 32 }, + { "RiderChangeContain", 128, 32 }, + { "InternetHackContain", 16, 16 }, + { "TunnelContain", 8, 8 }, + { "TunnelContainDie", 32, 32 }, + { "TunnelCreate", 32, 32 }, + { "TurretAI", 256, 32 }, + { "TurretStateMachine", 128, 32 }, + { "TurretSwapUpgrade", 512, 128 }, + { "UnitCrateCollide", 32, 32 }, + { "UnpauseSpecialPowerUpgrade", 32, 32 }, + { "VeterancyCrateCollide", 32, 32 }, + { "VeterancyGainCreate", 512, 128 }, + { "ConvertToCarBombCrateCollide", 256, 128 }, + { "ConvertToHijackedVehicleCrateCollide", 256, 128 }, + { "SabotageCommandCenterCrateCollide", 256, 128 }, + { "SabotageFakeBuildingCrateCollide", 256, 128 }, + { "SabotageInternetCenterCrateCollide", 256, 128 }, + { "SabotageMilitaryFactoryCrateCollide", 256, 128 }, + { "SabotagePowerPlantCrateCollide", 256, 128 }, + { "SabotageSuperweaponCrateCollide", 256, 128 }, + { "SabotageSupplyCenterCrateCollide", 256, 128 }, + { "SabotageSupplyDropzoneCrateCollide", 256, 128 }, + { "JetAIUpdate", 64, 32 }, + { "ChinookAIUpdate", 32, 32 }, + { "WanderAIUpdate", 32, 32 }, + { "WaveGuideUpdate", 16, 16 }, + { "WeaponBonusUpgrade", 512, 128 }, + { "WeaponSetUpgrade", 512, 128 }, + { "ArmorUpgrade", 512, 128 }, + { "WorkerAIUpdate", 128, 128 }, + { "WorkerStateMachine", 128, 128 }, + { "ChinookAIStateMachine", 32, 32 }, + { "DeployStyleAIUpdate", 32, 32 }, + { "AssaultTransportAIUpdate", 64, 32 }, + { "StreamingArchiveFile", 8, 8 }, + + { "DozerActionStateMachine", 256, 32 }, + { "DozerPrimaryStateMachine", 256, 32 }, + { "W3DDisplayString", 1400, 128 }, + { "W3DDefaultDraw", 1024, 128 }, + { "W3DDebrisDraw", 128, 128 }, + { "W3DDependencyModelDraw", 64, 64 }, + { "W3DLaserDraw", 32, 32 }, + { "W3DModelDraw", 2048, 512 }, + { "W3DOverlordTankDraw", 64, 64 }, + { "W3DOverlordTruckDraw", 64, 64 }, + { "W3DOverlordAircraftDraw", 64, 64 }, + { "W3DPoliceCarDraw", 32, 32 }, + { "W3DProjectileStreamDraw", 32, 32 }, + { "W3DRopeDraw", 32, 32 }, + { "W3DScienceModelDraw", 32, 32 }, + { "W3DSupplyDraw", 40, 16 }, + { "W3DTankDraw", 256, 32 }, + { "W3DTreeDraw", 16, 16 }, + { "W3DPropDraw", 16, 16 }, + { "W3DTracerDraw", 64, 32 }, + { "W3DTruckDraw", 128, 32 }, + { "W3DTankTruckDraw", 32, 16 }, + { "W3DTreeTextureClass", 4, 4 }, + { "DefaultSpecialPower", 32, 32 }, + { "OCLSpecialPower", 96, 32 }, + { "FireWeaponPower", 32, 32 }, +#ifdef ALLOW_DEMORALIZE + { "DemoralizeSpecialPower", 16, 16, }, +#endif + { "CashHackSpecialPower", 32, 32 }, + { "CommandSetUpgrade", 32, 32 }, + { "PassengersFireUpgrade", 32, 32 }, + { "GrantUpgradeCreate", 256, 32 }, + { "GrantScienceUpgrade", 256, 32 }, + { "ReplaceObjectUpgrade", 32, 32 }, + { "ModelConditionUpgrade", 32, 32 }, + { "SpyVisionSpecialPower", 256, 32 }, + { "StealthDetectorUpdate", 256, 32 }, + { "StealthUpdate", 512, 128 }, + { "StealthUpgrade", 256, 32 }, + { "StatusBitsUpgrade", 128, 128 }, + { "SubObjectsUpgrade", 128, 128 }, + { "ExperienceScalarUpgrade", 256, 128 }, + { "MaxHealthUpgrade", 128, 128 }, + { "WeaponBonusUpgrade", 128, 64 }, + { "StickyBombUpdate", 64, 32 }, + { "FireOCLAfterWeaponCooldownUpdate", 64, 32 }, + { "HijackerUpdate", 64, 32 }, + { "ChinaMinesUpgrade", 64, 32 }, + { "PowerPlantUpdate", 48, 16 }, + { "PowerPlantUpgrade", 48, 16 }, + { "DefectorSpecialPower", 16, 16 }, + { "CheckpointUpdate", 16, 16 }, + { "MobNexusContain", 128, 32 }, + { "MobMemberSlavedUpdate", 64, 32 }, + { "EMPUpdate", 64, 32 }, + { "LeafletDropBehavior", 64, 32 }, + { "Overridable", 32, 32 }, + + { "W3DGameWindow", 700, 256 }, + { "GameWindowDummy", 700, 256 }, + { "SuccessState", 32, 32 }, + { "FailureState", 32, 32 }, + { "ContinueState", 32, 32 }, + { "SleepState", 32, 32 }, + + { "AIDockWaitForClearanceState", 256, 32 }, + { "AIDockProcessDockState", 256, 32 }, + { "AIGuardInnerState", 32, 32 }, + { "AIGuardIdleState", 32, 32 }, + { "AIGuardOuterState", 32, 32 }, + { "AIGuardReturnState", 32, 32 }, + { "AIGuardPickUpCrateState", 32, 32 }, + { "AIGuardAttackAggressorState", 32, 32 }, + { "AIGuardRetaliateInnerState", 32, 32 }, + { "AIGuardRetaliateIdleState", 32, 32 }, + { "AIGuardRetaliateOuterState", 32, 32 }, + { "AIGuardRetaliateReturnState", 32, 32 }, + { "AIGuardRetaliatePickUpCrateState", 32, 32 }, + { "AIGuardRetaliateAttackAggressorState", 32, 32 }, + { "AITNGuardInnerState", 32, 32 }, + { "AITNGuardIdleState", 32, 32 }, + { "AITNGuardOuterState", 32, 32 }, + { "AITNGuardReturnState", 32, 32 }, + { "AITNGuardPickUpCrateState", 32, 32 }, + { "AITNGuardAttackAggressorState", 32, 32 }, + { "AIIdleState", 2400, 32 }, + { "AIRappelState", 600, 32 }, + { "AIBusyState", 600, 32 }, + { "AIWaitState", 600, 32 }, + { "AIAttackState", 4096, 32 }, + { "AIAttackSquadState", 600, 32 }, + { "AIDeadState", 600, 32 }, + { "AIDockState", 600, 32 }, + { "AIExitState", 600, 32 }, + { "AIExitInstantlyState", 600, 32 }, + { "AIGuardState", 600, 32 }, + { "AIGuardRetaliateState", 600, 32 }, + { "AITunnelNetworkGuardState", 600, 32 }, + { "AIHuntState", 600, 32 }, + { "AIAttackAreaState", 600, 32 }, + { "AIFaceState", 1200, 32 }, + { "ApproachState", 600, 32 }, + { "DeliveringState", 600, 32 }, + { "ConsiderNewApproachState", 600, 32 }, + { "RecoverFromOffMapState", 600, 32 }, + { "HeadOffMapState", 600, 32 }, + { "CleanUpState", 600, 32 }, + { "HackInternetState", 600, 32 }, + { "PackingState", 600, 32 }, + { "UnpackingState", 600, 32 }, + { "SupplyTruckWantsToPickUpOrDeliverBoxesState", 600, 32 }, + { "RegroupingState", 600, 32 }, + { "DockingState", 600, 32 }, + { "ChinookEvacuateState", 32, 32 }, + { "ChinookHeadOffMapState", 32, 32 }, + { "ChinookTakeoffOrLandingState", 32, 32 }, + { "ChinookCombatDropState", 32, 32 }, + { "DozerActionPickActionPosState", 256, 32 }, + { "DozerActionMoveToActionPosState", 256, 32 }, + { "DozerActionDoActionState", 256, 32 }, + { "DozerPrimaryIdleState", 256, 32 }, + { "DozerActionState", 256, 32 }, + { "DozerPrimaryGoingHomeState", 256, 32 }, + { "JetAwaitingRunwayState", 64, 32 }, + { "JetOrHeliCirclingDeadAirfieldState", 64, 32 }, + { "HeliTakeoffOrLandingState", 64, 32 }, + { "JetOrHeliParkOrientState", 64, 32 }, + { "JetOrHeliReloadAmmoState", 64, 32 }, + { "SupplyTruckBusyState", 600, 32 }, + { "SupplyTruckIdleState", 600, 32 }, + { "ActAsDozerState", 600, 32 }, + { "ActAsSupplyTruckState", 600, 32 }, + { "AIDockApproachState", 256, 32 }, + { "AIDockAdvancePositionState", 256, 32 }, + { "AIDockMoveToEntryState", 256, 32 }, + { "AIDockMoveToDockState", 256, 32 }, + { "AIDockMoveToExitState", 256, 32 }, + { "AIDockMoveToRallyState", 256, 32 }, + { "AIMoveToState", 600, 32 }, + { "AIMoveOutOfTheWayState", 600, 32 }, + { "AIMoveAndTightenState", 600, 32 }, + { "AIMoveAwayFromRepulsorsState", 600, 32 }, + { "AIAttackApproachTargetState", 96, 32 }, + { "AIAttackPursueTargetState", 96, 32 }, + { "AIAttackAimAtTargetState", 96, 32 }, + { "AIAttackFireWeaponState", 256, 32 }, + { "AIPickUpCrateState", 4096, 32 }, + { "AIFollowWaypointPathState", 1200, 32 }, + { "AIFollowWaypointPathExactState", 1200, 32 }, + { "AIWanderInPlaceState", 600, 32 }, + { "AIFollowPathState", 1200, 32 }, + { "AIMoveAndEvacuateState", 1200, 32 }, + { "AIMoveAndDeleteState", 600, 32 }, + { "AIEnterState", 600, 32 }, + { "JetOrHeliReturningToDeadAirfieldState", 64, 32 }, + { "JetOrHeliReturnForLandingState", 64, 32 }, + { "TurretAIIdleState", 600, 32 }, + { "TurretAIIdleScanState", 600, 32 }, + { "TurretAIAimTurretState", 600, 32 }, + { "TurretAIRecenterTurretState", 600, 32 }, + { "TurretAIHoldTurretState", 600, 32 }, + { "JetOrHeliTaxiState", 64, 32 }, + { "JetTakeoffOrLandingState", 64, 32 }, + { "JetPauseBeforeTakeoffState", 64, 32 }, + { "AIAttackMoveToState", 600, 32 }, + { "AIAttackFollowWaypointPathState", 1200, 32 }, + { "AIWanderState", 600, 32 }, + { "AIPanicState", 600, 32 }, + { "ChinookMoveToBldgState", 32, 32 }, + { "ChinookRecordCreationState", 32, 32 }, + { "ScienceInfo", 96, 32 }, + { "RankInfo", 32, 32 }, + + { "FireWeaponNugget", 32, 32 }, + { "AttackNugget", 32, 32 }, + { "DeliverPayloadNugget", 48, 32 }, + { "ApplyRandomForceNugget", 32, 32 }, + { "GenericObjectCreationNugget", 632, 32 }, + { "SoundFXNugget", 320, 32 }, + { "TracerFXNugget", 32, 32 }, + { "RayEffectFXNugget", 32, 32 }, + { "LightPulseFXNugget", 68, 32 }, + { "ViewShakeFXNugget", 140, 32 }, + { "TerrainScorchFXNugget", 48, 32 }, + { "ParticleSystemFXNugget", 832, 32 }, + { "FXListAtBonePosFXNugget", 32, 32 }, + { "Squad", 256, 32 }, + { "BuildListInfo", 400, 64 }, + + { "ScriptGroup", 128, 32 }, + { "OrCondition", 1024, 256 }, + { "ScriptAction", 2600, 512 }, + { "Script", 1024, 256 }, + { "Parameter", 8192, 1024 }, + { "Condition", 2048, 256 }, + { "Template", 32, 32 }, + { "ScriptList", 32, 32 }, + { "AttackPriorityInfo", 32, 32 }, + { "SequentialScript", 32, 32 }, + { "Win32LocalFile", 1024, 256 }, + { "StdLocalFile", 1024, 256 }, + { "RAMFile", 32, 32 }, + { "BattlePlanBonuses", 32, 32 }, + { "KindOfPercentProductionChange", 32, 32 }, + { "UserParser", 4096, 256 }, + { "XferBlockData", 32, 32 }, + { "EvaCheckInfo", 52, 16 }, + { "SuperweaponInfo", 32, 32 }, + { "NamedTimerInfo", 32, 32 }, + { "PopupMessageData", 32, 32 }, + { "FloatingTextData", 32, 32 }, + { "MapObject", 5000, 1024 }, + { "Waypoint", 1024, 32 }, + { "PolygonTrigger", 64, 64 }, + { "Bridge", 32, 32 }, + { "Mapping", 384, 64 }, + { "OutputChunk", 32, 32 }, + { "InputChunk", 32, 32 }, + { "AnimateWindow", 32, 32 }, + { "GameFont", 32, 32 }, + { "NetCommandRef", 256, 32 }, + { "GameMessageArgument", 1024, 256 }, + { "GameMessageParserArgumentType", 32, 32 }, + { "GameMessageParser", 32, 32 }, + { "WeaponBonusSet", 96, 32 }, + { "Campaign", 32, 32 }, + { "Mission", 88, 32 }, + { "ModalWindow", 32, 32 }, + { "NetPacket", 32, 32 }, + { "AISideInfo", 32, 32 }, + { "AISideBuildList", 32, 32 }, + { "MetaMapRec", 256, 32 }, + { "TransportStatus", 32, 32 }, + { "Anim2DTemplate", 32, 32 }, + { "ObjectTypes", 32, 32 }, + { "NetCommandList", 512, 32 }, + { "TurretAIData", 256, 32 }, + { "NetCommandMsg", 32, 32 }, + { "NetGameCommandMsg", 64, 32 }, + { "NetAckBothCommandMsg", 32, 32 }, + { "NetAckStage1CommandMsg", 32, 32 }, + { "NetAckStage2CommandMsg", 32, 32 }, + { "NetFrameCommandMsg", 32, 32 }, + { "NetPlayerLeaveCommandMsg", 32, 32 }, + { "NetRunAheadMetricsCommandMsg", 32, 32 }, + { "NetRunAheadCommandMsg", 32, 32 }, + { "NetDestroyPlayerCommandMsg", 32, 32 }, + { "NetDisconnectFrameCommandMsg", 32, 32 }, + { "NetDisconnectScreenOffCommandMsg", 32, 32 }, + { "NetFrameResendRequestCommandMsg", 32, 32 }, + { "NetKeepAliveCommandMsg", 32, 32 }, + { "NetDisconnectKeepAliveCommandMsg", 32, 32 }, + { "NetDisconnectPlayerCommandMsg", 32, 32 }, + { "NetPacketRouterQueryCommandMsg", 32, 32 }, + { "NetPacketRouterAckCommandMsg", 32, 32 }, + { "NetDisconnectChatCommandMsg", 32, 32 }, + { "NetChatCommandMsg", 32, 32 }, + { "NetDisconnectVoteCommandMsg", 32, 32 }, + { "NetProgressCommandMsg", 32, 32 }, + { "NetWrapperCommandMsg", 32, 32 }, + { "NetFileCommandMsg", 32, 32 }, + { "NetFileAnnounceCommandMsg", 32, 32 }, + { "NetFileProgressCommandMsg", 32, 32 }, + { "NetCommandWrapperListNode", 32, 32 }, + { "NetCommandWrapperList", 32, 32 }, + { "Connection", 32, 32 }, + { "User", 32, 32 }, + { "FrameDataManager", 32, 32 }, + { "DrawableIconInfo", 32, 32 }, + { "TintEnvelope", 128, 32 }, + { "DynamicAudioEventRTS", 4000, 256 }, + { "DrawableLocoInfo", 128, 32 }, + { "W3DPrototypeClass", 512, 256 }, + { "EnumeratedIP", 32, 32 }, + { "WaterTransparencySetting", 4, 4 }, + { "WeatherSetting", 4, 4 }, + + // W3D pools! + { "BoxPrototypeClass", 128, 128 }, + { "SpherePrototypeClass", 32, 32 }, + { "SoundRenderObjPrototypeClass", 32, 32 }, + { "RingPrototypeClass", 32, 32 }, + { "PrimitivePrototypeClass", 8192, 32 }, + { "HModelPrototypeClass", 256, 32 }, + { "ParticleEmitterPrototypeClass", 32, 32 }, + { "NullPrototypeClass", 32, 32 }, + { "HLodPrototypeClass", 700, 128 }, + { "HLodDefClass", 700, 128 }, + { "DistLODPrototypeClass", 32, 32 }, + { "DazzlePrototypeClass", 32, 32 }, + { "CollectionPrototypeClass", 32, 32 }, + { "BoxPrototypeClass", 256, 32 }, + { "AggregatePrototypeClass", 32, 32 }, + { "OBBoxRenderObjClass", 512, 128 }, + { "AABoxRenderObjClass", 32, 32 }, + { "VertexMaterialClass", 6000, 2048 }, + { "TextureClass", 1200, 256 }, + { "CloudMapTerrainTextureClass", 4, 4 }, + { "ScorchTextureClass", 4, 4 }, + { "LightMapTerrainTextureClass", 4, 4 }, + { "AlphaEdgeTextureClass", 4, 4 }, + { "AlphaTerrainTextureClass", 4, 4 }, + { "TerrainTextureClass", 4, 4 }, + { "MeshClass", 14000, 2000 }, + { "HTreeClass", 2048, 512 }, + { "HLodClass", 2048, 512 }, + { "MeshModelClass", 8192, 32 }, + { "ShareBufferClass", 32768, 1024 }, + { "AABTreeClass", 300, 128 }, + { "MotionChannelClass", 16384, 32 }, + { "BitChannelClass", 84, 32 }, + { "TimeCodedMotionChannelClass", 116, 32 }, + { "AdaptiveDeltaMotionChannelClass", 32, 32 }, + { "TimeCodedBitChannelClass", 32, 32 }, + { "UVBufferClass", 8192, 32 }, + { "TexBufferClass", 384, 128 }, + { "MatBufferClass", 256, 128 }, + { "MatrixMapperClass", 32, 32 }, + { "ScaleTextureMapperClass", 32, 32 }, + { "LinearOffsetTextureMapperClass", 96, 32 }, + { "GridTextureMapperClass", 32, 32 }, + { "RotateTextureMapperClass", 32, 32 }, + { "SineLinearOffsetTextureMapperClass", 32, 32 }, + { "StepLinearOffsetTextureMapperClass", 32, 32 }, + { "ZigZagLinearOffsetTextureMapperClass", 32, 32 }, + { "ClassicEnvironmentMapperClass", 32, 32 }, + { "EnvironmentMapperClass", 256, 32 }, + { "EdgeMapperClass", 32, 32 }, + { "WSClassicEnvironmentMapperClass", 32, 32 }, + { "WSEnvironmentMapperClass", 32, 32 }, + { "GridClassicEnvironmentMapperClass", 32, 32 }, + { "GridEnvironmentMapperClass", 32, 32 }, + { "ScreenMapperClass", 32, 32 }, + { "RandomTextureMapperClass", 32, 32 }, + { "BumpEnvTextureMapperClass", 32, 32 }, + { "MeshLoadContextClass", 4, 4 }, + { "MaterialInfoClass", 8192, 32 }, + { "MeshMatDescClass", 8192, 32 }, + { "TextureLoadTaskClass", 256, 32 }, + { "SortingNodeStruct", 288, 32 }, + { "ProxyArrayClass", 32, 32 }, + { "Line3DClass", 8, 8 }, + { "Render2DClass", 64, 32 }, + { "SurfaceClass", 128, 32 }, + { "FontCharsClassCharDataStruct", 1024, 32 }, + { "FontCharsBuffer", 16, 4 }, + { "FVFInfoClass", 152, 64 }, + { "TerrainTracksRenderObjClass", 128, 32 }, + { "DynamicIBAccessClass", 32, 32 }, + { "DX8IndexBufferClass", 128, 32 }, + { "SortingIndexBufferClass", 32, 32 }, + { "DX8VertexBufferClass", 128, 32 }, + { "SortingVertexBufferClass", 32, 32 }, + { "DynD3DMATERIAL8", 8192, 32 }, + { "DynamicMatrix3D", 512, 32 }, + { "MeshGeometryClass", 32, 32 }, + { "DynamicMeshModel", 32, 32 }, + { "GapFillerClass", 32, 32 }, + { "FontCharsClass", 64, 32 }, + { "ThumbnailManagerClass", 32, 32}, + { "SmudgeSet", 32, 32}, + { "Smudge", 128, 32}, + { 0, 0, 0 } +}; diff --git a/GeneralsMD/Code/GameEngine/Source/Common/System/MemoryInit.cpp b/GeneralsMD/Code/GameEngine/Source/Common/System/MemoryInit.cpp index f273e28379f..3f559fbdd05 100644 --- a/GeneralsMD/Code/GameEngine/Source/Common/System/MemoryInit.cpp +++ b/GeneralsMD/Code/GameEngine/Source/Common/System/MemoryInit.cpp @@ -49,27 +49,6 @@ #include "Lib/BaseType.h" #include "Common/GameMemory.h" - -//----------------------------------------------------------------------------- -void userMemoryManagerGetDmaParms(Int *numSubPools, const PoolInitRec **pParms) -{ - static const PoolInitRec defaultDMA[7] = - { - // name, allocsize, initialcount, overflowcount - { "dmaPool_16", 16, 130000, 10000 }, - { "dmaPool_32", 32, 250000, 10000 }, - { "dmaPool_64", 64, 100000, 10000 }, - { "dmaPool_128", 128, 80000, 10000 }, - { "dmaPool_256", 256, 20000, 5000 }, - { "dmaPool_512", 512, 16000, 5000 }, - { "dmaPool_1024", 1024, 6000, 1024} - }; - - *numSubPools = 7; - *pParms = defaultDMA; -} - -//----------------------------------------------------------------------------- struct PoolSizeRec { const char* name; @@ -77,645 +56,20 @@ struct PoolSizeRec Int overflow; }; -//----------------------------------------------------------------------------- -// And please be careful of duplicates. They are not rejected. -// not const -- we might override from INI -static PoolSizeRec sizes[] = -{ - { "PartitionContactListNode", 2048, 512 }, - { "BattleshipUpdate", 32, 32 }, - { "FlyToDestAndDestroyUpdate", 32, 32 }, - { "MusicTrack", 32, 32 }, - { "PositionalSoundPool", 32, 32 }, - { "GameMessage", 2048, 32 }, - { "NameKeyBucketPool", 9000, 1024 }, - { "ObjectSellInfo", 16, 16 }, - { "ProductionPrerequisitePool", 1024, 32 }, - { "RadarObject", 512, 32 }, - { "ResourceGatheringManager", 16, 16 }, - { "SightingInfo", 8192, 2048 },// Looks big, but all 3000 objects used to have 4 just built in. - { "SpecialPowerTemplate", 84, 32 }, - { "StateMachinePool", 32, 32 }, - { "TeamPool", 128, 32 }, // if you increase this, increase player/team relation map pools - { "PlayerRelationMapPool", 128, 32 }, - { "TeamRelationMapPool", 128, 32 }, - { "TeamPrototypePool", 256, 32 }, - { "TerrainType", 256, 32 }, - { "ThingTemplatePool", 2120, 32 }, - { "TunnelTracker", 16, 16 }, - { "Upgrade", 16, 16 }, - { "UpgradeTemplate", 128, 16 }, - { "Anim2D", 32, 32 }, - { "CommandButton", 1024, 256 }, - { "CommandSet", 820, 16 }, - { "DisplayString", 32, 32 }, - { "WebBrowserURL", 16, 16 }, - { "Drawable", 4096, 32 }, - { "Image", 2048, 32 }, - { "ParticlePool", 1400, 1024 }, - { "ParticleSystemTemplatePool", 1100, 32 }, - { "ParticleSystemPool", 1024, 32 }, - { "TerrainRoadType", 100, 32, }, - { "WindowLayoutPool", 32, 32 }, - { "AnimatedParticleSysBoneClientUpdate", 16, 16 }, - { "SwayClientUpdate", 32, 32 }, - { "BeaconClientUpdate", 64, 32 }, - { "AIGroupPool", 64, 32 }, - { "AIDockMachinePool", 256, 32 }, - { "AIGuardMachinePool", 32, 32 }, - { "AIGuardRetaliateMachinePool", 32, 32 }, - { "AITNGuardMachinePool", 32, 32 }, - { "PathNodePool", 8192, 1024 }, - { "PathPool", 256, 16 }, - { "WorkOrder", 32, 32 }, - { "TeamInQueue", 32, 32 }, - { "AIPlayer", 12, 4 }, - { "AISkirmishPlayer", 8, 8 }, - { "AIStateMachine", 600, 32 }, - { "JetAIStateMachine", 64, 32 }, - { "HeliAIStateMachine", 64, 32 }, - { "AIAttackMoveStateMachine", 2048, 32 }, - { "AIAttackThenIdleStateMachine", 512, 32 }, - { "AttackStateMachine", 512, 32 }, - { "CrateTemplate", 32, 32 }, - { "ExperienceTrackerPool", 2048, 512 }, - { "FiringTrackerPool", 4096, 256 }, - { "ObjectRepulsorHelper", 1024, 256 }, - { "ObjectSMCHelperPool", 2048, 256 }, - { "ObjectWeaponStatusHelperPool", 4096, 256 }, - { "ObjectDefectionHelperPool", 2048, 256 }, - { "StatusDamageHelper", 1500, 256 }, - { "SubdualDamageHelper", 1500, 256 }, - { "TempWeaponBonusHelper", 4096, 256 }, - { "Locomotor", 2048, 32 }, - { "LocomotorTemplate", 192, 32 }, - { "ObjectPool", 1500, 256 }, - { "SimpleObjectIteratorPool", 32, 32 }, - { "SimpleObjectIteratorClumpPool", 4096, 32 }, - { "PartitionDataPool", 2048, 512 }, - { "BuildEntry", 32, 32 }, - { "Weapon", 4096, 32 }, - { "WeaponTemplate", 360, 32 }, - { "AIUpdateInterface", 600, 32 }, - { "ActiveBody", 1024, 32 }, - { "ActiveShroudUpgrade", 32, 32 }, - { "AssistedTargetingUpdate", 32, 32 }, - { "AudioEventInfo", 4096, 64 }, - { "AudioRequest", 256, 8 }, - { "AutoHealBehavior", 1024, 256 }, - { "WeaponBonusUpdate", 16, 16 }, - { "GrantStealthBehavior", 4096, 32 }, - { "NeutronBlastBehavior", 4096, 32 }, - { "CountermeasuresBehavior", 256, 32 }, - { "BaseRegenerateUpdate", 128, 32 }, - { "BoneFXDamage", 64, 32 }, - { "BoneFXUpdate", 64, 32 }, - { "BridgeBehavior", 4, 4 }, - { "BridgeTowerBehavior", 32, 32 }, - { "BridgeScaffoldBehavior", 32, 32 }, - { "CaveContain", 16, 16 }, - { "HealContain", 32, 32 }, - { "CreateCrateDie", 256, 128 }, - { "CreateObjectDie", 1024, 32 }, - { "EjectPilotDie", 1024, 32 }, - { "CrushDie", 1024, 32 }, - { "DamDie", 8, 8 }, - { "DeliverPayloadStateMachine", 32, 32 }, - { "DeliverPayloadAIUpdate", 32, 32 }, - { "DeletionUpdate", 128, 32 }, - { "SmartBombTargetHomingUpdate", 8, 8 }, - { "DynamicAudioEventInfo", 16, 256 }, // Note: some levels have none, some have lots. Since all are allocated at level load time, we can set this low for the levels with none. - { "HackInternetStateMachine", 32, 32 }, - { "HackInternetAIUpdate", 32, 32 }, - { "MissileAIUpdate", 512, 32 }, - { "DumbProjectileBehavior", 64, 32 }, - { "DestroyDie", 1024, 32 }, - { "UpgradeDie", 128, 32 }, - { "KeepObjectDie", 128, 32 }, - { "DozerAIUpdate", 32, 32 }, - { "DynamicGeometryInfoUpdate", 16, 16 }, - { "DynamicShroudClearingRangeUpdate", 128, 16 }, - { "FXListDie", 1024, 32 }, - { "FireSpreadUpdate", 2048, 128 }, - { "FirestormDynamicGeometryInfoUpdate", 16, 16 }, - { "FireWeaponCollide", 2048, 32 }, - { "FireWeaponUpdate", 32, 32 }, - { "FlammableUpdate", 512, 256 }, - { "FloatUpdate", 512, 128 }, - { "TensileFormationUpdate", 256, 32 }, - { "GarrisonContain", 256, 32 }, - { "HealCrateCollide", 32, 32 }, - { "HeightDieUpdate", 32, 32 }, - { "FireWeaponWhenDamagedBehavior", 32, 32 }, - { "FireWeaponWhenDeadBehavior", 128, 64 }, - { "GenerateMinefieldBehavior", 32, 32 }, - { "HelicopterSlowDeathBehavior", 64, 32 }, - { "ParkingPlaceBehavior", 32, 32 }, - { "FlightDeckBehavior", 8, 8 }, -#ifdef ALLOW_SURRENDER - { "POWTruckAIUpdate", 32, 32, }, - { "POWTruckBehavior", 32, 32, }, - { "PrisonBehavior", 32, 32 }, - { "PrisonVisual", 32, 32 }, - { "PropagandaCenterBehavior", 16, 16 }, -#endif - { "PropagandaTowerBehavior", 16, 16 }, - { "BunkerBusterBehavior", 16, 16 }, - { "ObjectTracker", 128, 32 }, - { "OCLUpdate", 16, 16 }, - { "BodyParticleSystem", 196, 64 }, - { "HighlanderBody", 2048, 128 }, - { "UndeadBody", 32, 32 }, - { "HordeUpdate", 128, 32 }, - { "ImmortalBody", 128, 256 }, - { "InactiveBody", 2048, 32 }, - { "InstantDeathBehavior", 512, 32 }, - { "LaserUpdate", 32, 32 }, - { "PointDefenseLaserUpdate", 32, 32 }, - { "CleanupHazardUpdate", 32, 32 }, - { "AutoFindHealingUpdate", 256, 32 }, - { "CommandButtonHuntUpdate", 512, 8 }, - { "PilotFindVehicleUpdate", 256, 32 }, - { "DemoTrapUpdate", 32, 32 }, - { "ParticleUplinkCannonUpdate", 16, 16 }, - { "SpectreGunshipUpdate", 8, 8 }, - { "SpectreGunshipDeploymentUpdate", 8, 8 }, - { "BaikonurLaunchPower", 4, 4 }, - { "RadiusDecalUpdate", 16, 16 }, - { "BattlePlanUpdate", 32, 32 }, - { "LifetimeUpdate", 32, 32 }, - { "LocomotorSetUpgrade", 512, 128 }, - { "LockWeaponCreate", 64, 128 }, - { "AutoDepositUpdate", 256, 32 }, - { "NeutronMissileUpdate", 512, 32 }, - { "MoneyCrateCollide", 48, 16 }, - { "NeutronMissileSlowDeathBehavior", 8, 8 }, - { "OpenContain", 128, 32 }, - { "OverchargeBehavior", 32, 32 }, - { "OverlordContain", 32, 32 }, - { "HelixContain", 32, 32 }, - { "ParachuteContain", 128, 32 }, - { "PhysicsBehavior", 600, 32 }, - { "PoisonedBehavior", 512, 64 }, - { "ProductionEntry", 32, 32 }, - { "ProductionUpdate", 256, 32 }, - { "ProjectileStreamUpdate", 32, 32 }, - { "ProneUpdate", 128, 32 }, - { "QueueProductionExitUpdate", 32, 32 }, - { "RadarUpdate", 16, 16 }, - { "RadarUpgrade", 16, 16 }, - { "AnimationSteeringUpdate", 1024, 32 }, - { "SupplyWarehouseCripplingBehavior", 16, 16 }, - { "CostModifierUpgrade", 32, 32 }, - { "CashBountyPower", 32, 32 }, - { "CleanupAreaPower", 32, 32 }, - { "ObjectCreationUpgrade", 196, 32 }, - { "MinefieldBehavior", 256, 32 }, - { "JetSlowDeathBehavior", 64, 32 }, - { "BattleBusSlowDeathBehavior", 64, 32 }, - { "RebuildHoleBehavior", 64, 32 }, - { "RebuildHoleExposeDie", 64, 32 }, - { "RepairDockUpdate", 32, 32 }, -#ifdef ALLOW_SURRENDER - { "PrisonDockUpdate", 32, 32 }, +#if RTS_GENERALS +#include "GameMemoryInitDMA_Generals.inl" +#include "GameMemoryInitPools_Generals.inl" +#elif RTS_ZEROHOUR +#include "GameMemoryInitDMA_GeneralsMD.inl" +#include "GameMemoryInitPools_GeneralsMD.inl" #endif - { "RailedTransportDockUpdate", 16, 16 }, - { "RailedTransportAIUpdate", 16, 16 }, - { "RailedTransportContain", 16, 16 }, - { "RailroadBehavior", 16, 16 }, - { "SalvageCrateCollide", 32, 32 }, - { "ShroudCrateCollide", 32, 32 }, - { "SlavedUpdate", 64, 32 }, - { "SlowDeathBehavior", 1400, 256 }, - { "SpyVisionUpdate", 16, 16 }, - { "DefaultProductionExitUpdate", 32, 32 }, - { "SpawnPointProductionExitUpdate", 32, 32 }, - { "SpawnBehavior", 32, 32 }, - { "SpecialPowerCompletionDie", 32, 32 }, - { "SpecialPowerCreate", 32, 32 }, - { "PreorderCreate", 32, 32 }, - { "SpecialAbility", 512, 32 }, - { "SpecialAbilityUpdate", 512, 32 }, - { "MissileLauncherBuildingUpdate", 32, 32 }, - { "SquishCollide", 512, 32 }, - { "StructureBody", 512, 64 }, - { "HiveStructureBody", 64, 32 }, //Stinger sites - { "StructureCollapseUpdate", 32, 32 }, - { "StructureToppleUpdate", 32, 32 }, - { "SupplyCenterCreate", 32, 32 }, - { "SupplyCenterDockUpdate", 32, 32 }, - { "SupplyCenterProductionExitUpdate", 32, 32 }, - { "SupplyTruckStateMachine", 256, 32 }, - { "SupplyTruckAIUpdate", 32, 32 }, - { "SupplyWarehouseCreate", 48, 16 }, - { "SupplyWarehouseDockUpdate", 48, 16 }, - { "EnemyNearUpdate", 1024, 32 }, - { "TechBuildingBehavior", 32, 32 }, - { "ToppleUpdate", 256, 128 }, - { "TransitionDamageFX", 384, 128 }, - { "TransportAIUpdate", 64, 32 }, - { "TransportContain", 128, 32 }, - { "RiderChangeContain", 128, 32 }, - { "InternetHackContain", 16, 16 }, - { "TunnelContain", 8, 8 }, - { "TunnelContainDie", 32, 32 }, - { "TunnelCreate", 32, 32 }, - { "TurretAI", 256, 32 }, - { "TurretStateMachine", 128, 32 }, - { "TurretSwapUpgrade", 512, 128 }, - { "UnitCrateCollide", 32, 32 }, - { "UnpauseSpecialPowerUpgrade", 32, 32 }, - { "VeterancyCrateCollide", 32, 32 }, - { "VeterancyGainCreate", 512, 128 }, - { "ConvertToCarBombCrateCollide", 256, 128 }, - { "ConvertToHijackedVehicleCrateCollide", 256, 128 }, - { "SabotageCommandCenterCrateCollide", 256, 128 }, - { "SabotageFakeBuildingCrateCollide", 256, 128 }, - { "SabotageInternetCenterCrateCollide", 256, 128 }, - { "SabotageMilitaryFactoryCrateCollide", 256, 128 }, - { "SabotagePowerPlantCrateCollide", 256, 128 }, - { "SabotageSuperweaponCrateCollide", 256, 128 }, - { "SabotageSupplyCenterCrateCollide", 256, 128 }, - { "SabotageSupplyDropzoneCrateCollide", 256, 128 }, - { "JetAIUpdate", 64, 32 }, - { "ChinookAIUpdate", 32, 32 }, - { "WanderAIUpdate", 32, 32 }, - { "WaveGuideUpdate", 16, 16 }, - { "WeaponBonusUpgrade", 512, 128 }, - { "WeaponSetUpgrade", 512, 128 }, - { "ArmorUpgrade", 512, 128 }, - { "WorkerAIUpdate", 128, 128 }, - { "WorkerStateMachine", 128, 128 }, - { "ChinookAIStateMachine", 32, 32 }, - { "DeployStyleAIUpdate", 32, 32 }, - { "AssaultTransportAIUpdate", 64, 32 }, - { "StreamingArchiveFile", 8, 8 }, - { "DozerActionStateMachine", 256, 32 }, - { "DozerPrimaryStateMachine", 256, 32 }, - { "W3DDisplayString", 1400, 128 }, - { "W3DDefaultDraw", 1024, 128 }, - { "W3DDebrisDraw", 128, 128 }, - { "W3DDependencyModelDraw", 64, 64 }, - { "W3DLaserDraw", 32, 32 }, - { "W3DModelDraw", 2048, 512 }, - { "W3DOverlordTankDraw", 64, 64 }, - { "W3DOverlordTruckDraw", 64, 64 }, - { "W3DOverlordAircraftDraw", 64, 64 }, - { "W3DPoliceCarDraw", 32, 32 }, - { "W3DProjectileStreamDraw", 32, 32 }, - { "W3DRopeDraw", 32, 32 }, - { "W3DScienceModelDraw", 32, 32 }, - { "W3DSupplyDraw", 40, 16 }, - { "W3DTankDraw", 256, 32 }, - { "W3DTreeDraw", 16, 16 }, - { "W3DPropDraw", 16, 16 }, - { "W3DTracerDraw", 64, 32 }, - { "W3DTruckDraw", 128, 32 }, - { "W3DTankTruckDraw", 32, 16 }, - { "W3DTreeTextureClass", 4, 4 }, - { "DefaultSpecialPower", 32, 32 }, - { "OCLSpecialPower", 96, 32 }, - { "FireWeaponPower", 32, 32 }, -#ifdef ALLOW_DEMORALIZE - { "DemoralizeSpecialPower", 16, 16, }, -#endif - { "CashHackSpecialPower", 32, 32 }, - { "CommandSetUpgrade", 32, 32 }, - { "PassengersFireUpgrade", 32, 32 }, - { "GrantUpgradeCreate", 256, 32 }, - { "GrantScienceUpgrade", 256, 32 }, - { "ReplaceObjectUpgrade", 32, 32 }, - { "ModelConditionUpgrade", 32, 32 }, - { "SpyVisionSpecialPower", 256, 32 }, - { "StealthDetectorUpdate", 256, 32 }, - { "StealthUpdate", 512, 128 }, - { "StealthUpgrade", 256, 32 }, - { "StatusBitsUpgrade", 128, 128 }, - { "SubObjectsUpgrade", 128, 128 }, - { "ExperienceScalarUpgrade", 256, 128 }, - { "MaxHealthUpgrade", 128, 128 }, - { "WeaponBonusUpgrade", 128, 64 }, - { "StickyBombUpdate", 64, 32 }, - { "FireOCLAfterWeaponCooldownUpdate", 64, 32 }, - { "HijackerUpdate", 64, 32 }, - { "ChinaMinesUpgrade", 64, 32 }, - { "PowerPlantUpdate", 48, 16 }, - { "PowerPlantUpgrade", 48, 16 }, - { "DefectorSpecialPower", 16, 16 }, - { "CheckpointUpdate", 16, 16 }, - { "MobNexusContain", 128, 32 }, - { "MobMemberSlavedUpdate", 64, 32 }, - { "EMPUpdate", 64, 32 }, - { "LeafletDropBehavior", 64, 32 }, - { "Overridable", 32, 32 }, - - { "W3DGameWindow", 700, 256 }, - { "GameWindowDummy", 700, 256 }, - { "SuccessState", 32, 32 }, - { "FailureState", 32, 32 }, - { "ContinueState", 32, 32 }, - { "SleepState", 32, 32 }, - - { "AIDockWaitForClearanceState", 256, 32 }, - { "AIDockProcessDockState", 256, 32 }, - { "AIGuardInnerState", 32, 32 }, - { "AIGuardIdleState", 32, 32 }, - { "AIGuardOuterState", 32, 32 }, - { "AIGuardReturnState", 32, 32 }, - { "AIGuardPickUpCrateState", 32, 32 }, - { "AIGuardAttackAggressorState", 32, 32 }, - { "AIGuardRetaliateInnerState", 32, 32 }, - { "AIGuardRetaliateIdleState", 32, 32 }, - { "AIGuardRetaliateOuterState", 32, 32 }, - { "AIGuardRetaliateReturnState", 32, 32 }, - { "AIGuardRetaliatePickUpCrateState", 32, 32 }, - { "AIGuardRetaliateAttackAggressorState", 32, 32 }, - { "AITNGuardInnerState", 32, 32 }, - { "AITNGuardIdleState", 32, 32 }, - { "AITNGuardOuterState", 32, 32 }, - { "AITNGuardReturnState", 32, 32 }, - { "AITNGuardPickUpCrateState", 32, 32 }, - { "AITNGuardAttackAggressorState", 32, 32 }, - { "AIIdleState", 2400, 32 }, - { "AIRappelState", 600, 32 }, - { "AIBusyState", 600, 32 }, - { "AIWaitState", 600, 32 }, - { "AIAttackState", 4096, 32 }, - { "AIAttackSquadState", 600, 32 }, - { "AIDeadState", 600, 32 }, - { "AIDockState", 600, 32 }, - { "AIExitState", 600, 32 }, - { "AIExitInstantlyState", 600, 32 }, - { "AIGuardState", 600, 32 }, - { "AIGuardRetaliateState", 600, 32 }, - { "AITunnelNetworkGuardState", 600, 32 }, - { "AIHuntState", 600, 32 }, - { "AIAttackAreaState", 600, 32 }, - { "AIFaceState", 1200, 32 }, - { "ApproachState", 600, 32 }, - { "DeliveringState", 600, 32 }, - { "ConsiderNewApproachState", 600, 32 }, - { "RecoverFromOffMapState", 600, 32 }, - { "HeadOffMapState", 600, 32 }, - { "CleanUpState", 600, 32 }, - { "HackInternetState", 600, 32 }, - { "PackingState", 600, 32 }, - { "UnpackingState", 600, 32 }, - { "SupplyTruckWantsToPickUpOrDeliverBoxesState", 600, 32 }, - { "RegroupingState", 600, 32 }, - { "DockingState", 600, 32 }, - { "ChinookEvacuateState", 32, 32 }, - { "ChinookHeadOffMapState", 32, 32 }, - { "ChinookTakeoffOrLandingState", 32, 32 }, - { "ChinookCombatDropState", 32, 32 }, - { "DozerActionPickActionPosState", 256, 32 }, - { "DozerActionMoveToActionPosState", 256, 32 }, - { "DozerActionDoActionState", 256, 32 }, - { "DozerPrimaryIdleState", 256, 32 }, - { "DozerActionState", 256, 32 }, - { "DozerPrimaryGoingHomeState", 256, 32 }, - { "JetAwaitingRunwayState", 64, 32 }, - { "JetOrHeliCirclingDeadAirfieldState", 64, 32 }, - { "HeliTakeoffOrLandingState", 64, 32 }, - { "JetOrHeliParkOrientState", 64, 32 }, - { "JetOrHeliReloadAmmoState", 64, 32 }, - { "SupplyTruckBusyState", 600, 32 }, - { "SupplyTruckIdleState", 600, 32 }, - { "ActAsDozerState", 600, 32 }, - { "ActAsSupplyTruckState", 600, 32 }, - { "AIDockApproachState", 256, 32 }, - { "AIDockAdvancePositionState", 256, 32 }, - { "AIDockMoveToEntryState", 256, 32 }, - { "AIDockMoveToDockState", 256, 32 }, - { "AIDockMoveToExitState", 256, 32 }, - { "AIDockMoveToRallyState", 256, 32 }, - { "AIMoveToState", 600, 32 }, - { "AIMoveOutOfTheWayState", 600, 32 }, - { "AIMoveAndTightenState", 600, 32 }, - { "AIMoveAwayFromRepulsorsState", 600, 32 }, - { "AIAttackApproachTargetState", 96, 32 }, - { "AIAttackPursueTargetState", 96, 32 }, - { "AIAttackAimAtTargetState", 96, 32 }, - { "AIAttackFireWeaponState", 256, 32 }, - { "AIPickUpCrateState", 4096, 32 }, - { "AIFollowWaypointPathState", 1200, 32 }, - { "AIFollowWaypointPathExactState", 1200, 32 }, - { "AIWanderInPlaceState", 600, 32 }, - { "AIFollowPathState", 1200, 32 }, - { "AIMoveAndEvacuateState", 1200, 32 }, - { "AIMoveAndDeleteState", 600, 32 }, - { "AIEnterState", 600, 32 }, - { "JetOrHeliReturningToDeadAirfieldState", 64, 32 }, - { "JetOrHeliReturnForLandingState", 64, 32 }, - { "TurretAIIdleState", 600, 32 }, - { "TurretAIIdleScanState", 600, 32 }, - { "TurretAIAimTurretState", 600, 32 }, - { "TurretAIRecenterTurretState", 600, 32 }, - { "TurretAIHoldTurretState", 600, 32 }, - { "JetOrHeliTaxiState", 64, 32 }, - { "JetTakeoffOrLandingState", 64, 32 }, - { "JetPauseBeforeTakeoffState", 64, 32 }, - { "AIAttackMoveToState", 600, 32 }, - { "AIAttackFollowWaypointPathState", 1200, 32 }, - { "AIWanderState", 600, 32 }, - { "AIPanicState", 600, 32 }, - { "ChinookMoveToBldgState", 32, 32 }, - { "ChinookRecordCreationState", 32, 32 }, - { "ScienceInfo", 96, 32 }, - { "RankInfo", 32, 32 }, - - { "FireWeaponNugget", 32, 32 }, - { "AttackNugget", 32, 32 }, - { "DeliverPayloadNugget", 48, 32 }, - { "ApplyRandomForceNugget", 32, 32 }, - { "GenericObjectCreationNugget", 632, 32 }, - { "SoundFXNugget", 320, 32 }, - { "TracerFXNugget", 32, 32 }, - { "RayEffectFXNugget", 32, 32 }, - { "LightPulseFXNugget", 68, 32 }, - { "ViewShakeFXNugget", 140, 32 }, - { "TerrainScorchFXNugget", 48, 32 }, - { "ParticleSystemFXNugget", 832, 32 }, - { "FXListAtBonePosFXNugget", 32, 32 }, - { "Squad", 256, 32 }, - { "BuildListInfo", 400, 64 }, - - { "ScriptGroup", 128, 32 }, - { "OrCondition", 1024, 256 }, - { "ScriptAction", 2600, 512 }, - { "Script", 1024, 256 }, - { "Parameter", 8192, 1024 }, - { "Condition", 2048, 256 }, - { "Template", 32, 32 }, - { "ScriptList", 32, 32 }, - { "AttackPriorityInfo", 32, 32 }, - { "SequentialScript", 32, 32 }, - { "Win32LocalFile", 1024, 256 }, - { "StdLocalFile", 1024, 256 }, - { "RAMFile", 32, 32 }, - { "BattlePlanBonuses", 32, 32 }, - { "KindOfPercentProductionChange", 32, 32 }, - { "UserParser", 4096, 256 }, - { "XferBlockData", 32, 32 }, - { "EvaCheckInfo", 52, 16 }, - { "SuperweaponInfo", 32, 32 }, - { "NamedTimerInfo", 32, 32 }, - { "PopupMessageData", 32, 32 }, - { "FloatingTextData", 32, 32 }, - { "MapObject", 5000, 1024 }, - { "Waypoint", 1024, 32 }, - { "PolygonTrigger", 64, 64 }, - { "Bridge", 32, 32 }, - { "Mapping", 384, 64 }, - { "OutputChunk", 32, 32 }, - { "InputChunk", 32, 32 }, - { "AnimateWindow", 32, 32 }, - { "GameFont", 32, 32 }, - { "NetCommandRef", 256, 32 }, - { "GameMessageArgument", 1024, 256 }, - { "GameMessageParserArgumentType", 32, 32 }, - { "GameMessageParser", 32, 32 }, - { "WeaponBonusSet", 96, 32 }, - { "Campaign", 32, 32 }, - { "Mission", 88, 32 }, - { "ModalWindow", 32, 32 }, - { "NetPacket", 32, 32 }, - { "AISideInfo", 32, 32 }, - { "AISideBuildList", 32, 32 }, - { "MetaMapRec", 256, 32 }, - { "TransportStatus", 32, 32 }, - { "Anim2DTemplate", 32, 32 }, - { "ObjectTypes", 32, 32 }, - { "NetCommandList", 512, 32 }, - { "TurretAIData", 256, 32 }, - { "NetCommandMsg", 32, 32 }, - { "NetGameCommandMsg", 64, 32 }, - { "NetAckBothCommandMsg", 32, 32 }, - { "NetAckStage1CommandMsg", 32, 32 }, - { "NetAckStage2CommandMsg", 32, 32 }, - { "NetFrameCommandMsg", 32, 32 }, - { "NetPlayerLeaveCommandMsg", 32, 32 }, - { "NetRunAheadMetricsCommandMsg", 32, 32 }, - { "NetRunAheadCommandMsg", 32, 32 }, - { "NetDestroyPlayerCommandMsg", 32, 32 }, - { "NetDisconnectFrameCommandMsg", 32, 32 }, - { "NetDisconnectScreenOffCommandMsg", 32, 32 }, - { "NetFrameResendRequestCommandMsg", 32, 32 }, - { "NetKeepAliveCommandMsg", 32, 32 }, - { "NetDisconnectKeepAliveCommandMsg", 32, 32 }, - { "NetDisconnectPlayerCommandMsg", 32, 32 }, - { "NetPacketRouterQueryCommandMsg", 32, 32 }, - { "NetPacketRouterAckCommandMsg", 32, 32 }, - { "NetDisconnectChatCommandMsg", 32, 32 }, - { "NetChatCommandMsg", 32, 32 }, - { "NetDisconnectVoteCommandMsg", 32, 32 }, - { "NetProgressCommandMsg", 32, 32 }, - { "NetWrapperCommandMsg", 32, 32 }, - { "NetFileCommandMsg", 32, 32 }, - { "NetFileAnnounceCommandMsg", 32, 32 }, - { "NetFileProgressCommandMsg", 32, 32 }, - { "NetCommandWrapperListNode", 32, 32 }, - { "NetCommandWrapperList", 32, 32 }, - { "Connection", 32, 32 }, - { "User", 32, 32 }, - { "FrameDataManager", 32, 32 }, - { "DrawableIconInfo", 32, 32 }, - { "TintEnvelope", 128, 32 }, - { "DynamicAudioEventRTS", 4000, 256 }, - { "DrawableLocoInfo", 128, 32 }, - { "W3DPrototypeClass", 512, 256 }, - { "EnumeratedIP", 32, 32 }, - { "WaterTransparencySetting", 4, 4 }, - { "WeatherSetting", 4, 4 }, - - // W3D pools! - { "BoxPrototypeClass", 128, 128 }, - { "SpherePrototypeClass", 32, 32 }, - { "SoundRenderObjPrototypeClass", 32, 32 }, - { "RingPrototypeClass", 32, 32 }, - { "PrimitivePrototypeClass", 8192, 32 }, - { "HModelPrototypeClass", 256, 32 }, - { "ParticleEmitterPrototypeClass", 32, 32 }, - { "NullPrototypeClass", 32, 32 }, - { "HLodPrototypeClass", 700, 128 }, - { "HLodDefClass", 700, 128 }, - { "DistLODPrototypeClass", 32, 32 }, - { "DazzlePrototypeClass", 32, 32 }, - { "CollectionPrototypeClass", 32, 32 }, - { "BoxPrototypeClass", 256, 32 }, - { "AggregatePrototypeClass", 32, 32 }, - { "OBBoxRenderObjClass", 512, 128 }, - { "AABoxRenderObjClass", 32, 32 }, - { "VertexMaterialClass", 6000, 2048 }, - { "TextureClass", 1200, 256 }, - { "CloudMapTerrainTextureClass", 4, 4 }, - { "ScorchTextureClass", 4, 4 }, - { "LightMapTerrainTextureClass", 4, 4 }, - { "AlphaEdgeTextureClass", 4, 4 }, - { "AlphaTerrainTextureClass", 4, 4 }, - { "TerrainTextureClass", 4, 4 }, - { "MeshClass", 14000, 2000 }, - { "HTreeClass", 2048, 512 }, - { "HLodClass", 2048, 512 }, - { "MeshModelClass", 8192, 32 }, - { "ShareBufferClass", 32768, 1024 }, - { "AABTreeClass", 300, 128 }, - { "MotionChannelClass", 16384, 32 }, - { "BitChannelClass", 84, 32 }, - { "TimeCodedMotionChannelClass", 116, 32 }, - { "AdaptiveDeltaMotionChannelClass", 32, 32 }, - { "TimeCodedBitChannelClass", 32, 32 }, - { "UVBufferClass", 8192, 32 }, - { "TexBufferClass", 384, 128 }, - { "MatBufferClass", 256, 128 }, - { "MatrixMapperClass", 32, 32 }, - { "ScaleTextureMapperClass", 32, 32 }, - { "LinearOffsetTextureMapperClass", 96, 32 }, - { "GridTextureMapperClass", 32, 32 }, - { "RotateTextureMapperClass", 32, 32 }, - { "SineLinearOffsetTextureMapperClass", 32, 32 }, - { "StepLinearOffsetTextureMapperClass", 32, 32 }, - { "ZigZagLinearOffsetTextureMapperClass", 32, 32 }, - { "ClassicEnvironmentMapperClass", 32, 32 }, - { "EnvironmentMapperClass", 256, 32 }, - { "EdgeMapperClass", 32, 32 }, - { "WSClassicEnvironmentMapperClass", 32, 32 }, - { "WSEnvironmentMapperClass", 32, 32 }, - { "GridClassicEnvironmentMapperClass", 32, 32 }, - { "GridEnvironmentMapperClass", 32, 32 }, - { "ScreenMapperClass", 32, 32 }, - { "RandomTextureMapperClass", 32, 32 }, - { "BumpEnvTextureMapperClass", 32, 32 }, - { "MeshLoadContextClass", 4, 4 }, - { "MaterialInfoClass", 8192, 32 }, - { "MeshMatDescClass", 8192, 32 }, - { "TextureLoadTaskClass", 256, 32 }, - { "SortingNodeStruct", 288, 32 }, - { "ProxyArrayClass", 32, 32 }, - { "Line3DClass", 8, 8 }, - { "Render2DClass", 64, 32 }, - { "SurfaceClass", 128, 32 }, - { "FontCharsClassCharDataStruct", 1024, 32 }, - { "FontCharsBuffer", 16, 4 }, - { "FVFInfoClass", 152, 64 }, - { "TerrainTracksRenderObjClass", 128, 32 }, - { "DynamicIBAccessClass", 32, 32 }, - { "DX8IndexBufferClass", 128, 32 }, - { "SortingIndexBufferClass", 32, 32 }, - { "DX8VertexBufferClass", 128, 32 }, - { "SortingVertexBufferClass", 32, 32 }, - { "DynD3DMATERIAL8", 8192, 32 }, - { "DynamicMatrix3D", 512, 32 }, - { "MeshGeometryClass", 32, 32 }, - { "DynamicMeshModel", 32, 32 }, - { "GapFillerClass", 32, 32 }, - { "FontCharsClass", 64, 32 }, - { "ThumbnailManagerClass", 32, 32}, - { "SmudgeSet", 32, 32}, - { "Smudge", 128, 32}, - { 0, 0, 0 } -}; +//----------------------------------------------------------------------------- +void userMemoryManagerGetDmaParms(Int *numSubPools, const PoolInitRec **pParms) +{ + *numSubPools = ARRAY_SIZE(DefaultDMA); + *pParms = DefaultDMA; +} //----------------------------------------------------------------------------- void userMemoryAdjustPoolSize(const char *poolName, Int& initialAllocationCount, Int& overflowAllocationCount) @@ -723,7 +77,7 @@ void userMemoryAdjustPoolSize(const char *poolName, Int& initialAllocationCount, if (initialAllocationCount > 0) return; - for (const PoolSizeRec* p = sizes; p->name != NULL; ++p) + for (const PoolSizeRec* p = PoolSizes; p->name != NULL; ++p) { if (strcmp(p->name, poolName) == 0) { @@ -782,7 +136,7 @@ void userMemoryManagerInitPools() continue; if (sscanf(buf, "%s %d %d", poolName, &initial, &overflow ) == 3) { - for (PoolSizeRec* p = sizes; p->name != NULL; ++p) + for (PoolSizeRec* p = PoolSizes; p->name != NULL; ++p) { if (stricmp(p->name, poolName) == 0) { From 5c0998dc2139b14bae3192ecb3a5bcf753f6a62f Mon Sep 17 00:00:00 2001 From: xezon <4720891+xezon@users.noreply.github.com> Date: Sun, 10 Aug 2025 11:58:03 +0200 Subject: [PATCH 3/3] unify(memory): Move GameMemory files to Core (#1408) --- Core/GameEngine/CMakeLists.txt | 18 +- .../GameEngine/Include/Common/GameMemory.h | 0 .../Include/Common/GameMemoryNull.h | 0 .../Source/Common/System/GameMemory.cpp | 0 .../Source/Common/System/GameMemoryInit.cpp | 0 .../System/GameMemoryInitDMA_Generals.inl | 0 .../System/GameMemoryInitDMA_GeneralsMD.inl | 0 .../System/GameMemoryInitPools_Generals.inl | 0 .../System/GameMemoryInitPools_GeneralsMD.inl | 0 .../Source/Common/System/GameMemoryNull.cpp | 0 Generals/Code/GameEngine/CMakeLists.txt | 14 +- .../GameEngine/Include/Common/GameMemory.h | 918 ----- .../Source/Common/System/GameMemory.cpp | 3579 ----------------- .../Source/Common/System/MemoryInit.cpp | 154 - GeneralsMD/Code/GameEngine/CMakeLists.txt | 14 +- .../Include/Common/GameMemoryNull.h | 165 - .../Source/Common/System/GameMemoryNull.cpp | 218 - scripts/cpp/unify_move_files.py | 10 + 18 files changed, 33 insertions(+), 5057 deletions(-) rename {GeneralsMD/Code => Core}/GameEngine/Include/Common/GameMemory.h (100%) rename {Generals/Code => Core}/GameEngine/Include/Common/GameMemoryNull.h (100%) rename {GeneralsMD/Code => Core}/GameEngine/Source/Common/System/GameMemory.cpp (100%) rename GeneralsMD/Code/GameEngine/Source/Common/System/MemoryInit.cpp => Core/GameEngine/Source/Common/System/GameMemoryInit.cpp (100%) rename {Generals/Code => Core}/GameEngine/Source/Common/System/GameMemoryInitDMA_Generals.inl (100%) rename {GeneralsMD/Code => Core}/GameEngine/Source/Common/System/GameMemoryInitDMA_GeneralsMD.inl (100%) rename {Generals/Code => Core}/GameEngine/Source/Common/System/GameMemoryInitPools_Generals.inl (100%) rename {GeneralsMD/Code => Core}/GameEngine/Source/Common/System/GameMemoryInitPools_GeneralsMD.inl (100%) rename {Generals/Code => Core}/GameEngine/Source/Common/System/GameMemoryNull.cpp (100%) delete mode 100644 Generals/Code/GameEngine/Include/Common/GameMemory.h delete mode 100644 Generals/Code/GameEngine/Source/Common/System/GameMemory.cpp delete mode 100644 Generals/Code/GameEngine/Source/Common/System/MemoryInit.cpp delete mode 100644 GeneralsMD/Code/GameEngine/Include/Common/GameMemoryNull.h delete mode 100644 GeneralsMD/Code/GameEngine/Source/Common/System/GameMemoryNull.cpp diff --git a/Core/GameEngine/CMakeLists.txt b/Core/GameEngine/CMakeLists.txt index 15b9b827a9d..494d544f73d 100644 --- a/Core/GameEngine/CMakeLists.txt +++ b/Core/GameEngine/CMakeLists.txt @@ -45,7 +45,7 @@ set(GAMEENGINE_SRC Include/Common/GameDefines.h # Include/Common/GameEngine.h # Include/Common/GameLOD.h -# Include/Common/GameMemory.h + Include/Common/GameMemory.h Include/Common/GameMusic.h Include/Common/GameSounds.h # Include/Common/GameSpyMiscPreferences.h @@ -1139,18 +1139,18 @@ set(GAMEENGINE_SRC if(RTS_GAMEMEMORY_ENABLE) # Uses the original Game Memory implementation. list(APPEND GAMEENGINE_SRC -# Source/Common/System/GameMemory.cpp -# Source/Common/System/GameMemoryInit.cpp -# Source/Common/System/GameMemoryInitDMA_Generals.inl -# Source/Common/System/GameMemoryInitDMA_GeneralsMD.inl -# Source/Common/System/GameMemoryInitPools_Generals.inl -# Source/Common/System/GameMemoryInitPools_GeneralsMD.inl + Source/Common/System/GameMemory.cpp + Source/Common/System/GameMemoryInit.cpp + Source/Common/System/GameMemoryInitDMA_Generals.inl + Source/Common/System/GameMemoryInitDMA_GeneralsMD.inl + Source/Common/System/GameMemoryInitPools_Generals.inl + Source/Common/System/GameMemoryInitPools_GeneralsMD.inl ) else() # Uses the null implementation when disabled. list(APPEND GAMEENGINE_SRC -# Source/Common/System/GameMemoryNull.cpp -# Include/Common/GameMemoryNull.h + Source/Common/System/GameMemoryNull.cpp + Include/Common/GameMemoryNull.h ) endif() diff --git a/GeneralsMD/Code/GameEngine/Include/Common/GameMemory.h b/Core/GameEngine/Include/Common/GameMemory.h similarity index 100% rename from GeneralsMD/Code/GameEngine/Include/Common/GameMemory.h rename to Core/GameEngine/Include/Common/GameMemory.h diff --git a/Generals/Code/GameEngine/Include/Common/GameMemoryNull.h b/Core/GameEngine/Include/Common/GameMemoryNull.h similarity index 100% rename from Generals/Code/GameEngine/Include/Common/GameMemoryNull.h rename to Core/GameEngine/Include/Common/GameMemoryNull.h diff --git a/GeneralsMD/Code/GameEngine/Source/Common/System/GameMemory.cpp b/Core/GameEngine/Source/Common/System/GameMemory.cpp similarity index 100% rename from GeneralsMD/Code/GameEngine/Source/Common/System/GameMemory.cpp rename to Core/GameEngine/Source/Common/System/GameMemory.cpp diff --git a/GeneralsMD/Code/GameEngine/Source/Common/System/MemoryInit.cpp b/Core/GameEngine/Source/Common/System/GameMemoryInit.cpp similarity index 100% rename from GeneralsMD/Code/GameEngine/Source/Common/System/MemoryInit.cpp rename to Core/GameEngine/Source/Common/System/GameMemoryInit.cpp diff --git a/Generals/Code/GameEngine/Source/Common/System/GameMemoryInitDMA_Generals.inl b/Core/GameEngine/Source/Common/System/GameMemoryInitDMA_Generals.inl similarity index 100% rename from Generals/Code/GameEngine/Source/Common/System/GameMemoryInitDMA_Generals.inl rename to Core/GameEngine/Source/Common/System/GameMemoryInitDMA_Generals.inl diff --git a/GeneralsMD/Code/GameEngine/Source/Common/System/GameMemoryInitDMA_GeneralsMD.inl b/Core/GameEngine/Source/Common/System/GameMemoryInitDMA_GeneralsMD.inl similarity index 100% rename from GeneralsMD/Code/GameEngine/Source/Common/System/GameMemoryInitDMA_GeneralsMD.inl rename to Core/GameEngine/Source/Common/System/GameMemoryInitDMA_GeneralsMD.inl diff --git a/Generals/Code/GameEngine/Source/Common/System/GameMemoryInitPools_Generals.inl b/Core/GameEngine/Source/Common/System/GameMemoryInitPools_Generals.inl similarity index 100% rename from Generals/Code/GameEngine/Source/Common/System/GameMemoryInitPools_Generals.inl rename to Core/GameEngine/Source/Common/System/GameMemoryInitPools_Generals.inl diff --git a/GeneralsMD/Code/GameEngine/Source/Common/System/GameMemoryInitPools_GeneralsMD.inl b/Core/GameEngine/Source/Common/System/GameMemoryInitPools_GeneralsMD.inl similarity index 100% rename from GeneralsMD/Code/GameEngine/Source/Common/System/GameMemoryInitPools_GeneralsMD.inl rename to Core/GameEngine/Source/Common/System/GameMemoryInitPools_GeneralsMD.inl diff --git a/Generals/Code/GameEngine/Source/Common/System/GameMemoryNull.cpp b/Core/GameEngine/Source/Common/System/GameMemoryNull.cpp similarity index 100% rename from Generals/Code/GameEngine/Source/Common/System/GameMemoryNull.cpp rename to Core/GameEngine/Source/Common/System/GameMemoryNull.cpp diff --git a/Generals/Code/GameEngine/CMakeLists.txt b/Generals/Code/GameEngine/CMakeLists.txt index 4a2bae048bc..64236aa60d3 100644 --- a/Generals/Code/GameEngine/CMakeLists.txt +++ b/Generals/Code/GameEngine/CMakeLists.txt @@ -42,7 +42,7 @@ set(GAMEENGINE_SRC # Include/Common/GameDefines.h Include/Common/GameEngine.h Include/Common/GameLOD.h - Include/Common/GameMemory.h +# Include/Common/GameMemory.h # Include/Common/GameMusic.h # Include/Common/GameSounds.h Include/Common/GameSpyMiscPreferences.h @@ -1060,16 +1060,16 @@ set(GAMEENGINE_SRC if(RTS_GAMEMEMORY_ENABLE) # Uses the original Game Memory implementation. list(APPEND GAMEENGINE_SRC - Source/Common/System/GameMemory.cpp - Source/Common/System/GameMemoryInitDMA_Generals.inl - Source/Common/System/GameMemoryInitPools_Generals.inl - Source/Common/System/MemoryInit.cpp +# Source/Common/System/GameMemory.cpp +# Source/Common/System/GameMemoryInitDMA_Generals.inl +# Source/Common/System/GameMemoryInitPools_Generals.inl +# Source/Common/System/MemoryInit.cpp ) else() # Uses the null implementation when disabled. list(APPEND GAMEENGINE_SRC - Source/Common/System/GameMemoryNull.cpp - Include/Common/GameMemoryNull.h +# Source/Common/System/GameMemoryNull.cpp +# Include/Common/GameMemoryNull.h ) endif() diff --git a/Generals/Code/GameEngine/Include/Common/GameMemory.h b/Generals/Code/GameEngine/Include/Common/GameMemory.h deleted file mode 100644 index e43af713441..00000000000 --- a/Generals/Code/GameEngine/Include/Common/GameMemory.h +++ /dev/null @@ -1,918 +0,0 @@ -/* -** Command & Conquer Generals(tm) -** Copyright 2025 Electronic Arts Inc. -** -** This program is free software: you can redistribute it and/or modify -** it under the terms of the GNU General Public License as published by -** the Free Software Foundation, either version 3 of the License, or -** (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program. If not, see . -*/ - -//////////////////////////////////////////////////////////////////////////////// -// // -// (c) 2001-2003 Electronic Arts Inc. // -// // -//////////////////////////////////////////////////////////////////////////////// - -// FILE: Memory.h -//----------------------------------------------------------------------------- -// -// Westwood Studios Pacific. -// -// Confidential Information -// Copyright (C); 2001 - All Rights Reserved -// -//----------------------------------------------------------------------------- -// -// Project: RTS3 -// -// File name: Memory.h -// -// Created: Steven Johnson, August 2001 -// -// Desc: Memory manager -// -//----------------------------------------------------------------------------- -/////////////////////////////////////////////////////////////////////////////// - -#pragma once - -#ifndef _GAME_MEMORY_H_ -#define _GAME_MEMORY_H_ - -// Turn off memory pool checkpointing for now. -#ifndef DISABLE_MEMORYPOOL_CHECKPOINTING - #define DISABLE_MEMORYPOOL_CHECKPOINTING 1 -#endif - -#if defined(RTS_DEBUG) && !defined(MEMORYPOOL_DEBUG_CUSTOM_NEW) && !defined(DISABLE_MEMORYPOOL_DEBUG_CUSTOM_NEW) - #define MEMORYPOOL_DEBUG_CUSTOM_NEW -#endif - -//#if defined(RTS_DEBUG) && !defined(MEMORYPOOL_DEBUG) && !defined(DISABLE_MEMORYPOOL_DEBUG) -#if defined(RTS_DEBUG) && !defined(MEMORYPOOL_DEBUG) && !defined(DISABLE_MEMORYPOOL_DEBUG) - #define MEMORYPOOL_DEBUG -#endif - -// SYSTEM INCLUDES //////////////////////////////////////////////////////////// - -#include -#include -#ifdef MEMORYPOOL_OVERRIDE_MALLOC - #include -#endif - -// USER INCLUDES ////////////////////////////////////////////////////////////// - -#include "Lib/BaseType.h" -#include "Common/Debug.h" -#include "Common/Errors.h" - -// MACROS ////////////////////////////////////////////////////////////////// - -#ifdef MEMORYPOOL_DEBUG - - // by default, enable free-block-retention for checkpointing in debug mode - #if !defined(DISABLE_MEMORYPOOL_CHECKPOINTING) || DISABLE_MEMORYPOOL_CHECKPOINTING == 0 - #define MEMORYPOOL_CHECKPOINTING - #endif - - // by default, enable bounding walls in debug mode (unless we have specifically disabled them) - #ifndef DISABLE_MEMORYPOOL_BOUNDINGWALL - #define MEMORYPOOL_BOUNDINGWALL - #endif - - #if !defined(MEMORYPOOL_STACKTRACE) && !defined(DISABLE_MEMORYPOOL_STACKTRACE) - #define MEMORYPOOL_STACKTRACE - #endif - - // flags for the memory-report options. - enum - { - -#ifdef MEMORYPOOL_CHECKPOINTING - // ------------------------------------------------------ - // you usually won't use the _REPORT bits directly; see below for more convenient combinations. - - // you must set at least one of the 'allocate' bits. - _REPORT_CP_ALLOCATED_BEFORE = 0x0001, - _REPORT_CP_ALLOCATED_BETWEEN = 0x0002, - _REPORT_CP_ALLOCATED_DONTCARE = (_REPORT_CP_ALLOCATED_BEFORE|_REPORT_CP_ALLOCATED_BETWEEN), - - // you must set at least one of the 'freed' bits. - _REPORT_CP_FREED_BEFORE = 0x0010, - _REPORT_CP_FREED_BETWEEN = 0x0020, - _REPORT_CP_FREED_NEVER = 0x0040, // ie, still in existence - _REPORT_CP_FREED_DONTCARE = (_REPORT_CP_FREED_BEFORE|_REPORT_CP_FREED_BETWEEN|_REPORT_CP_FREED_NEVER), - // ------------------------------------------------------ -#endif // MEMORYPOOL_CHECKPOINTING - -#ifdef MEMORYPOOL_CHECKPOINTING - /** display the stacktrace for allocation location for all blocks found. - this bit may be mixed-n-matched with any other flag. - */ - REPORT_CP_STACKTRACE = 0x0100, -#endif - - /** display stats for each pool, in addition to each block. - (this is useful for finding suitable allocation counts for the pools.) - this bit may be mixed-n-matched with any other flag. - */ - REPORT_POOLINFO = 0x0200, - - /** report on the overall memory situation (including all pools and dma's). - this bit may be mixed-n-matched with any other flag. - */ - REPORT_FACTORYINFO = 0x0400, - - /** report on pools that have overflowed their initial allocation. - this bit may be mixed-n-matched with any other flag. - */ - REPORT_POOL_OVERFLOW = 0x0800, - - /** simple-n-cheap leak checking */ - REPORT_SIMPLE_LEAKS = 0x1000, - -#ifdef MEMORYPOOL_CHECKPOINTING - /** report on blocks that were allocated between the checkpoints. - (don't care if they were freed or not.) - */ - REPORT_CP_ALLOCATES = (_REPORT_CP_ALLOCATED_BETWEEN | _REPORT_CP_FREED_DONTCARE), - - /** report on blocks that were freed between the checkpoints. - (don't care when they were allocated.) - */ - REPORT_CP_FREES = (_REPORT_CP_ALLOCATED_DONTCARE | _REPORT_CP_FREED_BETWEEN), - - /** report on blocks that were allocated between the checkpoints, and still exist - (note that this reports *potential* leaks -- some such blocks may be desired) - */ - REPORT_CP_LEAKS = (_REPORT_CP_ALLOCATED_BETWEEN | _REPORT_CP_FREED_NEVER), - - /** report on blocks that existed before checkpoint #1 and still exist now. - */ - REPORT_CP_LONGTERM = (_REPORT_CP_ALLOCATED_BEFORE | _REPORT_CP_FREED_NEVER), - - /** report on blocks that were allocated-and-freed between the checkpoints. - */ - REPORT_CP_TRANSIENT = (_REPORT_CP_ALLOCATED_BETWEEN | _REPORT_CP_FREED_BETWEEN), - - /** report on all blocks that currently exist - */ - REPORT_CP_EXISTING = (_REPORT_CP_ALLOCATED_BEFORE | _REPORT_CP_ALLOCATED_BETWEEN | _REPORT_CP_FREED_NEVER), - - /** report on all blocks that have ever existed (!) (or at least, since the last call - to debugResetCheckpoints) - */ - REPORT_CP_ALL = (_REPORT_CP_ALLOCATED_DONTCARE | _REPORT_CP_FREED_DONTCARE) -#endif // MEMORYPOOL_CHECKPOINTING - - }; - -#endif // MEMORYPOOL_DEBUG - -// TheSuperHackers @build xezon 30/03/2025 Define DISABLE_GAMEMEMORY to use a null implementations for Game Memory. -// Useful for address sanitizer checks and other investigations. -// Is included below the macros so that memory pool debug code can still be used. -#ifdef DISABLE_GAMEMEMORY -#include "GameMemoryNull.h" -#else - -#ifdef MEMORYPOOL_DEBUG - - #define DECLARE_LITERALSTRING_ARG1 const char * debugLiteralTagString - #define PASS_LITERALSTRING_ARG1 debugLiteralTagString - #define DECLARE_LITERALSTRING_ARG2 , const char * debugLiteralTagString - #define PASS_LITERALSTRING_ARG2 , debugLiteralTagString - - #define MP_LOC_SUFFIX /*" [" DEBUG_FILENLINE "]"*/ - - #define allocateBlock(ARGLITERAL) allocateBlockImplementation(ARGLITERAL MP_LOC_SUFFIX) - #define allocateBlockDoNotZero(ARGLITERAL) allocateBlockDoNotZeroImplementation(ARGLITERAL MP_LOC_SUFFIX) - #define allocateBytes(ARGCOUNT,ARGLITERAL) allocateBytesImplementation(ARGCOUNT, ARGLITERAL MP_LOC_SUFFIX) - #define allocateBytesDoNotZero(ARGCOUNT,ARGLITERAL) allocateBytesDoNotZeroImplementation(ARGCOUNT, ARGLITERAL MP_LOC_SUFFIX) - #define newInstanceDesc(ARGCLASS,ARGLITERAL) new(ARGCLASS::ARGCLASS##_GLUE_NOT_IMPLEMENTED, ARGLITERAL MP_LOC_SUFFIX) ARGCLASS - #define newInstance(ARGCLASS) new(ARGCLASS::ARGCLASS##_GLUE_NOT_IMPLEMENTED, __FILE__) ARGCLASS - -#else - - #define DECLARE_LITERALSTRING_ARG1 - #define PASS_LITERALSTRING_ARG1 - #define DECLARE_LITERALSTRING_ARG2 - #define PASS_LITERALSTRING_ARG2 - - #define allocateBlock(ARGLITERAL) allocateBlockImplementation() - #define allocateBlockDoNotZero(ARGLITERAL) allocateBlockDoNotZeroImplementation() - #define allocateBytes(ARGCOUNT,ARGLITERAL) allocateBytesImplementation(ARGCOUNT) - #define allocateBytesDoNotZero(ARGCOUNT,ARGLITERAL) allocateBytesDoNotZeroImplementation(ARGCOUNT) - #define newInstanceDesc(ARGCLASS,ARGLITERAL) new(ARGCLASS::ARGCLASS##_GLUE_NOT_IMPLEMENTED) ARGCLASS - #define newInstance(ARGCLASS) new(ARGCLASS::ARGCLASS##_GLUE_NOT_IMPLEMENTED) ARGCLASS - -#endif - -// FORWARD REFERENCES ///////////////////////////////////////////////////////// - -class MemoryPoolSingleBlock; -class MemoryPoolBlob; -class MemoryPool; -class MemoryPoolFactory; -class DynamicMemoryAllocator; -class BlockCheckpointInfo; - -// TYPE DEFINES /////////////////////////////////////////////////////////////// - -// ---------------------------------------------------------------------------- -/** - This class is purely a convenience used to pass optional arguments to initMemoryManager(), - and by extension, to createDynamicMemoryAllocator(). You can specify how many sub-pools you - want, what size each is, what the allocation counts are to be, etc. Most apps will - construct an array of these to pass to initMemoryManager() and never use it elsewhere. -*/ -struct PoolInitRec -{ - const char *poolName; ///< name of the pool; by convention, "dmaPool_XXX" where XXX is allocationSize - Int allocationSize; ///< size, in bytes, of the pool. - Int initialAllocationCount; ///< initial number of blocks to allocate. - Int overflowAllocationCount; ///< when the pool runs out of space, allocate more blocks in this increment -}; - -enum -{ - MAX_DYNAMICMEMORYALLOCATOR_SUBPOOLS = 8 ///< The max number of subpools allowed in a DynamicMemoryAllocator -}; - -#ifdef MEMORYPOOL_CHECKPOINTING -// ---------------------------------------------------------------------------- -/** - This class exists purely for coding convenience, and should never be used by external code. - It simply allows MemoryPool and DynamicMemoryAllocator to share checkpoint-related - code in a seamless way. -*/ -class Checkpointable -{ -private: - BlockCheckpointInfo *m_firstCheckpointInfo; ///< head of the linked list of checkpoint infos for this pool/dma - Bool m_cpiEverFailed; ///< flag to detect if we ran out of memory accumulating checkpoint info. - -protected: - - Checkpointable(); - ~Checkpointable(); - - /// create a new checkpoint info and add it to the list. - BlockCheckpointInfo *debugAddCheckpointInfo( - const char *debugLiteralTagString, - Int allocCheckpoint, - Int blockSize - ); - -public: - /// dump a checkpoint report to logfile - void debugCheckpointReport(Int flags, Int startCheckpoint, Int endCheckpoint, const char *poolName); - /// reset all the checkpoints for this pool/dma - void debugResetCheckpoints(); -}; -#endif - -// ---------------------------------------------------------------------------- -/** - A MemoryPool provides a way to efficiently allocate objects of the same (or similar) - size. We allocate large a large chunk of memory (a "blob") and subdivide it into - even-size chunks, doling these out as needed. If the first blob gets full, we allocate - additional blobs as necessary. A given pool can allocate blocks of only one size; - if you need a different size, you should use a different pool. -*/ -class MemoryPool -#ifdef MEMORYPOOL_CHECKPOINTING - : public Checkpointable -#endif -{ -private: - - MemoryPoolFactory *m_factory; ///< the factory that created us - MemoryPool *m_nextPoolInFactory; ///< linked list node, managed by factory - const char *m_poolName; ///< name of this pool. (literal string; must not be freed) - Int m_allocationSize; ///< size of the blocks allocated by this pool, in bytes - Int m_initialAllocationCount; ///< number of blocks to be allocated in initial blob - Int m_overflowAllocationCount; ///< number of blocks to be allocated in any subsequent blob(s) - Int m_usedBlocksInPool; ///< total number of blocks in use in the pool. - Int m_totalBlocksInPool; ///< total number of blocks in all blobs of this pool (used or not). - Int m_peakUsedBlocksInPool; ///< high-water mark of m_usedBlocksInPool - MemoryPoolBlob *m_firstBlob; ///< head of linked list: first blob for this pool. - MemoryPoolBlob *m_lastBlob; ///< tail of linked list: last blob for this pool. (needed for efficiency) - MemoryPoolBlob *m_firstBlobWithFreeBlocks; ///< first blob in this pool that has at least one unallocated block. - -private: - /// create a new blob with the given number of blocks. - MemoryPoolBlob* createBlob(Int allocationCount); - - /// destroy a blob. - Int freeBlob(MemoryPoolBlob *blob); - -public: - - // 'public' funcs that are really only for use by MemoryPoolFactory - MemoryPool *getNextPoolInList(); ///< return next pool in linked list - void addToList(MemoryPool **pHead); ///< add this pool to head of the linked list - void removeFromList(MemoryPool **pHead); ///< remove this pool from the linked list - #ifdef MEMORYPOOL_DEBUG - static void debugPoolInfoReport( MemoryPool *pool, FILE *fp = NULL ); ///< dump a report about this pool to the logfile - const char *debugGetBlockTagString(void *pBlock); ///< return the tagstring for the given block (assumed to belong to this pool) - void debugMemoryVerifyPool(); ///< perform internal consistency check on this pool. - Int debugPoolReportLeaks( const char* owner ); - #endif - #ifdef MEMORYPOOL_CHECKPOINTING - void debugResetCheckpoints(); ///< throw away all checkpoint information for this pool. - #endif - -public: - - MemoryPool(); - - /// initialize the given memory pool. - void init(MemoryPoolFactory *factory, const char *poolName, Int allocationSize, Int initialAllocationCount, Int overflowAllocationCount); - - ~MemoryPool(); - - /// allocate a block from this pool. (don't call directly; use allocateBlock() macro) - void *allocateBlockImplementation(DECLARE_LITERALSTRING_ARG1); - - /// same as allocateBlockImplementation, but memory returned is not zeroed - void *allocateBlockDoNotZeroImplementation(DECLARE_LITERALSTRING_ARG1); - - /// free the block. it is OK to pass null. - void freeBlock(void *pMem); - - /// return the factory that created (and thus owns) this pool. - MemoryPoolFactory *getOwningFactory(); - - /// return the name of this pool. the result is a literal string and must not be freed. - const char *getPoolName(); - - /// return the block allocation size of this pool. - Int getAllocationSize(); - - /// return the number of free (available) blocks in this pool. - Int getFreeBlockCount(); - - /// return the number of blocks in use in this pool. - Int getUsedBlockCount(); - - /// return the total number of blocks in this pool. [ == getFreeBlockCount() + getUsedBlockCount() ] - Int getTotalBlockCount(); - - /// return the high-water mark for getUsedBlockCount() - Int getPeakBlockCount(); - - /// return the initial allocation count for this pool - Int getInitialBlockCount(); - - Int countBlobsInPool(); - - /// if this pool has any empty blobs, return them to the system. - Int releaseEmpties(); - - /// destroy all blocks and blobs in this pool. - void reset(); - - #ifdef MEMORYPOOL_DEBUG - /// return true iff this block was allocated by this pool. - Bool debugIsBlockInPool(void *pBlock); - #endif -}; - -// ---------------------------------------------------------------------------- -/** - The DynamicMemoryAllocator class is used to handle unpredictably-sized - allocation requests. It basically allocates a number of (private) MemoryPools, - then routes request to the smallest-size pool that will satisfy the request. - (Requests too large for any of the pool are routed to the system memory allocator.) - You should normally use this in place of malloc/free or (global) new/delete. -*/ -class DynamicMemoryAllocator -#ifdef MEMORYPOOL_CHECKPOINTING - : public Checkpointable -#endif -{ -private: - MemoryPoolFactory *m_factory; ///< the factory that created us - DynamicMemoryAllocator *m_nextDmaInFactory; ///< linked list node, managed by factory - Int m_numPools; ///< number of subpools (up to MAX_DYNAMICMEMORYALLOCATOR_SUBPOOLS) - Int m_usedBlocksInDma; ///< total number of blocks allocated, from subpools and "raw" - MemoryPool *m_pools[MAX_DYNAMICMEMORYALLOCATOR_SUBPOOLS]; ///< the subpools - MemoryPoolSingleBlock *m_rawBlocks; ///< linked list of "raw" blocks allocated directly from system - - /// return the best pool for the given allocSize, or null if none are suitable - MemoryPool *findPoolForSize(Int allocSize); - -public: - - // 'public' funcs that are really only for use by MemoryPoolFactory - - DynamicMemoryAllocator *getNextDmaInList(); ///< return next dma in linked list - void addToList(DynamicMemoryAllocator **pHead); ///< add this dma to the list - void removeFromList(DynamicMemoryAllocator **pHead); ///< remove this dma from the list - #ifdef MEMORYPOOL_DEBUG - Int debugCalcRawBlockBytes(Int *numBlocks); ///< calculate the number of bytes in "raw" (non-subpool) blocks - void debugMemoryVerifyDma(); ///< perform internal consistency check - const char *debugGetBlockTagString(void *pBlock); ///< return the tagstring for the given block (assumed to belong to this dma) - void debugDmaInfoReport( FILE *fp = NULL ); ///< dump a report about this pool to the logfile - Int debugDmaReportLeaks(); - #endif - #ifdef MEMORYPOOL_CHECKPOINTING - void debugResetCheckpoints(); ///< toss all checkpoint information - #endif - -public: - - DynamicMemoryAllocator(); - - /// initialize the dma. pass 0/null for numSubPool/parms to get some reasonable default subpools. - void init(MemoryPoolFactory *factory, Int numSubPools, const PoolInitRec pParms[]); - - ~DynamicMemoryAllocator(); - - /// allocate bytes from this pool. (don't call directly; use allocateBytes() macro) - void *allocateBytesImplementation(Int numBytes DECLARE_LITERALSTRING_ARG2); - - /// like allocateBytesImplementation, but zeroes the memory before returning - void *allocateBytesDoNotZeroImplementation(Int numBytes DECLARE_LITERALSTRING_ARG2); - -#ifdef MEMORYPOOL_DEBUG - void debugIgnoreLeaksForThisBlock(void* pBlockPtr); -#endif - - /// free the bytes. (assumes allocated by this dma.) - void freeBytes(void* pMem); - - /** - return the actual number of bytes that would be allocated - if you tried to allocate the given size. (It will generally be slightly - larger than you request.) This lets you use extra space if you're gonna get it anyway... - The idea is that you will call this before doing a memory allocation, to see if - you got any extra "bonus" space. - */ - Int getActualAllocationSize(Int numBytes); - - /// destroy all allocations performed by this DMA. - void reset(); - - Int getDmaMemoryPoolCount() const { return m_numPools; } - MemoryPool* getNthDmaMemoryPool(Int i) const { return m_pools[i]; } - - #ifdef MEMORYPOOL_DEBUG - - /// return true iff this block was allocated by this dma - Bool debugIsBlockInDma(void *pBlock); - - /// return true iff the pool is a subpool of this dma - Bool debugIsPoolInDma(MemoryPool *pool); - - #endif // MEMORYPOOL_DEBUG -}; - -// ---------------------------------------------------------------------------- -#ifdef MEMORYPOOL_DEBUG -enum { MAX_SPECIAL_USED = 256 }; -#endif - -// ---------------------------------------------------------------------------- -/** - The class that manages all the MemoryPools and DynamicMemoryAllocators. - Usually you will create exactly one of these (TheMemoryPoolFactory) - and use it for everything. -*/ -class MemoryPoolFactory -{ -private: - MemoryPool *m_firstPoolInFactory; ///< linked list of pools - DynamicMemoryAllocator *m_firstDmaInFactory; ///< linked list of dmas -#ifdef MEMORYPOOL_CHECKPOINTING - Int m_curCheckpoint; ///< most recent checkpoint value -#endif -#ifdef MEMORYPOOL_DEBUG - Int m_usedBytes; ///< total bytes in use - Int m_physBytes; ///< total bytes allocated to all pools (includes unused blocks) - Int m_peakUsedBytes; ///< high-water mark of m_usedBytes - Int m_peakPhysBytes; ///< high-water mark of m_physBytes - Int m_usedBytesSpecial[MAX_SPECIAL_USED]; - Int m_usedBytesSpecialPeak[MAX_SPECIAL_USED]; - Int m_physBytesSpecial[MAX_SPECIAL_USED]; - Int m_physBytesSpecialPeak[MAX_SPECIAL_USED]; -#endif - -public: - - // 'public' funcs that are really only for use by MemoryPool and friends - #ifdef MEMORYPOOL_DEBUG - /// adjust the usedBytes and physBytes variables by the given amoun ts. - void adjustTotals(const char* tagString, Int usedDelta, Int physDelta); - #endif - #ifdef MEMORYPOOL_CHECKPOINTING - /// return the current checkpoint value. - Int getCurCheckpoint() { return m_curCheckpoint; } - #endif - -public: - - MemoryPoolFactory(); - void init(); - ~MemoryPoolFactory(); - - /// create a new memory pool with the given settings. if a pool with the given name already exists, return it. - MemoryPool *createMemoryPool(const PoolInitRec *parms); - - /// overloaded version of createMemoryPool with explicit parms. - MemoryPool *createMemoryPool(const char *poolName, Int allocationSize, Int initialAllocationCount, Int overflowAllocationCount); - - /// return the pool with the given name. if no such pool exists, return null. - MemoryPool *findMemoryPool(const char *poolName); - - /// destroy the given pool. - void destroyMemoryPool(MemoryPool *pMemoryPool); - - /// create a DynamicMemoryAllocator with subpools with the given parms. - DynamicMemoryAllocator *createDynamicMemoryAllocator(Int numSubPools, const PoolInitRec pParms[]); - - /// destroy the given DynamicMemoryAllocator. - void destroyDynamicMemoryAllocator(DynamicMemoryAllocator *dma); - - /// destroy the contents of all pools and dmas. (the pools and dma's are not destroyed, just reset) - void reset(); - - void memoryPoolUsageReport( const char* filename, FILE *appendToFileInstead = NULL ); - - #ifdef MEMORYPOOL_DEBUG - - /// perform internal consistency checking - void debugMemoryVerify(); - - /// return true iff the block was allocated by any pool or dma owned by this factory. - Bool debugIsBlockInAnyPool(void *pBlock); - - /// return the tag string for the block. - const char *debugGetBlockTagString(void *pBlock); - - /// dump a report with the given options to the logfile. - void debugMemoryReport(Int flags, Int startCheckpoint, Int endCheckpoint, FILE *fp = NULL ); - - void debugSetInitFillerIndex(Int index); - - #endif - #ifdef MEMORYPOOL_CHECKPOINTING - - /// set a new checkpoint. - Int debugSetCheckpoint(); - - /// reset all checkpoint information. - void debugResetCheckpoints(); - - #endif -}; - -// how many bytes are we allowed to 'waste' per pool allocation before the debug code starts yelling at us... -#define MEMORY_POOL_OBJECT_ALLOCATION_SLOP 16 - -// ---------------------------------------------------------------------------- -#define GCMP_FIND(ARGCLASS, ARGPOOLNAME) \ -private: \ - static MemoryPool *getClassMemoryPool() \ - { \ - /* \ - Note that this static variable will be initialized exactly once: the first time \ - control flows over this section of code. This allows us to neatly resolve the \ - order-of-execution problem for static variables, ensuring this is not executed \ - prior to the initialization of TheMemoryPoolFactory. \ - */ \ - DEBUG_ASSERTCRASH(TheMemoryPoolFactory, ("TheMemoryPoolFactory is NULL")); \ - static MemoryPool *The##ARGCLASS##Pool = TheMemoryPoolFactory->findMemoryPool(ARGPOOLNAME); \ - DEBUG_ASSERTCRASH(The##ARGCLASS##Pool, ("Pool \"%s\" not found (did you set it up in initMemoryPools?)", ARGPOOLNAME)); \ - DEBUG_ASSERTCRASH(The##ARGCLASS##Pool->getAllocationSize() >= sizeof(ARGCLASS), ("Pool \"%s\" is too small for this class (currently %d, need %d)", ARGPOOLNAME, The##ARGCLASS##Pool->getAllocationSize(), sizeof(ARGCLASS))); \ - DEBUG_ASSERTCRASH(The##ARGCLASS##Pool->getAllocationSize() <= sizeof(ARGCLASS)+MEMORY_POOL_OBJECT_ALLOCATION_SLOP, ("Pool \"%s\" is too large for this class (currently %d, need %d)", ARGPOOLNAME, The##ARGCLASS##Pool->getAllocationSize(), sizeof(ARGCLASS))); \ - return The##ARGCLASS##Pool; \ - } - -// ---------------------------------------------------------------------------- -#define GCMP_CREATE(ARGCLASS, ARGPOOLNAME, ARGINITIAL, ARGOVERFLOW) \ -private: \ - static MemoryPool *getClassMemoryPool() \ - { \ - /* \ - Note that this static variable will be initialized exactly once: the first time \ - control flows over this section of code. This allows us to neatly resolve the \ - order-of-execution problem for static variables, ensuring this is not executed \ - prior to the initialization of TheMemoryPoolFactory. \ - */ \ - DEBUG_ASSERTCRASH(TheMemoryPoolFactory, ("TheMemoryPoolFactory is NULL")); \ - static MemoryPool *The##ARGCLASS##Pool = TheMemoryPoolFactory->createMemoryPool(ARGPOOLNAME, sizeof(ARGCLASS), ARGINITIAL, ARGOVERFLOW); \ - DEBUG_ASSERTCRASH(The##ARGCLASS##Pool, ("Pool \"%s\" not found (did you set it up in initMemoryPools?)", ARGPOOLNAME)); \ - DEBUG_ASSERTCRASH(The##ARGCLASS##Pool->getAllocationSize() >= sizeof(ARGCLASS), ("Pool \"%s\" is too small for this class (currently %d, need %d)", ARGPOOLNAME, The##ARGCLASS##Pool->getAllocationSize(), sizeof(ARGCLASS))); \ - DEBUG_ASSERTCRASH(The##ARGCLASS##Pool->getAllocationSize() <= sizeof(ARGCLASS)+MEMORY_POOL_OBJECT_ALLOCATION_SLOP, ("Pool \"%s\" is too large for this class (currently %d, need %d)", ARGPOOLNAME, The##ARGCLASS##Pool->getAllocationSize(), sizeof(ARGCLASS))); \ - return The##ARGCLASS##Pool; \ - } - -// ---------------------------------------------------------------------------- -#define MEMORY_POOL_GLUE_WITHOUT_GCMP(ARGCLASS) \ -protected: \ - virtual ~ARGCLASS(); \ -public: \ - enum ARGCLASS##MagicEnum { ARGCLASS##_GLUE_NOT_IMPLEMENTED = 0 }; \ -public: \ - inline void *operator new(size_t s, ARGCLASS##MagicEnum e DECLARE_LITERALSTRING_ARG2) \ - { \ - DEBUG_ASSERTCRASH(s == sizeof(ARGCLASS), ("The wrong operator new is being called; ensure all objects in the hierarchy have MemoryPoolGlue set up correctly")); \ - return ARGCLASS::getClassMemoryPool()->allocateBlockImplementation(PASS_LITERALSTRING_ARG1); \ - } \ -public: \ - /* \ - Note that this delete operator can't be called directly; it is called \ - only if the analogous new operator is called, AND the constructor \ - throws an exception... \ - */ \ - inline void operator delete(void *p, ARGCLASS##MagicEnum e DECLARE_LITERALSTRING_ARG2) \ - { \ - ARGCLASS::getClassMemoryPool()->freeBlock(p); \ - } \ -protected: \ - /* \ - Make normal new and delete protected, so they can't be called by the outside world. \ - Note that delete is funny, in that it can still be called by the class itself; \ - this is safe but not recommended, for consistency purposes. More problematically, \ - it can be called by another class that has declared itself 'friend' to us. \ - In theory, this shouldn't work, since it may not use the right operator-delete, \ - and thus the wrong memory pool; in practice, it seems the right delete IS called \ - in MSVC -- it seems to make operator delete virtual if the destructor is also virtual. \ - At any rate, this is undocumented behavior as far as I can tell, so we put a big old \ - crash into operator delete telling people to do the right thing and call deleteInstance \ - instead -- it'd be nice if we could catch this at compile time, but catching it at \ - runtime seems to be the best we can do... \ - */ \ - inline void *operator new(size_t s) \ - { \ - DEBUG_CRASH(("This operator new should normally never be called... please use new(char*) instead.")); \ - DEBUG_ASSERTCRASH(s == sizeof(ARGCLASS), ("The wrong operator new is being called; ensure all objects in the hierarchy have MemoryPoolGlue set up correctly")); \ - throw ERROR_BUG; \ - return 0; \ - } \ - inline void operator delete(void *p) \ - { \ - DEBUG_CRASH(("Please call deleteInstance instead of delete.")); \ - ARGCLASS::getClassMemoryPool()->freeBlock(p); \ - } \ -private: \ - virtual MemoryPool *getObjectMemoryPool() \ - { \ - return ARGCLASS::getClassMemoryPool(); \ - } \ -public: /* include this line at the end to reset visibility to 'public' */ - -// ---------------------------------------------------------------------------- -#define MEMORY_POOL_GLUE(ARGCLASS, ARGPOOLNAME) \ - MEMORY_POOL_GLUE_WITHOUT_GCMP(ARGCLASS) \ - GCMP_FIND(ARGCLASS, ARGPOOLNAME) - -// ---------------------------------------------------------------------------- -#define MEMORY_POOL_GLUE_WITH_EXPLICIT_CREATE(ARGCLASS, ARGPOOLNAME, ARGINITIAL, ARGOVERFLOW) \ - MEMORY_POOL_GLUE_WITHOUT_GCMP(ARGCLASS) \ - GCMP_CREATE(ARGCLASS, ARGPOOLNAME, ARGINITIAL, ARGOVERFLOW) - -// ---------------------------------------------------------------------------- -#define MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE(ARGCLASS, ARGPOOLNAME) \ - MEMORY_POOL_GLUE_WITHOUT_GCMP(ARGCLASS) \ - GCMP_CREATE(ARGCLASS, ARGPOOLNAME, -1, -1) - -// ---------------------------------------------------------------------------- -// this is the version for an Abstract Base Class, which will never be instantiated... -#define MEMORY_POOL_GLUE_ABC(ARGCLASS) \ -protected: \ - virtual ~ARGCLASS(); \ -public: \ - enum ARGCLASS##MagicEnum { ARGCLASS##_GLUE_NOT_IMPLEMENTED = 0 }; \ -protected: \ - inline void *operator new(size_t s, ARGCLASS##MagicEnum e DECLARE_LITERALSTRING_ARG2) \ - { \ - DEBUG_CRASH(("this should be impossible to call (abstract base class)")); \ - DEBUG_ASSERTCRASH(s == sizeof(ARGCLASS), ("The wrong operator new is being called; ensure all objects in the hierarchy have MemoryPoolGlue set up correctly")); \ - throw ERROR_BUG; \ - return 0; \ - } \ -protected: \ - inline void operator delete(void *p, ARGCLASS##MagicEnum e DECLARE_LITERALSTRING_ARG2) \ - { \ - DEBUG_CRASH(("this should be impossible to call (abstract base class)")); \ - } \ -protected: \ - inline void *operator new(size_t s) \ - { \ - DEBUG_CRASH(("this should be impossible to call (abstract base class)")); \ - DEBUG_ASSERTCRASH(s == sizeof(ARGCLASS), ("The wrong operator new is being called; ensure all objects in the hierarchy have MemoryPoolGlue set up correctly")); \ - throw ERROR_BUG; \ - return 0; \ - } \ - inline void operator delete(void *p) \ - { \ - DEBUG_CRASH(("this should be impossible to call (abstract base class)")); \ - } \ -private: \ - virtual MemoryPool *getObjectMemoryPool() \ - { \ - throw ERROR_BUG; \ - return 0; \ - } \ -public: /* include this line at the end to reset visibility to 'public' */ - - -// ---------------------------------------------------------------------------- -/** - This class is provided as a simple and safe way to integrate C++ object allocation - into MemoryPool usage. To use it, you must have your class inherit from - MemoryPoolObject, then put the macro MEMORY_POOL_GLUE(MyClassName, "MyPoolName") - at the start of your class definition. (This does not create the pool itself -- you - must create that manually using MemoryPoolFactory::createMemoryPool) -*/ -class MemoryPoolObject -{ -protected: - - /** ensure that all destructors are virtual */ - virtual ~MemoryPoolObject() { } - -protected: - inline void *operator new(size_t s) { DEBUG_CRASH(("This should be impossible")); return 0; } - inline void operator delete(void *p) { DEBUG_CRASH(("This should be impossible")); } - -protected: - - virtual MemoryPool *getObjectMemoryPool() = 0; - -public: - - static void deleteInstanceInternal(MemoryPoolObject* mpo) - { - if (mpo) - { - MemoryPool *pool = mpo->getObjectMemoryPool(); // save this, since the dtor will nuke our vtbl - mpo->~MemoryPoolObject(); // it's virtual, so the right one will be called. - pool->freeBlock((void *)mpo); - } - } -}; - -inline void deleteInstance(MemoryPoolObject* mpo) -{ - MemoryPoolObject::deleteInstanceInternal(mpo); -} - - -// INLINING /////////////////////////////////////////////////////////////////// - -// ---------------------------------------------------------------------------- -inline MemoryPoolFactory *MemoryPool::getOwningFactory() { return m_factory; } -inline MemoryPool *MemoryPool::getNextPoolInList() { return m_nextPoolInFactory; } -inline const char *MemoryPool::getPoolName() { return m_poolName; } -inline Int MemoryPool::getAllocationSize() { return m_allocationSize; } -inline Int MemoryPool::getFreeBlockCount() { return getTotalBlockCount() - getUsedBlockCount(); } -inline Int MemoryPool::getUsedBlockCount() { return m_usedBlocksInPool; } -inline Int MemoryPool::getTotalBlockCount() { return m_totalBlocksInPool; } -inline Int MemoryPool::getPeakBlockCount() { return m_peakUsedBlocksInPool; } -inline Int MemoryPool::getInitialBlockCount() { return m_initialAllocationCount; } - -// ---------------------------------------------------------------------------- -inline DynamicMemoryAllocator *DynamicMemoryAllocator::getNextDmaInList() { return m_nextDmaInFactory; } - -// EXTERNALS ////////////////////////////////////////////////////////////////// - -/** - Initialize the memory manager. Construct a new MemoryPoolFactory and - DynamicMemoryAllocator and store 'em in the singletons of the relevant - names. -*/ -extern void initMemoryManager(); - -/** - return true if initMemoryManager() has been called. - return false if only preMainInitMemoryManager() has been called. -*/ -extern Bool isMemoryManagerOfficiallyInited(); - -/** - similar to initMemoryManager, but this should be used if the memory manager must be initialized - prior to main() (e.g., from a static constructor). If preMainInitMemoryManager() is called prior - to initMemoryManager(), then subsequent calls to either are quietly ignored, AS IS any subsequent - call to shutdownMemoryManager() [since there's no safe way to ensure that shutdownMemoryManager - will execute after all static destructors]. - - (Note: this function is actually not externally visible, but is documented here for clarity.) -*/ -/* extern void preMainInitMemoryManager(); */ - -/** - Shut down the memory manager. Throw away TheMemoryPoolFactory and - TheDynamicMemoryAllocator. -*/ -extern void shutdownMemoryManager(); - -extern MemoryPoolFactory *TheMemoryPoolFactory; -extern DynamicMemoryAllocator *TheDynamicMemoryAllocator; - -/** - This function is declared in this header, but is not defined anywhere -- you must provide - it in your code. It is called by initMemoryManager() or preMainInitMemoryManager() in order - to get the specifics of the subpool for the dynamic memory allocator. (If you just want - some defaults, set both return arguments to zero.) The reason for this odd setup is that - we may need to init the memory manager prior to main() [due to static C++ ctors] and - this allows us a way to get the necessary parameters. -*/ -extern void userMemoryManagerGetDmaParms(Int *numSubPools, const PoolInitRec **pParms); - -/** - This function is declared in this header, but is not defined anywhere -- you must provide - it in your code. It is called by initMemoryManager() or preMainInitMemoryManager() in order - to initialize the pools to be used. (You can define an empty function if you like.) -*/ -extern void userMemoryManagerInitPools(); - -/** - This function is declared in this header, but is not defined anywhere -- you must provide - it in your code. It is called by createMemoryPool to adjust the allocation size(s) for a - given pool. Note that the counts are in-out parms! -*/ -extern void userMemoryAdjustPoolSize(const char *poolName, Int& initialAllocationCount, Int& overflowAllocationCount); - -#ifdef __cplusplus - -#ifndef _OPERATOR_NEW_DEFINED_ - - #define _OPERATOR_NEW_DEFINED_ - - extern void * __cdecl operator new (size_t size); - extern void __cdecl operator delete (void *p); - - extern void * __cdecl operator new[] (size_t size); - extern void __cdecl operator delete[] (void *p); - - // additional overloads to account for VC/MFC funky versions - extern void* __cdecl operator new(size_t nSize, const char *, int); - extern void __cdecl operator delete(void *, const char *, int); - - extern void* __cdecl operator new[](size_t nSize, const char *, int); - extern void __cdecl operator delete[](void *, const char *, int); - -#if defined(_MSC_VER) && _MSC_VER < 1300 - // additional overloads for 'placement new' - //inline void* __cdecl operator new (size_t s, void *p) { return p; } - //inline void __cdecl operator delete (void *, void *p) { } - inline void* __cdecl operator new[] (size_t s, void *p) { return p; } - inline void __cdecl operator delete[] (void *, void *p) { } -#endif - -#endif - -#ifdef MEMORYPOOL_DEBUG_CUSTOM_NEW - #define MSGNEW(MSG) new(MSG, 0) - #define NEW new(__FILE__, __LINE__) -#else - #define MSGNEW(MSG) new - #define NEW new -#endif - -#endif - -class STLSpecialAlloc -{ -public: - static void* allocate(size_t __n); - static void deallocate(void* __p, size_t); -}; - -#endif // DISABLE_GAMEMEMORY - - -/** - A simple utility class to ensure exception safety; this holds a MemoryPoolObject - and deletes it in its destructor. Especially useful for iterators! -*/ -class MemoryPoolObjectHolder -{ -private: - MemoryPoolObject *m_mpo; -public: - MemoryPoolObjectHolder(MemoryPoolObject *mpo = NULL) : m_mpo(mpo) { } - void hold(MemoryPoolObject *mpo) { DEBUG_ASSERTCRASH(!m_mpo, ("already holding")); m_mpo = mpo; } - void release() { m_mpo = NULL; } - ~MemoryPoolObjectHolder() { deleteInstance(m_mpo); } -}; - - -#define EMPTY_DTOR(CLASS) inline CLASS::~CLASS() { } - - -#endif // _GAME_MEMORY_H_ diff --git a/Generals/Code/GameEngine/Source/Common/System/GameMemory.cpp b/Generals/Code/GameEngine/Source/Common/System/GameMemory.cpp deleted file mode 100644 index 8275aa0db16..00000000000 --- a/Generals/Code/GameEngine/Source/Common/System/GameMemory.cpp +++ /dev/null @@ -1,3579 +0,0 @@ -/* -** Command & Conquer Generals(tm) -** Copyright 2025 Electronic Arts Inc. -** -** This program is free software: you can redistribute it and/or modify -** it under the terms of the GNU General Public License as published by -** the Free Software Foundation, either version 3 of the License, or -** (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program. If not, see . -*/ - -//////////////////////////////////////////////////////////////////////////////// -// // -// (c) 2001-2003 Electronic Arts Inc. // -// // -//////////////////////////////////////////////////////////////////////////////// - -// FILE: Memory.cpp -//----------------------------------------------------------------------------- -// -// Westwood Studios Pacific. -// -// Confidential Information -// Copyright (C) 2001 - All Rights Reserved -// -//----------------------------------------------------------------------------- -// -// Project: RTS3 -// -// File name: Memory.cpp -// -// Created: Steven Johnson, August 2001 -// -// Desc: Memory manager -// -// ---------------------------------------------------------------------------- - -#include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine - -// SYSTEM INCLUDES - -// USER INCLUDES -#include "Common/GameMemory.h" -#include "Common/CriticalSection.h" -#include "Common/Errors.h" -#include "Common/GlobalData.h" -#include "Common/PerfTimer.h" -#ifdef MEMORYPOOL_DEBUG -#include "GameClient/ClientRandomValue.h" -#endif -#ifdef MEMORYPOOL_STACKTRACE - #include "Common/StackDump.h" -#endif - -#ifdef MEMORYPOOL_DEBUG -DECLARE_PERF_TIMER(MemoryPoolDebugging) -DECLARE_PERF_TIMER(MemoryPoolInitFilling) -#endif - - - -// ---------------------------------------------------------------------------- -// DEFINES -// ---------------------------------------------------------------------------- - -/** - define MPSB_DLINK to add a backlink to MemoryPoolSingleBlock; this makes it - faster to free raw DMA blocks. - @todo verify this speedup is enough to be worth the extra space -*/ -#ifndef DISABLE_MEMORYPOOL_MPSB_DLINK - #define MPSB_DLINK -#endif - -#ifdef MEMORYPOOL_DEBUG - - /** - if you define MEMORYPOOL_INTENSE_VERIFY, we do intensive verifications after - nearly every memory operation. this is OFF by default, since it slows down - things a lot, but is worth turning on for really obscure memory corruption issues. - */ - #ifndef MEMORYPOOL_INTENSE_VERIFY - #define NO_MEMORYPOOL_INTENSE_VERIFY - #endif - - /** - if you define MEMORYPOOL_CHECK_BLOCK_OWNERSHIP, we do lots of calls to verify - that a block actually belongs to the pool it is called with. this is great - for debugging, but can be realllly slow, so is off by default. - */ - #ifndef MEMORYPOOL_CHECK_BLOCK_OWNERSHIP - #define NO_MEMORYPOOL_CHECK_BLOCK_OWNERSHIP - #endif - - static const char* FREE_SINGLEBLOCK_TAG_STRING = "FREE_SINGLEBLOCK_TAG_STRING"; - const Short SINGLEBLOCK_MAGIC_COOKIE = 12345; - const Int GARBAGE_FILL_VALUE = 0xdeadbeef; - - // flags for m_debugFlags - enum - { - IGNORE_LEAKS = 0x0001 - }; - - // in debug mode (but not internal), save stacktraces too - #if !defined(MEMORYPOOL_CHECKPOINTING) && defined(MEMORYPOOL_STACKTRACE) && defined(RTS_DEBUG) - #define MEMORYPOOL_SINGLEBLOCK_GETS_STACKTRACE - #endif - - #define USE_FILLER_VALUE - - const Int MAX_INIT_FILLER_COUNT = 8; - #ifdef USE_FILLER_VALUE - static UnsignedInt s_initFillerValue = 0xf00dcafe; // will be replaced, should never be this value at runtime - static void calcFillerValue(Int index) - { - s_initFillerValue = (index & 3) << 1; - s_initFillerValue |= 0x01; - s_initFillerValue |= (~(s_initFillerValue << 4)) & 0xf0; - s_initFillerValue |= (s_initFillerValue << 8); - s_initFillerValue |= (s_initFillerValue << 16); - //DEBUG_LOG(("Setting MemoryPool initFillerValue to %08x (index %d)",s_initFillerValue,index)); - } - #endif - -#endif - -#ifdef MEMORYPOOL_BOUNDINGWALL - - #define WALLCOUNT (2) // default setting of 8 requires 4*4*2==32 extra bytes PER BLOCK - #define WALLSIZE (WALLCOUNT * sizeof(Int)) - -#endif - -#ifdef MEMORYPOOL_STACKTRACE - - #define MEMORYPOOL_STACKTRACE_SIZE (20) - #define MEMORYPOOL_STACKTRACE_SKIP_SIZE (6) - #define MEMORYPOOL_STACKTRACE_SIZE_BYTES (MEMORYPOOL_STACKTRACE_SIZE * sizeof(void*)) - -#endif - -// ---------------------------------------------------------------------------- -// PRIVATE DATA -// ---------------------------------------------------------------------------- - -#ifdef MEMORYPOOL_BOUNDINGWALL - - static Int theBoundingWallPattern = 0xbabeface; - -#endif - -#ifdef MEMORYPOOL_STACKTRACE - - /** the max number levels to dump in the stacktrace. a variable rather than - constant so that you can fiddle with it in the debugger if desired, to - get shorter or longer dumps. (you can't go longer than MEMORYPOOL_STACKTRACE_SIZE - in any event. */ - static Int theStackTraceDepth = 16; - -#endif - -#ifdef MEMORYPOOL_DEBUG - - static Int theTotalSystemAllocationInBytes = 0; - static Int thePeakSystemAllocationInBytes = 0; - static Int theTotalLargeBlocks = 0; - static Int thePeakLargeBlocks = 0; - Int theTotalDMA = 0; - Int thePeakDMA = 0; - Int theWastedDMA = 0; - Int thePeakWastedDMA = 0; - -#ifdef INTENSE_DMA_BOOKKEEPING - struct UsedNPeak - { - Int used, peak, waste, peakwaste; - UsedNPeak() : used(0), peak(0), waste(0), peakwaste(0) { } - }; - typedef std::map< const char*, UsedNPeak, std::less > UsedNPeakMap; - static UsedNPeakMap TheUsedNPeakMap; - static Int doingIntenseDMA = 0; -#endif - - -#endif - -static Bool thePreMainInitFlag = false; -static Bool theMainInitFlag = false; - -// ---------------------------------------------------------------------------- -// PRIVATE PROTOTYPES -// ---------------------------------------------------------------------------- - -/// @todo srj -- make this work for 8 -#define MEM_BOUND_ALIGNMENT 4 - -static Int roundUpMemBound(Int i); -static void *sysAllocateDoNotZero(Int numBytes); -static void sysFree(void* p); -static void memset32(void* ptr, Int value, Int bytesToFill); -#ifdef MEMORYPOOL_STACKTRACE -static void doStackDumpOutput(const char* m); -static void doStackDump(void **stacktrace, int size); -#endif -static void preMainInitMemoryManager(); - -// ---------------------------------------------------------------------------- -// PRIVATE FUNCTIONS -// ---------------------------------------------------------------------------- - -//----------------------------------------------------------------------------- -/** round up to the nearest multiple of MEM_BOUND_ALIGNMENT */ -static Int roundUpMemBound(Int i) -{ - return (i + (MEM_BOUND_ALIGNMENT-1)) & ~(MEM_BOUND_ALIGNMENT-1); -} - -//----------------------------------------------------------------------------- -/** - this is the low-level allocator that we use to request memory from the OS. - all (repeat, all) memory allocations in this module should ultimately - go thru this routine (or sysAllocate). - - note: throws ERROR_OUT_OF_MEMORY on failure; never returns null -*/ -static void* sysAllocateDoNotZero(Int numBytes) -{ - void* p = ::GlobalAlloc(GMEM_FIXED, numBytes); - if (!p) - throw ERROR_OUT_OF_MEMORY; -#ifdef MEMORYPOOL_DEBUG - { - USE_PERF_TIMER(MemoryPoolDebugging) - #ifdef USE_FILLER_VALUE - { - USE_PERF_TIMER(MemoryPoolInitFilling) - ::memset32(p, s_initFillerValue, ::GlobalSize(p)); - } - #endif - theTotalSystemAllocationInBytes += ::GlobalSize(p); - if (thePeakSystemAllocationInBytes < theTotalSystemAllocationInBytes) - thePeakSystemAllocationInBytes = theTotalSystemAllocationInBytes; - } -#endif - return p; -} - -//----------------------------------------------------------------------------- -/** - the counterpart to sysAllocate / sysAllocateDoNotZero; used to free blocks - allocated by them. it is OK to pass null here (it will just be ignored). -*/ -static void sysFree(void* p) -{ - if (p) - { -#ifdef MEMORYPOOL_DEBUG - { - USE_PERF_TIMER(MemoryPoolDebugging) - ::memset32(p, GARBAGE_FILL_VALUE, ::GlobalSize(p)); - theTotalSystemAllocationInBytes -= ::GlobalSize(p); - } -#endif - ::GlobalFree(p); - } -} - -// ---------------------------------------------------------------------------- -/** - fills memory with a 32-bit value (note: assumes the ptr is 4-byte-aligned) -*/ -static void memset32(void* ptr, Int value, Int bytesToFill) -{ - Int wordsToFill = bytesToFill>>2; - bytesToFill -= (wordsToFill<<2); - - Int *p = (Int*)ptr; - for (++wordsToFill; --wordsToFill; ) - *p++ = value; - - Byte *b = (Byte *)p; - for (++bytesToFill; --bytesToFill; ) - *b++ = (Byte)value; -} - -#ifdef MEMORYPOOL_STACKTRACE -// ---------------------------------------------------------------------------- -/** - This is just a convenience routine that dumps output from the StackDump module - to our normal debug log file, with a little massaging for formatting. -*/ -static void doStackDumpOutput(const char* m) -{ - const char *PREPEND = "STACKTRACE"; - if (*m == 0) - { - DEBUG_LOG((m)); - } - else - { - // Note - I am moving the prepend to the end, as this allows double clicking in the - // output window to open the file in VisualStudio. jba. - DEBUG_LOG(("%s, %s",m, PREPEND)); - } -} -#endif - -#ifdef MEMORYPOOL_STACKTRACE -// ---------------------------------------------------------------------------- -/** - dump the given stacktrace to the debug log. -*/ -static void doStackDump(void **stacktrace, int size) -{ - ::doStackDumpOutput("Allocation Stack Trace:"); - ::StackDumpFromAddresses(stacktrace, size, ::doStackDumpOutput); -} -#endif - -// ---------------------------------------------------------------------------- -// PRIVATE TYPES -// ---------------------------------------------------------------------------- - -// ---------------------------------------------------------------------------- -#ifdef MEMORYPOOL_CHECKPOINTING -/** - This is a auxiliary record that we allocate in debug modes (actually, checkpoint modes) - to retain extra information about blocks; there is a one-to-one correspondence - between this record and a block allocation. The interesting bit about this record is that - we don't deallocate it when the corresponding block is freed; we retain it so we can - later provide information about what blocks were freed when, etc. Yes, this does chew - up a lot of memory! That's why it's debug-mode only; the presumption is that developers - machines have boatloads of RAM. (Note that we *do* free these when resetCheckpoints() is called.) - Note also that we directly allocate/free these with sysAllocate/sysFree, so ctors/dtors - are never executed, nor would virtual functions work -- I know, it's a little evil. -*/ -class BlockCheckpointInfo -{ -private: - BlockCheckpointInfo *m_next; ///< next checkpoint in this pool/dma - const char *m_debugLiteralTagString; ///< the tagstring for the block - Int m_allocCheckpoint; ///< when it was allocated - Int m_freeCheckpoint; ///< when it was freed (-1 if still in existence) - Int m_blockSize; ///< logical size of the block -#ifdef MEMORYPOOL_STACKTRACE - void* m_stacktrace[MEMORYPOOL_STACKTRACE_SIZE]; ///< stacktrace of when block was allocated -#endif - - ~BlockCheckpointInfo() {}; - -public: - - BlockCheckpointInfo *getNext(); ///< return next checkpointinfo for this pool/dma - - void debugSetFreepoint(Int f); ///< set the checkpoint at which the block was freed. - -#ifdef MEMORYPOOL_STACKTRACE - void **getStacktraceInfo(); ///< return a ptr to the allocation stacktrace info. -#endif - - static BlockCheckpointInfo *addToList( - BlockCheckpointInfo **pHead, - const char *debugLiteralTagString, - Int allocCheckpoint, - Int blockSize - ); - - static void freeList(BlockCheckpointInfo **pHead); - - Bool shouldBeInReport(Int flags, Int startCheckpoint, Int endCheckpoint); - - static void doBlockCheckpointReport( BlockCheckpointInfo *bi, const char *poolName, - Int flags, Int startCheckpoint, Int endCheckpoint ); -}; - -#endif - -// ---------------------------------------------------------------------------- -/** - This is the fundamental allocation unit; when you allocate via (say) MemoryPool::allocateBlock, - this is what is being allocated for you. (Of course, you don't see the private fields.) - For the most part, we allocate big chunks of these in a monolithic Blob and subdivide - from there. (However, we occasionally allocate these individually, for large blocks.) - - Note also that we directly allocate/free these with sysAllocate/sysFree, so ctors/dtors - are never executed, nor would virtual functions work -- I know, it's a little evil. -*/ -class MemoryPoolSingleBlock -{ -private: - - MemoryPoolBlob *m_owningBlob; ///< will be NULL if the single block was allocated via sysAllocate() - MemoryPoolSingleBlock *m_nextBlock; ///< if m_owningBlob is nonnull, this points to next free (unallocated) block in the blob; if m_owningBlob is null, this points to the next used (allocated) raw block in the pool. -#ifdef MPSB_DLINK - MemoryPoolSingleBlock *m_prevBlock; ///< if m_owningBlob is nonnull, this points to prev free (unallocated) block in the blob; if m_owningBlob is null, this points to the prev used (allocated) raw block in the pool. -#endif -#ifdef MEMORYPOOL_CHECKPOINTING - BlockCheckpointInfo *m_checkpointInfo; ///< ptr to the checkpointinfo for this block -#endif -#ifdef MEMORYPOOL_BOUNDINGWALL - Int m_wallPattern; ///< unique seed value for the bounding-walls for this block -#endif -#ifdef MEMORYPOOL_DEBUG - const char *m_debugLiteralTagString; ///< ptr to the tagstring for this block. - Int m_logicalSize; ///< logical size of block (not including overhead, walls, etc.) - Int m_wastedSize; ///< if allocated via DMA, the "wasted" bytes - Short m_magicCookie; ///< magic value used to verify that the block is one of ours (as opposed to random pointer) - Short m_debugFlags; ///< misc flags - #ifdef MEMORYPOOL_SINGLEBLOCK_GETS_STACKTRACE - void* m_stacktrace[MEMORYPOOL_STACKTRACE_SIZE]; ///< stacktrace of when block was allocated (if not checkpointing) - #endif -#endif - -private: - - void* getUserDataNoDbg(); -#ifdef MEMORYPOOL_BOUNDINGWALL - void debugFillInWalls(); -#endif - -public: - - static Int calcRawBlockSize(Int logicalSize); - static MemoryPoolSingleBlock *rawAllocateSingleBlock(MemoryPoolSingleBlock **pRawListHead, Int logicalSize, MemoryPoolFactory *owningFactory DECLARE_LITERALSTRING_ARG2); - void removeBlockFromList(MemoryPoolSingleBlock **pHead); - - void initBlock(Int logicalSize, MemoryPoolBlob *owningBlob, MemoryPoolFactory *owningFactory DECLARE_LITERALSTRING_ARG2); - void* getUserData(); - static MemoryPoolSingleBlock *recoverBlockFromUserData(void* pUserData); - MemoryPoolBlob *getOwningBlob(); - - MemoryPoolSingleBlock *getNextFreeBlock(); - void setNextFreeBlock(MemoryPoolSingleBlock *b); - MemoryPoolSingleBlock *getNextRawBlock(); - void setNextRawBlock(MemoryPoolSingleBlock *b); - -#ifdef MEMORYPOOL_DEBUG - void debugIgnoreLeaksForThisBlock(); - const char *debugGetLiteralTagString(); - Int debugGetLogicalSize(); - Int debugGetWastedSize(); - void debugSetWastedSize(Int waste); - void debugVerifyBlock(); - void debugMarkBlockAsFree(); - Bool debugCheckUnderrun(); - Bool debugCheckOverrun(); - Int debugSingleBlockReportLeak(const char* owner); -#endif // MEMORYPOOL_DEBUG -#ifdef MEMORYPOOL_CHECKPOINTING - BlockCheckpointInfo *debugGetCheckpointInfo(); - void debugSetCheckpointInfo(BlockCheckpointInfo *bi); - void debugResetCheckpoint(); -#endif - -}; -// ---------------------------------------------------------------------------- -class MemoryPoolBlob -{ -private: - MemoryPool *m_owningPool; ///< the pool that owns this blob - MemoryPoolBlob *m_nextBlob; ///< next blob in this pool - MemoryPoolBlob *m_prevBlob; ///< prev blob in this pool - MemoryPoolSingleBlock *m_firstFreeBlock; ///< ptr to first available block in this blob - Int m_usedBlocksInBlob; ///< total allocated blocks in this blob - Int m_totalBlocksInBlob; ///< total blocks in this blob (allocated + available) - char *m_blockData; ///< ptr to the blocks (really a MemoryPoolSingleBlock*) - -public: - - MemoryPoolBlob(); - ~MemoryPoolBlob(); - - void initBlob(MemoryPool *owningPool, Int allocationCount); - - void addBlobToList(MemoryPoolBlob **ppHead, MemoryPoolBlob **ppTail); - void removeBlobFromList(MemoryPoolBlob **ppHead, MemoryPoolBlob **ppTail); - MemoryPoolBlob *getNextInList(); - Bool hasAnyFreeBlocks(); - - MemoryPoolSingleBlock *allocateSingleBlock(DECLARE_LITERALSTRING_ARG1); - void freeSingleBlock(MemoryPoolSingleBlock *block); - - MemoryPool *getOwningPool(); - Int getFreeBlockCount(); - Int getUsedBlockCount(); - Int getTotalBlockCount(); - -#ifdef MEMORYPOOL_DEBUG - void debugMemoryVerifyBlob(); - Int debugBlobReportLeaks(const char* owner); - Bool debugIsBlockInBlob(void *pBlock); -#endif -#ifdef MEMORYPOOL_CHECKPOINTING - void debugResetCheckpoints(); -#endif - -}; - -// ---------------------------------------------------------------------------- -// PUBLIC DATA -// ---------------------------------------------------------------------------- - -MemoryPoolFactory *TheMemoryPoolFactory = NULL; -DynamicMemoryAllocator *TheDynamicMemoryAllocator = NULL; - -// ---------------------------------------------------------------------------- -// INLINES -// ---------------------------------------------------------------------------- - -//----------------------------------------------------------------------------- -#ifdef MEMORYPOOL_CHECKPOINTING -inline BlockCheckpointInfo *BlockCheckpointInfo::getNext() { return m_next; } -inline void BlockCheckpointInfo::debugSetFreepoint(Int f) { DEBUG_ASSERTCRASH(m_freeCheckpoint == -1, ("already have a freepoint")); m_freeCheckpoint = f; } -#ifdef MEMORYPOOL_STACKTRACE -inline void **BlockCheckpointInfo::getStacktraceInfo() { return m_stacktrace; } -#endif -#endif - -// ---------------------------------------------------------------------------- -/** - return a ptr to the user-data area of the block (ie, the part the enduser can deal with). - this call does NO debug verification and is for internal use of class MemoryPoolSingleBlock only. -*/ -inline void* MemoryPoolSingleBlock::getUserDataNoDbg() -{ - char* p = ((char*)this) + sizeof(MemoryPoolSingleBlock); - #ifdef MEMORYPOOL_BOUNDINGWALL - p += WALLSIZE; - #endif - return (void*)p; -} - -/** - return a ptr to the user-data area of the block (ie, the part the enduser can deal with). - this call verifies that the block is valid in debug mode. -*/ -inline void* MemoryPoolSingleBlock::getUserData() -{ - // yes, verify the block in this case for plain debug mode (not intense-verify mode) - #ifdef MEMORYPOOL_DEBUG - debugVerifyBlock(); - #endif - return getUserDataNoDbg(); -} - -/** - given a desired logical block size, calculate the physical size needed for each - MemoryPoolSingleBlock (including overhead, etc.) -*/ -inline /*static*/ Int MemoryPoolSingleBlock::calcRawBlockSize(Int logicalSize) -{ - Int s = ::roundUpMemBound(logicalSize) + sizeof(MemoryPoolSingleBlock); - #ifdef MEMORYPOOL_BOUNDINGWALL - s += WALLSIZE*2; - #endif - return s; -} - -/** - accessor -*/ -inline MemoryPoolBlob *MemoryPoolSingleBlock::getOwningBlob() -{ - return m_owningBlob; -} - -/** - return the next free block in this blob. this call assumes that the block - in question belongs to a blob, and will assert if not. -*/ -inline MemoryPoolSingleBlock *MemoryPoolSingleBlock::getNextFreeBlock() -{ - DEBUG_ASSERTCRASH(m_owningBlob != NULL, ("must be called on blob block")); - return m_nextBlock; -} - -/** - set the next free block in this blob. this call assumes that both blocks - in question belongs to a blob, but will NOT assert if not, since it may be - called when the blocks are in an inconsistent state. -*/ -inline void MemoryPoolSingleBlock::setNextFreeBlock(MemoryPoolSingleBlock *b) -{ - //DEBUG_ASSERTCRASH(m_owningBlob != NULL && b->m_owningBlob != NULL, ("must be called on blob block")); - // don't check the 'b' block -- we need to call this before 'b' is fully initialized. - DEBUG_ASSERTCRASH(m_owningBlob != NULL, ("must be called on blob block")); - this->m_nextBlock = b; -#ifdef MPSB_DLINK - if (b) { - b->m_prevBlock = this; - } -#endif -} - -/** - return the next raw block in this dma. this call assumes that the block - in question does NOT belong to a blob, and will assert if not. -*/ -inline MemoryPoolSingleBlock *MemoryPoolSingleBlock::getNextRawBlock() -{ - DEBUG_ASSERTCRASH(m_owningBlob == NULL, ("must be called on raw block")); - return m_nextBlock; -} - -/** - set the next raw block in this dma. this call assumes that the blocks - in question do NOT belong to a blob, and will assert if not. -*/ -inline void MemoryPoolSingleBlock::setNextRawBlock(MemoryPoolSingleBlock *b) -{ - DEBUG_ASSERTCRASH(m_owningBlob == NULL && (!b || b->m_owningBlob == NULL), ("must be called on raw block")); - m_nextBlock = b; -#ifdef MPSB_DLINK - if (b) - b->m_prevBlock = this; -#endif -} - -#ifdef MEMORYPOOL_DEBUG -inline void MemoryPoolSingleBlock::debugIgnoreLeaksForThisBlock() -{ - //USE_PERF_TIMER(MemoryPoolDebugging) not worth it - m_debugFlags |= IGNORE_LEAKS; -} -/** - accessor -*/ -inline const char *MemoryPoolSingleBlock::debugGetLiteralTagString() -{ - //USE_PERF_TIMER(MemoryPoolDebugging) not worth it - return m_debugLiteralTagString; -} -#endif - -#ifdef MEMORYPOOL_DEBUG -/** - accessor -*/ -inline Int MemoryPoolSingleBlock::debugGetLogicalSize() -{ - //USE_PERF_TIMER(MemoryPoolDebugging) not worth it - return m_logicalSize; -} -#endif - -#ifdef MEMORYPOOL_DEBUG -/** - accessor -*/ -inline Int MemoryPoolSingleBlock::debugGetWastedSize() -{ - //USE_PERF_TIMER(MemoryPoolDebugging) not worth it - return m_wastedSize; -} -#endif - -#ifdef MEMORYPOOL_DEBUG -inline void MemoryPoolSingleBlock::debugSetWastedSize(Int w) -{ - //USE_PERF_TIMER(MemoryPoolDebugging) not worth it - m_wastedSize = w; -} -#endif - -#ifdef MEMORYPOOL_CHECKPOINTING -/** - accessor -*/ -inline BlockCheckpointInfo *MemoryPoolSingleBlock::debugGetCheckpointInfo() -{ - return m_checkpointInfo; -} -#endif - -#ifdef MEMORYPOOL_CHECKPOINTING -/** - set the checkpoint info for this block. -*/ -inline void MemoryPoolSingleBlock::debugSetCheckpointInfo(BlockCheckpointInfo *bi) -{ - DEBUG_ASSERTCRASH(m_checkpointInfo == NULL, ("should be null")); - m_checkpointInfo = bi; -} -#endif - -#ifdef MEMORYPOOL_CHECKPOINTING -/** - sets the checkpointinfo to null, but does NOT free it... the checkpointinfo - is expected to be freed elsewhere. -*/ -inline void MemoryPoolSingleBlock::debugResetCheckpoint() -{ - m_checkpointInfo = NULL; -} -#endif - -// ---------------------------------------------------------------------------- -/// accessor -inline MemoryPoolBlob *MemoryPoolBlob::getNextInList() { return m_nextBlob; } -/// accessor -inline Bool MemoryPoolBlob::hasAnyFreeBlocks() { return m_firstFreeBlock != NULL; } -/// accessor -inline MemoryPool *MemoryPoolBlob::getOwningPool() { return m_owningPool; } -/// accessor -inline Int MemoryPoolBlob::getFreeBlockCount() { return getTotalBlockCount() - getUsedBlockCount(); } -/// accessor -inline Int MemoryPoolBlob::getUsedBlockCount() { return m_usedBlocksInBlob; } -/// accessor -inline Int MemoryPoolBlob::getTotalBlockCount() { return m_totalBlocksInBlob; } - -//----------------------------------------------------------------------------- -// METHODS for BlockCheckpointInfo -//----------------------------------------------------------------------------- - -//----------------------------------------------------------------------------- -#ifdef MEMORYPOOL_CHECKPOINTING -/// return true iff this checkpointinfo should be included in a checkpointreport with the given parameters. -Bool BlockCheckpointInfo::shouldBeInReport(Int flags, Int startCheckpoint, Int endCheckpoint) -{ - Bool allocFlagsOK = false; - Bool freedFlagsOK = false; - - if (m_allocCheckpoint < startCheckpoint && (flags & _REPORT_CP_ALLOCATED_BEFORE)) - allocFlagsOK = true; - if (m_allocCheckpoint >= startCheckpoint && m_allocCheckpoint < endCheckpoint && (flags & _REPORT_CP_ALLOCATED_BETWEEN)) - allocFlagsOK = true; - - if (m_freeCheckpoint == -1) - { - // block still exists! process this only if we want 'em. - freedFlagsOK = (flags & _REPORT_CP_FREED_NEVER) ? true : false; - } - else - { - if (m_freeCheckpoint < startCheckpoint && (flags & _REPORT_CP_FREED_BEFORE)) - freedFlagsOK = true; - if (m_freeCheckpoint >= startCheckpoint && m_freeCheckpoint < endCheckpoint && (flags & _REPORT_CP_FREED_BETWEEN)) - freedFlagsOK = true; - } - - // the block must match both the 'alloc' and 'free' criteria to get a report - return allocFlagsOK && freedFlagsOK; -} -#endif - -//----------------------------------------------------------------------------- -#ifdef MEMORYPOOL_CHECKPOINTING -/// print a checkpointreport for the given checkpointinfo. if checkpointinfo is null, print column headers. -/*static*/ void BlockCheckpointInfo::doBlockCheckpointReport(BlockCheckpointInfo *bi, - const char *poolName, Int flags, Int startCheckpoint, Int endCheckpoint ) -{ - const char *PREPEND = "BLOCKINFO"; // allows grepping more easily - - if (!bi) - { - DEBUG_LOG(("%s,%32s,%6s,%6s,%6s,%s",PREPEND,"POOLNAME","BLKSZ","ALLOC","FREED","BLOCKNAME")); - } - else - { - DEBUG_ASSERTCRASH(startCheckpoint >= 0 && startCheckpoint <= endCheckpoint, ("bad checkpoints")); - DEBUG_ASSERTCRASH((flags & _REPORT_CP_ALLOCATED_DONTCARE) != 0, ("bad flags: must set at least one alloc flag")); - DEBUG_ASSERTCRASH((flags & _REPORT_CP_FREED_DONTCARE) != 0, ("bad flags: must set at least one freed flag")); - - if (bi->shouldBeInReport(flags, startCheckpoint, endCheckpoint)) - { - DEBUG_LOG(("%s,%32s,%6d,%6d,%6d,%s",PREPEND,poolName,bi->m_blockSize,bi->m_allocCheckpoint,bi->m_freeCheckpoint,bi->m_debugLiteralTagString)); - #ifdef MEMORYPOOL_STACKTRACE - if (flags & REPORT_CP_STACKTRACE) - { - ::doStackDump(bi->m_stacktrace, min(MEMORYPOOL_STACKTRACE_SIZE, theStackTraceDepth )); - } - #endif - } - } -} -#endif - -// ---------------------------------------------------------------------------- -#ifdef MEMORYPOOL_CHECKPOINTING -/// free an entire list of checkpointinfos. -/*static*/ void BlockCheckpointInfo::freeList(BlockCheckpointInfo **pHead) -{ - BlockCheckpointInfo *p = *pHead; - while (p) - { - BlockCheckpointInfo *n = p->m_next; - ::sysFree((void *)p); - p = n; - } - *pHead = NULL; -} -#endif - -// ---------------------------------------------------------------------------- -#ifdef MEMORYPOOL_CHECKPOINTING -/** - allocate a new checkpointinfo with the given tag/checkpoint/size, add it to the - linked list, and return the checkpointinfo. (note that this will NOT throw an exception; - if there is not enough memory to allocate a new checkpointinfo, it will quietly return null.) -*/ -/*static*/ BlockCheckpointInfo *BlockCheckpointInfo::addToList( - BlockCheckpointInfo **pHead, - const char *debugLiteralTagString, - Int allocCheckpoint, - Int blockSize -) -{ - DEBUG_ASSERTCRASH(debugLiteralTagString != FREE_SINGLEBLOCK_TAG_STRING, ("bad tag string")); - - BlockCheckpointInfo *freed = NULL; - try { - freed = (BlockCheckpointInfo *)::sysAllocateDoNotZero(sizeof(BlockCheckpointInfo)); - } catch (...) { - freed = NULL; - } - if (freed) - { - DEBUG_ASSERTCRASH(debugLiteralTagString != NULL, ("null tagstrings are not allowed")); - freed->m_debugLiteralTagString = debugLiteralTagString; - freed->m_allocCheckpoint = allocCheckpoint; - freed->m_freeCheckpoint = -1; - freed->m_blockSize = blockSize; - freed->m_next = *pHead; - *pHead = freed; - } - return freed; -} -#endif - -//----------------------------------------------------------------------------- -// METHODS for MemoryPoolSingleBlock -//----------------------------------------------------------------------------- - -//----------------------------------------------------------------------------- -/** - fill in a block's fields. this is usually done only just after a block is allocated, - but might also be done at other points in debug mode. -*/ -void MemoryPoolSingleBlock::initBlock(Int logicalSize, MemoryPoolBlob *owningBlob, - MemoryPoolFactory *owningFactory DECLARE_LITERALSTRING_ARG2) -{ - // Note that while it is OK for owningBlob to be null, it is NEVER ok - // for owningFactory to be null. - DEBUG_ASSERTCRASH(owningFactory, ("null factory")); - -#ifdef MEMORYPOOL_DEBUG -{ - USE_PERF_TIMER(MemoryPoolDebugging) - m_magicCookie = SINGLEBLOCK_MAGIC_COOKIE; - m_debugFlags = 0; - if (!theMainInitFlag) - debugIgnoreLeaksForThisBlock(); - DEBUG_ASSERTCRASH(debugLiteralTagString != NULL, ("null tagstrings are not allowed")); - m_debugLiteralTagString = debugLiteralTagString; - m_logicalSize = logicalSize; - m_wastedSize = 0; - -#ifdef MEMORYPOOL_SINGLEBLOCK_GETS_STACKTRACE - if (theStackTraceDepth > 0 && (!TheGlobalData || TheGlobalData->m_checkForLeaks)) - { - memset(m_stacktrace, 0, MEMORYPOOL_STACKTRACE_SIZE_BYTES); - ::FillStackAddresses(m_stacktrace, min(MEMORYPOOL_STACKTRACE_SIZE, theStackTraceDepth), MEMORYPOOL_STACKTRACE_SKIP_SIZE); - } - else - { - m_stacktrace[0] = NULL; - } -#endif -} -#endif // MEMORYPOOL_DEBUG - -#ifdef MEMORYPOOL_CHECKPOINTING - m_checkpointInfo = NULL; -#endif - - m_nextBlock = NULL; -#ifdef MPSB_DLINK - m_prevBlock = NULL; -#endif - m_owningBlob = owningBlob; // could be NULL - -#ifdef MEMORYPOOL_BOUNDINGWALL - m_wallPattern = theBoundingWallPattern++; - debugFillInWalls(); -#endif -} - -//----------------------------------------------------------------------------- -/** - given a 'public' ptr to a block (ie, the ptr returned by the MemoryPool::allocateBlock), - recover the ptr to the MemoryPoolSingleBlock, so we can access the hidden fields. -*/ -/* static */ MemoryPoolSingleBlock *MemoryPoolSingleBlock::recoverBlockFromUserData(void* pUserData) -{ - DEBUG_ASSERTCRASH(pUserData, ("null pUserData")); - if (!pUserData) - return NULL; - char* p = ((char*)pUserData) - sizeof(MemoryPoolSingleBlock); - #ifdef MEMORYPOOL_BOUNDINGWALL - p -= WALLSIZE; - #endif - MemoryPoolSingleBlock *block = (MemoryPoolSingleBlock *)p; -// yes, verify the block in this case for plain debug mode (not intense-verify mode) -#ifdef MEMORYPOOL_DEBUG - block->debugVerifyBlock(); -#endif - return block; -} - -//----------------------------------------------------------------------------- -/** - allocate and initialize a single block. this should only used by DynamicMemoryAllocator - when allocating an extraordinarily large block. -*/ -/*static*/ MemoryPoolSingleBlock *MemoryPoolSingleBlock::rawAllocateSingleBlock( - MemoryPoolSingleBlock **pRawListHead, - Int logicalSize, - MemoryPoolFactory *owningFactory - DECLARE_LITERALSTRING_ARG2) -{ - MemoryPoolSingleBlock *block = (MemoryPoolSingleBlock *)::sysAllocateDoNotZero(calcRawBlockSize(logicalSize)); - block->initBlock(logicalSize, NULL, owningFactory PASS_LITERALSTRING_ARG2); - block->setNextRawBlock(*pRawListHead); - *pRawListHead = block; - return block; -} - -//----------------------------------------------------------------------------- -/** - remove the block from the list, which is presumed to be a list of raw blocks. - generally, only the DynamicMemoryAllocator should call this. -*/ -void MemoryPoolSingleBlock::removeBlockFromList(MemoryPoolSingleBlock **pHead) -{ - DEBUG_ASSERTCRASH(this->m_owningBlob == NULL, ("this function should only be used on raw blocks")); -#ifdef MPSB_DLINK - DEBUG_ASSERTCRASH(this->m_nextBlock == NULL || this->m_nextBlock->m_owningBlob == NULL, ("this function should only be used on raw blocks")); - if (this->m_prevBlock) - { - DEBUG_ASSERTCRASH(this->m_prevBlock->m_owningBlob == NULL, ("this function should only be used on raw blocks")); - DEBUG_ASSERTCRASH(*pHead != this, ("bad linkage")); - this->m_prevBlock->m_nextBlock = this->m_nextBlock; - } - else - { - DEBUG_ASSERTCRASH(*pHead == this, ("bad linkage")); - *pHead = this->m_nextBlock; - } - - if (this->m_nextBlock) - { - DEBUG_ASSERTCRASH(this->m_nextBlock->m_owningBlob == NULL, ("this function should only be used on raw blocks")); - this->m_nextBlock->m_prevBlock = this->m_prevBlock; - } -#else - // this isn't very efficient, and may need upgrading... but to do so - // would require adding a back link, so I'd rather do some testing - // first to see if it's really a speed issue in practice. (the only place - // this is used is when freeing 'raw' blocks allocated via the DMA). - MemoryPoolSingleBlock *prev = NULL; - for (MemoryPoolSingleBlock *cur = *pHead; cur; cur = cur->m_nextBlock) - { - DEBUG_ASSERTCRASH(cur->m_owningBlob == NULL, ("this function should only be used on raw blocks")); - if (cur == this) - { - if (prev) - { - prev->m_nextBlock = this->m_nextBlock; - } - else - { - *pHead = this->m_nextBlock; - } - break; - } - prev = cur; - } -#endif -} - -//----------------------------------------------------------------------------- -#ifdef MEMORYPOOL_DEBUG -Int MemoryPoolSingleBlock::debugSingleBlockReportLeak(const char* owner) -{ - //USE_PERF_TIMER(MemoryPoolDebugging) skip end-of-run reporting stuff - - // if allocated before main... just ignore the leak. - if (m_debugFlags & IGNORE_LEAKS) - return 0; - - // it's free, ergo, not leaked. - if (m_debugLiteralTagString == FREE_SINGLEBLOCK_TAG_STRING) - return 0; - - if (strcmp(m_debugLiteralTagString, "STR_AsciiString::ensureUniqueBufferOfSize") == 0) - { - /** @todo srj -- we leak a bunch of these for some reason (probably due to leaking Win32LocalFile) - so just ignore 'em for now... figure out later. */ - } - else if (strstr(m_debugLiteralTagString, "Win32LocalFileSystem.cpp") != NULL) - { - /** @todo srj -- we leak a bunch of these for some reason - so just ignore 'em for now... figure out later. */ - } - else - { - DEBUG_LOG(("Leaked a block of size %d, tagstring %s, from pool/dma %s",m_logicalSize,m_debugLiteralTagString,owner)); - } - - #ifdef MEMORYPOOL_SINGLEBLOCK_GETS_STACKTRACE - if (!TheGlobalData || TheGlobalData->m_checkForLeaks) - ::doStackDump(m_stacktrace, min(MEMORYPOOL_STACKTRACE_SIZE, theStackTraceDepth)); - #endif - - return 1; -} -#endif - -//----------------------------------------------------------------------------- -#ifdef MEMORYPOOL_DEBUG -/** - Verify internal consistency of this block. -*/ -void MemoryPoolSingleBlock::debugVerifyBlock() -{ - USE_PERF_TIMER(MemoryPoolDebugging) - - DEBUG_ASSERTCRASH(this, ("null this")); - DEBUG_ASSERTCRASH(m_magicCookie == SINGLEBLOCK_MAGIC_COOKIE, ("wrong cookie")); - DEBUG_ASSERTCRASH(m_debugLiteralTagString != NULL, ("bad tagstring")); - /// @todo Put this check back in after the AI memory usage is under control (MSB) - //DEBUG_ASSERTCRASH(m_logicalSize>0 && m_logicalSize < 0x00ffffff, ("unlikely value for m_logicalSize")); - DEBUG_ASSERTCRASH(m_nextBlock == NULL - || memcmp(&m_nextBlock->m_owningBlob, &s_initFillerValue, sizeof(s_initFillerValue)) == 0 - || m_nextBlock->m_owningBlob == m_owningBlob, ("owning blob mismatch...")); -#ifdef MPSB_DLINK - DEBUG_ASSERTCRASH(m_prevBlock == NULL - || memcmp(&m_prevBlock->m_owningBlob, &s_initFillerValue, sizeof(s_initFillerValue)) == 0 - || m_prevBlock->m_owningBlob == m_owningBlob, ("owning blob mismatch...")); -#endif - debugCheckUnderrun(); - debugCheckOverrun(); -} -#endif - -//----------------------------------------------------------------------------- -#ifdef MEMORYPOOL_DEBUG -/** - Fill block with bogus values and mark other internal fields for debugging purposes. -*/ -void MemoryPoolSingleBlock::debugMarkBlockAsFree() -{ - USE_PERF_TIMER(MemoryPoolDebugging) - - ::memset32(getUserDataNoDbg(), GARBAGE_FILL_VALUE, m_logicalSize); - m_debugLiteralTagString = FREE_SINGLEBLOCK_TAG_STRING; - #ifdef MEMORYPOOL_INTENSE_VERIFY - debugVerifyBlock(); - #endif -} -#endif - -//----------------------------------------------------------------------------- -#ifdef MEMORYPOOL_DEBUG -/** - Returns true iff someone overwrote part of the first bounding wall - (ie, tromped on memory just before the block) -*/ -Bool MemoryPoolSingleBlock::debugCheckUnderrun() -{ - USE_PERF_TIMER(MemoryPoolDebugging) - -#ifdef MEMORYPOOL_BOUNDINGWALL - Int *p = (Int*)(((char*)getUserDataNoDbg()) - WALLSIZE); - for (Int i = 0; i < WALLCOUNT; i++, p++) - { - if (*p != m_wallPattern+i) - { - DEBUG_CRASH(("memory underrun for block \"%s\" (expected %08x, got %08x)",m_debugLiteralTagString,m_wallPattern+i,*p)); - return true; - } - } -#endif - return false; -} -#endif - -//----------------------------------------------------------------------------- -#ifdef MEMORYPOOL_DEBUG -/** - Returns true iff someone overwrote part of the second bounding wall - (ie, tromped on memory just after the block) -*/ -Bool MemoryPoolSingleBlock::debugCheckOverrun() -{ - USE_PERF_TIMER(MemoryPoolDebugging) - -#ifdef MEMORYPOOL_BOUNDINGWALL - Int *p = (Int*)(((char*)getUserDataNoDbg()) + m_logicalSize); - for (Int i = 0; i < WALLCOUNT; i++, p++) - { - if (*p != m_wallPattern-i) - { - DEBUG_CRASH(("memory overrun for block \"%s\" (expected %08x, got %08x)",m_debugLiteralTagString,m_wallPattern+i,*p)); - return true; - } - } -#endif - return false; -} -#endif - -//----------------------------------------------------------------------------- -#ifdef MEMORYPOOL_BOUNDINGWALL -/** - Fill in the proper values for this block's bounding walls. -*/ -void MemoryPoolSingleBlock::debugFillInWalls() -{ - Int *p; - Int i; - - p = (Int*)(((char*)getUserDataNoDbg()) - WALLSIZE); - for (i = 0; i < WALLCOUNT; i++) - *p++ = m_wallPattern+i; - - p = (Int*)(((char*)getUserDataNoDbg()) + m_logicalSize); - for (i = 0; i < WALLCOUNT; i++) - *p++ = m_wallPattern-i; - - #ifdef MEMORYPOOL_INTENSE_VERIFY - debugVerifyBlock(); - #endif -} -#endif - - -//----------------------------------------------------------------------------- -// METHODS for MemoryPoolBlob -//----------------------------------------------------------------------------- - -//----------------------------------------------------------------------------- -/** - fill in safe default values. -*/ -MemoryPoolBlob::MemoryPoolBlob() : - m_owningPool(NULL), - m_nextBlob(NULL), - m_prevBlob(NULL), - m_firstFreeBlock(NULL), - m_usedBlocksInBlob(0), - m_totalBlocksInBlob(0), - m_blockData(NULL) -{ -} - -//----------------------------------------------------------------------------- -/** - throw away the blob. free the block data, if any. -*/ -MemoryPoolBlob::~MemoryPoolBlob() -{ - ::sysFree((void *)m_blockData); -} - -//----------------------------------------------------------------------------- -/** - initialize a Blob; this is called just after the blob is allocated. - allocate space for the blocks in this blob and initialize all those blocks. -*/ -void MemoryPoolBlob::initBlob(MemoryPool *owningPool, Int allocationCount) -{ - DEBUG_ASSERTCRASH(m_blockData == NULL, ("unlikely init call")); - - m_owningPool = owningPool; - m_totalBlocksInBlob = allocationCount; - m_usedBlocksInBlob = 0; - - Int rawBlockSize = MemoryPoolSingleBlock::calcRawBlockSize(m_owningPool->getAllocationSize()); - m_blockData = (char *)::sysAllocateDoNotZero(rawBlockSize * m_totalBlocksInBlob); // throws on failure - - // set up the list of free blocks in the blob (namely, all of 'em) - MemoryPoolSingleBlock *block = (MemoryPoolSingleBlock *)m_blockData; - MemoryPoolSingleBlock *next; - for (Int i = m_totalBlocksInBlob-1; i >= 0; i--) - { - next = (MemoryPoolSingleBlock *)(((char *)block) + rawBlockSize); -#ifdef MEMORYPOOL_DEBUG - block->initBlock(m_owningPool->getAllocationSize(), this, owningPool->getOwningFactory(), FREE_SINGLEBLOCK_TAG_STRING); -#else - block->initBlock(m_owningPool->getAllocationSize(), this, owningPool->getOwningFactory()); -#endif - block->setNextFreeBlock((i > 0) ? next : NULL); -#ifdef MEMORYPOOL_DEBUG - block->debugMarkBlockAsFree(); -#endif - block = next; - } - m_firstFreeBlock = (MemoryPoolSingleBlock *)m_blockData; - -#ifdef MEMORYPOOL_INTENSE_VERIFY - debugMemoryVerifyBlob(); -#endif -} - -//----------------------------------------------------------------------------- -/** - add this blob to a given pool's list-of-blobs -*/ -void MemoryPoolBlob::addBlobToList(MemoryPoolBlob **ppHead, MemoryPoolBlob **ppTail) -{ - m_prevBlob = *ppTail; - m_nextBlob = NULL; - - if (*ppTail != NULL) - (*ppTail)->m_nextBlob = this; - - if (*ppHead == NULL) - *ppHead = this; - - *ppTail = this; -} - -//----------------------------------------------------------------------------- -/** - remove this blob from a given pool's list-of-blobs -*/ -void MemoryPoolBlob::removeBlobFromList(MemoryPoolBlob **ppHead, MemoryPoolBlob **ppTail) -{ - if (*ppHead == this) - *ppHead = this->m_nextBlob; - else - this->m_prevBlob->m_nextBlob = this->m_nextBlob; - - if (*ppTail == this) - *ppTail = this->m_prevBlob; - else - this->m_nextBlob->m_prevBlob = this->m_prevBlob; -} - -//----------------------------------------------------------------------------- -/** - grab a free block from this blob, mark it as taken, and return it. - this method assumes that there is at least one free block in the blob! -*/ -MemoryPoolSingleBlock *MemoryPoolBlob::allocateSingleBlock(DECLARE_LITERALSTRING_ARG1) -{ - DEBUG_ASSERTCRASH(m_firstFreeBlock, ("no free blocks available in MemoryPoolBlob")); - - MemoryPoolSingleBlock *block = m_firstFreeBlock; - m_firstFreeBlock = block->getNextFreeBlock(); - ++m_usedBlocksInBlob; - -#ifdef MEMORYPOOL_INTENSE_VERIFY - block->debugVerifyBlock(); -#endif -#ifdef MEMORYPOOL_DEBUG - // this is debug-only because it only serves to update the debugLiteralTagString. - block->initBlock(m_owningPool->getAllocationSize(), this, m_owningPool->getOwningFactory(), debugLiteralTagString); -#endif -#ifdef MEMORYPOOL_INTENSE_VERIFY - debugMemoryVerifyBlob(); -#endif - -// don't need to zero this out... the caller will do that, if necessary -// memset(block->getUserData(), 0, m_owningPool->getAllocationSize()); - - return block; -} - -//----------------------------------------------------------------------------- -/** - make this block available for future allocations. it is assumed that the block - belongs to this blob, and is not already free. -*/ -void MemoryPoolBlob::freeSingleBlock(MemoryPoolSingleBlock *block) -{ - DEBUG_ASSERTCRASH(block->getOwningBlob() == this, ("block does not belong to this blob")); - - block->setNextFreeBlock(m_firstFreeBlock); - m_firstFreeBlock = block; - --m_usedBlocksInBlob; - -#ifdef MEMORYPOOL_INTENSE_VERIFY - block->debugVerifyBlock(); -#endif -#ifdef MEMORYPOOL_DEBUG - block->debugMarkBlockAsFree(); -#endif -#ifdef MEMORYPOOL_INTENSE_VERIFY - debugMemoryVerifyBlob(); -#endif - -} - -//----------------------------------------------------------------------------- -#ifdef MEMORYPOOL_DEBUG -/** - Perform internal consistency checking on this blob and all its blocks. -*/ -void MemoryPoolBlob::debugMemoryVerifyBlob() -{ - USE_PERF_TIMER(MemoryPoolDebugging) - - DEBUG_ASSERTCRASH(m_owningPool != NULL, ("bad owner")); - DEBUG_ASSERTCRASH(m_usedBlocksInBlob >= 0 && m_usedBlocksInBlob <= m_totalBlocksInBlob, ("unlikely m_usedBlocksInBlob")); - DEBUG_ASSERTCRASH(m_totalBlocksInBlob > 0, ("unlikely m_totalBlocksInBlob")); - - Int rawBlockSize = MemoryPoolSingleBlock::calcRawBlockSize(m_owningPool->getAllocationSize()); - char *blockData = m_blockData; - for (Int i = m_totalBlocksInBlob-1; i >= 0; i--, blockData += rawBlockSize) - { - MemoryPoolSingleBlock *block = (MemoryPoolSingleBlock *)blockData; - block->debugVerifyBlock(); - } -} -#endif - -//----------------------------------------------------------------------------- -#ifdef MEMORYPOOL_DEBUG -Int MemoryPoolBlob::debugBlobReportLeaks(const char* owner) -{ - //USE_PERF_TIMER(MemoryPoolDebugging) skip end-of-run reporting stuff - - Int any = 0; - Int rawBlockSize = MemoryPoolSingleBlock::calcRawBlockSize(m_owningPool->getAllocationSize()); - char *blockData = m_blockData; - for (Int i = m_totalBlocksInBlob-1; i >= 0; i--, blockData += rawBlockSize) - { - MemoryPoolSingleBlock *block = (MemoryPoolSingleBlock *)blockData; - any += block->debugSingleBlockReportLeak(owner); - } - return any; -} -#endif - -//----------------------------------------------------------------------------- -#ifdef MEMORYPOOL_DEBUG -/** - return true iff this block belongs to this blob. -*/ -Bool MemoryPoolBlob::debugIsBlockInBlob(void *pBlockPtr) -{ - USE_PERF_TIMER(MemoryPoolDebugging) - - MemoryPoolSingleBlock *block = MemoryPoolSingleBlock::recoverBlockFromUserData(pBlockPtr); - Int rawBlockSize = MemoryPoolSingleBlock::calcRawBlockSize(m_owningPool->getAllocationSize()); - char *blockData = m_blockData; - for (Int i = m_totalBlocksInBlob-1; i >= 0; i--) - { - if ((char *)block == blockData) - return true; - blockData += rawBlockSize; - } - return false; -} -#endif - -//----------------------------------------------------------------------------- -#ifdef MEMORYPOOL_CHECKPOINTING -/** - set all the checkpointinfos to null for all the blocks in this blob. - this does NOT free the checkpointinfos; that is presumed to happen elsewhere. -*/ -void MemoryPoolBlob::debugResetCheckpoints() -{ - Int rawBlockSize = MemoryPoolSingleBlock::calcRawBlockSize(m_owningPool->getAllocationSize()); - char *blockData = m_blockData; - for (Int i = m_totalBlocksInBlob-1; i >= 0; i--, blockData += rawBlockSize) - { - MemoryPoolSingleBlock *block = (MemoryPoolSingleBlock *)blockData; - block->debugResetCheckpoint(); - } -} -#endif - -//----------------------------------------------------------------------------- -// METHODS for Checkpointable -//----------------------------------------------------------------------------- - -#ifdef MEMORYPOOL_CHECKPOINTING -//----------------------------------------------------------------------------- -/** - init fields of Checkpointable to safe values. -*/ -Checkpointable::Checkpointable() : - m_firstCheckpointInfo(NULL), - m_cpiEverFailed(false) -{ -} -#endif - -#ifdef MEMORYPOOL_CHECKPOINTING -//----------------------------------------------------------------------------- -/** - destroy the object. discard any remaining checkpointinfo. -*/ -Checkpointable::~Checkpointable() -{ - BlockCheckpointInfo::freeList(&m_firstCheckpointInfo); - m_firstCheckpointInfo = NULL; - m_cpiEverFailed = false; -} -#endif - -//----------------------------------------------------------------------------- -#ifdef MEMORYPOOL_CHECKPOINTING -/** - create a new checkpointinfo and fill it in appropriately. this does NOT - throw an exception on failure; it quietly returns null if there is not - enough memory, and sets a flag to indicate our checkpointinfo is not complete. -*/ -BlockCheckpointInfo *Checkpointable::debugAddCheckpointInfo( - const char *debugLiteralTagString, - Int allocCheckpoint, - Int blockSize -) -{ - - BlockCheckpointInfo *bi = BlockCheckpointInfo::addToList(&m_firstCheckpointInfo, debugLiteralTagString, - allocCheckpoint, blockSize); - - if (bi) - { -#ifdef MEMORYPOOL_STACKTRACE - void **stacktrace = bi->getStacktraceInfo(); - if (theStackTraceDepth > 0 && !TheGlobalData || TheGlobalData->m_checkForLeaks) - { - memset(stacktrace, 0, MEMORYPOOL_STACKTRACE_SIZE_BYTES); - ::FillStackAddresses(stacktrace, min(MEMORYPOOL_STACKTRACE_SIZE, theStackTraceDepth), MEMORYPOOL_STACKTRACE_SKIP_SIZE); - } - else - { - stacktrace[0] = NULL; - } -#endif - } - else - { - m_cpiEverFailed = true; - } - - return bi; -} -#endif - -//----------------------------------------------------------------------------- -#ifdef MEMORYPOOL_CHECKPOINTING -/** - print a report on the checkpointinfos belonging to this pool/dma. -*/ -void Checkpointable::debugCheckpointReport( Int flags, Int startCheckpoint, Int endCheckpoint, const char *poolName ) -{ - DEBUG_ASSERTCRASH(startCheckpoint >= 0 && startCheckpoint <= endCheckpoint, ("bad checkpoints")); - DEBUG_ASSERTCRASH((flags & _REPORT_CP_ALLOCATED_DONTCARE) != 0, ("bad flags: must set at least one alloc flag")); - DEBUG_ASSERTCRASH((flags & _REPORT_CP_FREED_DONTCARE) != 0, ("bad flags: must set at least one freed flag")); - - if (m_cpiEverFailed) - { - DEBUG_LOG((" *** WARNING *** info on freed blocks may be inaccurate or incomplete!")); - } - - for (BlockCheckpointInfo *bi = m_firstCheckpointInfo; bi; bi = bi->getNext()) - { - BlockCheckpointInfo::doBlockCheckpointReport( bi, poolName, flags, startCheckpoint, endCheckpoint ); - } -} -#endif - -//----------------------------------------------------------------------------- -#ifdef MEMORYPOOL_CHECKPOINTING -/** - throw away all the checkpointinfos. this frees the memory, but blocks might still - refer to the discarded infos; you must zero those elsewhere. -*/ -void Checkpointable::debugResetCheckpoints() -{ - BlockCheckpointInfo::freeList(&m_firstCheckpointInfo); -} -#endif - -//----------------------------------------------------------------------------- -// METHODS for MemoryPool -//----------------------------------------------------------------------------- - -//----------------------------------------------------------------------------- -/** - init to safe values. -*/ -MemoryPool::MemoryPool() : - m_factory(NULL), - m_nextPoolInFactory(NULL), - m_poolName(""), - m_allocationSize(0), - m_initialAllocationCount(0), - m_overflowAllocationCount(0), - m_usedBlocksInPool(0), - m_totalBlocksInPool(0), - m_peakUsedBlocksInPool(0), - m_firstBlob(NULL), - m_lastBlob(NULL), - m_firstBlobWithFreeBlocks(NULL) -{ -} - -//----------------------------------------------------------------------------- -/** - initialize the memory pool with the given parameters. allocate the initial - set of blocks. -*/ -void MemoryPool::init(MemoryPoolFactory *factory, const char *poolName, Int allocationSize, Int initialAllocationCount, Int overflowAllocationCount) -{ - m_factory = factory; - m_poolName = poolName; - m_allocationSize = ::roundUpMemBound(allocationSize); // round up to four-byte boundary - m_initialAllocationCount = initialAllocationCount; - m_overflowAllocationCount = overflowAllocationCount; - m_usedBlocksInPool = 0; - m_totalBlocksInPool = 0; - m_peakUsedBlocksInPool = 0; - m_firstBlob = NULL; - m_lastBlob = NULL; - m_firstBlobWithFreeBlocks = NULL; - - // go ahead and init the initial block here (will throw on failure) - createBlob(m_initialAllocationCount); -} - -//----------------------------------------------------------------------------- -/** - throw away the pool, and all blocks/blobs associated with it. -*/ -MemoryPool::~MemoryPool() -{ - // toss everything. we could do this slightly more efficiently, - // but not really worth the extra code to do so. - while (m_firstBlob) - { - freeBlob(m_firstBlob); - } -} - -//----------------------------------------------------------------------------- -/** - create a new blob for this pool. if you set up good values for initialAllocationCount, - this should rarely (if ever) be called (though during development it will be called - frequently). -*/ -MemoryPoolBlob* MemoryPool::createBlob(Int allocationCount) -{ - DEBUG_ASSERTCRASH(allocationCount > 0 && allocationCount%MEM_BOUND_ALIGNMENT==0, ("bad allocationCount (must be >0 and evenly divisible by %d)",MEM_BOUND_ALIGNMENT)); - - MemoryPoolBlob* blob = new (::sysAllocateDoNotZero(sizeof(MemoryPoolBlob))) MemoryPoolBlob; // will throw on failure - - blob->initBlob(this, allocationCount); // will throw on failure - - blob->addBlobToList(&m_firstBlob, &m_lastBlob); - - DEBUG_ASSERTCRASH(m_firstBlobWithFreeBlocks == NULL, ("DO NOT IGNORE. Please call John McD - x36872 (m_firstBlobWithFreeBlocks != NULL)")); - m_firstBlobWithFreeBlocks = blob; - - // bookkeeping - m_totalBlocksInPool += allocationCount; - -#ifdef MEMORYPOOL_DEBUG - m_factory->adjustTotals("", 0, allocationCount*getAllocationSize()); -#endif - - return blob; -} - -//----------------------------------------------------------------------------- -/** - throw away a given blob, and all its blocks. it's assumed that the blob belongs - to this pool. -*/ -Int MemoryPool::freeBlob(MemoryPoolBlob* blob) -{ - DEBUG_ASSERTCRASH(blob, ("null blob")); - DEBUG_ASSERTCRASH(blob->getOwningPool() == this, ("blob does not belong to this pool")); - - // save these for later... - Int totalBlocksInBlob = blob->getTotalBlockCount(); - Int usedBlocksInBlob = blob->getUsedBlockCount(); - DEBUG_ASSERTCRASH(usedBlocksInBlob == 0, ("freeing a nonempty blob (%d)",usedBlocksInBlob)); - - // this is really just an estimate... will be too small in debug mode. - Int amtFreed = totalBlocksInBlob * getAllocationSize() + sizeof(MemoryPoolBlob); - - // de-link it from our list - blob->removeBlobFromList(&m_firstBlob, &m_lastBlob); - - // ensure that the 'first free' blob is still a valid blob. - // (doesn't need to actually have free blocks, just be a valid blob) - if (m_firstBlobWithFreeBlocks == blob) - m_firstBlobWithFreeBlocks = m_firstBlob; - - // this is evil... since there is no 'placement delete' we must do this the hard way - // and call the dtor directly. ordinarily this is heinous, but in this case we'll - // make an exception. - blob->~MemoryPoolBlob(); - ::sysFree((void *)blob); - - // finally... bookkeeping - m_usedBlocksInPool -= usedBlocksInBlob; - m_totalBlocksInPool -= totalBlocksInBlob; - -#ifdef MEMORYPOOL_DEBUG - m_factory->adjustTotals("", -usedBlocksInBlob*getAllocationSize(), -totalBlocksInBlob*getAllocationSize()); -#endif - - return amtFreed; -} - -//----------------------------------------------------------------------------- -/** - allocate a block from this pool and return it, but don't bother zeroing - out the block. if unable to allocate, throw ERROR_OUT_OF_MEMORY. this - function will never return null. -*/ -void* MemoryPool::allocateBlockDoNotZeroImplementation(DECLARE_LITERALSTRING_ARG1) -{ - ScopedCriticalSection scopedCriticalSection(TheMemoryPoolCriticalSection); - - if (m_firstBlobWithFreeBlocks != NULL && !m_firstBlobWithFreeBlocks->hasAnyFreeBlocks()) - { - // hmm... the current 'free' blob has nothing available. look and see if there - // are any other existing blobs with freespace. - MemoryPoolBlob *blob = m_firstBlob; - for (; blob != NULL; blob = blob->getNextInList()) - { - if (blob->hasAnyFreeBlocks()) - break; - } - - // note that if we walk thru the list without finding anything, this will - // reset m_firstBlobWithFreeBlocks to null and fall thru. - m_firstBlobWithFreeBlocks = blob; - } - - // OK, if we are here then we have no blobs with freespace... darn. - // allocate an overflow block. - if (m_firstBlobWithFreeBlocks == NULL) - { - if (m_overflowAllocationCount == 0) - { - throw ERROR_OUT_OF_MEMORY; // this pool is not allowed to grow - } - else - { - createBlob(m_overflowAllocationCount); // throws on failure - } - } - - MemoryPoolBlob *blob = m_firstBlobWithFreeBlocks; - - DEBUG_ASSERTCRASH(blob, ("no blob with free blocks available in MemoryPool::allocate")); - - MemoryPoolSingleBlock *block = blob->allocateSingleBlock(PASS_LITERALSTRING_ARG1); - DEBUG_ASSERTCRASH(block, ("should not fail here")); - -#ifdef MEMORYPOOL_CHECKPOINTING - BlockCheckpointInfo *bi = debugAddCheckpointInfo(block->debugGetLiteralTagString(), m_factory->getCurCheckpoint(), getAllocationSize()); - if (bi) - block->debugSetCheckpointInfo(bi); -#endif - - // bookkeeping - ++m_usedBlocksInPool; - if (m_peakUsedBlocksInPool < m_usedBlocksInPool) - m_peakUsedBlocksInPool = m_usedBlocksInPool; - -#ifdef MEMORYPOOL_DEBUG - m_factory->adjustTotals(debugLiteralTagString, 1*getAllocationSize(), 0); - #ifdef USE_FILLER_VALUE - { - USE_PERF_TIMER(MemoryPoolInitFilling) - ::memset32(block->getUserData(), s_initFillerValue, getAllocationSize()); - } - #endif -#endif - - return block->getUserData(); -} - -//----------------------------------------------------------------------------- -/** - allocate a block from this pool and return it, and zero out the contents - of the block. if unable to allocate, throw ERROR_OUT_OF_MEMORY. this - function will never return null. -*/ -void* MemoryPool::allocateBlockImplementation(DECLARE_LITERALSTRING_ARG1) -{ - void* p = allocateBlockDoNotZeroImplementation(PASS_LITERALSTRING_ARG1); // throws on failure - memset(p, 0, getAllocationSize()); - return p; -} - -//----------------------------------------------------------------------------- -/** - free a block allocated by this pool. it's ok to pass null. -*/ -void MemoryPool::freeBlock(void* pBlockPtr) -{ - if (!pBlockPtr) - return; // my, that was easy - - ScopedCriticalSection scopedCriticalSection(TheMemoryPoolCriticalSection); - - MemoryPoolSingleBlock *block = MemoryPoolSingleBlock::recoverBlockFromUserData(pBlockPtr); - MemoryPoolBlob *blob = block->getOwningBlob(); -#ifdef MEMORYPOOL_DEBUG - const char* tagString = block->debugGetLiteralTagString(); -#endif - - DEBUG_ASSERTCRASH(blob && blob->getOwningPool() == this, ("block does not belong to this pool")); - -#ifdef MEMORYPOOL_CHECKPOINTING - BlockCheckpointInfo *bi = block->debugGetCheckpointInfo(); - DEBUG_ASSERTCRASH(bi, ("hmm, no checkpoint info")); - if (bi) - bi->debugSetFreepoint(m_factory->getCurCheckpoint()); -#endif - - blob->freeSingleBlock(block); - - // if we want to free the blobs as they become empty, do that here. - // normally we don't bother, but just in case this is ever desired, here's how you'd do it... - // - // if (blob->m_usedBlocksInBlob == 0) - // { - // freeBlob(blob); - // return; - //} - - if (!m_firstBlobWithFreeBlocks) - m_firstBlobWithFreeBlocks = blob; - - // bookkeeping - --m_usedBlocksInPool; - -#ifdef MEMORYPOOL_DEBUG - m_factory->adjustTotals(tagString, -1*getAllocationSize(), 0); -#endif -} - -//----------------------------------------------------------------------------- -Int MemoryPool::countBlobsInPool() -{ - Int blobs = 0; - for (MemoryPoolBlob* blob = m_firstBlob; blob;) - { - ++blobs; - blob = blob->getNextInList(); - } - return blobs; -} - -//----------------------------------------------------------------------------- -/** - if the pool has any blobs that are completely unused, they are released back to the - operating system. this will rarely, if ever, be called, but may be useful - in odd situations. -*/ -Int MemoryPool::releaseEmpties() -{ - ScopedCriticalSection scopedCriticalSection(TheMemoryPoolCriticalSection); - - Int released = 0; - - for (MemoryPoolBlob* blob = m_firstBlob; blob;) - { - MemoryPoolBlob* pNext = blob->getNextInList(); - if (blob->getUsedBlockCount() == 0) - released += freeBlob(blob); - blob = pNext; - } - return released; -} - - -//----------------------------------------------------------------------------- -/** - throw away everything in the pool, but keep the pool itself valid. -*/ -void MemoryPool::reset() -{ - ScopedCriticalSection scopedCriticalSection(TheMemoryPoolCriticalSection); - - // toss everything. we could do this slightly more efficiently, - // but not really worth the extra code to do so. - while (m_firstBlob) - { - freeBlob(m_firstBlob); - } - m_firstBlob = NULL; - m_lastBlob = NULL; - m_firstBlobWithFreeBlocks = NULL; - - init(m_factory, m_poolName, m_allocationSize, m_initialAllocationCount, m_overflowAllocationCount); // will throw on failure - -} - -//----------------------------------------------------------------------------- -/** - add this pool to the factory's list-of-pools. -*/ -void MemoryPool::addToList(MemoryPool **pHead) -{ - this->m_nextPoolInFactory = *pHead; - *pHead = this; -} - -//----------------------------------------------------------------------------- -/** - remove this pool from the factory's list-of-pools. -*/ -void MemoryPool::removeFromList(MemoryPool **pHead) -{ - // this isn't very efficient, but then, we rarely remove pools... - // usually only at shutdown. so don't bother optimizing. - MemoryPool *prev = NULL; - for (MemoryPool *cur = *pHead; cur; cur = cur->m_nextPoolInFactory) - { - if (cur == this) - { - if (prev) - { - prev->m_nextPoolInFactory = this->m_nextPoolInFactory; - } - else - { - *pHead = this->m_nextPoolInFactory; - } - break; - } - prev = cur; - } -} - -//----------------------------------------------------------------------------- -#ifdef MEMORYPOOL_DEBUG -/** - print a report about per-pool allocation statistics to the debug log. - if the pool is null, print column headers. -*/ -/*static*/ void MemoryPool::debugPoolInfoReport( MemoryPool *pool, FILE *fp ) -{ - //USE_PERF_TIMER(MemoryPoolDebugging) skip end-of-run reporting stuff - - const char *PREPEND = "POOLINFO"; // allows grepping more easily - - if (!pool) - { - DEBUG_LOG(("%s,%32s,%6s,%6s,%6s,%6s,%6s,%6s",PREPEND,"POOLNAME","BLKSZ","INIT","OVRFL","USED","TOTAL","PEAK")); - if( fp ) - fprintf( fp, "%s,%32s,%6s,%6s,%6s,%6s,%6s,%6s\n",PREPEND,"POOLNAME","BLKSZ","INIT","OVRFL","USED","TOTAL","PEAK" ); - } - else - { - DEBUG_LOG(("%s,%32s,%6d,%6d,%6d,%6d,%6d,%6d",PREPEND, - pool->m_poolName,pool->m_allocationSize,pool->m_initialAllocationCount,pool->m_overflowAllocationCount, - pool->m_usedBlocksInPool,pool->m_totalBlocksInPool,pool->m_peakUsedBlocksInPool)); - if( fp ) - { - fprintf( fp, "%s,%32s,%6d,%6d,%6d,%6d,%6d,%6d\n",PREPEND, - pool->m_poolName,pool->m_allocationSize,pool->m_initialAllocationCount,pool->m_overflowAllocationCount, - pool->m_usedBlocksInPool,pool->m_totalBlocksInPool,pool->m_peakUsedBlocksInPool ); - } - } -} -#endif - -//----------------------------------------------------------------------------- -#ifdef MEMORYPOOL_DEBUG -Int MemoryPool::debugPoolReportLeaks( const char* owner ) -{ - //USE_PERF_TIMER(MemoryPoolDebugging) skip end-of-run reporting stuff - - Int any = 0; - for (MemoryPoolBlob* blob = m_firstBlob; blob; blob = blob->getNextInList()) - { - any += blob->debugBlobReportLeaks(owner); - } - return any; -} -#endif - -//----------------------------------------------------------------------------- -#ifdef MEMORYPOOL_DEBUG -/** - perform internal consistency checking on the memory pool. -*/ -void MemoryPool::debugMemoryVerifyPool() -{ - USE_PERF_TIMER(MemoryPoolDebugging) - - Int used = 0; - Int total = 0; - for (MemoryPoolBlob* blob = m_firstBlob; blob; blob = blob->getNextInList()) - { - blob->debugMemoryVerifyBlob(); - used += blob->getUsedBlockCount(); - total += blob->getTotalBlockCount(); - } - DEBUG_ASSERTCRASH(m_usedBlocksInPool == used, ("used mismatch %d %d",m_usedBlocksInPool,used)); - DEBUG_ASSERTCRASH(m_totalBlocksInPool == total, ("total mismatch %d %d",m_totalBlocksInPool,total)); -} -#endif - -//----------------------------------------------------------------------------- -#ifdef MEMORYPOOL_DEBUG -/** - return true iff the block is a valid block in this pool. -*/ -Bool MemoryPool::debugIsBlockInPool(void *pBlockPtr) -{ - USE_PERF_TIMER(MemoryPoolDebugging) - - if (!pBlockPtr) - return false; - -#ifdef MEMORYPOOL_INTENSE_VERIFY - debugMemoryVerifyPool(); -#endif - - Bool check1 = false, check2 = false; - - MemoryPoolSingleBlock *block = MemoryPoolSingleBlock::recoverBlockFromUserData(pBlockPtr); - MemoryPoolBlob *ownerBlob = block->getOwningBlob(); - for (MemoryPoolBlob* blob = m_firstBlob; blob; blob = blob->getNextInList()) - { - if (blob->debugIsBlockInBlob(pBlockPtr)) - check1 = true; - - if (blob == ownerBlob) - check2 = true; - } - - DEBUG_ASSERTCRASH(check1 == check2, ("mismatch checks in debugIsBlockInPool")); - - return check1 && check2; -} -#endif - -//----------------------------------------------------------------------------- -#ifdef MEMORYPOOL_DEBUG -/** - return the tagstring for the block. this will never return null; if - the block is null or invalid, "FREE_SINGLEBLOCK_TAG_STRING" will be returned. - it is assumed that the block was allocated by this pool. -*/ -const char *MemoryPool::debugGetBlockTagString(void *pBlockPtr) -{ - USE_PERF_TIMER(MemoryPoolDebugging) - - if (!pBlockPtr) - return FREE_SINGLEBLOCK_TAG_STRING; - -#ifdef MEMORYPOOL_INTENSE_VERIFY - debugMemoryVerifyPool(); -#endif - if (!debugIsBlockInPool(pBlockPtr)) - { - DEBUG_CRASH(("block is not in this pool")); - return FREE_SINGLEBLOCK_TAG_STRING; - } - MemoryPoolSingleBlock *block = MemoryPoolSingleBlock::recoverBlockFromUserData(pBlockPtr); - return block->debugGetLiteralTagString(); -} -#endif - -//----------------------------------------------------------------------------- -#ifdef MEMORYPOOL_CHECKPOINTING -/** - free all checkpointinfo for this pool, and reset all ptrs to checkpointinfo. -*/ -void MemoryPool::debugResetCheckpoints() -{ - Checkpointable::debugResetCheckpoints(); - for (MemoryPoolBlob* blob = m_firstBlob; blob; blob = blob->getNextInList()) - { - blob->debugResetCheckpoints(); - } -} -#endif - -//----------------------------------------------------------------------------- -// METHODS for DynamicMemoryAllocator -//----------------------------------------------------------------------------- - -//----------------------------------------------------------------------------- -/** - init the DMA to safe values. -*/ -DynamicMemoryAllocator::DynamicMemoryAllocator() : - m_factory(NULL), - m_nextDmaInFactory(NULL), - m_numPools(0), - m_usedBlocksInDma(0), - m_rawBlocks(NULL) -{ - for (Int i = 0; i < MAX_DYNAMICMEMORYALLOCATOR_SUBPOOLS; i++) - m_pools[i] = 0; -} - -//----------------------------------------------------------------------------- -/** - Initialize the dma and its subpools. -*/ -void DynamicMemoryAllocator::init(MemoryPoolFactory *factory, Int numSubPools, const PoolInitRec pParms[]) -{ - const PoolInitRec defaultDMA[7] = - { - { "dmaPool_16", 16, 64, 64 }, - { "dmaPool_32", 32, 64, 64 }, - { "dmaPool_64", 64, 64, 64 }, - { "dmaPool_128", 128, 64, 64 }, - { "dmaPool_256", 256, 64, 64 }, - { "dmaPool_512", 512, 64, 64 }, - { "dmaPool_1024", 1024, 64, 64 } - }; - - if (numSubPools == 0 || pParms == NULL) - { - // use the defaults... - numSubPools = 7; - pParms = defaultDMA; - } - - - m_factory = factory; - m_numPools = numSubPools; - if (m_numPools > MAX_DYNAMICMEMORYALLOCATOR_SUBPOOLS) - m_numPools = MAX_DYNAMICMEMORYALLOCATOR_SUBPOOLS; - m_usedBlocksInDma = 0; - for (Int i = 0; i < m_numPools; i++) - { - DEBUG_ASSERTCRASH(i == 0 || pParms[i].allocationSize > pParms[i-1].allocationSize, ("alloc size must increase monotonically for DMA")); - m_pools[i] = m_factory->createMemoryPool(&pParms[i]); - } -} - -//----------------------------------------------------------------------------- -/** - destroy the dma and its subpools. -*/ -DynamicMemoryAllocator::~DynamicMemoryAllocator() -{ - DEBUG_ASSERTCRASH(m_usedBlocksInDma == 0, ("destroying a nonempty dma")); - - /// @todo this may cause double-destruction of the subpools -- test & fix - for (Int i = 0; i < m_numPools; i++) - { - m_factory->destroyMemoryPool(m_pools[i]); - m_pools[i] = NULL; - } - - while (m_rawBlocks) - { - freeBytes(m_rawBlocks->getUserData()); - } -} - -//----------------------------------------------------------------------------- -/** - find the best-fitting subpool in this dma for a given allocation size. - if no subpool can satisfy the size, return null. -*/ -MemoryPool *DynamicMemoryAllocator::findPoolForSize(Int allocSize) -{ - for (Int i = 0; i < m_numPools; i++) - { - DEBUG_ASSERTCRASH(m_pools[i], ("null pool")); - if (allocSize <= m_pools[i]->getAllocationSize()) - return m_pools[i]; - } - return NULL; -} - -//----------------------------------------------------------------------------- -/** - add this DMA to the factory's list of dmas. -*/ -void DynamicMemoryAllocator::addToList(DynamicMemoryAllocator **pHead) -{ - this->m_nextDmaInFactory = *pHead; - *pHead = this; -} - -//----------------------------------------------------------------------------- -/** - remove this DMA from the factory's list of dmas. -*/ -void DynamicMemoryAllocator::removeFromList(DynamicMemoryAllocator **pHead) -{ - // this isn't very efficient, but then, we rarely remove these... - // usually only at shutdown. so don't bother optimizing. - DynamicMemoryAllocator *prev = NULL; - for (DynamicMemoryAllocator *cur = *pHead; cur; cur = cur->m_nextDmaInFactory) - { - if (cur == this) - { - if (prev) - { - prev->m_nextDmaInFactory = this->m_nextDmaInFactory; - } - else - { - *pHead = this->m_nextDmaInFactory; - } - break; - } - prev = cur; - } -} - -//----------------------------------------------------------------------------- -#ifdef MEMORYPOOL_DEBUG -void DynamicMemoryAllocator::debugIgnoreLeaksForThisBlock(void* pBlockPtr) -{ - USE_PERF_TIMER(MemoryPoolDebugging) - - if (!pBlockPtr) - return; - -#ifdef MEMORYPOOL_CHECK_BLOCK_OWNERSHIP - DEBUG_ASSERTCRASH(debugIsBlockInDma(pBlockPtr), ("block is not in this dma")); -#endif - - MemoryPoolSingleBlock *block = MemoryPoolSingleBlock::recoverBlockFromUserData(pBlockPtr); - if (block->getOwningBlob()) - { -#ifdef MEMORYPOOL_DEBUG - DEBUG_ASSERTCRASH(findPoolForSize(block->debugGetLogicalSize()) == block->getOwningBlob()->getOwningPool(), ("pool mismatch")); -#endif - block->debugIgnoreLeaksForThisBlock(); - } - else - { - DEBUG_CRASH(("cannot currently ignore leaks for raw blocks (allocation too large)")); - } -} -#endif - -//----------------------------------------------------------------------------- -/** - allocate a chunk-o-bytes from this DMA and return it, but don't bother zeroing - out the block. if unable to allocate, throw ERROR_OUT_OF_MEMORY. this - function will never return null. - - added code to make sure we're on a DWord boundary, throw exception if not -*/ -void *DynamicMemoryAllocator::allocateBytesDoNotZeroImplementation(Int numBytes DECLARE_LITERALSTRING_ARG2) -{ - ScopedCriticalSection scopedCriticalSection(TheDmaCriticalSection); - - void *result = NULL; - -#ifdef MEMORYPOOL_DEBUG - DEBUG_ASSERTCRASH(debugLiteralTagString != NULL, ("bad tagstring")); - Int waste = 0; -#endif - - MemoryPool *pool = findPoolForSize(numBytes); - if (pool != NULL) - { - result = pool->allocateBlockDoNotZeroImplementation(PASS_LITERALSTRING_ARG1); -#ifdef MEMORYPOOL_DEBUG - { - USE_PERF_TIMER(MemoryPoolDebugging) - waste = pool->getAllocationSize() - numBytes; - MemoryPoolSingleBlock *wblock = MemoryPoolSingleBlock::recoverBlockFromUserData(result); - wblock->debugSetWastedSize(waste); -#ifdef INTENSE_DMA_BOOKKEEPING - if (doingIntenseDMA == 0) -#endif - { - theWastedDMA += (waste); - if (thePeakWastedDMA < theWastedDMA) - thePeakWastedDMA = theWastedDMA; - } - } -#endif // MEMORYPOOL_DEBUG - } - else - { - // too big for our pools -- just go right to the metal. - MemoryPoolSingleBlock *block = MemoryPoolSingleBlock::rawAllocateSingleBlock(&m_rawBlocks, numBytes, m_factory PASS_LITERALSTRING_ARG2); - -#ifdef MEMORYPOOL_CHECKPOINTING - BlockCheckpointInfo *bi = debugAddCheckpointInfo(block->debugGetLiteralTagString(), m_factory->getCurCheckpoint(), numBytes); - if (bi) - block->debugSetCheckpointInfo(bi); -#endif - - result = block->getUserData(); - -#ifdef MEMORYPOOL_DEBUG - m_factory->adjustTotals(debugLiteralTagString, numBytes, numBytes); - theTotalLargeBlocks += numBytes; - if (thePeakLargeBlocks < theTotalLargeBlocks) - thePeakLargeBlocks = theTotalLargeBlocks; -#endif - } - -#ifdef MEMORYPOOL_DEBUG -{ - USE_PERF_TIMER(MemoryPoolDebugging) - theTotalDMA += numBytes; - if (thePeakDMA < theTotalDMA) - thePeakDMA = theTotalDMA; -#ifdef INTENSE_DMA_BOOKKEEPING - if (isMemoryManagerOfficiallyInited() && doingIntenseDMA == 0) - { - ++doingIntenseDMA; - UsedNPeak& up = TheUsedNPeakMap[debugLiteralTagString]; - up.used += numBytes; - if (up.peak < up.used) - up.peak = up.used; - up.waste += waste; - if (up.peakwaste < up.waste) - up.peakwaste = up.waste; - --doingIntenseDMA; - } -#endif -} -#endif // MEMORYPOOL_DEBUG - - ++m_usedBlocksInDma; - DEBUG_ASSERTCRASH(m_usedBlocksInDma >= 0, ("negative count for m_usedBlocksInDma")); -#ifdef MEMORYPOOL_DEBUG - #ifdef USE_FILLER_VALUE - { - USE_PERF_TIMER(MemoryPoolInitFilling) - ::memset32(result, s_initFillerValue, numBytes); - } - #endif -#endif - -#if defined(RTS_DEBUG) - // check alignment - if (unsigned(result)&3) - throw ERROR_OUT_OF_MEMORY; -#endif - - return result; -} - -//----------------------------------------------------------------------------- -/** - allocate a chunk-o-bytes from this DMA and return it, and zero out the contents first. - if unable to allocate, throw ERROR_OUT_OF_MEMORY. - this function will never return null. -*/ -void *DynamicMemoryAllocator::allocateBytesImplementation(Int numBytes DECLARE_LITERALSTRING_ARG2) -{ - void* p = allocateBytesDoNotZeroImplementation(numBytes PASS_LITERALSTRING_ARG2); // throws on failure - memset(p, 0, numBytes); - return p; -} - -//----------------------------------------------------------------------------- -/** - free a chunk-o-bytes allocated by this dma. it's ok to pass null. -*/ -void DynamicMemoryAllocator::freeBytes(void* pBlockPtr) -{ - if (!pBlockPtr) - return; - - ScopedCriticalSection scopedCriticalSection(TheDmaCriticalSection); - -#ifdef MEMORYPOOL_CHECK_BLOCK_OWNERSHIP - DEBUG_ASSERTCRASH(debugIsBlockInDma(pBlockPtr), ("block is not in this dma")); -#endif - - MemoryPoolSingleBlock *block = MemoryPoolSingleBlock::recoverBlockFromUserData(pBlockPtr); -#ifdef MEMORYPOOL_DEBUG - Int waste = 0, used = 0; -#ifdef INTENSE_DMA_BOOKKEEPING - const char* tagString; -#endif - { - USE_PERF_TIMER(MemoryPoolDebugging) - waste = 0; - used = block->debugGetLogicalSize(); - theTotalDMA -= used; - if (thePeakDMA < theTotalDMA) - thePeakDMA = theTotalDMA; - #ifdef INTENSE_DMA_BOOKKEEPING - tagString = block->debugGetLiteralTagString(); - #endif - } -#endif // MEMORYPOOL_DEBUG - - if (block->getOwningBlob()) - { -#ifdef MEMORYPOOL_DEBUG - { - USE_PERF_TIMER(MemoryPoolDebugging) - DEBUG_ASSERTCRASH(findPoolForSize(used) == block->getOwningBlob()->getOwningPool(), ("pool mismatch")); - #ifdef INTENSE_DMA_BOOKKEEPING - if (doingIntenseDMA == 0) - #endif - { - waste = block->debugGetWastedSize(); - theWastedDMA -= waste; - if (thePeakWastedDMA < theWastedDMA) - thePeakWastedDMA = theWastedDMA; - } - } -#endif // MEMORYPOOL_DEBUG - block->getOwningBlob()->getOwningPool()->freeBlock(pBlockPtr); - } - else - { - // was allocated via sysAllocate. -#ifdef MEMORYPOOL_CHECKPOINTING - BlockCheckpointInfo *bi = block->debugGetCheckpointInfo(); - DEBUG_ASSERTCRASH(bi, ("hmm, no checkpoint info")); - if (bi) - bi->debugSetFreepoint(m_factory->getCurCheckpoint()); -#endif - -#ifdef MEMORYPOOL_DEBUG - m_factory->adjustTotals(block->debugGetLiteralTagString(), -used, -used); - theTotalLargeBlocks -= used; - if (thePeakLargeBlocks < theTotalLargeBlocks) - thePeakLargeBlocks = theTotalLargeBlocks; - block->debugMarkBlockAsFree(); -#endif - - block->removeBlockFromList(&m_rawBlocks); - - ::sysFree((void *)block); - - } - --m_usedBlocksInDma; - DEBUG_ASSERTCRASH(m_usedBlocksInDma >= 0, ("negative count for m_usedBlocksInDma")); - -#ifdef INTENSE_DMA_BOOKKEEPING - if (isMemoryManagerOfficiallyInited() && doingIntenseDMA == 0) - { - ++doingIntenseDMA; - UsedNPeak& up = TheUsedNPeakMap[tagString]; - up.used -= used; - if (up.peak < up.used) - up.peak = up.used; - up.waste -= waste; - if (up.peakwaste < up.waste) - up.peakwaste = up.waste; - --doingIntenseDMA; - } -#endif - -} - -//----------------------------------------------------------------------------- -Int DynamicMemoryAllocator::getActualAllocationSize(Int numBytes) -{ - MemoryPool *pool = findPoolForSize(numBytes); - return pool ? pool->getAllocationSize() : numBytes; -} - -//----------------------------------------------------------------------------- -/** - throw away everything in the DMA, but keep the DMA itself valid. -*/ -void DynamicMemoryAllocator::reset() -{ - for (Int i = 0; i < m_numPools; i++) - { - if (m_pools[i]) - { - m_pools[i]->reset(); - } - } - - while (m_rawBlocks) - freeBytes(m_rawBlocks->getUserData()); - - m_usedBlocksInDma = 0; -} - -//----------------------------------------------------------------------------- -#ifdef MEMORYPOOL_DEBUG -/** - return true iff the given pool is a subpool of this dma. -*/ -Bool DynamicMemoryAllocator::debugIsPoolInDma(MemoryPool *pool) -{ - USE_PERF_TIMER(MemoryPoolDebugging) - - if (!pool) - return false; - - for (Int i = 0; i < m_numPools; i++) - { - if (m_pools[i] == pool) - return true; - } - - return false; -} -#endif - -//----------------------------------------------------------------------------- -#ifdef MEMORYPOOL_DEBUG -/** - return true iff the block was allocated by this dma - (either from a subpool or as a raw block). -*/ -Bool DynamicMemoryAllocator::debugIsBlockInDma(void *pBlockPtr) -{ - USE_PERF_TIMER(MemoryPoolDebugging) - - if (!pBlockPtr) - return false; - - MemoryPoolSingleBlock *block = MemoryPoolSingleBlock::recoverBlockFromUserData(pBlockPtr); - if (block->getOwningBlob()) - { - MemoryPool *pool = block->getOwningBlob()->getOwningPool(); - return pool && pool->debugIsBlockInPool(pBlockPtr) && debugIsPoolInDma(pool); - } - else - { - for (MemoryPoolSingleBlock *b = m_rawBlocks; b; b = b->getNextRawBlock()) - { - if (b == block) - return true; - } - return false; - } -} -#endif - -//----------------------------------------------------------------------------- -#ifdef MEMORYPOOL_DEBUG -/** - return the tagstring for the block. this will never return null; if - the block is null or invalid, "FREE_SINGLEBLOCK_TAG_STRING" will be returned. - it is assumed that the block was allocated by this dma. -*/ -const char *DynamicMemoryAllocator::debugGetBlockTagString(void *pBlockPtr) -{ - USE_PERF_TIMER(MemoryPoolDebugging) - - if (!pBlockPtr) - return FREE_SINGLEBLOCK_TAG_STRING; - - if (!debugIsBlockInDma(pBlockPtr)) - { - DEBUG_CRASH(("block is not in this dma")); - return FREE_SINGLEBLOCK_TAG_STRING; - } - MemoryPoolSingleBlock *block = MemoryPoolSingleBlock::recoverBlockFromUserData(pBlockPtr); - return block->debugGetLiteralTagString(); -} -#endif - -//----------------------------------------------------------------------------- -#ifdef MEMORYPOOL_DEBUG -/** - perform internal consistency checking on this DMA. -*/ -void DynamicMemoryAllocator::debugMemoryVerifyDma() -{ - USE_PERF_TIMER(MemoryPoolDebugging) - - for (MemoryPoolSingleBlock *b = m_rawBlocks; b; b = b->getNextRawBlock()) - { - b->debugVerifyBlock(); - } -} -#endif - -//----------------------------------------------------------------------------- -#ifdef MEMORYPOOL_CHECKPOINTING -/** - free all checkpointinfo for this dma, and reset all ptrs to checkpointinfo. -*/ -void DynamicMemoryAllocator::debugResetCheckpoints() -{ - Checkpointable::debugResetCheckpoints(); - for (MemoryPoolSingleBlock *b = m_rawBlocks; b; b = b->getNextRawBlock()) - { - b->debugResetCheckpoint(); - } -} -#endif - -//----------------------------------------------------------------------------- -#ifdef MEMORYPOOL_DEBUG -/** - calculate the total number of raw blocks allocated by this dma, - and the total number of bytes (logical) used by those raw blocks. -*/ -Int DynamicMemoryAllocator::debugCalcRawBlockBytes(Int *numBlocks) -{ - USE_PERF_TIMER(MemoryPoolDebugging) - - if (numBlocks) - *numBlocks = 0; - Int bytes = 0; - for (MemoryPoolSingleBlock *b = m_rawBlocks; b; b = b->getNextRawBlock()) - { - if (numBlocks) - *numBlocks += 1; - bytes += b->debugGetLogicalSize(); - } - return bytes; -} -#endif - -//----------------------------------------------------------------------------- -#ifdef MEMORYPOOL_DEBUG -Int DynamicMemoryAllocator::debugDmaReportLeaks() -{ - //USE_PERF_TIMER(MemoryPoolDebugging) skip end-of-run reporting stuff - - Int any = false; - for (MemoryPoolSingleBlock *b = m_rawBlocks; b; b = b->getNextRawBlock()) - { - any += b->debugSingleBlockReportLeak("(DMA)"); - } - return any; -} -#endif - -//----------------------------------------------------------------------------- -#ifdef MEMORYPOOL_DEBUG -/** - print a report about raw block allocations to the debug log. -*/ -void DynamicMemoryAllocator::debugDmaInfoReport( FILE *fp ) -{ - //USE_PERF_TIMER(MemoryPoolDebugging) skip end-of-run reporting stuff - - const char *PREPEND = "POOLINFO"; // allows grepping more easily - - Int numBlocks; - Int bytes = debugCalcRawBlockBytes(&numBlocks); - DEBUG_LOG(("%s,Total Raw Blocks = %d",PREPEND,numBlocks)); - DEBUG_LOG(("%s,Total Raw Block Bytes = %d",PREPEND,bytes)); - DEBUG_LOG(("%s,Average Raw Block Size = %d",PREPEND,numBlocks?bytes/numBlocks:0)); - DEBUG_LOG(("%s,Raw Blocks:",PREPEND)); - if( fp ) - { - fprintf( fp, "%s,Total Raw Blocks = %d\n",PREPEND,numBlocks ); - fprintf( fp, "%s,Total Raw Block Bytes = %d\n",PREPEND,bytes ); - fprintf( fp, "%s,Average Raw Block Size = %d\n",PREPEND,numBlocks?bytes/numBlocks:0 ); - fprintf( fp, "%s,Raw Blocks:\n",PREPEND ); - } - for (MemoryPoolSingleBlock *b = m_rawBlocks; b; b = b->getNextRawBlock()) - { - DEBUG_LOG(("%s, Blocksize=%d",PREPEND,b->debugGetLogicalSize())); - //if( fp ) - //{ - // fprintf( fp, "%s, Blocksize=%d\n",PREPEND,b->debugGetLogicalSize() ); - //} - } - -} -#endif - -//----------------------------------------------------------------------------- -// METHODS for MemoryPoolFactory -//----------------------------------------------------------------------------- - -//----------------------------------------------------------------------------- -/** - init the factory to safe values. -*/ -MemoryPoolFactory::MemoryPoolFactory() : - m_firstPoolInFactory(NULL), - m_firstDmaInFactory(NULL) -#ifdef MEMORYPOOL_CHECKPOINTING - , m_curCheckpoint(0) -#endif -#ifdef MEMORYPOOL_DEBUG - , m_usedBytes(0) - , m_physBytes(0) - , m_peakUsedBytes(0) - , m_peakPhysBytes(0) -#endif -{ -#ifdef MEMORYPOOL_DEBUG - for (int i = 0; i < MAX_SPECIAL_USED; ++i) - { - m_usedBytesSpecial[i] = 0; - m_usedBytesSpecialPeak[i] = 0; - m_physBytesSpecial[i] = 0; - m_physBytesSpecialPeak[i] = 0; - } - #ifdef USE_FILLER_VALUE - calcFillerValue(GameClientRandomValue(0, MAX_INIT_FILLER_COUNT-1)); - #endif -#endif -} -//----------------------------------------------------------------------------- -/** - initialize the factory. -*/ -void MemoryPoolFactory::init() -{ - // my, that was easy -} - -//----------------------------------------------------------------------------- -/** - destroy the factory, and all its pools and dmas. -*/ -MemoryPoolFactory::~MemoryPoolFactory() -{ - while (m_firstPoolInFactory) - { - destroyMemoryPool(m_firstPoolInFactory); - } - - while (m_firstDmaInFactory) - { - destroyDynamicMemoryAllocator(m_firstDmaInFactory); - } -} - -//----------------------------------------------------------------------------- -/** - create a new memory pool. -*/ -MemoryPool *MemoryPoolFactory::createMemoryPool(const PoolInitRec *parms) -{ - return createMemoryPool(parms->poolName, parms->allocationSize, parms->initialAllocationCount, parms->overflowAllocationCount); -} - -//----------------------------------------------------------------------------- -/** - create a new memory pool. (alternate argument list) -*/ -MemoryPool *MemoryPoolFactory::createMemoryPool(const char *poolName, Int allocationSize, Int initialAllocationCount, Int overflowAllocationCount) -{ - MemoryPool *pool = findMemoryPool(poolName); - if (pool) - { - DEBUG_ASSERTCRASH(allocationSize == pool->getAllocationSize(), ("pool size mismatch")); - return pool; - } - - userMemoryAdjustPoolSize(poolName, initialAllocationCount, overflowAllocationCount); - - if (initialAllocationCount <= 0 || overflowAllocationCount < 0) - { - DEBUG_CRASH(("illegal pool size: %d %d",initialAllocationCount,overflowAllocationCount)); - throw ERROR_OUT_OF_MEMORY; - } - - pool = new (::sysAllocateDoNotZero(sizeof(MemoryPool))) MemoryPool; // will throw on failure - pool->init(this, poolName, allocationSize, initialAllocationCount, overflowAllocationCount); // will throw on failure - - pool->addToList(&m_firstPoolInFactory); - - return pool; -} - -//----------------------------------------------------------------------------- -/** - find a memory pool with the given name; return null if no such pool exists, - return null. note that this function isn't particularly fast (it just does - a linear search), so you should probably cache the result. -*/ -MemoryPool *MemoryPoolFactory::findMemoryPool(const char *poolName) -{ - for (MemoryPool *pool = m_firstPoolInFactory; pool; pool = pool->getNextPoolInList()) - { - if (!strcmp(poolName, pool->getPoolName())) - { - DEBUG_ASSERTCRASH(poolName == pool->getPoolName(), ("hmm, ptrs should probably match here")); - return pool; - } - } - return NULL; -} - -//----------------------------------------------------------------------------- -/** - destroy the given memory pool. you normally will never need to call this directly. -*/ -void MemoryPoolFactory::destroyMemoryPool(MemoryPool *pMemoryPool) -{ - if (!pMemoryPool) - return; - - DEBUG_ASSERTCRASH(pMemoryPool->getUsedBlockCount() == 0, ("destroying a nonempty pool")); - - pMemoryPool->removeFromList(&m_firstPoolInFactory); - - // this is evil... since there is no 'placement delete' we must do this the hard way - // and call the dtor directly. ordinarily this is heinous, but in this case we'll - // make an exception. - pMemoryPool->~MemoryPool(); - ::sysFree((void *)pMemoryPool); -} - -//----------------------------------------------------------------------------- -/** - create a new dynamicMemoryAllocator. You normally will never need to call this directly. -*/ -DynamicMemoryAllocator *MemoryPoolFactory::createDynamicMemoryAllocator(Int numSubPools, const PoolInitRec pParms[]) -{ - DynamicMemoryAllocator *dma; - - dma = new (::sysAllocateDoNotZero(sizeof(DynamicMemoryAllocator))) DynamicMemoryAllocator; // will throw on failure - dma->init(this, numSubPools, pParms); // will throw on failure - - dma->addToList(&m_firstDmaInFactory); - - return dma; -} - -//----------------------------------------------------------------------------- -/** - destroy the given dynamicMemoryAllocator. You normally will never need to call this directly. -*/ -void MemoryPoolFactory::destroyDynamicMemoryAllocator(DynamicMemoryAllocator *dma) -{ - if (!dma) - return; - - dma->removeFromList(&m_firstDmaInFactory); - - // this is evil... since there is no 'placement delete' we must do this the hard way - // and call the dtor directly. ordinarily this is heinous, but in this case we'll - // make an exception. - dma->~DynamicMemoryAllocator(); - ::sysFree((void *)dma); -} - -//----------------------------------------------------------------------------- -/** - throw away everything in all pools/dmas owned by this factory, but keep the factory - and pools/dmas themselves valid. -*/ -void MemoryPoolFactory::reset() -{ -#ifdef MEMORYPOOL_CHECKPOINTING - debugResetCheckpoints(); -#endif - - for (MemoryPool *pool = m_firstPoolInFactory; pool; pool = pool->getNextPoolInList()) - { - pool->reset(); - } - for (DynamicMemoryAllocator *dma = m_firstDmaInFactory; dma; dma = dma->getNextDmaInList()) - { - dma->reset(); - } - -#ifdef MEMORYPOOL_DEBUG - m_usedBytes = 0; - m_physBytes = 0; - m_peakUsedBytes = 0; - m_peakPhysBytes = 0; - for (int i = 0; i < MAX_SPECIAL_USED; ++i) - { - m_usedBytesSpecial[i] = 0; - m_usedBytesSpecialPeak[i] = 0; - m_physBytesSpecial[i] = 0; - m_physBytesSpecialPeak[i] = 0; - } - #ifdef USE_FILLER_VALUE - calcFillerValue(GameClientRandomValue(0, MAX_INIT_FILLER_COUNT-1)); - #endif -#endif -} - -//----------------------------------------------------------------------------- -#ifdef MEMORYPOOL_DEBUG -static const char* s_specialPrefixes[MAX_SPECIAL_USED] = -{ - "Misc", // the catchall for stuff that doesn't match others - "W3D_", - "W3A_", - "STL_", - "STR_", - NULL -}; - -#endif - -//----------------------------------------------------------------------------- -#ifdef MEMORYPOOL_DEBUG -/** - perform bookkeeping on memory usage statistics. -*/ -void MemoryPoolFactory::adjustTotals(const char* tagString, Int usedDelta, Int physDelta) -{ - USE_PERF_TIMER(MemoryPoolDebugging) - - m_usedBytes += usedDelta; - m_physBytes += physDelta; - if (m_peakUsedBytes < m_usedBytes) - m_peakUsedBytes = m_usedBytes; - if (m_peakPhysBytes < m_physBytes) - m_peakPhysBytes = m_physBytes; - - int found = 0; // if no matches found, goes into slot zero - for (int i = 1; i < MAX_SPECIAL_USED; ++i) // start at 1, not zero - { - if (s_specialPrefixes[i] == NULL) - break; - - if (strncmp(tagString, s_specialPrefixes[i], strlen(s_specialPrefixes[i])) == 0) - { - found = i; - break; - } - } - m_usedBytesSpecial[found] += usedDelta; - m_physBytesSpecial[found] += physDelta; - if (m_usedBytesSpecialPeak[found] < m_usedBytesSpecial[found]) - m_usedBytesSpecialPeak[found] = m_usedBytesSpecial[found]; - if (m_physBytesSpecialPeak[found] < m_physBytesSpecial[found]) - m_physBytesSpecialPeak[found] = m_physBytesSpecial[found]; -} -#endif - -//----------------------------------------------------------------------------- -#ifdef MEMORYPOOL_DEBUG -void MemoryPoolFactory::debugSetInitFillerIndex(Int index) -{ - #ifdef USE_FILLER_VALUE - if (index < 0 || index >= MAX_INIT_FILLER_COUNT) - index = GameClientRandomValue(0, MAX_INIT_FILLER_COUNT-1); - calcFillerValue(index); - #endif -} -#endif - -//----------------------------------------------------------------------------- -#ifdef MEMORYPOOL_DEBUG -/** - perform internal consistency checking on the factory, and all of its - pools and dmas. -*/ -void MemoryPoolFactory::debugMemoryVerify() -{ - USE_PERF_TIMER(MemoryPoolDebugging) - - Int used = 0, phys = 0; - - for (MemoryPool *pool = m_firstPoolInFactory; pool; pool = pool->getNextPoolInList()) - { - pool->debugMemoryVerifyPool(); - used += pool->getUsedBlockCount()*pool->getAllocationSize(); - phys += pool->getTotalBlockCount()*pool->getAllocationSize(); - } - - for (DynamicMemoryAllocator *dma = m_firstDmaInFactory; dma; dma = dma->getNextDmaInList()) - { - dma->debugMemoryVerifyDma(); - Int tmp = dma->debugCalcRawBlockBytes(NULL); - used += tmp; - phys += tmp; - } - - DEBUG_ASSERTCRASH(used == m_usedBytes, ("used count mismatch")); - DEBUG_ASSERTCRASH(phys == m_physBytes, ("phys count mismatch")); -} -#endif - -//----------------------------------------------------------------------------- -#ifdef MEMORYPOOL_DEBUG -/** - return true iff the block was allocated by any of the pools/dmas owned - by this factory. -*/ -Bool MemoryPoolFactory::debugIsBlockInAnyPool(void *pBlock) -{ - USE_PERF_TIMER(MemoryPoolDebugging) - -#ifdef MEMORYPOOL_INTENSE_VERIFY - debugMemoryVerify(); -#endif - for (MemoryPool *pool = m_firstPoolInFactory; pool; pool = pool->getNextPoolInList()) - { - if (pool->debugIsBlockInPool(pBlock)) - return true; - } - - for (DynamicMemoryAllocator *dma = m_firstDmaInFactory; dma; dma = dma->getNextDmaInList()) - { - if (dma->debugIsBlockInDma(pBlock)) - return true; - } - - return false; -} -#endif - -//----------------------------------------------------------------------------- -#ifdef MEMORYPOOL_DEBUG -/** - return the tagstring for this block. this will never return null; if - the block is null or invalid, "FREE_SINGLEBLOCK_TAG_STRING" will be returned. - it is assumed that the block was allocated by this factory. -*/ -const char *MemoryPoolFactory::debugGetBlockTagString(void *pBlockPtr) -{ - USE_PERF_TIMER(MemoryPoolDebugging) - - if (!pBlockPtr) - return FREE_SINGLEBLOCK_TAG_STRING; - -#ifdef MEMORYPOOL_INTENSE_VERIFY - debugMemoryVerify(); -#endif - if (!debugIsBlockInAnyPool(pBlockPtr)) - { - DEBUG_CRASH(("block is not in this factory")); - return FREE_SINGLEBLOCK_TAG_STRING; - } - MemoryPoolSingleBlock *block = MemoryPoolSingleBlock::recoverBlockFromUserData(pBlockPtr); - return block->debugGetLiteralTagString(); -} -#endif - -//----------------------------------------------------------------------------- -#ifdef MEMORYPOOL_CHECKPOINTING -/** - set a new checkpoint for all future blocks allocated/freed by this factory's pools/dmas. -*/ -Int MemoryPoolFactory::debugSetCheckpoint() -{ - return ++m_curCheckpoint; -} -#endif - -//----------------------------------------------------------------------------- -#ifdef MEMORYPOOL_CHECKPOINTING -/** - throw away all checkpoint info for all pools/dmas. -*/ -void MemoryPoolFactory::debugResetCheckpoints() -{ - for (MemoryPool *pool = m_firstPoolInFactory; pool; pool = pool->getNextPoolInList()) - { - pool->debugResetCheckpoints(); - } - for (DynamicMemoryAllocator *dma = m_firstDmaInFactory; dma; dma = dma->getNextDmaInList()) - { - dma->debugResetCheckpoints(); - } - m_curCheckpoint = 0; -} -#endif - -//----------------------------------------------------------------------------- -void MemoryPoolFactory::memoryPoolUsageReport( const char* filename, FILE *appendToFileInstead ) -{ -#ifdef MEMORYPOOL_DEBUG - //USE_PERF_TIMER(MemoryPoolDebugging) skip end-of-run reporting stuff - - FILE* perfStatsFile = NULL; - Int totalNamedPoolPeak = 0; - - if( !appendToFileInstead ) - { - char tmp[256]; - strcpy(tmp,filename); - strcat(tmp,".csv"); - perfStatsFile = fopen(tmp, "w"); - } - else - { - perfStatsFile = appendToFileInstead; - } - - if (perfStatsFile == NULL) - { - DEBUG_CRASH(("could not open/create perf file %s -- is it open in another app?",filename)); - return; - } - - Int lineIdx = 0; - MemoryPool *pool = m_firstPoolInFactory; -#ifdef INTENSE_DMA_BOOKKEEPING - UsedNPeakMap::const_iterator it = TheUsedNPeakMap.begin(); -#endif - for (;;) - { - Bool keepGoing = false; - if (pool) - { - if (lineIdx == 0) - { - fprintf(perfStatsFile, "%s,%d","Unpooled Large Blocks (>1024 bytes)",thePeakLargeBlocks/1024); - } - else - { - Int sz = pool->getAllocationSize(); - Int initial = pool->getInitialBlockCount()*sz; - Int peak = pool->getPeakBlockCount()*sz; - Int waste = initial - peak; - if (waste < 0) waste = 0; - fprintf(perfStatsFile, "%s,%d,%d",pool->getPoolName(),peak/1024,waste/1024); - totalNamedPoolPeak += peak; - pool = pool->getNextPoolInList(); - } - keepGoing = true; - } - else - { - fprintf(perfStatsFile, ",,"); - } - -#ifdef INTENSE_DMA_BOOKKEEPING - if (it != TheUsedNPeakMap.end()) - { - Int wastepct = (it->second.peakwaste * 100) / (it->second.peak + it->second.peakwaste); - fprintf(perfStatsFile, ",,,,%s,%d,%d,%d",it->first,it->second.peak/1024,it->second.peakwaste/1024,wastepct); - ++it; - keepGoing = true; - } - else - { - fprintf(perfStatsFile, ",,,,,,,"); - } -#endif - - if (lineIdx < MAX_SPECIAL_USED && s_specialPrefixes[lineIdx] != NULL) - { - fprintf(perfStatsFile, ",,,%s,%d",s_specialPrefixes[lineIdx],m_usedBytesSpecialPeak[lineIdx]/1024); - keepGoing = true; - } - - fprintf(perfStatsFile, "\n"); - ++lineIdx; - - if (!keepGoing) - break; - } - - fflush(perfStatsFile); - - if( !appendToFileInstead ) - { - fclose(perfStatsFile); - } -#endif -} - -//----------------------------------------------------------------------------- -#ifdef MEMORYPOOL_DEBUG -/** - send a memory reports (based on the flags/checkpoints) to the debug log. -*/ -void MemoryPoolFactory::debugMemoryReport(Int flags, Int startCheckpoint, Int endCheckpoint, FILE *fp ) -{ - //USE_PERF_TIMER(MemoryPoolDebugging) skip end-of-run reporting stuff - -#ifdef ALLOW_DEBUG_UTILS - Int oldFlags = DebugGetFlags(); - DebugSetFlags(oldFlags & ~DEBUG_FLAG_PREPEND_TIME); -#endif - -#ifdef MEMORYPOOL_CHECKPOINTING - Bool doBlockReport = (flags & _REPORT_CP_ALLOCATED_DONTCARE) != 0 && (flags & _REPORT_CP_FREED_DONTCARE) != 0; - DEBUG_ASSERTCRASH(startCheckpoint >= 0 && startCheckpoint <= endCheckpoint && endCheckpoint <= m_curCheckpoint, ("bad checkpoints")); - DEBUG_ASSERTCRASH(((flags & _REPORT_CP_ALLOCATED_DONTCARE) != 0) == ((flags & _REPORT_CP_FREED_DONTCARE) != 0), ("bad flags: must set at both alloc and free flag")); -#endif - - debugMemoryVerify(); - - if (flags & REPORT_FACTORYINFO) - { - DEBUG_LOG(("------------------------------------------")); - DEBUG_LOG(("Begin Factory Info Report")); - DEBUG_LOG(("------------------------------------------")); - DEBUG_LOG(("Bytes in use (logical) = %d",m_usedBytes)); - DEBUG_LOG(("Bytes in use (physical) = %d",m_physBytes)); - DEBUG_LOG(("PEAK Bytes in use (logical) = %d",m_peakUsedBytes)); - DEBUG_LOG(("PEAK Bytes in use (physical) = %d",m_peakPhysBytes)); - DEBUG_LOG(("------------------------------------------")); - DEBUG_LOG(("End Factory Info Report")); - DEBUG_LOG(("------------------------------------------")); - if( fp ) - { - fprintf( fp, "------------------------------------------\n" ); - fprintf( fp, "Begin Factory Info Report\n" ); - fprintf( fp, "------------------------------------------\n" ); - fprintf( fp, "Bytes in use (logical) = %d\n",m_usedBytes ); - fprintf( fp, "Bytes in use (physical) = %d\n",m_physBytes ); - fprintf( fp, "PEAK Bytes in use (logical) = %d\n",m_peakUsedBytes ); - fprintf( fp, "PEAK Bytes in use (physical) = %d\n",m_peakPhysBytes ); - fprintf( fp, "------------------------------------------\n" ); - fprintf( fp, "End Factory Info Report\n" ); - fprintf( fp, "------------------------------------------\n" ); - } - } - - if (flags & REPORT_POOLINFO) - { - DEBUG_LOG(("------------------------------------------")); - DEBUG_LOG(("Begin Pool Info Report")); - DEBUG_LOG(("------------------------------------------")); - if( fp ) - { - fprintf( fp, "------------------------------------------\n" ); - fprintf( fp, "Begin Pool Info Report\n" ); - fprintf( fp, "------------------------------------------\n" ); - } - MemoryPool::debugPoolInfoReport( NULL, fp ); - for (MemoryPool *pool = m_firstPoolInFactory; pool; pool = pool->getNextPoolInList()) - { - MemoryPool::debugPoolInfoReport( pool, fp ); - } - for (DynamicMemoryAllocator *dma = m_firstDmaInFactory; dma; dma = dma->getNextDmaInList()) - { - dma->debugDmaInfoReport( fp ); - } - DEBUG_LOG(("------------------------------------------")); - DEBUG_LOG(("End Pool Info Report")); - DEBUG_LOG(("------------------------------------------")); - if( fp ) - { - fprintf( fp, "------------------------------------------\n" ); - fprintf( fp, "End Pool Info Report\n" ); - fprintf( fp, "------------------------------------------\n" ); - } - } - - if (flags & REPORT_POOL_OVERFLOW) - { - DEBUG_LOG(("------------------------------------------")); - DEBUG_LOG(("Begin Pool Overflow Report")); - DEBUG_LOG(("------------------------------------------")); - MemoryPool *pool = m_firstPoolInFactory; - for (; pool; pool = pool->getNextPoolInList()) - { - if (pool->getPeakBlockCount() > pool->getInitialBlockCount()) - { - DEBUG_LOG(("*** Pool %s overflowed initial allocation of %d (peak allocation was %d)",pool->getPoolName(),pool->getInitialBlockCount(),pool->getPeakBlockCount())); - } - } - DEBUG_LOG(("------------------------------------------")); - DEBUG_LOG(("End Pool Overflow Report")); - DEBUG_LOG(("------------------------------------------")); - DEBUG_LOG(("------------------------------------------")); - DEBUG_LOG(("Begin Pool Underflow Report")); - DEBUG_LOG(("------------------------------------------")); - for (pool = m_firstPoolInFactory; pool; pool = pool->getNextPoolInList()) - { - Int peak = pool->getPeakBlockCount()*pool->getAllocationSize(); - Int initial = pool->getInitialBlockCount()*pool->getAllocationSize(); - if (peak < initial/2 && (initial - peak) > 4096) - { - DEBUG_LOG(("*** Pool %s used less than half its initial allocation of %d (peak allocation was %d, wasted %dk)", - pool->getPoolName(),pool->getInitialBlockCount(),pool->getPeakBlockCount(),(initial - peak)/1024)); - } - } - DEBUG_LOG(("------------------------------------------")); - DEBUG_LOG(("End Pool Underflow Report")); - DEBUG_LOG(("------------------------------------------")); - } - - if( flags & REPORT_SIMPLE_LEAKS ) - { - DEBUG_LOG(("------------------------------------------")); - DEBUG_LOG(("Begin Simple Leak Report")); - DEBUG_LOG(("------------------------------------------")); - Int any = 0; - for (MemoryPool *pool = m_firstPoolInFactory; pool; pool = pool->getNextPoolInList()) - { - any += pool->debugPoolReportLeaks( pool->getPoolName() ); - } - for (DynamicMemoryAllocator *dma = m_firstDmaInFactory; dma; dma = dma->getNextDmaInList()) - { - any += dma->debugDmaReportLeaks(); - } - DEBUG_ASSERTCRASH(!any, ("There were %d memory leaks. Please fix them.",any)); - DEBUG_LOG(("------------------------------------------")); - DEBUG_LOG(("End Simple Leak Report")); - DEBUG_LOG(("------------------------------------------")); - } - -#ifdef MEMORYPOOL_CHECKPOINTING - if (doBlockReport) - { - const char* nm = (this == TheMemoryPoolFactory) ? "TheMemoryPoolFactory" : "*** UNKNOWN *** MemoryPoolFactory"; - - DEBUG_LOG_RAW(("\n")); - DEBUG_LOG(("------------------------------------------")); - DEBUG_LOG(("Begin Block Report for %s", nm)); - DEBUG_LOG(("------------------------------------------")); - char buf[256] = ""; - if (flags & _REPORT_CP_ALLOCATED_BEFORE) strcat(buf, "AllocBefore "); - if (flags & _REPORT_CP_ALLOCATED_BETWEEN) strcat(buf, "AllocBetween "); - if (flags & _REPORT_CP_FREED_BEFORE) strcat(buf, "FreedBefore "); - if (flags & _REPORT_CP_FREED_BETWEEN) strcat(buf, "FreedBetween "); - if (flags & _REPORT_CP_FREED_NEVER) strcat(buf, "StillExisting "); - DEBUG_LOG(("Options: Between checkpoints %d and %d, report on (%s)",startCheckpoint,endCheckpoint,buf)); - DEBUG_LOG(("------------------------------------------")); - - BlockCheckpointInfo::doBlockCheckpointReport( NULL, "", 0, 0, 0 ); - for (MemoryPool *pool = m_firstPoolInFactory; pool; pool = pool->getNextPoolInList()) - { - pool->debugCheckpointReport(flags, startCheckpoint, endCheckpoint, pool->getPoolName()); - } - for (DynamicMemoryAllocator *dma = m_firstDmaInFactory; dma; dma = dma->getNextDmaInList()) - { - dma->debugCheckpointReport(flags, startCheckpoint, endCheckpoint, "(Oversized)"); - } - - DEBUG_LOG(("------------------------------------------")); - DEBUG_LOG(("End Block Report for %s", nm)); - DEBUG_LOG(("------------------------------------------")); - } -#endif - -#ifdef ALLOW_DEBUG_UTILS - DebugSetFlags(oldFlags); -#endif -} -#endif - -//----------------------------------------------------------------------------- -// GLOBAL FUNCTIONS -//----------------------------------------------------------------------------- - -static int theLinkTester = 0; - -//----------------------------------------------------------------------------- -void* STLSpecialAlloc::allocate(size_t __n) -{ - ++theLinkTester; - preMainInitMemoryManager(); - DEBUG_ASSERTCRASH(TheDynamicMemoryAllocator != NULL, ("must init memory manager before calling global operator new")); - return TheDynamicMemoryAllocator->allocateBytes(__n, "STL_"); -} - -//----------------------------------------------------------------------------- -void STLSpecialAlloc::deallocate(void* __p, size_t) -{ - ++theLinkTester; - preMainInitMemoryManager(); - DEBUG_ASSERTCRASH(TheDynamicMemoryAllocator != NULL, ("must init memory manager before calling global operator new")); - TheDynamicMemoryAllocator->freeBytes(__p); -} - -//----------------------------------------------------------------------------- -/** - overload for global operator new; send requests to TheDynamicMemoryAllocator. -*/ -void *operator new(size_t size) -{ - ++theLinkTester; - preMainInitMemoryManager(); - DEBUG_ASSERTCRASH(TheDynamicMemoryAllocator != NULL, ("must init memory manager before calling global operator new")); - return TheDynamicMemoryAllocator->allocateBytes(size, "global operator new"); -} - -//----------------------------------------------------------------------------- -/** - overload for global operator new[]; send requests to TheDynamicMemoryAllocator. -*/ -void *operator new[](size_t size) -{ - ++theLinkTester; - preMainInitMemoryManager(); - DEBUG_ASSERTCRASH(TheDynamicMemoryAllocator != NULL, ("must init memory manager before calling global operator new")); - return TheDynamicMemoryAllocator->allocateBytes(size, "global operator new[]"); -} - -//----------------------------------------------------------------------------- -/** - overload for global operator delete; send requests to TheDynamicMemoryAllocator. -*/ -void operator delete(void *p) -{ - ++theLinkTester; - preMainInitMemoryManager(); - DEBUG_ASSERTCRASH(TheDynamicMemoryAllocator != NULL, ("must init memory manager before calling global operator delete")); - TheDynamicMemoryAllocator->freeBytes(p); -} - -//----------------------------------------------------------------------------- -/** - overload for global operator delete[]; send requests to TheDynamicMemoryAllocator. -*/ -void operator delete[](void *p) -{ - ++theLinkTester; - preMainInitMemoryManager(); - DEBUG_ASSERTCRASH(TheDynamicMemoryAllocator != NULL, ("must init memory manager before calling global operator delete")); - TheDynamicMemoryAllocator->freeBytes(p); -} - -//----------------------------------------------------------------------------- -/** - overload for global operator new (MFC debug version); send requests to TheDynamicMemoryAllocator. -*/ -void* operator new(size_t size, const char * fname, int) -{ - ++theLinkTester; - preMainInitMemoryManager(); - DEBUG_ASSERTCRASH(TheDynamicMemoryAllocator != NULL, ("must init memory manager before calling global operator new")); -#ifdef MEMORYPOOL_DEBUG - return TheDynamicMemoryAllocator->allocateBytesImplementation(size, fname); -#else - return TheDynamicMemoryAllocator->allocateBytesImplementation(size); -#endif -} - -//----------------------------------------------------------------------------- -/** - overload for global operator delete (MFC debug version); send requests to TheDynamicMemoryAllocator. -*/ -void operator delete(void * p, const char *, int) -{ - ++theLinkTester; - preMainInitMemoryManager(); - DEBUG_ASSERTCRASH(TheDynamicMemoryAllocator != NULL, ("must init memory manager before calling global operator delete")); - TheDynamicMemoryAllocator->freeBytes(p); -} - -//----------------------------------------------------------------------------- -/** - overload for global operator new (MFC debug version); send requests to TheDynamicMemoryAllocator. -*/ -void* operator new[](size_t size, const char * fname, int) -{ - ++theLinkTester; - preMainInitMemoryManager(); - DEBUG_ASSERTCRASH(TheDynamicMemoryAllocator != NULL, ("must init memory manager before calling global operator new")); -#ifdef MEMORYPOOL_DEBUG - return TheDynamicMemoryAllocator->allocateBytesImplementation(size, fname); -#else - return TheDynamicMemoryAllocator->allocateBytesImplementation(size); -#endif -} - -//----------------------------------------------------------------------------- -/** - overload for global operator delete (MFC debug version); send requests to TheDynamicMemoryAllocator. -*/ -void operator delete[](void * p, const char *, int) -{ - ++theLinkTester; - preMainInitMemoryManager(); - DEBUG_ASSERTCRASH(TheDynamicMemoryAllocator != NULL, ("must init memory manager before calling global operator delete")); - TheDynamicMemoryAllocator->freeBytes(p); -} - -//----------------------------------------------------------------------------- -#ifdef MEMORYPOOL_OVERRIDE_MALLOC -void *calloc(size_t a, size_t b) -{ - ++theLinkTester; - preMainInitMemoryManager(); - DEBUG_ASSERTCRASH(TheDynamicMemoryAllocator != NULL, ("must init memory manager")); - return TheDynamicMemoryAllocator->allocateBytes(a * b, "calloc"); -} -#endif - -//----------------------------------------------------------------------------- -#ifdef MEMORYPOOL_OVERRIDE_MALLOC -void free(void * p) -{ - ++theLinkTester; - preMainInitMemoryManager(); - DEBUG_ASSERTCRASH(TheDynamicMemoryAllocator != NULL, ("must init memory manager")); - TheDynamicMemoryAllocator->freeBytes(p); -} -#endif - -//----------------------------------------------------------------------------- -#ifdef MEMORYPOOL_OVERRIDE_MALLOC -void *malloc(size_t a) -{ - ++theLinkTester; - preMainInitMemoryManager(); - DEBUG_ASSERTCRASH(TheDynamicMemoryAllocator != NULL, ("must init memory manager")); - return TheDynamicMemoryAllocator->allocateBytesDoNotZero(a, "malloc"); -} -#endif - -//----------------------------------------------------------------------------- -#ifdef MEMORYPOOL_OVERRIDE_MALLOC -void *realloc(void *p, size_t s) -{ - DEBUG_CRASH(("realloc is evil. do not call it.")); - throw ERROR_OUT_OF_MEMORY; -} -#endif - -//----------------------------------------------------------------------------- -/** - Initialize the memory manager, and create TheMemoryPoolFactory and TheDynamicMemoryAllocator. -*/ -void initMemoryManager() -{ - if (TheMemoryPoolFactory == NULL) - { - Int numSubPools; - const PoolInitRec *pParms; - userMemoryManagerGetDmaParms(&numSubPools, &pParms); - TheMemoryPoolFactory = new (::sysAllocateDoNotZero(sizeof(MemoryPoolFactory))) MemoryPoolFactory; // will throw on failure - TheMemoryPoolFactory->init(); // will throw on failure - TheDynamicMemoryAllocator = TheMemoryPoolFactory->createDynamicMemoryAllocator(numSubPools, pParms); // will throw on failure - userMemoryManagerInitPools(); - thePreMainInitFlag = false; - - DEBUG_INIT(DEBUG_FLAGS_DEFAULT); - DEBUG_LOG(("*** Initialized the Memory Manager")); - } - else - { - if (thePreMainInitFlag) - { - // quietly ignore the call - } - else - { - DEBUG_CRASH(("Memory Manager is already initialized")); - } - } - - char* linktest; - - theLinkTester = 0; - - linktest = new char; - delete linktest; - - linktest = new char[8]; - delete [] linktest; - - linktest = new char('\0'); - delete linktest; - -#ifdef MEMORYPOOL_OVERRIDE_MALLOC - linktest = (char*)malloc(1); - free(linktest); - - linktest = (char*)calloc(1,1); - free(linktest); -#endif - -#ifdef MEMORYPOOL_OVERRIDE_MALLOC - if (theLinkTester != 10) -#else - if (theLinkTester != 6) -#endif - { - DEBUG_CRASH(("Wrong operator new/delete linked in! Fix this...")); - } - - theMainInitFlag = true; - -} - -//----------------------------------------------------------------------------- -Bool isMemoryManagerOfficiallyInited() -{ - return theMainInitFlag; -} - -//----------------------------------------------------------------------------- -/** - Initialize the memory manager, and create TheMemoryPoolFactory and TheDynamicMemoryAllocator. - This is only called if memory is allocated prior to the normal call to initMemoryManager - (generally via a static C++ ctor). -*/ -static void preMainInitMemoryManager() -{ - if (TheMemoryPoolFactory == NULL) - { - - Int numSubPools; - const PoolInitRec *pParms; - userMemoryManagerGetDmaParms(&numSubPools, &pParms); - TheMemoryPoolFactory = new (::sysAllocateDoNotZero(sizeof(MemoryPoolFactory))) MemoryPoolFactory; // will throw on failure - TheMemoryPoolFactory->init(); // will throw on failure - - TheDynamicMemoryAllocator = TheMemoryPoolFactory->createDynamicMemoryAllocator(numSubPools, pParms); // will throw on failure - userMemoryManagerInitPools(); - thePreMainInitFlag = true; - - DEBUG_INIT(DEBUG_FLAGS_DEFAULT); - DEBUG_LOG(("*** Initialized the Memory Manager prior to main!")); - } -} - -//----------------------------------------------------------------------------- -/** - shutdown the memory manager and discard all memory. Note: if preMainInitMemoryManager() - was called prior to initMemoryManager(), this call will do nothing. -*/ -void shutdownMemoryManager() -{ - if (thePreMainInitFlag) - { - #ifdef MEMORYPOOL_DEBUG - DEBUG_LOG(("*** Memory Manager was inited prior to main -- skipping shutdown!")); - #endif - } - else - { - if (TheDynamicMemoryAllocator) - { - DEBUG_ASSERTCRASH(TheMemoryPoolFactory, ("hmm, no factory")); - if (TheMemoryPoolFactory) - TheMemoryPoolFactory->destroyDynamicMemoryAllocator(TheDynamicMemoryAllocator); - TheDynamicMemoryAllocator = NULL; - } - - if (TheMemoryPoolFactory) - { - // this is evil... since there is no 'placement delete' we must do this the hard way - // and call the dtor directly. ordinarily this is heinous, but in this case we'll - // make an exception. - TheMemoryPoolFactory->~MemoryPoolFactory(); - ::sysFree((void *)TheMemoryPoolFactory); - TheMemoryPoolFactory = NULL; - } - - #ifdef MEMORYPOOL_DEBUG - DEBUG_LOG(("Peak system allocation was %d bytes",thePeakSystemAllocationInBytes)); - DEBUG_LOG(("Wasted DMA space (peak) was %d bytes",thePeakWastedDMA)); - DEBUG_ASSERTCRASH(theTotalSystemAllocationInBytes == 0, ("Leaked a total of %d raw bytes", theTotalSystemAllocationInBytes)); - #endif - } - - theMainInitFlag = false; - - DEBUG_SHUTDOWN(); -} - -//----------------------------------------------------------------------------- -void* createW3DMemPool(const char *poolName, int allocationSize) -{ - ++theLinkTester; - preMainInitMemoryManager(); - MemoryPool* pool = TheMemoryPoolFactory->createMemoryPool(poolName, allocationSize, 0, 0); - DEBUG_ASSERTCRASH(pool && pool->getAllocationSize() == allocationSize, ("bad w3d pool")); - return pool; -} - -//----------------------------------------------------------------------------- -void* allocateFromW3DMemPool(void* pool, int allocationSize) -{ - DEBUG_ASSERTCRASH(pool, ("pool is null")); - DEBUG_ASSERTCRASH(pool && ((MemoryPool*)pool)->getAllocationSize() == allocationSize, ("bad w3d pool size %s",((MemoryPool*)pool)->getPoolName())); - return ((MemoryPool*)pool)->allocateBlock("allocateFromW3DMemPool"); -} - -//----------------------------------------------------------------------------- -void* allocateFromW3DMemPool(void* pool, int allocationSize, const char* msg, int unused) -{ - DEBUG_ASSERTCRASH(pool, ("pool is null")); - DEBUG_ASSERTCRASH(pool && ((MemoryPool*)pool)->getAllocationSize() == allocationSize, ("bad w3d pool size %s",((MemoryPool*)pool)->getPoolName())); - return ((MemoryPool*)pool)->allocateBlock(msg); -} - -//----------------------------------------------------------------------------- -void freeFromW3DMemPool(void* pool, void* p) -{ - DEBUG_ASSERTCRASH(pool, ("pool is null")); - ((MemoryPool*)pool)->freeBlock(p); -} diff --git a/Generals/Code/GameEngine/Source/Common/System/MemoryInit.cpp b/Generals/Code/GameEngine/Source/Common/System/MemoryInit.cpp deleted file mode 100644 index 5bb04a9d78e..00000000000 --- a/Generals/Code/GameEngine/Source/Common/System/MemoryInit.cpp +++ /dev/null @@ -1,154 +0,0 @@ -/* -** Command & Conquer Generals(tm) -** Copyright 2025 Electronic Arts Inc. -** -** This program is free software: you can redistribute it and/or modify -** it under the terms of the GNU General Public License as published by -** the Free Software Foundation, either version 3 of the License, or -** (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program. If not, see . -*/ - -//////////////////////////////////////////////////////////////////////////////// -// // -// (c) 2001-2003 Electronic Arts Inc. // -// // -//////////////////////////////////////////////////////////////////////////////// - -// FILE: MemoryInit.cpp -//----------------------------------------------------------------------------- -// -// Westwood Studios Pacific. -// -// Confidential Information -// Copyright (C) 2001 - All Rights Reserved -// -//----------------------------------------------------------------------------- -// -// Project: RTS3 -// -// File name: MemoryInit.cpp -// -// Created: Steven Johnson, August 2001 -// -// Desc: Memory manager -// -// ---------------------------------------------------------------------------- -#include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine - -// SYSTEM INCLUDES - -// USER INCLUDES -#include "Lib/BaseType.h" -#include "Common/GameMemory.h" - -struct PoolSizeRec -{ - const char* name; - Int initial; - Int overflow; -}; - -#if RTS_GENERALS -#include "GameMemoryInitDMA_Generals.inl" -#include "GameMemoryInitPools_Generals.inl" -#elif RTS_ZEROHOUR -#include "GameMemoryInitDMA_GeneralsMD.inl" -#include "GameMemoryInitPools_GeneralsMD.inl" -#endif - -//----------------------------------------------------------------------------- -void userMemoryManagerGetDmaParms(Int *numSubPools, const PoolInitRec **pParms) -{ - *numSubPools = ARRAY_SIZE(DefaultDMA); - *pParms = DefaultDMA; -} - -//----------------------------------------------------------------------------- -void userMemoryAdjustPoolSize(const char *poolName, Int& initialAllocationCount, Int& overflowAllocationCount) -{ - if (initialAllocationCount > 0) - return; - - for (const PoolSizeRec* p = PoolSizes; p->name != NULL; ++p) - { - if (strcmp(p->name, poolName) == 0) - { - initialAllocationCount = p->initial; - overflowAllocationCount = p->overflow; - return; - } - } - - DEBUG_CRASH(("Initial size for pool %s not found -- you should add it to MemoryInit.cpp",poolName)); -} - -//----------------------------------------------------------------------------- -static Int roundUpMemBound(Int i) -{ - const int MEM_BOUND_ALIGNMENT = 4; - - if (i < MEM_BOUND_ALIGNMENT) - return MEM_BOUND_ALIGNMENT; - else - return (i + (MEM_BOUND_ALIGNMENT-1)) & ~(MEM_BOUND_ALIGNMENT-1); -} - -//----------------------------------------------------------------------------- -void userMemoryManagerInitPools() -{ - // note that we MUST use stdio stuff here, and not the normal game file system - // (with bigfile support, etc), because that relies on memory pools, which - // aren't yet initialized properly! so rely ONLY on straight stdio stuff here. - // (not even AsciiString. thanks.) - - // since we're called prior to main, the cur dir might not be what - // we expect. so do it the hard way. - char buf[_MAX_PATH]; - ::GetModuleFileName(NULL, buf, sizeof(buf)); - char* pEnd = buf + strlen(buf); - while (pEnd != buf) - { - if (*pEnd == '\\') - { - *pEnd = 0; - break; - } - --pEnd; - } - strcat(buf, "\\Data\\INI\\MemoryPools.ini"); - - FILE* fp = fopen(buf, "r"); - if (fp) - { - char poolName[256]; - int initial, overflow; - while (fgets(buf, _MAX_PATH, fp)) - { - if (buf[0] == ';') - continue; - if (sscanf(buf, "%s %d %d", poolName, &initial, &overflow ) == 3) - { - for (PoolSizeRec* p = PoolSizes; p->name != NULL; ++p) - { - if (stricmp(p->name, poolName) == 0) - { - // currently, these must be multiples of 4. so round up. - p->initial = roundUpMemBound(initial); - p->overflow = roundUpMemBound(overflow); - break; // from for-p - } - } - } - } - fclose(fp); - } -} - diff --git a/GeneralsMD/Code/GameEngine/CMakeLists.txt b/GeneralsMD/Code/GameEngine/CMakeLists.txt index 81b96301dac..5546c7bc915 100644 --- a/GeneralsMD/Code/GameEngine/CMakeLists.txt +++ b/GeneralsMD/Code/GameEngine/CMakeLists.txt @@ -45,7 +45,7 @@ set(GAMEENGINE_SRC # Include/Common/GameDefines.h Include/Common/GameEngine.h Include/Common/GameLOD.h - Include/Common/GameMemory.h +# Include/Common/GameMemory.h # Include/Common/GameMusic.h # Include/Common/GameSounds.h Include/Common/GameSpyMiscPreferences.h @@ -1138,16 +1138,16 @@ set(GAMEENGINE_SRC if(RTS_GAMEMEMORY_ENABLE) # Uses the original Game Memory implementation. list(APPEND GAMEENGINE_SRC - Source/Common/System/GameMemory.cpp - Source/Common/System/GameMemoryInitDMA_GeneralsMD.inl - Source/Common/System/GameMemoryInitPools_GeneralsMD.inl - Source/Common/System/MemoryInit.cpp +# Source/Common/System/GameMemory.cpp +# Source/Common/System/GameMemoryInitDMA_GeneralsMD.inl +# Source/Common/System/GameMemoryInitPools_GeneralsMD.inl +# Source/Common/System/MemoryInit.cpp ) else() # Uses the null implementation when disabled. list(APPEND GAMEENGINE_SRC - Source/Common/System/GameMemoryNull.cpp - Include/Common/GameMemoryNull.h +# Source/Common/System/GameMemoryNull.cpp +# Include/Common/GameMemoryNull.h ) endif() diff --git a/GeneralsMD/Code/GameEngine/Include/Common/GameMemoryNull.h b/GeneralsMD/Code/GameEngine/Include/Common/GameMemoryNull.h deleted file mode 100644 index bf0ee87bc3d..00000000000 --- a/GeneralsMD/Code/GameEngine/Include/Common/GameMemoryNull.h +++ /dev/null @@ -1,165 +0,0 @@ -/* -** Command & Conquer Generals Zero Hour(tm) -** Copyright 2025 TheSuperHackers -** -** This program is free software: you can redistribute it and/or modify -** it under the terms of the GNU General Public License as published by -** the Free Software Foundation, either version 3 of the License, or -** (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program. If not, see . -*/ - -#pragma once - -#define allocateBytes(ARGCOUNT,ARGLITERAL) allocateBytesImplementation(ARGCOUNT) -#define allocateBytesDoNotZero(ARGCOUNT,ARGLITERAL) allocateBytesDoNotZeroImplementation(ARGCOUNT) -#define newInstanceDesc(ARGCLASS,ARGLITERAL) new ARGCLASS -#define newInstance(ARGCLASS) new ARGCLASS -#define MSGNEW(MSG) new -#define NEW new - - -/** - The DynamicMemoryAllocator class is used to handle unpredictably-sized - allocation requests. -*/ -class DynamicMemoryAllocator -{ -public: - - /// allocate bytes from this pool. (don't call directly; use allocateBytes() macro) - void *allocateBytesImplementation(Int numBytes); - - /// like allocateBytesImplementation, but zeroes the memory before returning - void *allocateBytesDoNotZeroImplementation(Int numBytes); - -#ifdef MEMORYPOOL_DEBUG - void debugIgnoreLeaksForThisBlock(void* pBlockPtr); -#endif - - /// free the bytes. (assumes allocated by this dma.) - void freeBytes(void* pMem); - - /** - return the actual number of bytes that would be allocated - if you tried to allocate the given size. - */ - Int getActualAllocationSize(Int numBytes); -}; - - -/** - The class that manages all the MemoryPools and DynamicMemoryAllocators. - Usually you will create exactly one of these (TheMemoryPoolFactory) - and use it for everything. -*/ -class MemoryPoolFactory -{ -public: - - void memoryPoolUsageReport( const char* filename, FILE *appendToFileInstead = NULL ); - -#ifdef MEMORYPOOL_DEBUG - - void debugMemoryReport(Int flags, Int startCheckpoint, Int endCheckpoint, FILE *fp = NULL ); - void debugSetInitFillerIndex(Int index); - -#endif -}; - - -#define MEMORY_POOL_GLUE_WITHOUT_GCMP(ARGCLASS) \ -protected: \ - virtual ~ARGCLASS(); \ -public: /* include this line at the end to reset visibility to 'public' */ - - -#define MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE(ARGCLASS, ARGPOOLNAME) \ - MEMORY_POOL_GLUE_WITHOUT_GCMP(ARGCLASS) - - -// this is the version for an Abstract Base Class, which will never be instantiated... -#define MEMORY_POOL_GLUE_ABC(ARGCLASS) \ -protected: \ - virtual ~ARGCLASS(); \ -public: /* include this line at the end to reset visibility to 'public' */ - - -/** - This class is provided as a simple and safe way to integrate C++ object allocation - into MemoryPool usage. To use it, you must have your class inherit from - MemoryPoolObject, then put the macro MEMORY_POOL_GLUE(MyClassName, "MyPoolName") - at the start of your class definition. (This does not create the pool itself -- you - must create that manually using MemoryPoolFactory::createMemoryPool) -*/ -class MemoryPoolObject -{ -protected: - - /** ensure that all destructors are virtual */ - virtual ~MemoryPoolObject() { } - -public: - - static void deleteInstanceInternal(MemoryPoolObject* mpo) - { - delete mpo; - } -}; - -inline void deleteInstance(MemoryPoolObject* mpo) -{ - MemoryPoolObject::deleteInstanceInternal(mpo); -} - - -/** - Initialize the memory manager. Construct a new MemoryPoolFactory and - DynamicMemoryAllocator and store 'em in the singletons of the relevant - names. -*/ -extern void initMemoryManager(); - -/** - return true if initMemoryManager() has been called. - return false if only preMainInitMemoryManager() has been called. -*/ -extern Bool isMemoryManagerOfficiallyInited(); - -/** - Shut down the memory manager. Throw away TheMemoryPoolFactory and - TheDynamicMemoryAllocator. -*/ -extern void shutdownMemoryManager(); - -extern MemoryPoolFactory *TheMemoryPoolFactory; -extern DynamicMemoryAllocator *TheDynamicMemoryAllocator; - - -// TheSuperHackers @info -// The new operator overloads will zero all memory after allocation. -// This replicates the behavior of the original Game Memory implementation and is necessary to avoid crashing the game, -// where data is not properly zero initialized. Disable these operators when fixing those issues. -#ifndef DISABLE_GAMEMEMORY_NEW_OPERATORS - -extern void * __cdecl operator new(size_t size); -extern void __cdecl operator delete(void *p); - -extern void * __cdecl operator new[](size_t size); -extern void __cdecl operator delete[](void *p); - -// additional overloads to account for VC/MFC funky versions -extern void* __cdecl operator new(size_t size, const char *, int); -extern void __cdecl operator delete(void *p, const char *, int); - -extern void* __cdecl operator new[](size_t size, const char *, int); -extern void __cdecl operator delete[](void *p, const char *, int); - -#endif diff --git a/GeneralsMD/Code/GameEngine/Source/Common/System/GameMemoryNull.cpp b/GeneralsMD/Code/GameEngine/Source/Common/System/GameMemoryNull.cpp deleted file mode 100644 index 8520a77de9b..00000000000 --- a/GeneralsMD/Code/GameEngine/Source/Common/System/GameMemoryNull.cpp +++ /dev/null @@ -1,218 +0,0 @@ -/* -** Command & Conquer Generals Zero Hour(tm) -** Copyright 2025 TheSuperHackers -** -** This program is free software: you can redistribute it and/or modify -** it under the terms of the GNU General Public License as published by -** the Free Software Foundation, either version 3 of the License, or -** (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program. If not, see . -*/ - -#include "PreRTS.h" - -#include - -#include "Common/GameMemoryNull.h" - -static Bool theMainInitFlag = false; - -// ---------------------------------------------------------------------------- -// PUBLIC DATA -// ---------------------------------------------------------------------------- - -MemoryPoolFactory *TheMemoryPoolFactory = NULL; -DynamicMemoryAllocator *TheDynamicMemoryAllocator = NULL; - -//----------------------------------------------------------------------------- -// METHODS for DynamicMemoryAllocator -//----------------------------------------------------------------------------- - -/** - allocate a chunk-o-bytes from this DMA and return it, but don't bother zeroing - out the block. if unable to allocate, throw ERROR_OUT_OF_MEMORY. this - function will never return null. - - added code to make sure we're on a DWord boundary, throw exception if not -*/ -void *DynamicMemoryAllocator::allocateBytesDoNotZeroImplementation(Int numBytes) -{ - void *p = malloc(numBytes); - if (p == NULL) - throw ERROR_OUT_OF_MEMORY; - return p; -} - -/** - allocate a chunk-o-bytes from this DMA and return it, and zero out the contents first. - if unable to allocate, throw ERROR_OUT_OF_MEMORY. - this function will never return null. -*/ -void *DynamicMemoryAllocator::allocateBytesImplementation(Int numBytes) -{ - void* p = allocateBytesDoNotZeroImplementation(numBytes); // throws on failure - memset(p, 0, numBytes); - return p; -} - -/** - free a chunk-o-bytes allocated by this dma. it's ok to pass null. -*/ -void DynamicMemoryAllocator::freeBytes(void* pBlockPtr) -{ - free(pBlockPtr); -} - -Int DynamicMemoryAllocator::getActualAllocationSize(Int numBytes) -{ - return numBytes; -} - -#ifdef MEMORYPOOL_DEBUG -void DynamicMemoryAllocator::debugIgnoreLeaksForThisBlock(void* pBlockPtr) -{ -} -#endif - -//----------------------------------------------------------------------------- -// METHODS for MemoryPoolFactory -//----------------------------------------------------------------------------- - -void MemoryPoolFactory::memoryPoolUsageReport( const char* filename, FILE *appendToFileInstead ) -{ -} - -#ifdef MEMORYPOOL_DEBUG -void MemoryPoolFactory::debugMemoryReport(Int flags, Int startCheckpoint, Int endCheckpoint, FILE *fp ) -{ -} -void MemoryPoolFactory::debugSetInitFillerIndex(Int index) -{ -} -#endif - -//----------------------------------------------------------------------------- -// GLOBAL FUNCTIONS -//----------------------------------------------------------------------------- - -/** - Initialize the memory manager, and create TheMemoryPoolFactory and TheDynamicMemoryAllocator. -*/ -void initMemoryManager() -{ - if (TheMemoryPoolFactory == NULL && TheDynamicMemoryAllocator == NULL) - { - TheMemoryPoolFactory = new (malloc(sizeof MemoryPoolFactory)) MemoryPoolFactory; - TheDynamicMemoryAllocator = new (malloc(sizeof DynamicMemoryAllocator)) DynamicMemoryAllocator; - - DEBUG_INIT(DEBUG_FLAGS_DEFAULT); - DEBUG_LOG(("*** Initialized the Null Memory Manager")); - } - else - { - DEBUG_CRASH(("Null Memory Manager is already initialized")); - } - - theMainInitFlag = true; -} - -//----------------------------------------------------------------------------- -Bool isMemoryManagerOfficiallyInited() -{ - return theMainInitFlag; -} - -//----------------------------------------------------------------------------- -/** - shutdown the memory manager and discard all memory. Note: if preMainInitMemoryManager() - was called prior to initMemoryManager(), this call will do nothing. -*/ -void shutdownMemoryManager() -{ - if (TheDynamicMemoryAllocator != NULL) - { - TheDynamicMemoryAllocator->~DynamicMemoryAllocator(); - free((void *)TheDynamicMemoryAllocator); - TheDynamicMemoryAllocator = NULL; - } - - if (TheMemoryPoolFactory != NULL) - { - TheMemoryPoolFactory->~MemoryPoolFactory(); - free((void *)TheMemoryPoolFactory); - TheMemoryPoolFactory = NULL; - } - - theMainInitFlag = false; - - DEBUG_SHUTDOWN(); -} - - -#ifndef DISABLE_GAMEMEMORY_NEW_OPERATORS - -extern void * __cdecl operator new(size_t size) -{ - void *p = malloc(size); - if (p == NULL) - throw ERROR_OUT_OF_MEMORY; - memset(p, 0, size); - return p; -} - -extern void __cdecl operator delete(void *p) -{ - free(p); -} - -extern void * __cdecl operator new[](size_t size) -{ - void *p = malloc(size); - if (p == NULL) - throw ERROR_OUT_OF_MEMORY; - memset(p, 0, size); - return p; -} - -extern void __cdecl operator delete[](void *p) -{ - free(p); -} - -// additional overloads to account for VC/MFC funky versions -extern void* __cdecl operator new(size_t size, const char *, int) -{ - void *p = malloc(size); - if (p == NULL) - throw ERROR_OUT_OF_MEMORY; - memset(p, 0, size); - return p; -} - -extern void __cdecl operator delete(void *p, const char *, int) -{ - free(p); -} - -extern void* __cdecl operator new[](size_t size, const char *, int) -{ - void *p = malloc(size); - if (p == NULL) - throw ERROR_OUT_OF_MEMORY; - memset(p, 0, size); - return p; -} - -extern void __cdecl operator delete[](void *p, const char *, int) -{ - free(p); -} - -#endif diff --git a/scripts/cpp/unify_move_files.py b/scripts/cpp/unify_move_files.py index 9d34e5fb985..d43aa334965 100644 --- a/scripts/cpp/unify_move_files.py +++ b/scripts/cpp/unify_move_files.py @@ -156,6 +156,16 @@ def main(): #unify_move_file(Game.ZEROHOUR, "GameEngineDevice/Source/VideoDevice/FFmpeg/FFmpegFile.cpp", Game.CORE, "GameEngineDevice/Source/VideoDevice/FFmpeg/FFmpegFile.cpp") #unify_move_file(Game.ZEROHOUR, "GameEngineDevice/Source/VideoDevice/FFmpeg/FFmpegVideoPlayer.cpp", Game.CORE, "GameEngineDevice/Source/VideoDevice/FFmpeg/FFmpegVideoPlayer.cpp") + #unify_file(Game.ZEROHOUR, "GameEngine/Include/Common/GameMemory.h", Game.CORE, "GameEngine/Include/Common/GameMemory.h") + #unify_file(Game.ZEROHOUR, "GameEngine/Include/Common/GameMemoryNull.h", Game.CORE, "GameEngine/Include/Common/GameMemoryNull.h") + #unify_file(Game.ZEROHOUR, "GameEngine/Source/Common/System/GameMemory.cpp", Game.CORE, "GameEngine/Source/Common/System/GameMemory.cpp") + #unify_file(Game.ZEROHOUR, "GameEngine/Source/Common/System/GameMemoryNull.cpp", Game.CORE, "GameEngine/Source/Common/System/GameMemoryNull.cpp") + #unify_file(Game.ZEROHOUR, "GameEngine/Source/Common/System/MemoryInit.cpp", Game.CORE, "GameEngine/Source/Common/System/GameMemoryInit.cpp") + #unify_move_file(Game.GENERALS, "GameEngine/Source/Common/System/GameMemoryInitDMA_Generals.inl", Game.CORE, "GameEngine/Source/Common/System/GameMemoryInitDMA_Generals.inl") + #unify_move_file(Game.ZEROHOUR, "GameEngine/Source/Common/System/GameMemoryInitDMA_GeneralsMD.inl", Game.CORE, "GameEngine/Source/Common/System/GameMemoryInitDMA_GeneralsMD.inl") + #unify_move_file(Game.GENERALS, "GameEngine/Source/Common/System/GameMemoryInitPools_Generals.inl", Game.CORE, "GameEngine/Source/Common/System/GameMemoryInitPools_Generals.inl") + #unify_move_file(Game.ZEROHOUR, "GameEngine/Source/Common/System/GameMemoryInitPools_GeneralsMD.inl", Game.CORE, "GameEngine/Source/Common/System/GameMemoryInitPools_GeneralsMD.inl") + return