diff --git a/configure.py b/configure.py index 30f1ab3bf..7826ed5b7 100644 --- a/configure.py +++ b/configure.py @@ -762,7 +762,7 @@ config.libs = [ Object(Matching, "JSystem/JKernel/JKRDisposer.cpp"), Object(Matching, "JSystem/JKernel/JKRThread.cpp"), Object(Matching, "JSystem/JKernel/JKRAram.cpp"), - Object(NonMatching, "JSystem/JKernel/JKRAramHeap.cpp"), + Object(Matching, "JSystem/JKernel/JKRAramHeap.cpp"), Object(NonMatching, "JSystem/JKernel/JKRAramBlock.cpp"), Object(NonMatching, "JSystem/JKernel/JKRAramPiece.cpp"), Object(NonMatching, "JSystem/JKernel/JKRAramStream.cpp"), diff --git a/include/JSystem/JKernel/JKRAramBlock.h b/include/JSystem/JKernel/JKRAramBlock.h index 15058145b..630547f07 100644 --- a/include/JSystem/JKernel/JKRAramBlock.h +++ b/include/JSystem/JKernel/JKRAramBlock.h @@ -29,7 +29,7 @@ public: /* 0x18 */ u32 mSize; /* 0x1C */ u32 mFreeSize; /* 0x20 */ u8 mGroupId; - /* 0x21 */ u8 mIsTempMemory; + /* 0x21 */ bool mIsTempMemory; /* 0x22 */ u8 padding[2]; }; diff --git a/src/JSystem/JKernel/JKRAramHeap.cpp b/src/JSystem/JKernel/JKRAramHeap.cpp index 78b974efc..ab2488349 100644 --- a/src/JSystem/JKernel/JKRAramHeap.cpp +++ b/src/JSystem/JKernel/JKRAramHeap.cpp @@ -4,49 +4,152 @@ // #include "JSystem/JKernel/JKRAramHeap.h" -#include "dolphin/types.h" +#include "JSystem/JKernel/JKRHeap.h" +#include "dolphin/os/OS.h" +#include "global.h" + +JSUList JKRAramHeap::sAramList; /* 802B53E8-802B54B8 .text __ct__11JKRAramHeapFUlUl */ -JKRAramHeap::JKRAramHeap(unsigned long, unsigned long) { - /* Nonmatching */ +JKRAramHeap::JKRAramHeap(u32 startAddress, u32 size) { + OSInitMutex(&mMutex); + + mHeap = JKRHeap::findFromRoot(this); + mSize = ALIGN_PREV(size, 0x20); + mHeadAddress = ALIGN_NEXT(startAddress, 0x20); + mTailAddress = mHeadAddress + mSize; + mGroupId = -1; + + JKRAramBlock* block = new (mHeap, 0) JKRAramBlock(mHeadAddress, 0, mSize, -1, false); + sAramList.append(&block->mBlockLink); } /* 802B54B8-802B5560 .text __dt__11JKRAramHeapFv */ JKRAramHeap::~JKRAramHeap() { - /* Nonmatching */ + JSUListIterator iterator(sAramList.getFirst()); + while (iterator != sAramList.getEnd()) { + delete (iterator++).getObject(); + } } /* 802B5560-802B55D8 .text alloc__11JKRAramHeapFUlQ211JKRAramHeap10EAllocMode */ -void JKRAramHeap::alloc(unsigned long, JKRAramHeap::EAllocMode) { - /* Nonmatching */ +JKRAramBlock* JKRAramHeap::alloc(u32 size, JKRAramHeap::EAllocMode allocationMode) { + lock(); + + JKRAramBlock* block; + if (allocationMode == JKRAramHeap::HEAD) { + block = allocFromHead(size); + } else { + block = allocFromTail(size); + } + + unlock(); + return block; } /* 802B55D8-802B5660 .text allocFromHead__11JKRAramHeapFUl */ -void JKRAramHeap::allocFromHead(unsigned long) { - /* Nonmatching */ +JKRAramBlock* JKRAramHeap::allocFromHead(u32 size) { + u32 alignedSize = ALIGN_NEXT(size, 0x20); + u32 bestFreeSize = UINT32_MAX; + JKRAramBlock* bestBlock = NULL; + + JSUList* list = &sAramList; + for (JSUListIterator iterator = list; iterator != list->getEnd(); ++iterator) { + JKRAramBlock* block = iterator.getObject(); + if (block->mFreeSize < alignedSize) + continue; + if (bestFreeSize <= block->mFreeSize) + continue; + + bestFreeSize = block->mFreeSize; + bestBlock = block; + + if (block->mFreeSize == alignedSize) { + break; + } + } + + if (bestBlock) { + return bestBlock->allocHead(alignedSize, mGroupId, this); + } + + return NULL; } /* 802B5660-802B56D8 .text allocFromTail__11JKRAramHeapFUl */ -void JKRAramHeap::allocFromTail(unsigned long) { - /* Nonmatching */ +JKRAramBlock* JKRAramHeap::allocFromTail(u32 size) { + u32 alignedSize = ALIGN_NEXT(size, 0x20); + JKRAramBlock* tailBlock = NULL; + + JSUList* list = &sAramList; + JSUListIterator iterator = list->getLast(); + for (; iterator != list->getEnd(); --iterator) { + JKRAramBlock* block = iterator.getObject(); + if (block->mFreeSize >= alignedSize) { + tailBlock = block; + break; + } + } + + if (tailBlock) { + return tailBlock->allocTail(alignedSize, mGroupId, this); + } + + return NULL; } /* 802B56D8-802B5750 .text getFreeSize__11JKRAramHeapFv */ -void JKRAramHeap::getFreeSize() { - /* Nonmatching */ +u32 JKRAramHeap::getFreeSize() { + u32 maxFreeSize = 0; + + lock(); + + JSUList* list = &sAramList; + JSUListIterator iterator = list; + for (; iterator != list->getEnd(); ++iterator) { + if (iterator->mFreeSize > maxFreeSize) { + maxFreeSize = iterator->mFreeSize; + } + } + + unlock(); + return maxFreeSize; } /* 802B5750-802B57BC .text getTotalFreeSize__11JKRAramHeapFv */ -void JKRAramHeap::getTotalFreeSize() { - /* Nonmatching */ +u32 JKRAramHeap::getTotalFreeSize() { + u32 totalFreeSize = 0; + + lock(); + + JSUList* list = &sAramList; + JSUListIterator iterator = list; + for (; iterator != list->getEnd(); ++iterator) { + totalFreeSize += iterator->mFreeSize; + } + + unlock(); + return totalFreeSize; } /* 802B57BC-802B590C .text dump__11JKRAramHeapFv */ void JKRAramHeap::dump() { - /* Nonmatching */ -} + lock(); -/* 802B5950-802B59A4 .text __dt__23JSUList<12JKRAramBlock>Fv */ -JSUList::~JSUList() { - /* Nonmatching */ + OSReport("\nJKRAramHeap dump\n"); + OSReport(" attr address: size gid\n"); + u32 bytesUsed = 0; + for (JSUListIterator iterator = sAramList.getFirst() ; iterator != sAramList.getEnd(); ++iterator) { + if (iterator->mSize) { + const char* type; + OSReport("%s %08x: %08x %3d\n", iterator->isTempMemory() ? " temp" : "alloc", iterator->mAddress, iterator->mSize, iterator->mGroupId); + } + if (iterator->mFreeSize) { + OSReport(" free %08x: %08x 0\n", iterator->mAddress + iterator->mSize, iterator->mFreeSize); + } + bytesUsed += iterator->mSize; + } + OSReport("%d / %d bytes (%6.2f%%) used\n", bytesUsed, mSize, (f32)bytesUsed / (f32)mSize * 100.0f); + + unlock(); }