diff --git a/include/Kyoto/Alloc/CGameAllocator.hpp b/include/Kyoto/Alloc/CGameAllocator.hpp index d65e892c..0b3aea10 100644 --- a/include/Kyoto/Alloc/CGameAllocator.hpp +++ b/include/Kyoto/Alloc/CGameAllocator.hpp @@ -11,6 +11,7 @@ class COsContext; class CGameAllocator : public IAllocator { public: class SGameMemInfo { + friend class CGameAllocator; public: SGameMemInfo(SGameMemInfo* prev, SGameMemInfo* next, SGameMemInfo* nextFree, uint len, const char* fileAndLine, const char* type) : x0_priorGuard(0xefefefef) @@ -46,6 +47,10 @@ public: } bool IsAllocated() const { return ((size_t)x10_prev) & 1; } + + bool IsPostGuardIntact() const { return x1c_postGuard == 0xeaeaeaea; } + bool IsPriorGuardIntact() const { return x0_priorGuard == 0xefefefef; } + private: int x0_priorGuard; size_t x4_len; @@ -75,7 +80,7 @@ public: bool FreeSecondary(const void* ptr) override; void ReleaseAllSecondary() override; void SetOutOfMemoryCallback(FOutOfMemoryCb cb, const void* target) override; - void EnumAllocations(FEnumAllocationsCb func, const void* ptr, bool b) const override; + int EnumAllocations(FEnumAllocationsCb func, const void* ptr, bool b) const override; SAllocInfo GetAllocInfo(const void* ptr) const override; SMetrics GetMetrics() const override; void OffsetFakeStatics(int offset) override; diff --git a/include/Kyoto/Alloc/CSmallAllocPool.hpp b/include/Kyoto/Alloc/CSmallAllocPool.hpp index 8ea46da4..f0326e6d 100644 --- a/include/Kyoto/Alloc/CSmallAllocPool.hpp +++ b/include/Kyoto/Alloc/CSmallAllocPool.hpp @@ -12,7 +12,6 @@ public: void* Alloc(uint size); bool Free(const void* ptr); -private: bool PtrWithinPool(const void* ptr) const { return u32((reinterpret_cast< const u8* >(ptr) - reinterpret_cast< u8* >(x0_mainData)) / 4) < x8_numBlocks; } diff --git a/include/Kyoto/Alloc/IAllocator.hpp b/include/Kyoto/Alloc/IAllocator.hpp index 38d3063b..16fe2a28 100644 --- a/include/Kyoto/Alloc/IAllocator.hpp +++ b/include/Kyoto/Alloc/IAllocator.hpp @@ -58,12 +58,21 @@ public: }; struct SAllocInfo { - void* x0_infoPtr; + const void* x0_infoPtr; uint x4_len; - bool x8_hasPrevious; + bool x8_isAllocated; bool x9_; - const char* xc_fileAndLne; + const char* xc_fileAndLine; const char* x10_type; + + SAllocInfo(const void* ptr, uint len, bool isAllocated, bool b2, const char* fileAndLine, + const char* type) + : x0_infoPtr(ptr) + , x4_len(len) + , x8_isAllocated(isAllocated) + , x9_(b2) + , xc_fileAndLine(fileAndLine) + , x10_type(type) {} }; typedef const bool (*FOutOfMemoryCb)(const void*, uint); @@ -81,7 +90,7 @@ public: virtual bool FreeSecondary(const void* ptr) = 0; virtual void ReleaseAllSecondary() = 0; virtual void SetOutOfMemoryCallback(FOutOfMemoryCb cb, const void* data) = 0; - virtual void EnumAllocations(FEnumAllocationsCb func, const void* ptr, bool b) const = 0; + virtual int EnumAllocations(FEnumAllocationsCb func, const void* ptr, bool b) const = 0; virtual SAllocInfo GetAllocInfo(const void* ptr) const = 0; virtual void OffsetFakeStatics(int offset) = 0; virtual SMetrics GetMetrics() const = 0; diff --git a/src/Kyoto/Alloc/CGameAllocator.cpp b/src/Kyoto/Alloc/CGameAllocator.cpp index 09b1e5d9..87ff6a06 100644 --- a/src/Kyoto/Alloc/CGameAllocator.cpp +++ b/src/Kyoto/Alloc/CGameAllocator.cpp @@ -68,7 +68,8 @@ void CGameAllocator::Shutdown() { x54_ = 0; } -void* CGameAllocator::Alloc(size_t size, EHint hint, EScope scope, EType type, const CCallStack& callstack) { +void* CGameAllocator::Alloc(size_t size, EHint hint, EScope scope, EType type, + const CCallStack& callstack) { OSTick startTick = OSGetTick(); if (hint & kHI_RoundUpLen) { @@ -113,7 +114,8 @@ void* CGameAllocator::Alloc(size_t size, EHint hint, EScope scope, EType type, c buf = x74_mediumPool->Alloc(size); if (buf == nullptr) { - buf = Alloc(0x21000, kHI_None, kSC_Unk1, kTP_Unk0, CCallStack(-1, "MediumAllocMainData ", " - Ignore")); + buf = Alloc(0x21000, kHI_None, kSC_Unk1, kTP_Unk0, + CCallStack(-1, "MediumAllocMainData ", " - Ignore")); x74_mediumPool->AddPuddle(0x1000, buf, 1); buf = x74_mediumPool->Alloc(size); } @@ -267,7 +269,8 @@ void CGameAllocator::ReleaseAll() { x10_last = nullptr; }; -void* CGameAllocator::AllocSecondary(size_t size, EHint hint, EScope scope, EType type, const CCallStack& callstack) { +void* CGameAllocator::AllocSecondary(size_t size, EHint hint, EScope scope, EType type, + const CCallStack& callstack) { Alloc(size, hint, scope, type, callstack); }; @@ -280,25 +283,58 @@ void CGameAllocator::SetOutOfMemoryCallback(FOutOfMemoryCb cb, const void* targe x5c_oomTarget = target; }; -IAllocator::SAllocInfo CGameAllocator::GetAllocInfo(const void* ptr) const {}; +IAllocator::SAllocInfo CGameAllocator::GetAllocInfo(const void* ptr) const { + SGameMemInfo* info = GetMemInfoFromBlockPtr(ptr); + + return SAllocInfo((const void*)info, info->GetLength(), info->IsAllocated(), false, + info->x8_fileAndLine, info->xc_type); +}; IAllocator::SMetrics CGameAllocator::GetMetrics() const { - u32 mediumAllocTotalAllocated = x74_mediumPool != nullptr ? x74_mediumPool->GetTotalEntries() * 32 : 0; - u32 mediumAllocBlocksAvailable = x74_mediumPool != nullptr ? x74_mediumPool->GetNumBlocksAvailable() : 0; + u32 mediumAllocTotalAllocated = + x74_mediumPool != nullptr ? x74_mediumPool->GetTotalEntries() * 32 : 0; + u32 mediumAllocBlocksAvailable = + x74_mediumPool != nullptr ? x74_mediumPool->GetNumBlocksAvailable() : 0; u32 mediumAllocAllocatedSize = - x74_mediumPool != nullptr ? x74_mediumPool->GetTotalEntries() - x74_mediumPool->GetNumBlocksAvailable() : 0; + x74_mediumPool != nullptr + ? x74_mediumPool->GetTotalEntries() - x74_mediumPool->GetNumBlocksAvailable() + : 0; u32 mediumAllocNumAllocs = x74_mediumPool != nullptr ? x74_mediumPool->GetNumAllocs() : 0; SMetrics ret(x8_heapSize, x80_, x84_, x88_, x8c_, x90_heapSize2, x94_, x98_, x9c_, xa0_, xa4_, x60_smallAllocPool != nullptr ? x60_smallAllocPool->GetNumAllocs() : 0, x60_smallAllocPool != nullptr ? x60_smallAllocPool->GetAllocatedSize() : 0, - x60_smallAllocPool != nullptr ? x60_smallAllocPool->GetNumBlocksAvailable() : 0, mediumAllocNumAllocs, - mediumAllocAllocatedSize, mediumAllocBlocksAvailable, x80_ - xb0_, (uint)xb4_physicalAddr, xbc_, mediumAllocTotalAllocated, + x60_smallAllocPool != nullptr ? x60_smallAllocPool->GetNumBlocksAvailable() : 0, + mediumAllocNumAllocs, mediumAllocAllocatedSize, mediumAllocBlocksAvailable, + x80_ - xb0_, (uint)xb4_physicalAddr, xbc_, mediumAllocTotalAllocated, xb8_fakeStatics); xb0_ = x80_; return ret; }; -void CGameAllocator::EnumAllocations(FEnumAllocationsCb func, const void* ptr, bool b) const {}; +int CGameAllocator::EnumAllocations(FEnumAllocationsCb func, const void* ptr, bool b) const { + + int i = 0; + SGameMemInfo* iter = xc_first; + + while (iter != nullptr) { + if (!iter->IsPostGuardIntact()) { + return -1; + } + + if (!iter->IsPriorGuardIntact()) { + return -1; + } + + SGameMemInfo* next = iter->GetNext(); + SAllocInfo alloc((const void*)iter, iter->GetLength(), iter->IsAllocated(), false, + iter->x8_fileAndLine, iter->xc_type); + func(alloc, ptr); + ++i; + iter = next; + } + + return i; +}; uint CGameAllocator::GetFreeBinEntryForSize(uint size) { uint maxLen = 0x20; @@ -371,4 +407,4 @@ size_t CGameAllocator::GetLargestFreeChunk() const { return ret; } -void CGameAllocator::OffsetFakeStatics(int offset) { xb8_fakeStatics += offset; }; +void CGameAllocator::OffsetFakeStatics(int offset) { xb8_fakeStatics += offset; }