diff --git a/configure.py b/configure.py index feb72740..e8b11465 100755 --- a/configure.py +++ b/configure.py @@ -590,7 +590,7 @@ LIBS = [ "Kyoto/Math/RMathUtils", ["Kyoto/CCrc32", True], ["Kyoto/Alloc/CCircularBuffer", True], - "Kyoto/Alloc/CMemory", + ["Kyoto/Alloc/CMemory", True], ["Kyoto/Alloc/IAllocator", True], "Kyoto/PVS/CPVSVisOctree", "Kyoto/PVS/CPVSVisSet", diff --git a/include/Kyoto/Alloc/CMemory.hpp b/include/Kyoto/Alloc/CMemory.hpp index e068ae92..5941b8a2 100644 --- a/include/Kyoto/Alloc/CMemory.hpp +++ b/include/Kyoto/Alloc/CMemory.hpp @@ -2,11 +2,23 @@ #define _CMEMORY #include "types.h" +#include "Kyoto/Alloc/IAllocator.hpp" -namespace CMemory { -void* Alloc(size_t sz); -void Free(const void* ptr); -} // namespace CMemory +class COsContext; +class CMemory { + static IAllocator* mpAllocator; + static bool mInitialized; + +public: + static void Startup(COsContext& ctx); + static void Shutdown(); + static void SetAllocator(COsContext& ctx, IAllocator& allocator); + static IAllocator* GetAllocator(); + static void* Alloc(size_t len, IAllocator::EHint hint, IAllocator::EScope scope, IAllocator::EType type, const CCallStack& callstack); + static void Free(const void* ptr); + static void SetOutOfMemoryCallback(IAllocator::FOutOfMemoryCb callback, const void* context); + static void OffsetFakeStatics(int); +}; void* operator new(size_t sz, const char*, const char*); void* operator new[](size_t sz, const char*, const char*); diff --git a/include/Kyoto/CMemorySys.hpp b/include/Kyoto/Alloc/CMemorySys.hpp similarity index 100% rename from include/Kyoto/CMemorySys.hpp rename to include/Kyoto/Alloc/CMemorySys.hpp diff --git a/include/Kyoto/Alloc/IAllocator.hpp b/include/Kyoto/Alloc/IAllocator.hpp index 4904c3be..df868757 100644 --- a/include/Kyoto/Alloc/IAllocator.hpp +++ b/include/Kyoto/Alloc/IAllocator.hpp @@ -1,7 +1,6 @@ #ifndef _IALLOCATOR #define _IALLOCATOR -#include "Kyoto/Alloc/CMemory.hpp" #include "types.h" #include @@ -22,8 +21,8 @@ public: }; enum EType { - kTP_Unk0, - kTP_Unk1, + kTP_Heap, + kTP_Array, }; struct SMetrics { @@ -77,6 +76,7 @@ public: typedef const bool (*FOutOfMemoryCb)(const void*, uint); typedef const bool (*FEnumAllocationsCb)(const SAllocInfo& info, const void* ptr); + virtual ~IAllocator(); virtual bool Initialize(COsContext& ctx) = 0; diff --git a/include/MetroidPrime/CGameGlobalObjects.hpp b/include/MetroidPrime/CGameGlobalObjects.hpp index 04716159..1156f0b3 100644 --- a/include/MetroidPrime/CGameGlobalObjects.hpp +++ b/include/MetroidPrime/CGameGlobalObjects.hpp @@ -8,7 +8,7 @@ #include "Kyoto/Basics/COsContext.hpp" #include "Kyoto/CMemoryCardSys.hpp" -#include "Kyoto/CMemorySys.hpp" +#include "Kyoto/Alloc/CMemorySys.hpp" #include "Kyoto/CResFactory.hpp" #include "Kyoto/CSimplePool.hpp" #include "Kyoto/CToken.hpp" diff --git a/include/MetroidPrime/CMain.hpp b/include/MetroidPrime/CMain.hpp index a0e81a1b..e369f02f 100644 --- a/include/MetroidPrime/CMain.hpp +++ b/include/MetroidPrime/CMain.hpp @@ -7,7 +7,7 @@ #include "Kyoto/Basics/COsContext.hpp" #include "Kyoto/Basics/CStopwatch.hpp" -#include "Kyoto/CMemorySys.hpp" +#include "Kyoto/Alloc/CMemorySys.hpp" #include "Kyoto/Streams/CInputStream.hpp" #include "Kyoto/TReservedAverage.hpp" #include "MetroidPrime/CGameArchitectureSupport.hpp" diff --git a/obj_files.mk b/obj_files.mk index fb3c9575..eaaa1f98 100644 --- a/obj_files.mk +++ b/obj_files.mk @@ -529,7 +529,7 @@ KYOTO_1 :=\ $(BUILD_DIR)/asm/Kyoto/Math/RMathUtils.o\ $(BUILD_DIR)/src/Kyoto/CCrc32.o\ $(BUILD_DIR)/src/Kyoto/Alloc/CCircularBuffer.o\ - $(BUILD_DIR)/asm/Kyoto/Alloc/CMemory.o\ + $(BUILD_DIR)/src/Kyoto/Alloc/CMemory.o\ $(BUILD_DIR)/src/Kyoto/Alloc/IAllocator.o\ $(BUILD_DIR)/asm/Kyoto/PVS/CPVSVisOctree.o\ $(BUILD_DIR)/asm/Kyoto/PVS/CPVSVisSet.o\ diff --git a/src/Kyoto/Alloc/CGameAllocator.cpp b/src/Kyoto/Alloc/CGameAllocator.cpp index 0dbddc17..052c15ed 100644 --- a/src/Kyoto/Alloc/CGameAllocator.cpp +++ b/src/Kyoto/Alloc/CGameAllocator.cpp @@ -112,7 +112,7 @@ void* CGameAllocator::Alloc(size_t size, EHint hint, EScope scope, EType type, buf = x74_mediumPool->Alloc(size); if (buf == nullptr) { - buf = Alloc(0x21000, kHI_None, kSC_Unk1, kTP_Unk0, + buf = Alloc(0x21000, kHI_None, kSC_Unk1, kTP_Heap, CCallStack(-1, "MediumAllocMainData ", " - Ignore")); x74_mediumPool->AddPuddle(0x1000, buf, 1); buf = x74_mediumPool->Alloc(size); diff --git a/src/Kyoto/Alloc/CMemory.cpp b/src/Kyoto/Alloc/CMemory.cpp new file mode 100644 index 00000000..459e8180 --- /dev/null +++ b/src/Kyoto/Alloc/CMemory.cpp @@ -0,0 +1,90 @@ +#include "Kyoto/Alloc/CMemory.hpp" +#include "Kyoto/Alloc/CMemorySys.hpp" + +#include "Kyoto/Alloc/CCallStack.hpp" +#include "Kyoto/Alloc/CGameAllocator.hpp" +#include "Kyoto/Basics/RAssertDolphin.hpp" + +#include "dolphin/os.h" + +static CGameAllocator gGameAllocator; +IAllocator* CMemory::mpAllocator = &gGameAllocator; +bool CMemory::mInitialized; +uint gLeakCount = 0; +uint gLeakBytes = 0; + +CMemorySys::CMemorySys(COsContext& ctx, IAllocator& allocator) { + CMemory::Startup(ctx); + CMemory::SetAllocator(ctx, allocator); +} + +CMemorySys::~CMemorySys() { CMemory::Shutdown(); } + +IAllocator& CMemorySys::GetGameAllocator() { return gGameAllocator; } + +void CMemory::Startup(COsContext& ctx) { mInitialized = mpAllocator->Initialize(ctx); } + +void CMemory::SetAllocator(COsContext& ctx, IAllocator& allocator) { + if (mpAllocator != &allocator) { + if (mpAllocator != nullptr) { + mpAllocator->ReleaseAll(); + } + mpAllocator = &allocator; + mpAllocator->Initialize(ctx); + } +} + +static bool cmemory_enum_alloc_cb(const IAllocator::SAllocInfo& info, const void* ptr) { + if (info.x8_isAllocated && info.x9_ == 0) { + ++gLeakCount; + gLeakBytes += info.x4_len; + } + return true; +} + +void CMemory::Shutdown() { + CMemory::mInitialized = false; + + if (mpAllocator->GetMetrics().x8_ != 0) { + gLeakCount = 0; + gLeakBytes = 0; + mpAllocator->EnumAllocations((IAllocator::FEnumAllocationsCb)cmemory_enum_alloc_cb, nullptr, + false); + } + mpAllocator->Shutdown(); +} + +void* CMemory::Alloc(size_t len, IAllocator::EHint hint, IAllocator::EScope scope, + IAllocator::EType type, const CCallStack& callstack) { + volatile bool enabled = OSDisableInterrupts(); + void* ret = mpAllocator->Alloc(len, hint, scope, type, callstack); + if (ret == nullptr) { + rs_debugger_printf("Alloc failed - Size: %d", len); + } + + OSRestoreInterrupts(enabled); + return ret; +} + +void CMemory::Free(const void* ptr) { + volatile bool enabled = OSDisableInterrupts(); + if (ptr != nullptr) { + mpAllocator->Free(ptr); + } + OSRestoreInterrupts(enabled); +} + +void CMemory::SetOutOfMemoryCallback(IAllocator::FOutOfMemoryCb cb, const void* context) { + mpAllocator->SetOutOfMemoryCallback(cb, context); +} + +void CMemory::OffsetFakeStatics(int offset) { mpAllocator->OffsetFakeStatics(offset); } + +void* operator new(size_t sz, const char* fileAndLine, const char* type) { + return CMemory::Alloc(sz, IAllocator::kHI_None, IAllocator::kSC_Unk1, IAllocator::kTP_Heap, + CCallStack(-1, fileAndLine, type)); +} +void* operator new[](size_t sz, const char* fileAndLine, const char* type) { + return CMemory::Alloc(sz, IAllocator::kHI_None, IAllocator::kSC_Unk1, IAllocator::kTP_Array, + CCallStack(-1, fileAndLine, type)); +} diff --git a/src/Kyoto/Alloc/IAllocator.cpp b/src/Kyoto/Alloc/IAllocator.cpp index bac410b7..d165b826 100644 --- a/src/Kyoto/Alloc/IAllocator.cpp +++ b/src/Kyoto/Alloc/IAllocator.cpp @@ -1,5 +1,6 @@ #include "Kyoto/Alloc/IAllocator.hpp" +#include "Kyoto/Alloc/CMemory.hpp" #include "Kyoto/Basics/COsContext.hpp" IAllocator::SMetrics::SMetrics(uint heapSize, uint unk1, uint unk2, uint unk3, uint unk4,