summaryrefslogtreecommitdiffstats
path: root/src/core
diff options
context:
space:
mode:
Diffstat (limited to 'src/core')
-rw-r--r--src/core/CdStream.cpp1
-rw-r--r--src/core/CdStreamPosix.cpp2
-rw-r--r--src/core/FileLoader.cpp11
-rw-r--r--src/core/Game.cpp111
-rw-r--r--src/core/Pools.cpp19
-rw-r--r--src/core/Streaming.cpp42
-rw-r--r--src/core/World.cpp3
-rw-r--r--src/core/main.cpp329
-rw-r--r--src/core/templates.h16
9 files changed, 407 insertions, 127 deletions
diff --git a/src/core/CdStream.cpp b/src/core/CdStream.cpp
index 1d39aa52..f987dea5 100644
--- a/src/core/CdStream.cpp
+++ b/src/core/CdStream.cpp
@@ -5,6 +5,7 @@
#include "CdStream.h"
#include "rwcore.h"
#include "RwHelper.h"
+#include "MemoryMgr.h"
#define CDDEBUG(f, ...) debug ("%s: " f "\n", "cdvd_stream", ## __VA_ARGS__)
#define CDTRACE(f, ...) printf("%s: " f "\n", "cdvd_stream", ## __VA_ARGS__)
diff --git a/src/core/CdStreamPosix.cpp b/src/core/CdStreamPosix.cpp
index 35a90a74..0854d850 100644
--- a/src/core/CdStreamPosix.cpp
+++ b/src/core/CdStreamPosix.cpp
@@ -16,7 +16,7 @@
#include "CdStream.h"
#include "rwcore.h"
-#include "RwHelper.h"
+#include "MemoryMgr.h"
#define CDDEBUG(f, ...) debug ("%s: " f "\n", "cdvd_stream", ## __VA_ARGS__)
#define CDTRACE(f, ...) printf("%s: " f "\n", "cdvd_stream", ## __VA_ARGS__)
diff --git a/src/core/FileLoader.cpp b/src/core/FileLoader.cpp
index f46b6134..88a99fa9 100644
--- a/src/core/FileLoader.cpp
+++ b/src/core/FileLoader.cpp
@@ -24,6 +24,7 @@
#include "ZoneCull.h"
#include "CdStream.h"
#include "FileLoader.h"
+#include "MemoryHeap.h"
char CFileLoader::ms_line[256];
@@ -71,11 +72,13 @@ CFileLoader::LoadLevel(const char *filename)
if(strncmp(line, "IMAGEPATH", 9) == 0){
RwImageSetPath(line + 10);
}else if(strncmp(line, "TEXDICTION", 10) == 0){
+ PUSH_MEMID(MEMID_TEXTURES);
strcpy(txdname, line+11);
LoadingScreenLoadingFile(txdname);
RwTexDictionary *txd = LoadTexDictionary(txdname);
AddTexDictionaries(savedTxd, txd);
RwTexDictionaryDestroy(txd);
+ POP_MEMID();
}else if(strncmp(line, "COLFILE", 7) == 0){
int level;
sscanf(line+8, "%d", &level);
@@ -94,12 +97,16 @@ CFileLoader::LoadLevel(const char *filename)
LoadObjectTypes(line + 4);
}else if(strncmp(line, "IPL", 3) == 0){
if(!objectsLoaded){
+ PUSH_MEMID(MEMID_DEF_MODELS);
CModelInfo::ConstructMloClumps();
+ POP_MEMID();
CObjectData::Initialise("DATA\\OBJECT.DAT");
objectsLoaded = true;
}
+ PUSH_MEMID(MEMID_WORLD);
LoadingScreenLoadingFile(line + 4);
LoadScene(line + 4);
+ POP_MEMID();
}else if(strncmp(line, "MAPZONE", 7) == 0){
LoadingScreenLoadingFile(line + 8);
LoadMapZones(line + 8);
@@ -188,6 +195,8 @@ CFileLoader::LoadCollisionFile(const char *filename)
CBaseModelInfo *mi;
ColHeader header;
+ PUSH_MEMID(MEMID_COLLISION);
+
debug("Loading collision file %s\n", filename);
fd = CFileMgr::OpenFile(filename, "rb");
@@ -211,6 +220,8 @@ CFileLoader::LoadCollisionFile(const char *filename)
}
CFileMgr::CloseFile(fd);
+
+ POP_MEMID();
}
void
diff --git a/src/core/Game.cpp b/src/core/Game.cpp
index 1283ecd1..d22a7184 100644
--- a/src/core/Game.cpp
+++ b/src/core/Game.cpp
@@ -90,6 +90,7 @@
#include "custompipes.h"
#include "screendroplets.h"
#include "crossplatform.h"
+#include "MemoryHeap.h"
eLevelName CGame::currLevel;
bool CGame::bDemoMode = true;
@@ -327,21 +328,35 @@ CGame::FinalShutdown(void)
bool CGame::Initialise(const char* datFile)
{
+#ifdef GTA_PS2
+ // TODO: upload VU0 collision code here
+#else
ResetLoadingScreenBar();
strcpy(aDatFile, datFile);
- CPools::Initialise();
+ CPools::Initialise(); // done in CWorld on PS2
CIniFile::LoadIniFile();
+#endif
+
currLevel = LEVEL_INDUSTRIAL;
+
+ PUSH_MEMID(MEMID_TEXTURES);
LoadingScreen("Loading the Game", "Loading generic textures", GetRandomSplashScreen());
gameTxdSlot = CTxdStore::AddTxdSlot("generic");
CTxdStore::Create(gameTxdSlot);
CTxdStore::AddRef(gameTxdSlot);
+
LoadingScreen("Loading the Game", "Loading particles", nil);
int particleTxdSlot = CTxdStore::AddTxdSlot("particle");
CTxdStore::LoadTxd(particleTxdSlot, "MODELS/PARTICLE.TXD");
CTxdStore::AddRef(particleTxdSlot);
CTxdStore::SetCurrentTxd(gameTxdSlot);
LoadingScreen("Loading the Game", "Setup game variables", nil);
+ POP_MEMID();
+
+#ifdef GTA_PS2
+ CDma::SyncChannel(0, true);
+#endif
+
CGameLogic::InitAtStartOfGame();
CReferences::Init();
TheCamera.Init();
@@ -361,20 +376,41 @@ bool CGame::Initialise(const char* datFile)
CMessages::ClearAllMessagesDisplayedByGame();
CRecordDataForGame::Init();
CRestart::Initialise();
+
+ PUSH_MEMID(MEMID_WORLD);
CWorld::Initialise();
+ POP_MEMID();
+
+ PUSH_MEMID(MEMID_TEXTURES);
CParticle::Initialise();
-#ifdef PS2
+ POP_MEMID();
+
+#ifdef GTA_PS2
gStartX = -180.0f;
gStartY = 180.0f;
gStartZ = 14.0f;
#endif
+
+ PUSH_MEMID(MEMID_ANIMATION);
CAnimManager::Initialise();
CCutsceneMgr::Initialise();
+ POP_MEMID();
+
+ PUSH_MEMID(MEMID_CARS);
CCarCtrl::Init();
+ POP_MEMID();
+
+#ifndef GTA_PS2
InitModelIndices();
+#endif
+
+ PUSH_MEMID(MEMID_DEF_MODELS);
CModelInfo::Initialise();
+#ifndef GTA_PS2
+ // probably moved before LoadLevel for multiplayer maps?
CPickups::Init();
CTheCarGenerators::Init();
+#endif
CdStreamAddImage("MODELS\\GTA3.IMG");
CFileLoader::LoadLevel("DATA\\DEFAULT.DAT");
CFileLoader::LoadLevel(datFile);
@@ -386,17 +422,23 @@ bool CGame::Initialise(const char* datFile)
CVehicleModelInfo::LoadVehicleColours();
CVehicleModelInfo::LoadEnvironmentMaps();
CTheZones::PostZoneCreation();
+ POP_MEMID();
+
LoadingScreen("Loading the Game", "Setup paths", GetRandomSplashScreen());
ThePaths.PreparePathData();
+ // done elsewhere on PS2
for (int i = 0; i < NUMPLAYERS; i++)
CWorld::Players[i].Clear();
CWorld::Players[0].LoadPlayerSkin();
TestModelIndices();
+ //
+
LoadingScreen("Loading the Game", "Setup water", nil);
CWaterLevel::Initialise("DATA\\WATER.DAT");
TheConsole.Init();
CDraw::SetFOV(120.0f);
CDraw::ms_fLODDistance = 500.0f;
+
LoadingScreen("Loading the Game", "Setup streaming", nil);
CStreaming::Init();
CStreaming::LoadInitialVehicles();
@@ -404,8 +446,12 @@ bool CGame::Initialise(const char* datFile)
CStreaming::RequestBigBuildings(LEVEL_GENERIC);
CStreaming::LoadAllRequestedModels(false);
printf("Streaming uses %zuK of its memory", CStreaming::ms_memoryUsed / 1024); // original modifier was %d
+
LoadingScreen("Loading the Game", "Load animations", GetRandomSplashScreen());
+ PUSH_MEMID(MEMID_ANIMATION);
CAnimManager::LoadAnimFiles();
+ POP_MEMID();
+
CPed::Initialise();
CRouteNode::Initialise();
CEventList::Initialise();
@@ -414,13 +460,16 @@ bool CGame::Initialise(const char* datFile)
#endif
LoadingScreen("Loading the Game", "Find big buildings", nil);
CRenderer::Init();
+
LoadingScreen("Loading the Game", "Setup game variables", nil);
CRadar::Initialise();
CRadar::LoadTextures();
CWeapon::InitialiseWeapons();
+
LoadingScreen("Loading the Game", "Setup traffic lights", nil);
CTrafficLights::ScanForLightsOnMap();
CRoadBlocks::Init();
+
LoadingScreen("Loading the Game", "Setup game variables", nil);
CPopulation::Initialise();
CWorld::PlayerInFocus = 0;
@@ -431,26 +480,48 @@ bool CGame::Initialise(const char* datFile)
CAntennas::Init();
CGlass::Init();
gPhoneInfo.Initialise();
+#ifndef GTA_PS2
CSceneEdit::Initialise();
+#endif
+
LoadingScreen("Loading the Game", "Load scripts", nil);
+ PUSH_MEMID(MEMID_SCRIPT);
CTheScripts::Init();
CGangs::Initialise();
+ POP_MEMID();
+
LoadingScreen("Loading the Game", "Setup game variables", nil);
+#ifdef GTA_PS2
+ CTimer::Initialise();
+#endif
CClock::Initialise(1000);
+#ifdef GTA_PS2
+ CTheCarGenerators::Init();
+#endif
CHeli::InitHelis();
CCranes::InitCranes();
CMovingThings::Init();
CDarkel::Init();
CStats::Init();
+#ifdef GTA_PS2
+ CPickups::Init();
+#endif
CPacManPickups::Init();
+ // CGarages::Init(); here on PS2 instead
CRubbish::Init();
CClouds::Init();
+#ifdef GTA_PS2
+ CRemote::Init();
+#endif
CSpecialFX::Init();
CWaterCannons::Init();
CBridge::Init();
CGarages::Init();
+
LoadingScreen("Loading the Game", "Position dynamic objects", nil);
CWorld::RepositionCertainDynamicObjects();
+ // CCullZones::ResolveVisibilities(); on PS2 here instead
+
LoadingScreen("Loading the Game", "Initialise vehicle paths", nil);
CCullZones::ResolveVisibilities();
CTrain::InitTrains();
@@ -458,6 +529,7 @@ bool CGame::Initialise(const char* datFile)
CCredits::Init();
CRecordDataForChase::Init();
CReplay::Init();
+
#ifdef PS2_MENU
if ( !TheMemoryCard.m_bWantToLoad )
{
@@ -469,6 +541,7 @@ bool CGame::Initialise(const char* datFile)
#ifdef PS2_MENU
}
#endif
+
LoadingScreen("Loading the Game", "Load scene", nil);
CModelInfo::RemoveColModelsFromOtherLevels(currLevel);
CCollision::ms_collisionInMemory = currLevel;
@@ -550,7 +623,7 @@ void CGame::ReInitGameObjectVariables(void)
CWorld::bDoingCarCollisions = false;
CHud::ReInitialise();
CRadar::Initialise();
-#ifdef PS2
+#ifdef GTA_PS2
gStartX = -180.0f;
gStartY = 180.0f;
gStartZ = 14.0f;
@@ -573,15 +646,19 @@ void CGame::ReInitGameObjectVariables(void)
CWorld::Players[i].Clear();
CWorld::PlayerInFocus = 0;
-#ifdef PS2
+#ifdef GTA_PS2
CWeaponEffects::Init();
CSkidmarks::Init();
#endif
CAntennas::Init();
CGlass::Init();
gPhoneInfo.Initialise();
+
+ PUSH_MEMID(MEMID_SCRIPT);
CTheScripts::Init();
CGangs::Initialise();
+ POP_MEMID();
+
CTimer::Initialise();
CClock::Initialise(1000);
CTheCarGenerators::Init();
@@ -592,7 +669,7 @@ void CGame::ReInitGameObjectVariables(void)
CPickups::Init();
CPacManPickups::Init();
CGarages::Init();
-#ifdef PS2
+#ifdef GTA_PS2
CClouds::Init();
CRemote::Init();
#endif
@@ -807,7 +884,7 @@ void CGame::InitialiseWhenRestarting(void)
void CGame::Process(void)
{
CPad::UpdatePads();
-#ifdef GTA_PS2
+#ifdef USE_CUSTOM_ALLOCATOR
ProcessTidyUpMemory();
#endif
TheCamera.SetMotionBlurAlpha(0);
@@ -817,8 +894,12 @@ void CGame::Process(void)
DebugMenuProcess();
#endif
CCutsceneMgr::Update();
+
+ PUSH_MEMID(MEMID_FRONTEND);
if (!CCutsceneMgr::IsCutsceneProcessing() && !CTimer::GetIsCodePaused())
FrontEndMenuManager.Process();
+ POP_MEMID();
+
CStreaming::Update();
if (!CTimer::GetIsPaused())
{
@@ -831,7 +912,11 @@ void CGame::Process(void)
CPad::DoCheats();
CClock::Update();
CWeather::Update();
+
+ PUSH_MEMID(MEMID_SCRIPT);
CTheScripts::Process();
+ POP_MEMID();
+
CCollision::Update();
CTrain::UpdateTrains();
CPlane::UpdatePlanes();
@@ -855,7 +940,11 @@ void CGame::Process(void)
CWaterCannons::Update();
CUserDisplay::Process();
CReplay::Update();
+
+ PUSH_MEMID(MEMID_WORLD);
CWorld::Process();
+ POP_MEMID();
+
gAccidentManager.Update();
CPacManPickups::Update();
CPickups::Update();
@@ -876,33 +965,35 @@ void CGame::Process(void)
gPhoneInfo.Update();
if (!CReplay::IsPlayingBack())
{
+ PUSH_MEMID(MEMID_CARS);
CCarCtrl::GenerateRandomCars();
CRoadBlocks::GenerateRoadBlocks();
CCarCtrl::RemoveDistantCars();
+ POP_MEMID();
}
}
-#ifdef PS2
+#ifdef GTA_PS2
CMemCheck::DoTest();
#endif
}
void CGame::DrasticTidyUpMemory(bool)
{
-#ifdef PS2
+#ifdef USE_CUSTOM_ALLOCATOR
// meow
#endif
}
void CGame::TidyUpMemory(bool, bool)
{
-#ifdef PS2
+#ifdef USE_CUSTOM_ALLOCATOR
// meow
#endif
}
void CGame::ProcessTidyUpMemory(void)
{
-#ifdef PS2
+#ifdef USE_CUSTOM_ALLOCATOR
// meow
#endif
}
diff --git a/src/core/Pools.cpp b/src/core/Pools.cpp
index bd0814d0..79841c14 100644
--- a/src/core/Pools.cpp
+++ b/src/core/Pools.cpp
@@ -12,6 +12,7 @@
#include "Streaming.h"
#include "Wanted.h"
#include "World.h"
+#include "MemoryHeap.h"
CCPtrNodePool *CPools::ms_pPtrNodePool;
CEntryInfoNodePool *CPools::ms_pEntryInfoNodePool;
@@ -23,18 +24,36 @@ CObjectPool *CPools::ms_pObjectPool;
CDummyPool *CPools::ms_pDummyPool;
CAudioScriptObjectPool *CPools::ms_pAudioScriptObjectPool;
+#ifdef GTA_PS2 // or USE_CUSTOM_ALLOCATOR
+#define CHECKMEM(msg) CMemCheck::AllocateMemCheckBlock(msg)
+#else
+#define CHECKMEM(msg)
+#endif
+
void
CPools::Initialise(void)
{
+ PUSH_MEMID(MEMID_POOLS);
+ CHECKMEM("before pools");
ms_pPtrNodePool = new CCPtrNodePool(NUMPTRNODES);
+ CHECKMEM("after CPtrNodePool");
ms_pEntryInfoNodePool = new CEntryInfoNodePool(NUMENTRYINFOS);
+ CHECKMEM("after CEntryInfoNodePool");
ms_pPedPool = new CPedPool(NUMPEDS);
+ CHECKMEM("after CPedPool");
ms_pVehiclePool = new CVehiclePool(NUMVEHICLES);
+ CHECKMEM("after CVehiclePool");
ms_pBuildingPool = new CBuildingPool(NUMBUILDINGS);
+ CHECKMEM("after CBuildingPool");
ms_pTreadablePool = new CTreadablePool(NUMTREADABLES);
+ CHECKMEM("after CTreadablePool");
ms_pObjectPool = new CObjectPool(NUMOBJECTS);
+ CHECKMEM("after CObjectPool");
ms_pDummyPool = new CDummyPool(NUMDUMMIES);
+ CHECKMEM("after CDummyPool");
ms_pAudioScriptObjectPool = new CAudioScriptObjectPool(NUMAUDIOSCRIPTOBJECTS);
+ CHECKMEM("after pools");
+ POP_MEMID();
}
void
diff --git a/src/core/Streaming.cpp b/src/core/Streaming.cpp
index 77d1773b..a28fe39d 100644
--- a/src/core/Streaming.cpp
+++ b/src/core/Streaming.cpp
@@ -34,6 +34,8 @@
#include "main.h"
#include "Frontend.h"
#include "Font.h"
+#include "MemoryMgr.h"
+#include "MemoryHeap.h"
bool CStreaming::ms_disableStreaming;
bool CStreaming::ms_bLoadingBigModel;
@@ -489,8 +491,10 @@ CStreaming::ConvertBufferToObject(int8 *buf, int32 streamId)
// Set Txd to use
CTxdStore::AddRef(mi->GetTxdSlot());
- CTxdStore::SetCurrentTxd(mi->GetTxdSlot());
+ PUSH_MEMID(MEMID_STREAM_MODELS);
+ CTxdStore::SetCurrentTxd(mi->GetTxdSlot());
+// TODO(USE_CUSTOM_ALLOCATOR): register mem pointers
if(mi->IsSimple()){
success = CFileLoader::LoadAtomicFile(stream, streamId);
} else if (mi->GetModelType() == MITYPE_VEHICLE) {
@@ -502,6 +506,7 @@ CStreaming::ConvertBufferToObject(int8 *buf, int32 streamId)
}else{
success = CFileLoader::LoadClumpFile(stream, streamId);
}
+ POP_MEMID();
UpdateMemoryUsed();
// Txd no longer needed unless we only read part of the file
@@ -525,12 +530,14 @@ CStreaming::ConvertBufferToObject(int8 *buf, int32 streamId)
return false;
}
+ PUSH_MEMID(MEMID_STREAM_TEXUTRES);
if(ms_bLoadingBigModel || cdsize > 200){
success = CTxdStore::StartLoadTxd(streamId - STREAM_OFFSET_TXD, stream);
if(success)
ms_aInfoForModel[streamId].m_loadState = STREAMSTATE_STARTED;
}else
success = CTxdStore::LoadTxd(streamId - STREAM_OFFSET_TXD, stream);
+ POP_MEMID();
UpdateMemoryUsed();
if(!success){
@@ -580,7 +587,9 @@ CStreaming::ConvertBufferToObject(int8 *buf, int32 streamId)
// Mark objects as loaded
if(ms_aInfoForModel[streamId].m_loadState != STREAMSTATE_STARTED){
ms_aInfoForModel[streamId].m_loadState = STREAMSTATE_LOADED;
+#ifndef USE_CUSTOM_ALLOCATOR
ms_memoryUsed += ms_aInfoForModel[streamId].GetCdSize() * CDSTREAM_SECTOR_SIZE;
+#endif
}
endTime = CTimer::GetCurrentTimeInCycles() / CTimer::GetCyclesPerMillisecond();
@@ -619,32 +628,40 @@ CStreaming::FinishLoadingLargeFile(int8 *buf, int32 streamId)
if(streamId < STREAM_OFFSET_TXD){
// Model
+// TODO(USE_CUSTOM_ALLOCATOR): register pointers
mi = CModelInfo::GetModelInfo(streamId);
+ PUSH_MEMID(MEMID_STREAM_MODELS);
CTxdStore::SetCurrentTxd(mi->GetTxdSlot());
success = CFileLoader::FinishLoadClumpFile(stream, streamId);
if(success)
success = AddToLoadedVehiclesList(streamId);
+ POP_MEMID();
mi->RemoveRef();
CTxdStore::RemoveRefWithoutDelete(mi->GetTxdSlot());
}else{
// Txd
CTxdStore::AddRef(streamId - STREAM_OFFSET_TXD);
+ PUSH_MEMID(MEMID_STREAM_TEXUTRES);
success = CTxdStore::FinishLoadTxd(streamId - STREAM_OFFSET_TXD, stream);
+ POP_MEMID();
CTxdStore::RemoveRefWithoutDelete(streamId - STREAM_OFFSET_TXD);
}
RwStreamClose(stream, &mem);
- ms_aInfoForModel[streamId].m_loadState = STREAMSTATE_LOADED;
+
+ ms_aInfoForModel[streamId].m_loadState = STREAMSTATE_LOADED; // only done if success on PS2
+#ifndef USE_CUSTOM_ALLOCATOR
ms_memoryUsed += ms_aInfoForModel[streamId].GetCdSize() * CDSTREAM_SECTOR_SIZE;
+#endif
if(!success){
RemoveModel(streamId);
ReRequestModel(streamId);
- UpdateMemoryUsed();
+ UpdateMemoryUsed(); // directly after pop on PS2
return false;
}
- UpdateMemoryUsed();
+ UpdateMemoryUsed(); // directly after pop on PS2
endTime = CTimer::GetCurrentTimeInCycles() / CTimer::GetCyclesPerMillisecond();
timeDiff = endTime - startTime;
@@ -877,7 +894,11 @@ CStreaming::RemoveModel(int32 id)
CModelInfo::GetModelInfo(id)->DeleteRwObject();
else
CTxdStore::RemoveTxd(id - STREAM_OFFSET_TXD);
+#ifdef USE_CUSTOM_ALLOCATOR
+ UpdateMemoryUsed();
+#else
ms_memoryUsed -= ms_aInfoForModel[id].GetCdSize()*CDSTREAM_SECTOR_SIZE;
+#endif
}
if(ms_aInfoForModel[id].m_next){
@@ -899,6 +920,9 @@ CStreaming::RemoveModel(int32 id)
RpClumpGtaCancelStream();
else
CTxdStore::RemoveTxd(id - STREAM_OFFSET_TXD);
+#ifdef USE_CUSTOM_ALLOCATOR
+ UpdateMemoryUsed();
+#endif
}
ms_aInfoForModel[id].m_loadState = STREAMSTATE_NOTLOADED;
@@ -2063,19 +2087,25 @@ CStreaming::FlushRequestList(void)
void
CStreaming::ImGonnaUseStreamingMemory(void)
{
- // empty
+ PUSH_MEMID(MEMID_STREAM);
}
void
CStreaming::IHaveUsedStreamingMemory(void)
{
+ POP_MEMID();
UpdateMemoryUsed();
}
void
CStreaming::UpdateMemoryUsed(void)
{
- // empty
+#ifdef USE_CUSTOM_ALLOCATOR
+ ms_memoryUsed =
+ gMainHeap.GetMemoryUsed(MEMID_STREAM) +
+ gMainHeap.GetMemoryUsed(MEMID_STREAM_MODELS) +
+ gMainHeap.GetMemoryUsed(MEMID_STREAM_TEXUTRES);
+#endif
}
#define STREAM_DIST 80.0f
diff --git a/src/core/World.cpp b/src/core/World.cpp
index d65d57dd..33c2f1c1 100644
--- a/src/core/World.cpp
+++ b/src/core/World.cpp
@@ -53,6 +53,9 @@ bool CWorld::bIncludeCarTyres;
void
CWorld::Initialise()
{
+#ifdef GTA_PS2
+ CPools::Initialise();
+#endif
pIgnoreEntity = nil;
bDoingCarCollisions = false;
bSecondShift = false;
diff --git a/src/core/main.cpp b/src/core/main.cpp
index ea88de59..d34eb8f3 100644
--- a/src/core/main.cpp
+++ b/src/core/main.cpp
@@ -67,6 +67,7 @@
#include "custompipes.h"
#include "screendroplets.h"
#include "frontendoption.h"
+#include "MemoryHeap.h"
GlobalScene Scene;
@@ -109,6 +110,15 @@ void TheGame(void);
void DebugMenuPopulate(void);
#endif
+
+#ifdef GTA_PS2
+#define WANT_TO_LOAD TheMemoryCard.m_bWantToLoad
+#define FOUND_GAME_TO_LOAD TheMemoryCard.b_FoundRecentSavedGameWantToLoad
+#else
+#define WANT_TO_LOAD FrontEndMenuManager.m_bWantToLoad
+#define FOUND_GAME_TO_LOAD b_FoundRecentSavedGameWantToLoad
+#endif
+
void
ValidateVersion()
{
@@ -772,6 +782,170 @@ tZonePrint ZonePrint[] =
};
#ifndef MASTER
+
+void
+PrintMemoryUsage(void)
+{
+// little hack
+if(CPools::GetPtrNodePool() == nil)
+return;
+
+ // Style taken from LCS, modified for III
+// CFont::SetFontStyle(FONT_PAGER);
+ CFont::SetFontStyle(FONT_BANK);
+ CFont::SetBackgroundOff();
+ CFont::SetWrapx(640.0f);
+// CFont::SetScale(0.5f, 0.75f);
+ CFont::SetScale(0.4f, 0.75f);
+ CFont::SetCentreOff();
+ CFont::SetCentreSize(640.0f);
+ CFont::SetJustifyOff();
+ CFont::SetPropOn();
+ CFont::SetColor(CRGBA(200, 200, 200, 200));
+ CFont::SetBackGroundOnlyTextOff();
+ CFont::SetDropShadowPosition(0);
+
+ float y;
+
+#ifdef USE_CUSTOM_ALLOCATOR
+ y = 24.0f;
+ sprintf(gString, "Total: %d blocks, %d bytes", gMainHeap.m_totalBlocksUsed, gMainHeap.m_totalMemUsed);
+ AsciiToUnicode(gString, gUString);
+ CFont::PrintString(24.0f, y, gUString);
+ y += 12.0f;
+
+ sprintf(gString, "Game: %d blocks, %d bytes", gMainHeap.GetBlocksUsed(MEMID_GAME), gMainHeap.GetMemoryUsed(MEMID_GAME));
+ AsciiToUnicode(gString, gUString);
+ CFont::PrintString(24.0f, y, gUString);
+ y += 12.0f;
+
+ sprintf(gString, "World: %d blocks, %d bytes", gMainHeap.GetBlocksUsed(MEMID_WORLD), gMainHeap.GetMemoryUsed(MEMID_WORLD));
+ AsciiToUnicode(gString, gUString);
+ CFont::PrintString(24.0f, y, gUString);
+ y += 12.0f;
+
+ sprintf(gString, "Render: %d blocks, %d bytes", gMainHeap.GetBlocksUsed(MEMID_RENDER), gMainHeap.GetMemoryUsed(MEMID_RENDER));
+ AsciiToUnicode(gString, gUString);
+ CFont::PrintString(24.0f, y, gUString);
+ y += 12.0f;
+
+ sprintf(gString, "Render List: %d blocks, %d bytes", gMainHeap.GetBlocksUsed(MEMID_RENDERLIST), gMainHeap.GetMemoryUsed(MEMID_RENDERLIST));
+ AsciiToUnicode(gString, gUString);
+ CFont::PrintString(24.0f, y, gUString);
+ y += 12.0f;
+
+ sprintf(gString, "Default Models: %d blocks, %d bytes", gMainHeap.GetBlocksUsed(MEMID_DEF_MODELS), gMainHeap.GetMemoryUsed(MEMID_DEF_MODELS));
+ AsciiToUnicode(gString, gUString);
+ CFont::PrintString(24.0f, y, gUString);
+ y += 12.0f;
+
+ sprintf(gString, "Textures: %d blocks, %d bytes", gMainHeap.GetBlocksUsed(MEMID_TEXTURES), gMainHeap.GetMemoryUsed(MEMID_TEXTURES));
+ AsciiToUnicode(gString, gUString);
+ CFont::PrintString(24.0f, y, gUString);
+ y += 12.0f;
+
+ sprintf(gString, "Streaming: %d blocks, %d bytes", gMainHeap.GetBlocksUsed(MEMID_STREAM), gMainHeap.GetMemoryUsed(MEMID_STREAM));
+ AsciiToUnicode(gString, gUString);
+ CFont::PrintString(24.0f, y, gUString);
+ y += 12.0f;
+
+ sprintf(gString, "Streamed Models: %d blocks, %d bytes", gMainHeap.GetBlocksUsed(MEMID_STREAM_MODELS), gMainHeap.GetMemoryUsed(MEMID_STREAM_MODELS));
+ AsciiToUnicode(gString, gUString);
+ CFont::PrintString(24.0f, y, gUString);
+ y += 12.0f;
+
+ sprintf(gString, "Streamed Textures: %d blocks, %d bytes", gMainHeap.GetBlocksUsed(MEMID_STREAM_TEXUTRES), gMainHeap.GetMemoryUsed(MEMID_STREAM_TEXUTRES));
+ AsciiToUnicode(gString, gUString);
+ CFont::PrintString(24.0f, y, gUString);
+ y += 12.0f;
+
+ sprintf(gString, "Animation: %d blocks, %d bytes", gMainHeap.GetBlocksUsed(MEMID_ANIMATION), gMainHeap.GetMemoryUsed(MEMID_ANIMATION));
+ AsciiToUnicode(gString, gUString);
+ CFont::PrintString(24.0f, y, gUString);
+ y += 12.0f;
+
+ sprintf(gString, "Pools: %d blocks, %d bytes", gMainHeap.GetBlocksUsed(MEMID_POOLS), gMainHeap.GetMemoryUsed(MEMID_POOLS));
+ AsciiToUnicode(gString, gUString);
+ CFont::PrintString(24.0f, y, gUString);
+ y += 12.0f;
+
+ sprintf(gString, "Collision: %d blocks, %d bytes", gMainHeap.GetBlocksUsed(MEMID_COLLISION), gMainHeap.GetMemoryUsed(MEMID_COLLISION));
+ AsciiToUnicode(gString, gUString);
+ CFont::PrintString(24.0f, y, gUString);
+ y += 12.0f;
+
+ sprintf(gString, "Game Process: %d blocks, %d bytes", gMainHeap.GetBlocksUsed(MEMID_GAME_PROCESS), gMainHeap.GetMemoryUsed(MEMID_GAME_PROCESS));
+ AsciiToUnicode(gString, gUString);
+ CFont::PrintString(24.0f, y, gUString);
+ y += 12.0f;
+
+ sprintf(gString, "Script: %d blocks, %d bytes", gMainHeap.GetBlocksUsed(MEMID_SCRIPT), gMainHeap.GetMemoryUsed(MEMID_SCRIPT));
+ AsciiToUnicode(gString, gUString);
+ CFont::PrintString(24.0f, y, gUString);
+ y += 12.0f;
+
+ sprintf(gString, "Cars: %d blocks, %d bytes", gMainHeap.GetBlocksUsed(MEMID_CARS), gMainHeap.GetMemoryUsed(MEMID_CARS));
+ AsciiToUnicode(gString, gUString);
+ CFont::PrintString(24.0f, y, gUString);
+ y += 12.0f;
+
+ sprintf(gString, "Frontend: %d blocks, %d bytes", gMainHeap.GetBlocksUsed(MEMID_FRONTEND), gMainHeap.GetMemoryUsed(MEMID_FRONTEND));
+ AsciiToUnicode(gString, gUString);
+ CFont::PrintString(24.0f, y, gUString);
+ y += 12.0f;
+#endif
+
+ y = 132.0f;
+ AsciiToUnicode("Pools usage:", gUString);
+ CFont::PrintString(400.0f, y, gUString);
+ y += 12.0f;
+
+ sprintf(gString, "PtrNode: %d/%d", CPools::GetPtrNodePool()->GetNoOfUsedSpaces(), CPools::GetPtrNodePool()->GetSize());
+ AsciiToUnicode(gString, gUString);
+ CFont::PrintString(400.0f, y, gUString);
+ y += 12.0f;
+
+ sprintf(gString, "EntryInfoNode: %d/%d", CPools::GetEntryInfoNodePool()->GetNoOfUsedSpaces(), CPools::GetEntryInfoNodePool()->GetSize());
+ AsciiToUnicode(gString, gUString);
+ CFont::PrintString(400.0f, y, gUString);
+ y += 12.0f;
+
+ sprintf(gString, "Ped: %d/%d", CPools::GetPedPool()->GetNoOfUsedSpaces(), CPools::GetPedPool()->GetSize());
+ AsciiToUnicode(gString, gUString);
+ CFont::PrintString(400.0f, y, gUString);
+ y += 12.0f;
+
+ sprintf(gString, "Vehicle: %d/%d", CPools::GetVehiclePool()->GetNoOfUsedSpaces(), CPools::GetVehiclePool()->GetSize());
+ AsciiToUnicode(gString, gUString);
+ CFont::PrintString(400.0f, y, gUString);
+ y += 12.0f;
+
+ sprintf(gString, "Building: %d/%d", CPools::GetBuildingPool()->GetNoOfUsedSpaces(), CPools::GetBuildingPool()->GetSize());
+ AsciiToUnicode(gString, gUString);
+ CFont::PrintString(400.0f, y, gUString);
+ y += 12.0f;
+
+ sprintf(gString, "Treadable: %d/%d", CPools::GetTreadablePool()->GetNoOfUsedSpaces(), CPools::GetTreadablePool()->GetSize());
+ AsciiToUnicode(gString, gUString);
+ CFont::PrintString(400.0f, y, gUString);
+ y += 12.0f;
+
+ sprintf(gString, "Object: %d/%d", CPools::GetObjectPool()->GetNoOfUsedSpaces(), CPools::GetObjectPool()->GetSize());
+ AsciiToUnicode(gString, gUString);
+ CFont::PrintString(400.0f, y, gUString);
+ y += 12.0f;
+
+ sprintf(gString, "Dummy: %d/%d", CPools::GetDummyPool()->GetNoOfUsedSpaces(), CPools::GetDummyPool()->GetSize());
+ AsciiToUnicode(gString, gUString);
+ CFont::PrintString(400.0f, y, gUString);
+ y += 12.0f;
+
+ sprintf(gString, "AudioScriptObjects: %d/%d", CPools::GetAudioScriptObjectPool()->GetNoOfUsedSpaces(), CPools::GetAudioScriptObjectPool()->GetSize());
+ AsciiToUnicode(gString, gUString);
+ CFont::PrintString(400.0f, y, gUString);
+ y += 12.0f;
+}
+
void
DisplayGameDebugText()
{
@@ -785,6 +959,7 @@ DisplayGameDebugText()
}
#endif
+// PrintMemoryUsage(); // TODO: put this somewhere else
char str[200];
wchar ustr[200];
@@ -1001,13 +1176,9 @@ RenderMenus(void)
{
if (FrontEndMenuManager.m_bMenuActive)
{
-#ifdef PS2
- gMainHeap.PushMemId(_TODOCONST(17));
-#endif
+ PUSH_MEMID(MEMID_FRONTEND);
FrontEndMenuManager.DrawFrontEnd();
-#ifdef PS2
- gMainHeap.PopMemId();
-#endif
+ POP_MEMID();
}
}
@@ -1046,24 +1217,29 @@ Idle(void *arg)
CPad::UpdatePads();
FrontEndMenuManager.Process();
} else {
+ PUSH_MEMID(MEMID_GAME_PROCESS);
CPointLights::InitPerFrame();
tbStartTimer(0, "CGame::Process");
CGame::Process();
tbEndTimer("CGame::Process");
+ POP_MEMID();
+
tbStartTimer(0, "DMAudio.Service");
DMAudio.Service();
-
tbEndTimer("DMAudio.Service");
}
if (RsGlobal.quit)
return;
#else
+
+ PUSH_MEMID(MEMID_GAME_PROCESS);
CPointLights::InitPerFrame();
tbStartTimer(0, "CGame::Process");
CGame::Process();
tbEndTimer("CGame::Process");
+ POP_MEMID();
tbStartTimer(0, "DMAudio.Service");
DMAudio.Service();
@@ -1071,21 +1247,12 @@ Idle(void *arg)
#endif
if(CGame::bDemoMode && CTimer::GetTimeInMilliseconds() > (3*60 + 30)*1000 && !CCutsceneMgr::IsCutsceneProcessing()){
-#ifdef PS2_MENU
- TheMemoryCard.m_bWantToLoad = false;
- FrontEndMenuManager.m_bWantToRestart = true;
-#else
+ WANT_TO_LOAD = false;
FrontEndMenuManager.m_bWantToRestart = true;
- FrontEndMenuManager.m_bWantToLoad = false;
-#endif
return;
}
-#ifdef PS2_MENU
- if ( FrontEndMenuManager.m_bWantToRestart || TheMemoryCard.b_FoundRecentSavedGameWantToLoad )
-#else
- if(FrontEndMenuManager.m_bWantToRestart || b_FoundRecentSavedGameWantToLoad)
-#endif
+ if(FrontEndMenuManager.m_bWantToRestart || FOUND_GAME_TO_LOAD)
{
return;
}
@@ -1095,6 +1262,8 @@ Idle(void *arg)
if(arg == nil)
return;
+ PUSH_MEMID(MEMID_RENDER);
+
if((!FrontEndMenuManager.m_bMenuActive || FrontEndMenuManager.m_bRenderGameInMenu) &&
TheCamera.GetScreenFadeStatus() != FADE_2)
{
@@ -1107,6 +1276,8 @@ Idle(void *arg)
RsMouseSetPos(&pos);
}
#endif
+
+ PUSH_MEMID(MEMID_RENDERLIST);
tbStartTimer(0, "CnstrRenderList");
CRenderer::ConstructRenderList();
tbEndTimer("CnstrRenderList");
@@ -1114,6 +1285,7 @@ Idle(void *arg)
tbStartTimer(0, "PreRender");
CRenderer::PreRender();
tbEndTimer("PreRender");
+ POP_MEMID();
#ifdef FIX_BUGS
RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void *)FALSE); // TODO: temp? this fixes OpenGL render but there should be a better place for this
@@ -1124,12 +1296,12 @@ Idle(void *arg)
if(CWeather::LightningFlash && !CCullZones::CamNoRain()){
if(!DoRWStuffStartOfFrame_Horizon(255, 255, 255, 255, 255, 255, 255))
- return;
+ goto popret;
}else{
if(!DoRWStuffStartOfFrame_Horizon(CTimeCycle::GetSkyTopRed(), CTimeCycle::GetSkyTopGreen(), CTimeCycle::GetSkyTopBlue(),
CTimeCycle::GetSkyBottomRed(), CTimeCycle::GetSkyBottomGreen(), CTimeCycle::GetSkyBottomBlue(),
255))
- return;
+ goto popret;
}
DefinedState();
@@ -1176,7 +1348,7 @@ Idle(void *arg)
CVisibilityPlugins::SetRenderWareCamera(Scene.camera);
RwCameraClear(Scene.camera, &gColourTop, rwCAMERACLEARZ);
if(!RsCameraBeginUpdate(Scene.camera))
- return;
+ goto popret;
}
#ifdef PS2_SAVE_DIALOG
@@ -1189,7 +1361,7 @@ Idle(void *arg)
#ifdef PS2_MENU
if ( TheMemoryCard.m_bWantToLoad )
- return;
+ goto popret;
#endif
tbStartTimer(0, "DoFade");
@@ -1208,8 +1380,13 @@ Idle(void *arg)
DoRWStuffEndOfFrame();
+ POP_MEMID(); // MEMID_RENDER
+
if(g_SlowMode)
ProcessSlowMode();
+ return;
+
+popret: POP_MEMID(); // MEMID_RENDER
}
void
@@ -1375,14 +1552,13 @@ TheModelViewer(void)
}
#endif
-#ifdef PS2
+
+#ifdef GTA_PS2
void TheGame(void)
{
printf("Into TheGame!!!\n");
-#ifdef GTA_PS2
- gMainHeap.PushMemId(_TODOCONST(1));
-#endif
+ PUSH_MEMID(MEMID_GAME); // NB: not popped
CTimer::Initialise();
@@ -1420,77 +1596,49 @@ void TheGame(void)
while (true)
{
-#ifdef PS2
- if (TheMemoryCard.m_bWantToLoad)
-#else
- if (FrontEndMenuManager.m_bWantToLoad)
-#endif
+ if (WANT_TO_LOAD)
{
Const char *splash1 = GetLevelSplashScreen(CGame::currLevel);
LoadSplash(splash1);
}
-#ifdef PS2
- TheMemoryCard.m_bWantToLoad = false;
-#else
- FrontEndMenuManager.m_bWantToLoad = false;
-#endif
+ WANT_TO_LOAD = false;
CTimer::Update();
-#ifdef PS2
- while (!(FrontEndMenuManager.m_bWantToRestart || TheMemoryCard.b_FoundRecentSavedGameWantToLoad))
-#else
- while (!(FrontEndMenuManager.m_bWantToRestart || b_FoundRecentSavedGameWantToLoad))
-#endif
+ while (!(FrontEndMenuManager.m_bWantToRestart || FOUND_GAME_TO_LOAD))
{
CSprite2d::InitPerFrame();
CFont::InitPerFrame();
-#ifdef GTA_PS2
- gMainHeap.PushMemId(_TODOCONST(12));
-#endif
- CPointLights::NumLights = 0;
+ PUSH_MEMID(MEMID_GAME_PROCESS)
+ CPointLights::InitPerFrame();
CGame::Process();
-#ifdef GTA_PS2
- gMainHeap.PopMemId();
-#endif
+ POP_MEMID();
DMAudio.Service();
if (CGame::bDemoMode && CTimer::GetTimeInMilliseconds() > (3*60 + 30)*1000 && !CCutsceneMgr::IsCutsceneProcessing())
{
-#ifdef PS2
- TheMemoryCard.m_bWantToLoad = false;
-#else
- FrontEndMenuManager.m_bWantToLoad = false;
-#endif
+ WANT_TO_LOAD = false;
FrontEndMenuManager.m_bWantToRestart = true;
break;
}
-#ifdef PS2
- if (FrontEndMenuManager.m_bWantToRestart || TheMemoryCard.b_FoundRecentSavedGameWantToLoad)
-#else
- if (FrontEndMenuManager.m_bWantToRestart || b_FoundRecentSavedGameWantToLoad)
-#endif
+ if (FrontEndMenuManager.m_bWantToRestart || FOUND_GAME_TO_LOAD)
break;
SetLightsWithTimeOfDayColour(Scene.world);
-#ifdef GTA_PS2
- gMainHeap.PushMemId(_TODOCONST(15));
-#endif
+
+ PUSH_MEMID(MEMID_RENDER);
if (!FrontEndMenuManager.m_bMenuActive || FrontEndMenuManager.m_bRenderGameInMenu == true && TheCamera.GetScreenFadeStatus() != FADE_2 )
{
-#ifdef GTA_PS2
- gMainHeap.PushMemId(_TODOCONST(11));
-#endif
+
+ PUSH_MEMID(MEMID_RENDERLIST);
CRenderer::ConstructRenderList();
CRenderer::PreRender();
-#ifdef GTA_PS2
- gMainHeap.PopMemId();
-#endif
+ POP_MEMID();
if (CWeather::LightningFlash && !CCullZones::CamNoRain())
DoRWStuffStartOfFrame_Horizon(255, 255, 255, 255, 255, 255, 255);
@@ -1522,15 +1670,9 @@ void TheGame(void)
RenderMenus();
-#ifdef PS2
- if (TheMemoryCard.m_bWantToLoad)
-#else
- if (FrontEndMenuManager.m_bWantToLoad)
-#endif
+ if (WANT_TO_LOAD)
{
-#ifdef GTA_PS2
- gMainHeap.PopMemId();
-#endif
+ POP_MEMID(); // MEMID_RENDER
break;
}
@@ -1547,9 +1689,7 @@ void TheGame(void)
CTimer::Update();
-#ifdef GTA_PS2
- gMainHeap.PopMemId();
-#endif
+ POP_MEMID(): // MEMID_RENDER
if (g_SlowMode)
ProcessSlowMode();
@@ -1561,24 +1701,12 @@ void TheGame(void)
CGame::ShutDownForRestart();
CTimer::Stop();
-#ifdef PS2
- if (FrontEndMenuManager.m_bWantToRestart || TheMemoryCard.b_FoundRecentSavedGameWantToLoad)
-#else
- if (FrontEndMenuManager.m_bWantToRestart || b_FoundRecentSavedGameWantToLoad)
-#endif
+ if (FrontEndMenuManager.m_bWantToRestart || FOUND_GAME_TO_LOAD)
{
-#ifdef PS2
- if (TheMemoryCard.b_FoundRecentSavedGameWantToLoad)
-#else
- if (b_FoundRecentSavedGameWantToLoad)
-#endif
+ if (FOUND_GAME_TO_LOAD)
{
FrontEndMenuManager.m_bWantToRestart = true;
-#ifdef PS2
- TheMemoryCard.m_bWantToLoad = true;
-#else
- FrontEndMenuManager.m_bWantToLoad = true;
-#endif
+ WANT_TO_LOAD = true;
}
CGame::InitialiseWhenRestarting();
@@ -1718,7 +1846,7 @@ void SystemInit()
//
#endif
-#ifdef PS2
+#ifdef GTA_PS2
TheMemoryCard.Init();
#endif
}
@@ -1747,7 +1875,7 @@ void GameInit()
#endif
CdStreamInit(MAX_CDCHANNELS);
-#ifdef PS2
+#ifdef GTA_PS2
Initialise3D(); //no params
#else
//TODO
@@ -1861,14 +1989,11 @@ void GameInit()
CSprite2d::SetRecipNearClip();
CTxdStore::Initialise();
-#ifdef GTA_PS2
- gMainHeap.PushMemId(_TODOCONST(9));
-#endif
+
+ PUSH_MEMID(MEMID_TEXTURES);
CFont::Initialise();
CHud::Initialise();
-#ifdef GTA_PS2
- gMainHeap.PopMemId();
-#endif
+ POP_MEMID();
ValidateVersion();
@@ -1896,7 +2021,7 @@ main(int argc, char *argv[])
SystemInit();
-#ifdef PS2
+#ifdef GTA_PS2
int32 r = TheMemoryCard.CheckCardStateAtGameStartUp(CARD_ONE);
if ( r == CMemoryCard::ERR_DIRNOENTRY || r == CMemoryCard::ERR_NOFORMAT
diff --git a/src/core/templates.h b/src/core/templates.h
index 4f7b8490..86239664 100644
--- a/src/core/templates.h
+++ b/src/core/templates.h
@@ -46,8 +46,8 @@ class CPool
public:
CPool(int size){
// TODO: use new here
- m_entries = (U*)malloc(sizeof(U)*size);
- m_flags = (Flags*)malloc(sizeof(Flags)*size);
+ m_entries = (U*)new uint8[sizeof(U)*size];
+ m_flags = (Flags*)new uint8[sizeof(Flags)*size];
m_size = size;
m_allocPtr = 0;
for(int i = 0; i < size; i++){
@@ -61,8 +61,8 @@ public:
}
void Flush() {
if (m_size > 0) {
- free(m_entries);
- free(m_flags);
+ delete[] (uint8*)m_entries;
+ delete[] (uint8*)m_flags;
m_entries = nil;
m_flags = nil;
m_size = 0;
@@ -141,8 +141,8 @@ public:
}
bool IsFreeSlot(int i) { return !!m_flags[i].free; }
void ClearStorage(uint8 *&flags, U *&entries){
- free(flags);
- free(entries);
+ delete[] (uint8*)flags;
+ delete[] (uint8*)entries;
flags = nil;
entries = nil;
}
@@ -156,8 +156,8 @@ public:
debug("CopyBack:%d (/%d)\n", GetNoOfUsedSpaces(), m_size); /* Assumed inlining */
}
void Store(uint8 *&flags, U *&entries){
- flags = (uint8*)malloc(sizeof(uint8)*m_size);
- entries = (U*)malloc(sizeof(U)*m_size);
+ flags = (uint8*)new uint8[sizeof(uint8)*m_size];
+ entries = (U*)new uint8[sizeof(U)*m_size];
memcpy(flags, m_flags, sizeof(uint8)*m_size);
memcpy(entries, m_entries, sizeof(U)*m_size);
debug("Stored:%d (/%d)\n", GetNoOfUsedSpaces(), m_size); /* Assumed inlining */