From 80f6963c480afb1201347a92bd5c8f6c7596a7a0 Mon Sep 17 00:00:00 2001 From: enzo Date: Tue, 31 Mar 2026 19:14:22 -0300 Subject: [PATCH 1/6] add heap.c --- config/eur/arm9/delinks.txt | 3 + config/eur/arm9/symbols.txt | 32 +-- config/usa/arm9/delinks.txt | 3 + config/usa/arm9/symbols.txt | 32 +-- libs/nds/include/nds/heap.h | 55 ++++ libs/nds/src/heap.c | 394 ++++++++++++++++++++++++++ src/04_Load/Actor/ActorManager_04.cpp | 8 +- src/08_GameStart/Init.cpp | 8 +- 8 files changed, 495 insertions(+), 40 deletions(-) create mode 100644 libs/nds/include/nds/heap.h create mode 100644 libs/nds/src/heap.c diff --git a/config/eur/arm9/delinks.txt b/config/eur/arm9/delinks.txt index 3b906b159..d75f97c7c 100644 --- a/config/eur/arm9/delinks.txt +++ b/config/eur/arm9/delinks.txt @@ -83,3 +83,6 @@ src/Main/DTCM/UnkStruct_027e05f8_2.cpp: .init start:0x02050cb4 end:0x02050ce0 .ctor start:0x02057260 end:0x02057264 .dtcm start:0x027e05f8 end:0x027e060c + +libs/nds/src/heap.c: + .text start:0x02017034 end:0x02017530 \ No newline at end of file diff --git a/config/eur/arm9/symbols.txt b/config/eur/arm9/symbols.txt index b5cfcfa72..bb2c3ba0c 100644 --- a/config/eur/arm9/symbols.txt +++ b/config/eur/arm9/symbols.txt @@ -677,22 +677,22 @@ func_02016efc kind:function(thumb,size=0xd0) addr:0x02016efc func_02016fcc kind:function(thumb,size=0x1a) addr:0x02016fcc func_02016fe8 kind:function(thumb,size=0x2e) addr:0x02016fe8 func_02017018 kind:function(thumb,size=0x1c) addr:0x02017018 -func_02017034 kind:function(thumb,size=0x1a) addr:0x02017034 -func_02017050 kind:function(thumb,size=0x1c) addr:0x02017050 -func_0201706c kind:function(thumb,size=0x20) addr:0x0201706c -func_0201708c kind:function(thumb,size=0x1a) addr:0x0201708c -func_020170a8 kind:function(thumb,size=0x50) addr:0x020170a8 -func_020170f8 kind:function(thumb,size=0x100) addr:0x020170f8 -func_020171f8 kind:function(thumb,size=0x7c) addr:0x020171f8 -func_02017274 kind:function(thumb,size=0x74) addr:0x02017274 -func_020172e8 kind:function(thumb,size=0x8c) addr:0x020172e8 -func_02017374 kind:function(thumb,size=0x20) addr:0x02017374 -func_02017394 kind:function(thumb,size=0x8) addr:0x02017394 -NewEXPH kind:function(thumb,size=0x20) addr:0x0201739c -func_020173bc kind:function(thumb,size=0xe8) addr:0x020173bc -func_020174a4 kind:function(thumb,size=0x2a) addr:0x020174a4 -func_020174d0 kind:function(thumb,size=0x16) addr:0x020174d0 -func_020174e8 kind:function(thumb,size=0x46) addr:0x020174e8 +Heap_GetRegion kind:function(thumb,size=0x1a) addr:0x02017034 +Heap_RemoveBlock kind:function(thumb,size=0x1c) addr:0x02017050 +Heap_InsertBlock kind:function(thumb,size=0x20) addr:0x0201706c +Heap_InitBlock kind:function(thumb,size=0x1a) addr:0x0201708c +Heap_EXPHInit kind:function(thumb,size=0x50) addr:0x020170a8 +Heap_AllocFreeBlock kind:function(thumb,size=0x100) addr:0x020170f8 +Heap_AllocHead kind:function(thumb,size=0x7c) addr:0x020171f8 +Heap_AllocTail kind:function(thumb,size=0x74) addr:0x02017274 +Heap_EmptyRegion kind:function(thumb,size=0x8c) addr:0x020172e8 +Heap_EXPHCreate kind:function(thumb,size=0x20) addr:0x02017374 +Heap_EXPHDestroy kind:function(thumb,size=0x8) addr:0x02017394 +Heap_EXPHNew kind:function(thumb,size=0x20) addr:0x0201739c +Heap_EXPHResizeBlock kind:function(thumb,size=0xe8) addr:0x020173bc +Heap_EXPHFreeBlock kind:function(thumb,size=0x2a) addr:0x020174a4 +Heap_EXPHGetEmptySize kind:function(thumb,size=0x16) addr:0x020174d0 +Heap_EXPHGetMaxEmptySize kind:function(thumb,size=0x46) addr:0x020174e8 func_02017530 kind:function(thumb,size=0x2c) addr:0x02017530 func_0201755c kind:function(thumb,size=0x3e) addr:0x0201755c func_0201759c kind:function(thumb,size=0x3c) addr:0x0201759c diff --git a/config/usa/arm9/delinks.txt b/config/usa/arm9/delinks.txt index 5f43dfcb4..c4600260e 100644 --- a/config/usa/arm9/delinks.txt +++ b/config/usa/arm9/delinks.txt @@ -79,3 +79,6 @@ src/Main/DTCM/UnkStruct_027e05f8_2.cpp: .init start:0x02050c70 end:0x02050c9c .ctor start:0x02057218 end:0x0205721c .dtcm start:0x027e05f8 end:0x027e060c + +libs/nds/src/heap.c: + .text start:0x02017034 end:0x02017530 \ No newline at end of file diff --git a/config/usa/arm9/symbols.txt b/config/usa/arm9/symbols.txt index f51170221..43c445e29 100644 --- a/config/usa/arm9/symbols.txt +++ b/config/usa/arm9/symbols.txt @@ -677,22 +677,22 @@ func_02016efc kind:function(thumb,size=0xd0) addr:0x02016efc func_02016fcc kind:function(thumb,size=0x1a) addr:0x02016fcc func_02016fe8 kind:function(thumb,size=0x2e) addr:0x02016fe8 func_02017018 kind:function(thumb,size=0x1c) addr:0x02017018 -func_02017034 kind:function(thumb,size=0x1a) addr:0x02017034 -func_02017050 kind:function(thumb,size=0x1c) addr:0x02017050 -func_0201706c kind:function(thumb,size=0x20) addr:0x0201706c -func_0201708c kind:function(thumb,size=0x1a) addr:0x0201708c -func_020170a8 kind:function(thumb,size=0x50) addr:0x020170a8 -func_020170f8 kind:function(thumb,size=0x100) addr:0x020170f8 -func_020171f8 kind:function(thumb,size=0x7c) addr:0x020171f8 -func_02017274 kind:function(thumb,size=0x74) addr:0x02017274 -func_020172e8 kind:function(thumb,size=0x8c) addr:0x020172e8 -func_02017374 kind:function(thumb,size=0x20) addr:0x02017374 -func_02017394 kind:function(thumb,size=0x8) addr:0x02017394 -NewEXPH kind:function(thumb,size=0x20) addr:0x0201739c -func_020173bc kind:function(thumb,size=0xe8) addr:0x020173bc -func_020174a4 kind:function(thumb,size=0x2a) addr:0x020174a4 -func_020174d0 kind:function(thumb,size=0x16) addr:0x020174d0 -func_020174e8 kind:function(thumb,size=0x46) addr:0x020174e8 +Heap_GetRegion kind:function(thumb,size=0x1a) addr:0x02017034 +Heap_RemoveBlock kind:function(thumb,size=0x1c) addr:0x02017050 +Heap_InsertBlock kind:function(thumb,size=0x20) addr:0x0201706c +Heap_InitBlock kind:function(thumb,size=0x1a) addr:0x0201708c +Heap_EXPHInit kind:function(thumb,size=0x50) addr:0x020170a8 +Heap_AllocFreeBlock kind:function(thumb,size=0x100) addr:0x020170f8 +Heap_AllocHead kind:function(thumb,size=0x7c) addr:0x020171f8 +Heap_AllocTail kind:function(thumb,size=0x74) addr:0x02017274 +Heap_EmptyRegion kind:function(thumb,size=0x8c) addr:0x020172e8 +Heap_EXPHCreate kind:function(thumb,size=0x20) addr:0x02017374 +Heap_EXPHDestroy kind:function(thumb,size=0x8) addr:0x02017394 +Heap_EXPHNew kind:function(thumb,size=0x20) addr:0x0201739c +Heap_EXPHResizeBlock kind:function(thumb,size=0xe8) addr:0x020173bc +Heap_EXPHFreeBlock kind:function(thumb,size=0x2a) addr:0x020174a4 +Heap_EXPHGetEmptySize kind:function(thumb,size=0x16) addr:0x020174d0 +Heap_EXPHGetMaxEmptySize kind:function(thumb,size=0x46) addr:0x020174e8 func_02017530 kind:function(thumb,size=0x2c) addr:0x02017530 func_0201755c kind:function(thumb,size=0x3e) addr:0x0201755c func_0201759c kind:function(thumb,size=0x3c) addr:0x0201759c diff --git a/libs/nds/include/nds/heap.h b/libs/nds/include/nds/heap.h new file mode 100644 index 000000000..e5bbcefb6 --- /dev/null +++ b/libs/nds/include/nds/heap.h @@ -0,0 +1,55 @@ +#include "global.h" +#include "types.h" + +typedef struct Heap_Region_ { + /* 00 */ void *start; + /* 04 */ void *end; + /* 08 */ +} Heap_Region; + +typedef struct Heap_LinkedObject_ { + /* 00 */ void *prev; + /* 04 */ void *next; + /* 08 */ +} Heap_LinkedObject; + +typedef struct Heap_LinkedList_ { + /* 00 */ void *head; + /* 04 */ void *tail; + /* 08 */ u16 numElements; + /* 0a */ u16 offset; + /* 0c */ +} Heap_LinkedList; + +typedef struct Heap_Header_ { + /* 00 */ u32 stamp; + /* 04 */ Heap_LinkedObject link; + /* 0c */ Heap_LinkedList children; + /* 18 */ void *startAddr; + /* 1c */ void *endAddr; + /* 20 */ u32 flags; + /* 24 */ +} Heap_Header; + +typedef struct Heap_EXPHBlockHeader_ { + /* 00 */ u16 stamp; + /* 02 */ u16 flags; + /* 04 */ u32 size; + /* 08 */ struct Heap_EXPHBlockHeader_ *prev; + /* 0c */ struct Heap_EXPHBlockHeader_ *next; + /* 20 */ +} Heap_EXPHBlockHeader; + +typedef struct Heap_EXPHBlockList_ { + /* 00 */ Heap_EXPHBlockHeader *head; + /* 04 */ Heap_EXPHBlockHeader *tail; + /* 08 */ +} Heap_EXPHBlockList; + +typedef struct Heap_EXPHHeader_ { + /* 00 */ Heap_EXPHBlockList freeBlocks; + /* 08 */ Heap_EXPHBlockList usedBlocks; + /* 10 */ u16 id; + /* 12 */ u16 flags; + /* 14 */ +} Heap_EXPHHeader; \ No newline at end of file diff --git a/libs/nds/src/heap.c b/libs/nds/src/heap.c new file mode 100644 index 000000000..3eafb0611 --- /dev/null +++ b/libs/nds/src/heap.c @@ -0,0 +1,394 @@ +#include "nds/heap.h" + +#define SetBit(data, st, bits, val) \ + { \ + u32 maskBits = ((1 << bits) - 1); \ + u32 newVal = val & maskBits; \ + maskBits <<= st; \ + data &= ~maskBits; \ + data |= newVal << st; \ + }; + +static inline u32 Diff_Ptr_inline(const void *start, const void *end) { + return end - start; +} + +static inline void *AddU32_inline(void *ptr, u32 val) { + return (void *) (val + (u32) ptr); +} + +static inline void Fill32_inline(Heap_Header *header, void *address, u32 size) { + if ((u16) (header->flags & 0xFF) & 1) { + Fill32(0, address, size); + } +} + +static inline Heap_EXPHHeader *GetEXPH_inline(Heap_Header *header) { + return (u32) header + sizeof(Heap_Header); +} + +THUMB void Heap_GetRegion(Heap_Region *region, Heap_EXPHBlockHeader *block) { + region->start = (u32) block - (u16) (block->flags >> 8 & 0x7F); + region->end = block->size + ((u32) block + sizeof(Heap_EXPHBlockHeader)); +} + +Heap_EXPHBlockHeader *Heap_RemoveBlock(Heap_EXPHBlockList *list, Heap_EXPHBlockHeader *block) { + Heap_EXPHBlockHeader *const p = block->prev; + Heap_EXPHBlockHeader *const n = block->next; + + if (p) { + p->next = n; + } else { + list->head = n; + } + + if (n) { + n->prev = p; + } else { + list->tail = p; + } + + return p; +} + +Heap_EXPHBlockHeader *Heap_InsertBlock(Heap_EXPHBlockList *list, Heap_EXPHBlockHeader *block, Heap_EXPHBlockHeader *prev) { + Heap_EXPHBlockHeader *next; + + block->prev = prev; + if (prev) { + next = prev->next; + prev->next = block; + } else { + next = list->head; + list->head = block; + } + + block->next = next; + if (next) { + next->prev = block; + } else { + list->tail = block; + } + + return block; +} + +Heap_EXPHBlockHeader *Heap_InitBlock(const Heap_Region *r, u16 stamp) { + Heap_EXPHBlockHeader *block = r->start; + block->stamp = stamp; + block->flags = 0; + block->size = r->end - ((u32) block + 0x10); + block->prev = NULL; + block->next = NULL; + return block; +} + +Heap_Header *Heap_EXPHInit(void *start, void *end, u16 flag) { + Heap_EXPHBlockHeader *emptyBlock; + Heap_Region region; + Heap_Header *header = start; + Heap_EXPHHeader *EXPHHeader = (void *) ((u32) header + sizeof(Heap_Header)); + + func_0201776c(header, 'EXPH', (void *) ((u32) EXPHHeader + sizeof(Heap_EXPHHeader)), end, flag); + + EXPHHeader->id = 0; + EXPHHeader->flags = 0; + SetBit(EXPHHeader->flags, 0, 1, 0); + + region.start = header->startAddr; + region.end = header->endAddr; + emptyBlock = Heap_InitBlock(®ion, 'FR'); + + EXPHHeader->freeBlocks.head = emptyBlock; + EXPHHeader->freeBlocks.tail = emptyBlock; + EXPHHeader->usedBlocks.head = NULL; + EXPHHeader->usedBlocks.tail = NULL; + + return header; +} + +void *Heap_AllocFreeBlock(Heap_EXPHHeader *EXPHHeader, Heap_EXPHBlockHeader *blockHeader, void *block, u32 size, + u16 direction) { + Heap_Region free1; + Heap_Region free2; + Heap_EXPHBlockHeader *prev; + Heap_EXPHBlockHeader *usedBlock; + Heap_Region r; + + Heap_GetRegion(&free1, blockHeader); + free2.end = free1.end; + free2.start = AddU32_inline(block, size); + free1.end = (u32) block - (u32) sizeof(Heap_EXPHBlockHeader); + prev = Heap_RemoveBlock(&EXPHHeader->freeBlocks, blockHeader); + + if (free1.end - free1.start < (u32) 0x14) { + free1.end = free1.start; + } else { + prev = Heap_InsertBlock(&EXPHHeader->freeBlocks, Heap_InitBlock(&free1, 'FR'), prev); + } + + if (free2.end - free2.start < (u32) 0x14) { + free2.start = free2.end; + } else { + Heap_InsertBlock(&EXPHHeader->freeBlocks, Heap_InitBlock(&free2, 'FR'), prev); + } + + Fill32_inline((u32) EXPHHeader - sizeof(Heap_Header), free1.end, free2.start - free1.end); + + r.start = (u32) block - (u32) sizeof(Heap_EXPHBlockHeader); + r.end = free2.start; + usedBlock = Heap_InitBlock(&r, 'UD'); + SetBit(usedBlock->flags, 15, 1, direction); + SetBit(usedBlock->flags, 8, 7, (u16) Diff_Ptr_inline(free1.end, usedBlock)); + SetBit(usedBlock->flags, 0, 8, EXPHHeader->id); + Heap_InsertBlock(&EXPHHeader->usedBlocks, usedBlock, EXPHHeader->usedBlocks.tail); + return block; +} + +void *Heap_AllocHead(Heap_Header *header, u32 size, int alignment) { + Heap_EXPHHeader *expHeader = GetEXPH_inline(header); + Heap_EXPHBlockHeader *blockHeader; + const u32 flag1 = (u16) (expHeader->flags & 1) == 0; + + Heap_EXPHBlockHeader *foundBlockHeader = NULL; + u32 foundSize = 0xffffffff; + void *foundBlock = NULL; + + for (blockHeader = expHeader->freeBlocks.head; blockHeader; blockHeader = blockHeader->next) { + void *const mblock = AddU32_inline(blockHeader, sizeof(Heap_EXPHBlockHeader)); + void *const reqBlock = ((alignment - 1) + (u32) mblock) & ~(alignment - 1); + const u32 offset = reqBlock - mblock; + + if (blockHeader->size >= size + offset && foundSize > blockHeader->size) { + foundBlockHeader = blockHeader; + foundSize = blockHeader->size; + foundBlock = reqBlock; + + if (flag1 || foundSize == size) { + break; + } + } + } + + if (!foundBlockHeader) { + return NULL; + } + + return Heap_AllocFreeBlock(expHeader, foundBlockHeader, foundBlock, size, 0); +} + +void *Heap_AllocTail(Heap_Header *header, u32 size, int alignment) { + Heap_EXPHHeader *expHeader = GetEXPH_inline(header); + Heap_EXPHBlockHeader *blockHeader; + + const u32 flag1 = (u16) (expHeader->flags & 1) == 0; + + Heap_EXPHBlockHeader *foundBlockHeader = NULL; + u32 foundSize = 0xffffffff; + void *foundBlock = NULL; + + for (blockHeader = expHeader->freeBlocks.tail; blockHeader; blockHeader = blockHeader->prev) { + void *const mblock = AddU32_inline(blockHeader, sizeof(Heap_EXPHBlockHeader)); + void *const mblockEnd = AddU32_inline(mblock, blockHeader->size); + void *const reqBlock = (u32) (mblockEnd - size) & ~(alignment - 1); + + if (reqBlock - mblock >= 0 && foundSize > blockHeader->size) { + foundBlockHeader = blockHeader; + foundSize = blockHeader->size; + foundBlock = reqBlock; + + if (flag1 || foundSize == size) { + break; + } + } + } + + if (!foundBlockHeader) { + return NULL; + } + + return Heap_AllocFreeBlock(expHeader, foundBlockHeader, foundBlock, size, 1); +} + +u32 Heap_EmptyRegion(Heap_EXPHHeader *expHeader, const Heap_Region *r) { + Heap_EXPHBlockHeader *freeBlockHeader = NULL; + Heap_Region freeRgn = *r; + Heap_EXPHBlockHeader *block; + + for (block = expHeader->freeBlocks.head; block; block = block->next) { + if (block < r->start) { + freeBlockHeader = block; + continue; + } + + if (block == r->end) { + freeRgn.end = AddU32_inline(AddU32_inline(block, sizeof(Heap_EXPHBlockHeader)), block->size); + Heap_RemoveBlock(&expHeader->freeBlocks, block); + } + break; + } + + if (freeBlockHeader && + AddU32_inline(AddU32_inline(freeBlockHeader, sizeof(Heap_EXPHBlockHeader)), freeBlockHeader->size) == r->start) { + freeRgn.start = freeBlockHeader; + freeBlockHeader = Heap_RemoveBlock(&expHeader->freeBlocks, freeBlockHeader); + } + + if (freeRgn.end - freeRgn.start < sizeof(Heap_EXPHBlockHeader)) { + return 0; + } + + Heap_InsertBlock(&expHeader->freeBlocks, Heap_InitBlock(&freeRgn, 'FR'), freeBlockHeader); + return 1; +} + +Heap_Header *Heap_EXPHCreate(void *startAddress, u32 size, u16 optFlag) { + void *endAddress; + Heap_Header *header; + endAddress = ((u32) AddU32_inline(startAddress, size)) & ~3; + startAddress = (u32) startAddress + 3 & ~3; + + if (startAddress > endAddress || endAddress - startAddress < (u32) 0x4c) { + return NULL; + } + + header = Heap_EXPHInit(startAddress, endAddress, optFlag); + return header; +} + +void Heap_EXPHDestroy(Heap_Header *heap) { + func_020177c8(heap); +} + +void *Heap_EXPHNew(Heap_Header *heap, u32 size, int alignment) { + void *h = NULL; + + if (size == 0) { + size = 1; + } + + size = (size + 3) & ~3; + + if (alignment >= 0) { + h = Heap_AllocHead(heap, size, alignment); + } else { + h = Heap_AllocTail(heap, size, -alignment); + } + + return h; +} + +u32 Heap_EXPHResizeBlock(Heap_Header *heap, void *memBlock, u32 size) { + Heap_EXPHHeader *expHeader; + Heap_EXPHBlockHeader *blockHeader; + + expHeader = AddU32_inline(heap, sizeof(Heap_Header)); + blockHeader = (u32) memBlock - sizeof(Heap_EXPHBlockHeader); + + size = (size + 3) & ~3; + if (size == blockHeader->size) { + return size; + } + + if (size > blockHeader->size) { + void *end = AddU32_inline(AddU32_inline(blockHeader, sizeof(Heap_EXPHBlockHeader)), blockHeader->size); + Heap_EXPHBlockHeader *block; + Heap_Region tmpRgn; + void *tmpStart; + Heap_EXPHBlockHeader *newPrev; + + for (block = expHeader->freeBlocks.head; block; block = block->next) { + if (block == end) { + break; + } + } + + if (!block || size > blockHeader->size + sizeof(Heap_EXPHBlockHeader) + block->size) { + return 0; + } + + Heap_GetRegion(&tmpRgn, block); + newPrev = Heap_RemoveBlock(&expHeader->freeBlocks, block); + + tmpStart = tmpRgn.start; + tmpRgn.start = AddU32_inline(memBlock, size); + + if (tmpRgn.end - tmpRgn.start < sizeof(Heap_EXPHBlockHeader)) { + tmpRgn.start = tmpRgn.end; + } + + blockHeader->size = tmpRgn.start - memBlock; + + if (tmpRgn.end - tmpRgn.start >= sizeof(Heap_EXPHBlockHeader)) { + Heap_InsertBlock(&expHeader->freeBlocks, Heap_InitBlock(&tmpRgn, 'FR'), newPrev); + } + + Fill32_inline(heap, tmpStart, tmpRgn.start - tmpStart); + + } else { + Heap_Region tmpRgn; + const u32 oldBlockSize = blockHeader->size; + + tmpRgn.start = AddU32_inline(memBlock, size); + tmpRgn.end = AddU32_inline(AddU32_inline(blockHeader, sizeof(Heap_EXPHBlockHeader)), blockHeader->size); + blockHeader->size = size; + + if (!Heap_EmptyRegion(expHeader, &tmpRgn)) { + blockHeader->size = oldBlockSize; + } + } + + return blockHeader->size; +} + +void Heap_EXPHFreeBlock(Heap_Header *heap, void *memBlock) { + Heap_Header *header = heap; + Heap_EXPHHeader *expHeader = AddU32_inline(header, sizeof(Heap_Header)); + Heap_EXPHBlockHeader *blockHeader = (Heap_EXPHBlockHeader *) (memBlock - sizeof(Heap_EXPHBlockHeader)); + Heap_Region region; + + Heap_GetRegion(®ion, blockHeader); + Heap_RemoveBlock(&expHeader->usedBlocks, blockHeader); + Heap_EmptyRegion(expHeader, ®ion); +} + +u32 Heap_EXPHGetEmptySize(Heap_Header *heap) { + u32 totalSize = 0; + Heap_EXPHBlockHeader *blockHeader; + Heap_EXPHHeader *expHeader = AddU32_inline(heap, sizeof(Heap_Header)); + + for (blockHeader = expHeader->freeBlocks.head; blockHeader; blockHeader = blockHeader->next) { + totalSize += blockHeader->size; + } + + return totalSize; +} + +u32 Heap_EXPHGetMaxEmptySize(Heap_Header *heap, int alignment) { + + alignment = abs(alignment); + + { + Heap_EXPHHeader *expHeader = AddU32_inline(heap, sizeof(Heap_Header)); + u32 maxSize = 0; + u32 offsetMin = 0xFFFFFFFF; + Heap_EXPHBlockHeader *blockHeader; + + for (blockHeader = expHeader->freeBlocks.head; blockHeader; blockHeader = blockHeader->next) { + void *baseAddress = + ((u32) AddU32_inline(blockHeader, sizeof(Heap_EXPHBlockHeader)) + (alignment - 1)) & ~(alignment - 1); + + if (baseAddress < AddU32_inline(AddU32_inline(blockHeader, sizeof(Heap_EXPHBlockHeader)), blockHeader->size)) { + const u32 blockSize = + AddU32_inline(AddU32_inline(blockHeader, sizeof(Heap_EXPHBlockHeader)), blockHeader->size) - baseAddress; + const u32 offset = baseAddress - AddU32_inline(blockHeader, sizeof(Heap_EXPHBlockHeader)); + + if (maxSize < blockSize || (maxSize == blockSize && offsetMin > offset)) { + maxSize = blockSize; + offsetMin = offset; + } + } + } + return maxSize; + } +} \ No newline at end of file diff --git a/src/04_Load/Actor/ActorManager_04.cpp b/src/04_Load/Actor/ActorManager_04.cpp index 84a1f9702..fdf8fe763 100644 --- a/src/04_Load/Actor/ActorManager_04.cpp +++ b/src/04_Load/Actor/ActorManager_04.cpp @@ -129,7 +129,7 @@ THUMB void ActorManager::func_ov004_0210532c() { return; } -extern "C" void func_020174a4(u32 *, void *); +extern "C" void Heap_EXPHFreeBlock(u32 *, void *); extern "C" void func_ov017_02168a90(); extern "C" void func_ov025_0216d6dc(); extern "C" void func_ov029_0216d6f0(unk32 *); @@ -147,7 +147,7 @@ THUMB void ActorManager::func_ov004_021053dc() { this->DeleteActor(i, true); } } - func_020174a4(data_027e0ce0[1], this->mActorTable); + Heap_EXPHFreeBlock(data_027e0ce0[1], this->mActorTable); this->mActorTable = NULL; delete this->mUnk_14; this->mUnk_14 = NULL; @@ -179,7 +179,7 @@ THUMB void ActorManager::func_ov004_021053dc() { } extern "C" void func_ov000_020c3388(unk32); -extern "C" void *NewEXPH(u32 *id, s32 length, s32 param_3); +extern "C" void *Heap_EXPHNew(u32 *id, s32 length, s32 param_3); THUMB void ActorManager::func_ov004_021054a4(FileEntryFlag *param1, s32 param2, unk32 param3) { u16 sVar1; u16 sVar2; @@ -205,7 +205,7 @@ THUMB void ActorManager::func_ov004_021054a4(FileEntryFlag *param1, s32 param2, } param1->vfunc_0c(); func_ov000_020c3388(sVar2); - this->mActorTable = (Actor **) NewEXPH(data_027e0ce0[1], this->mMaxActors * 4, 4); + this->mActorTable = (Actor **) Heap_EXPHNew(data_027e0ce0[1], this->mMaxActors * 4, 4); Fill256(0, this->mActorTable, this->mMaxActors * 4); this->mUnk_14 = new(data_027e0ce0[1], 4) ActorManager_Unk14(this->mMaxActors); } diff --git a/src/08_GameStart/Init.cpp b/src/08_GameStart/Init.cpp index 0481ca38f..3251c45b5 100644 --- a/src/08_GameStart/Init.cpp +++ b/src/08_GameStart/Init.cpp @@ -22,9 +22,9 @@ void func_0200a318(u8 *); unk32 func_0200dd94(); unk32 func_0200a284(u8 *); u16 func_ov001_020efdac(); -void *NewEXPH(char *id, s32 length, s32 param_3); +void *Heap_EXPHNew(char *id, s32 length, s32 param_3); unk32 func_ov000_020773c0(); -void func_020174a4(u32 *, void *); +void Heap_EXPHFreeBlock(u32 *, void *); void func_0201f378(); void func_0202019c(void *, const char *, u32 *, unk32); void func_020213f0(u32 *); @@ -165,13 +165,13 @@ ARM UnkStruct_020ee698::UnkStruct_020ee698() : mUnk_02(0), mUnk_04(func_ov001_020efdac()), mUnk_08(0x0D) { - void *newHeap = NewEXPH((char *) data_027e0ce0[1], 0x700, 0x20); + void *newHeap = Heap_EXPHNew((char *) data_027e0ce0[1], 0x700, 0x20); if (func_ov000_020773c0() == 3) { this->mUnk_00 = 1; } - func_020174a4(data_027e0ce0[1], newHeap); + Heap_EXPHFreeBlock(data_027e0ce0[1], newHeap); } // --- data_ov000_020ee734 --- From 55a6e01d09c80e4fc5590c5071f163c32d1b3abc Mon Sep 17 00:00:00 2001 From: enzo Date: Tue, 2 Jun 2026 13:59:09 -0300 Subject: [PATCH 2/6] add frmh heap --- config/eur/arm9/delinks.txt | 2 +- config/eur/arm9/symbols.txt | 30 +++--- config/usa/arm9/delinks.txt | 2 +- config/usa/arm9/symbols.txt | 30 +++--- libs/nds/include/nds/heap.h | 17 +++- libs/nds/src/heap.c | 190 +++++++++++++++++++++++++++++++++++- 6 files changed, 234 insertions(+), 37 deletions(-) diff --git a/config/eur/arm9/delinks.txt b/config/eur/arm9/delinks.txt index d75f97c7c..233b0dddc 100644 --- a/config/eur/arm9/delinks.txt +++ b/config/eur/arm9/delinks.txt @@ -85,4 +85,4 @@ src/Main/DTCM/UnkStruct_027e05f8_2.cpp: .dtcm start:0x027e05f8 end:0x027e060c libs/nds/src/heap.c: - .text start:0x02017034 end:0x02017530 \ No newline at end of file + .text start:0x02017034 end:0x02017710 \ No newline at end of file diff --git a/config/eur/arm9/symbols.txt b/config/eur/arm9/symbols.txt index bb2c3ba0c..2f944ff84 100644 --- a/config/eur/arm9/symbols.txt +++ b/config/eur/arm9/symbols.txt @@ -683,8 +683,8 @@ Heap_InsertBlock kind:function(thumb,size=0x20) addr:0x0201706c Heap_InitBlock kind:function(thumb,size=0x1a) addr:0x0201708c Heap_EXPHInit kind:function(thumb,size=0x50) addr:0x020170a8 Heap_AllocFreeBlock kind:function(thumb,size=0x100) addr:0x020170f8 -Heap_AllocHead kind:function(thumb,size=0x7c) addr:0x020171f8 -Heap_AllocTail kind:function(thumb,size=0x74) addr:0x02017274 +Heap_EXPHAllocHead kind:function(thumb,size=0x7c) addr:0x020171f8 +Heap_EXPHAllocTail kind:function(thumb,size=0x74) addr:0x02017274 Heap_EmptyRegion kind:function(thumb,size=0x8c) addr:0x020172e8 Heap_EXPHCreate kind:function(thumb,size=0x20) addr:0x02017374 Heap_EXPHDestroy kind:function(thumb,size=0x8) addr:0x02017394 @@ -693,19 +693,19 @@ Heap_EXPHResizeBlock kind:function(thumb,size=0xe8) addr:0x020173bc Heap_EXPHFreeBlock kind:function(thumb,size=0x2a) addr:0x020174a4 Heap_EXPHGetEmptySize kind:function(thumb,size=0x16) addr:0x020174d0 Heap_EXPHGetMaxEmptySize kind:function(thumb,size=0x46) addr:0x020174e8 -func_02017530 kind:function(thumb,size=0x2c) addr:0x02017530 -func_0201755c kind:function(thumb,size=0x3e) addr:0x0201755c -func_0201759c kind:function(thumb,size=0x3c) addr:0x0201759c -func_020175d8 kind:function(thumb,size=0xe) addr:0x020175d8 -func_020175e8 kind:function(thumb,size=0x1a) addr:0x020175e8 -func_02017604 kind:function(thumb,size=0x20) addr:0x02017604 -func_02017624 kind:function(thumb,size=0x8) addr:0x02017624 -NewFRMH kind:function(thumb,size=0x22) addr:0x0201762c -func_02017650 kind:function(thumb,size=0x1e) addr:0x02017650 -func_02017670 kind:function(thumb,size=0x24) addr:0x02017670 -func_02017694 kind:function(thumb,size=0x2e) addr:0x02017694 -func_020176c4 kind:function(thumb,size=0x30) addr:0x020176c4 -func_020176f4 kind:function(thumb,size=0x1c) addr:0x020176f4 +Heap_FRMHInit kind:function(thumb,size=0x2c) addr:0x02017530 +Heap_FRMHAllocHead kind:function(thumb,size=0x3e) addr:0x0201755c +Heap_FRMHAllocTail kind:function(thumb,size=0x3c) addr:0x0201759c +Heap_FRMHFreeHead kind:function(thumb,size=0xe) addr:0x020175d8 +Heap_FRMHFreeTail kind:function(thumb,size=0x1a) addr:0x020175e8 +Heap_FRMHCreate kind:function(thumb,size=0x20) addr:0x02017604 +Heap_FRMHDestroy kind:function(thumb,size=0x8) addr:0x02017624 +Heap_FRMHNew kind:function(thumb,size=0x22) addr:0x0201762c +Heap_FRMHFreeBlock kind:function(thumb,size=0x1e) addr:0x02017650 +Heap_FRMHGetMaxEmptySize kind:function(thumb,size=0x24) addr:0x02017670 +Heap_FRMHSaveState kind:function(thumb,size=0x2e) addr:0x02017694 +Heap_FRMHLoadState kind:function(thumb,size=0x30) addr:0x020176c4 +Heap_FRMHFreeEmpty kind:function(thumb,size=0x1c) addr:0x020176f4 func_02017710 kind:function(thumb,size=0x3e) addr:0x02017710 func_02017750 kind:function(thumb,size=0x1c) addr:0x02017750 func_0201776c kind:function(thumb,size=0x5c) addr:0x0201776c diff --git a/config/usa/arm9/delinks.txt b/config/usa/arm9/delinks.txt index c4600260e..05081305d 100644 --- a/config/usa/arm9/delinks.txt +++ b/config/usa/arm9/delinks.txt @@ -81,4 +81,4 @@ src/Main/DTCM/UnkStruct_027e05f8_2.cpp: .dtcm start:0x027e05f8 end:0x027e060c libs/nds/src/heap.c: - .text start:0x02017034 end:0x02017530 \ No newline at end of file + .text start:0x02017034 end:0x02017710 \ No newline at end of file diff --git a/config/usa/arm9/symbols.txt b/config/usa/arm9/symbols.txt index 43c445e29..f74a92cf9 100644 --- a/config/usa/arm9/symbols.txt +++ b/config/usa/arm9/symbols.txt @@ -683,8 +683,8 @@ Heap_InsertBlock kind:function(thumb,size=0x20) addr:0x0201706c Heap_InitBlock kind:function(thumb,size=0x1a) addr:0x0201708c Heap_EXPHInit kind:function(thumb,size=0x50) addr:0x020170a8 Heap_AllocFreeBlock kind:function(thumb,size=0x100) addr:0x020170f8 -Heap_AllocHead kind:function(thumb,size=0x7c) addr:0x020171f8 -Heap_AllocTail kind:function(thumb,size=0x74) addr:0x02017274 +Heap_EXPHAllocHead kind:function(thumb,size=0x7c) addr:0x020171f8 +Heap_EXPHAllocTail kind:function(thumb,size=0x74) addr:0x02017274 Heap_EmptyRegion kind:function(thumb,size=0x8c) addr:0x020172e8 Heap_EXPHCreate kind:function(thumb,size=0x20) addr:0x02017374 Heap_EXPHDestroy kind:function(thumb,size=0x8) addr:0x02017394 @@ -693,19 +693,19 @@ Heap_EXPHResizeBlock kind:function(thumb,size=0xe8) addr:0x020173bc Heap_EXPHFreeBlock kind:function(thumb,size=0x2a) addr:0x020174a4 Heap_EXPHGetEmptySize kind:function(thumb,size=0x16) addr:0x020174d0 Heap_EXPHGetMaxEmptySize kind:function(thumb,size=0x46) addr:0x020174e8 -func_02017530 kind:function(thumb,size=0x2c) addr:0x02017530 -func_0201755c kind:function(thumb,size=0x3e) addr:0x0201755c -func_0201759c kind:function(thumb,size=0x3c) addr:0x0201759c -func_020175d8 kind:function(thumb,size=0xe) addr:0x020175d8 -func_020175e8 kind:function(thumb,size=0x1a) addr:0x020175e8 -func_02017604 kind:function(thumb,size=0x20) addr:0x02017604 -func_02017624 kind:function(thumb,size=0x8) addr:0x02017624 -NewFRMH kind:function(thumb,size=0x22) addr:0x0201762c -func_02017650 kind:function(thumb,size=0x1e) addr:0x02017650 -func_02017670 kind:function(thumb,size=0x24) addr:0x02017670 -func_02017694 kind:function(thumb,size=0x2e) addr:0x02017694 -func_020176c4 kind:function(thumb,size=0x30) addr:0x020176c4 -func_020176f4 kind:function(thumb,size=0x1c) addr:0x020176f4 +Heap_FRMHInit kind:function(thumb,size=0x2c) addr:0x02017530 +Heap_FRMHAllocHead kind:function(thumb,size=0x3e) addr:0x0201755c +Heap_FRMHAllocTail kind:function(thumb,size=0x3c) addr:0x0201759c +Heap_FRMHFreeHead kind:function(thumb,size=0xe) addr:0x020175d8 +Heap_FRMHFreeTail kind:function(thumb,size=0x1a) addr:0x020175e8 +Heap_FRMHCreate kind:function(thumb,size=0x20) addr:0x02017604 +Heap_FRMHDestroy kind:function(thumb,size=0x8) addr:0x02017624 +Heap_FRMHNew kind:function(thumb,size=0x22) addr:0x0201762c +Heap_FRMHFreeBlock kind:function(thumb,size=0x1e) addr:0x02017650 +Heap_FRMHGetMaxEmptySize kind:function(thumb,size=0x24) addr:0x02017670 +Heap_FRMHSaveState kind:function(thumb,size=0x2e) addr:0x02017694 +Heap_FRMHLoadState kind:function(thumb,size=0x30) addr:0x020176c4 +Heap_FRMHFreeEmpty kind:function(thumb,size=0x1c) addr:0x020176f4 func_02017710 kind:function(thumb,size=0x3e) addr:0x02017710 func_02017750 kind:function(thumb,size=0x1c) addr:0x02017750 func_0201776c kind:function(thumb,size=0x5c) addr:0x0201776c diff --git a/libs/nds/include/nds/heap.h b/libs/nds/include/nds/heap.h index e5bbcefb6..0a57ca947 100644 --- a/libs/nds/include/nds/heap.h +++ b/libs/nds/include/nds/heap.h @@ -52,4 +52,19 @@ typedef struct Heap_EXPHHeader_ { /* 10 */ u16 id; /* 12 */ u16 flags; /* 14 */ -} Heap_EXPHHeader; \ No newline at end of file +} Heap_EXPHHeader; + +typedef struct Heap_FRMHState_ { + /* 00 */ u32 id; + /* 04 */ void *head; + /* 08 */ void *tail; + /* 0c */ struct Heap_FRMHState_ *prev; + /* 10 */ +} Heap_FRMHState; + +typedef struct Heap_FRMHHeader_ { + /* 00 */ void *head; + /* 04 */ void *tail; + /* 08 */ Heap_FRMHState *state; + /* 0c */ +} Heap_FRMHHeader; \ No newline at end of file diff --git a/libs/nds/src/heap.c b/libs/nds/src/heap.c index 3eafb0611..7522ed64a 100644 --- a/libs/nds/src/heap.c +++ b/libs/nds/src/heap.c @@ -145,7 +145,7 @@ void *Heap_AllocFreeBlock(Heap_EXPHHeader *EXPHHeader, Heap_EXPHBlockHeader *blo return block; } -void *Heap_AllocHead(Heap_Header *header, u32 size, int alignment) { +void *Heap_EXPHAllocHead(Heap_Header *header, u32 size, int alignment) { Heap_EXPHHeader *expHeader = GetEXPH_inline(header); Heap_EXPHBlockHeader *blockHeader; const u32 flag1 = (u16) (expHeader->flags & 1) == 0; @@ -177,7 +177,7 @@ void *Heap_AllocHead(Heap_Header *header, u32 size, int alignment) { return Heap_AllocFreeBlock(expHeader, foundBlockHeader, foundBlock, size, 0); } -void *Heap_AllocTail(Heap_Header *header, u32 size, int alignment) { +void *Heap_EXPHAllocTail(Heap_Header *header, u32 size, int alignment) { Heap_EXPHHeader *expHeader = GetEXPH_inline(header); Heap_EXPHBlockHeader *blockHeader; @@ -270,9 +270,9 @@ void *Heap_EXPHNew(Heap_Header *heap, u32 size, int alignment) { size = (size + 3) & ~3; if (alignment >= 0) { - h = Heap_AllocHead(heap, size, alignment); + h = Heap_EXPHAllocHead(heap, size, alignment); } else { - h = Heap_AllocTail(heap, size, -alignment); + h = Heap_EXPHAllocTail(heap, size, -alignment); } return h; @@ -391,4 +391,186 @@ u32 Heap_EXPHGetMaxEmptySize(Heap_Header *heap, int alignment) { } return maxSize; } +} + +static inline Heap_FRMHHeader *Get_FRMHHeader_inline(Heap_Header *header) { + return AddU32_inline(header, sizeof(Heap_Header)); +} + +Heap_Header *Heap_FRMHInit(void *startAddress, void *endAddress, u16 optFlag) { + Heap_Header *header = startAddress; + Heap_FRMHHeader *frmHeader = (void *) header + sizeof(Heap_Header); + + func_0201776c(header, 'FRMH', (void *) frmHeader + sizeof(Heap_FRMHHeader), endAddress, optFlag); + + frmHeader->head = header->startAddr; + frmHeader->tail = header->endAddr; + frmHeader->state = NULL; + + return header; +} + +void *Heap_FRMHAllocHead(Heap_FRMHHeader *header, u32 size, int alignment) { + void *newBlock = ((alignment - 1) + ((u32) header->head)) & ~(alignment - 1); + void *endAddress = AddU32_inline(newBlock, size); + + if ((u32) endAddress > (u32) header->tail) { + return NULL; + } + + Fill32_inline((void *) ((u32) (header) - sizeof(Heap_Header)), header->head, endAddress - header->head); + header->head = endAddress; + + return newBlock; +} + +void *Heap_FRMHAllocTail(Heap_FRMHHeader *header, u32 size, int alignment) { + void *newBlock = (u32) (header->tail - size) & ~(alignment - 1); + + if ((u32) (newBlock) < (u32) (header->head)) { + return NULL; + } + + Fill32_inline((void *) ((u32) (header) - sizeof(Heap_Header)), newBlock, header->tail - newBlock); + header->tail = newBlock; + + return newBlock; +} + +void Heap_FRMHFreeHead(Heap_Header *header) { + Heap_FRMHHeader *frmHeader = (u32) header + sizeof(Heap_Header); + frmHeader->head = header->startAddr; + frmHeader->state = NULL; +} + +void Heap_FRMHFreeTail(Heap_Header *header) { + Heap_FRMHHeader *frmHeader = Get_FRMHHeader_inline(header); + Heap_FRMHState *pState; + + for (pState = frmHeader->state; pState; pState = pState->prev) { + pState->tail = header->endAddr; + } + + frmHeader->tail = header->endAddr; +} + +Heap_Header *Heap_FRMHCreate(void *startAddress, u32 size, u16 optFlag) { + void *endAddress; + Heap_Header *header; + + endAddress = (size + (u32) startAddress) & ~3; + startAddress = (3 + (u32) startAddress) & ~3; + + if ((u32) (startAddress) > (u32) (endAddress) || + endAddress - startAddress < sizeof(Heap_Header) + sizeof(Heap_FRMHHeader)) { + return NULL; + } + + header = Heap_FRMHInit(startAddress, endAddress, optFlag); + return header; +} + +void Heap_FRMHDestroy(Heap_Header *heap) { + func_020177c8(heap); +} + +void *Heap_FRMHNew(Heap_Header *heap, u32 size, int alignment) { + void *memory; + Heap_FRMHHeader *header; + + header = (void *) heap + sizeof(Heap_Header); + + if (size == 0) { + size = 1; + } + + size = size + 3 & ~3; + + if (alignment >= 0) { + memory = Heap_FRMHAllocHead(header, size, alignment); + } else { + memory = Heap_FRMHAllocTail(header, size, -alignment); + } + + return memory; +} + +void Heap_FRMHFreeBlock(Heap_Header *heap, int mode) { + if (mode & 1) { + Heap_FRMHFreeHead(heap); + } + + if (mode & 2) { + Heap_FRMHFreeTail(heap); + } +} + +u32 Heap_FRMHGetMaxEmptySize(Heap_Header *heap, int alignment) { + const Heap_FRMHHeader *header; + const void *block; + + alignment = abs(alignment); + header = AddU32_inline(heap, sizeof(Heap_Header)); + block = (alignment - 1) + (u32) header->head & ~(alignment - 1); + + if ((u32) block > (u32) header->tail) { + return 0; + } + + return header->tail - (u32) block; +} + +u32 Heap_FRMHSaveState(Heap_Header *heap, u32 id) { + Heap_FRMHHeader *header = Get_FRMHHeader_inline(heap); + void *oldHead = header->head; + + Heap_FRMHState *state = Heap_FRMHAllocHead(header, sizeof(Heap_FRMHState), 4); + if (!state) { + return 0; + } + + state->id = id; + state->head = oldHead; + state->tail = header->tail; + state->prev = header->state; + header->state = state; + + return 1; +} + +u32 Heap_FRMHLoadState(Heap_Header *heap, u32 id) { + Heap_FRMHHeader *header = AddU32_inline(heap, sizeof(Heap_Header)); + Heap_FRMHState *state = header->state; + + if (id != 0) { + while (state) { + if (state->id == id) { + break; + } + state = state->prev; + } + } + + if (!state) { + return 0; + } + + header->head = state->head; + header->tail = state->tail; + header->state = state->prev; + + return 1; +} + +u32 Heap_FRMHFreeEmpty(Heap_Header *heap) { + Heap_Header *header = heap; + Heap_FRMHHeader *frmHeader = AddU32_inline(header, sizeof(Heap_Header)); + + if (0 < ((u32) header->endAddr - (u32) frmHeader->tail)) { + return 0; + } + + frmHeader->tail = header->endAddr = frmHeader->head; + + return ((u32) header->endAddr - (u32) heap); } \ No newline at end of file From c790d602864082d78c53b0f2eda8546f9e7cbae2 Mon Sep 17 00:00:00 2001 From: enzo Date: Wed, 3 Jun 2026 00:48:36 -0300 Subject: [PATCH 3/6] add heap_list --- config/eur/arm9/delinks.txt | 3 +- config/eur/arm9/symbols.txt | 30 +++---- config/usa/arm9/delinks.txt | 3 +- config/usa/arm9/symbols.txt | 30 +++---- libs/nds/include/nds/heap.h | 9 +- libs/nds/src/heap.c | 158 +++++++++++++++++++++++++++++++++++- 6 files changed, 196 insertions(+), 37 deletions(-) diff --git a/config/eur/arm9/delinks.txt b/config/eur/arm9/delinks.txt index 076e2202a..b8dfa295c 100644 --- a/config/eur/arm9/delinks.txt +++ b/config/eur/arm9/delinks.txt @@ -91,4 +91,5 @@ libs/nds/src/sbc.c: .bss start:0x0205ae08 end:0x0205db08 libs/nds/src/heap.c: - .text start:0x02017034 end:0x02017710 \ No newline at end of file + .text start:0x02017034 end:0x020178fc + .bss start:0x0205ade4 end:0x0205adf4 \ No newline at end of file diff --git a/config/eur/arm9/symbols.txt b/config/eur/arm9/symbols.txt index a26d1b956..264ae6420 100644 --- a/config/eur/arm9/symbols.txt +++ b/config/eur/arm9/symbols.txt @@ -704,19 +704,19 @@ Heap_FRMHGetMaxEmptySize kind:function(thumb,size=0x24) addr:0x02017670 Heap_FRMHSaveState kind:function(thumb,size=0x2e) addr:0x02017694 Heap_FRMHLoadState kind:function(thumb,size=0x30) addr:0x020176c4 Heap_FRMHFreeEmpty kind:function(thumb,size=0x1c) addr:0x020176f4 -func_02017710 kind:function(thumb,size=0x3e) addr:0x02017710 -func_02017750 kind:function(thumb,size=0x1c) addr:0x02017750 -func_0201776c kind:function(thumb,size=0x5c) addr:0x0201776c -func_020177c8 kind:function(thumb,size=0x10) addr:0x020177c8 -func_020177d8 kind:function(thumb,size=0x10) addr:0x020177d8 -func_020177e8 kind:function(thumb,size=0xc) addr:0x020177e8 -func_020177f4 kind:function(thumb,size=0x1a) addr:0x020177f4 -func_02017810 kind:function(thumb,size=0x2c) addr:0x02017810 -func_0201783c kind:function(thumb,size=0x2a) addr:0x0201783c -func_02017868 kind:function(thumb,size=0x36) addr:0x02017868 -func_020178a0 kind:function(thumb,size=0x3a) addr:0x020178a0 -func_020178dc kind:function(thumb,size=0x10) addr:0x020178dc -func_020178ec kind:function(thumb,size=0xe) addr:0x020178ec +Heap_FindBlockInternal kind:function(thumb,size=0x3e) addr:0x02017710 +Heap_FindParentHeap kind:function(thumb,size=0x1c) addr:0x02017750 +Heap_InitHeader kind:function(thumb,size=0x5c) addr:0x0201776c +Heap_Destroy kind:function(thumb,size=0x10) addr:0x020177c8 +Heap_FindBlock kind:function(thumb,size=0x10) addr:0x020177d8 +Heap_InitList kind:function(thumb,size=0xc) addr:0x020177e8 +Heap_ListSetFirst kind:function(thumb,size=0x1a) addr:0x020177f4 +Heap_ListAppend kind:function(thumb,size=0x2c) addr:0x02017810 +Heap_ListPrepend kind:function(thumb,size=0x2a) addr:0x0201783c +Heap_ListInsertBefore kind:function(thumb,size=0x36) addr:0x02017868 +Heap_ListRemove kind:function(thumb,size=0x3a) addr:0x020178a0 +Heap_ListNext kind:function(thumb,size=0x10) addr:0x020178dc +Heap_ListPrev kind:function(thumb,size=0xe) addr:0x020178ec func_020178fc kind:function(thumb,size=0x98) addr:0x020178fc func_02017994 kind:function(thumb,size=0x8) addr:0x02017994 func_0201799c kind:function(thumb,size=0x10) addr:0x0201799c @@ -3014,8 +3014,8 @@ data_0205ada8 kind:bss addr:0x0205ada8 data_0205adac kind:bss addr:0x0205adac data_0205adc0 kind:bss addr:0x0205adc0 data_0205ade0 kind:bss addr:0x0205ade0 -data_0205ade4 kind:bss addr:0x0205ade4 -data_0205ade8 kind:bss addr:0x0205ade8 +gHeapListInitialized kind:bss addr:0x0205ade4 +gHeapList kind:bss addr:0x0205ade8 data_0205adf4 kind:bss addr:0x0205adf4 data_0205ae08 kind:bss addr:0x0205ae08 data_0205db08 kind:bss addr:0x0205db08 diff --git a/config/usa/arm9/delinks.txt b/config/usa/arm9/delinks.txt index 7df7bf6d8..2a1153776 100644 --- a/config/usa/arm9/delinks.txt +++ b/config/usa/arm9/delinks.txt @@ -87,4 +87,5 @@ libs/nds/src/sbc.c: .bss start:0x0205ada8 end:0x0205daa8 libs/nds/src/heap.c: - .text start:0x02017034 end:0x02017710 \ No newline at end of file + .text start:0x02017034 end:0x020178fc + .bss start:0x0205ad84 end:0x0205ad94 \ No newline at end of file diff --git a/config/usa/arm9/symbols.txt b/config/usa/arm9/symbols.txt index 61e51a771..bc6d36b4a 100644 --- a/config/usa/arm9/symbols.txt +++ b/config/usa/arm9/symbols.txt @@ -704,19 +704,19 @@ Heap_FRMHGetMaxEmptySize kind:function(thumb,size=0x24) addr:0x02017670 Heap_FRMHSaveState kind:function(thumb,size=0x2e) addr:0x02017694 Heap_FRMHLoadState kind:function(thumb,size=0x30) addr:0x020176c4 Heap_FRMHFreeEmpty kind:function(thumb,size=0x1c) addr:0x020176f4 -func_02017710 kind:function(thumb,size=0x3e) addr:0x02017710 -func_02017750 kind:function(thumb,size=0x1c) addr:0x02017750 -func_0201776c kind:function(thumb,size=0x5c) addr:0x0201776c -func_020177c8 kind:function(thumb,size=0x10) addr:0x020177c8 -func_020177d8 kind:function(thumb,size=0x10) addr:0x020177d8 -func_020177e8 kind:function(thumb,size=0xc) addr:0x020177e8 -func_020177f4 kind:function(thumb,size=0x1a) addr:0x020177f4 -func_02017810 kind:function(thumb,size=0x2c) addr:0x02017810 -func_0201783c kind:function(thumb,size=0x2a) addr:0x0201783c -func_02017868 kind:function(thumb,size=0x36) addr:0x02017868 -func_020178a0 kind:function(thumb,size=0x3a) addr:0x020178a0 -func_020178dc kind:function(thumb,size=0x10) addr:0x020178dc -func_020178ec kind:function(thumb,size=0xe) addr:0x020178ec +Heap_FindBlockInternal kind:function(thumb,size=0x3e) addr:0x02017710 +Heap_FindParentHeap kind:function(thumb,size=0x1c) addr:0x02017750 +Heap_InitHeader kind:function(thumb,size=0x5c) addr:0x0201776c +Heap_Destroy kind:function(thumb,size=0x10) addr:0x020177c8 +Heap_FindBlock kind:function(thumb,size=0x10) addr:0x020177d8 +Heap_InitList kind:function(thumb,size=0xc) addr:0x020177e8 +Heap_ListSetFirst kind:function(thumb,size=0x1a) addr:0x020177f4 +Heap_ListAppend kind:function(thumb,size=0x2c) addr:0x02017810 +Heap_ListPrepend kind:function(thumb,size=0x2a) addr:0x0201783c +Heap_ListInsertBefore kind:function(thumb,size=0x36) addr:0x02017868 +Heap_ListRemove kind:function(thumb,size=0x3a) addr:0x020178a0 +Heap_ListNext kind:function(thumb,size=0x10) addr:0x020178dc +Heap_ListPrev kind:function(thumb,size=0xe) addr:0x020178ec func_020178fc kind:function(thumb,size=0x98) addr:0x020178fc func_02017994 kind:function(thumb,size=0x8) addr:0x02017994 func_0201799c kind:function(thumb,size=0x10) addr:0x0201799c @@ -3014,8 +3014,8 @@ data_0205ada8 kind:bss addr:0x0205ad48 data_0205adac kind:bss addr:0x0205ad4c data_0205adc0 kind:bss addr:0x0205ad60 data_0205ade0 kind:bss addr:0x0205ad80 -data_0205ade4 kind:bss addr:0x0205ad84 -data_0205ade8 kind:bss addr:0x0205ad88 +gHeapListInitialized kind:bss addr:0x0205ad84 +gHeapList kind:bss addr:0x0205ad88 data_0205adf4 kind:bss addr:0x0205ad94 data_0205ae08 kind:bss addr:0x0205ada8 data_0205db08 kind:bss addr:0x0205daa8 diff --git a/libs/nds/include/nds/heap.h b/libs/nds/include/nds/heap.h index 0a57ca947..d3a6fc05d 100644 --- a/libs/nds/include/nds/heap.h +++ b/libs/nds/include/nds/heap.h @@ -67,4 +67,11 @@ typedef struct Heap_FRMHHeader_ { /* 04 */ void *tail; /* 08 */ Heap_FRMHState *state; /* 0c */ -} Heap_FRMHHeader; \ No newline at end of file +} Heap_FRMHHeader; + +void Heap_InitHeader(Heap_Header *pHeapHd, u32 signature, void *heapStart, void *heapEnd, u16 optFlag); +void Heap_Destroy(Heap_Header *pHeapHd); +void Heap_InitList(Heap_LinkedList *list, u16 offset); +void Heap_ListAppend(Heap_LinkedList *list, void *object); +void Heap_ListRemove(Heap_LinkedList *list, void *object); +void *Heap_ListNext(Heap_LinkedList *list, void *object); \ No newline at end of file diff --git a/libs/nds/src/heap.c b/libs/nds/src/heap.c index 7522ed64a..85d295518 100644 --- a/libs/nds/src/heap.c +++ b/libs/nds/src/heap.c @@ -9,6 +9,9 @@ data |= newVal << st; \ }; +static Heap_LinkedList gHeapList; +static u32 gHeapListInitialized = 0; + static inline u32 Diff_Ptr_inline(const void *start, const void *end) { return end - start; } @@ -89,7 +92,7 @@ Heap_Header *Heap_EXPHInit(void *start, void *end, u16 flag) { Heap_Header *header = start; Heap_EXPHHeader *EXPHHeader = (void *) ((u32) header + sizeof(Heap_Header)); - func_0201776c(header, 'EXPH', (void *) ((u32) EXPHHeader + sizeof(Heap_EXPHHeader)), end, flag); + Heap_InitHeader(header, 'EXPH', (void *) ((u32) EXPHHeader + sizeof(Heap_EXPHHeader)), end, flag); EXPHHeader->id = 0; EXPHHeader->flags = 0; @@ -257,7 +260,7 @@ Heap_Header *Heap_EXPHCreate(void *startAddress, u32 size, u16 optFlag) { } void Heap_EXPHDestroy(Heap_Header *heap) { - func_020177c8(heap); + Heap_Destroy(heap); } void *Heap_EXPHNew(Heap_Header *heap, u32 size, int alignment) { @@ -401,7 +404,7 @@ Heap_Header *Heap_FRMHInit(void *startAddress, void *endAddress, u16 optFlag) { Heap_Header *header = startAddress; Heap_FRMHHeader *frmHeader = (void *) header + sizeof(Heap_Header); - func_0201776c(header, 'FRMH', (void *) frmHeader + sizeof(Heap_FRMHHeader), endAddress, optFlag); + Heap_InitHeader(header, 'FRMH', (void *) frmHeader + sizeof(Heap_FRMHHeader), endAddress, optFlag); frmHeader->head = header->startAddr; frmHeader->tail = header->endAddr; @@ -471,7 +474,7 @@ Heap_Header *Heap_FRMHCreate(void *startAddress, u32 size, u16 optFlag) { } void Heap_FRMHDestroy(Heap_Header *heap) { - func_020177c8(heap); + Heap_Destroy(heap); } void *Heap_FRMHNew(Heap_Header *heap, u32 size, int alignment) { @@ -573,4 +576,151 @@ u32 Heap_FRMHFreeEmpty(Heap_Header *heap) { frmHeader->tail = header->endAddr = frmHeader->head; return ((u32) header->endAddr - (u32) heap); +} + +Heap_Header *Heap_FindBlockInternal(Heap_LinkedList *list, const void *block) { + Heap_Header *header = NULL; + while (NULL != (header = Heap_ListNext(list, header))) { + if ((u32) (header->startAddr) <= (u32) (block) && (u32) (block) < (u32) (header->endAddr)) { + Heap_Header *subHeader = Heap_FindBlockInternal(&header->children, block); + if (subHeader) { + return subHeader; + } + return header; + } + } + return NULL; +} + +Heap_LinkedList *Heap_FindParentHeap(Heap_Header *header) { + Heap_LinkedList *list = &gHeapList; + Heap_Header *res = Heap_FindBlockInternal(&gHeapList, header); + if (res) { + list = &res->children; + } + + return list; +} + +void Heap_InitHeader(Heap_Header *header, u32 stamp, void *heapStart, void *heapEnd, u16 optFlag) { + header->stamp = stamp; + header->startAddr = heapStart; + header->endAddr = heapEnd; + header->flags = 0; + SetBit(header->flags, 0, 8, optFlag); + + Heap_InitList(&header->children, offsetof(Heap_Header, link)); + + if (!gHeapListInitialized) { + Heap_InitList(&gHeapList, offsetof(Heap_Header, link)); + gHeapListInitialized = 1; + } + + Heap_ListAppend(Heap_FindParentHeap(header), header); +} + +void Heap_Destroy(Heap_Header *header) { + Heap_ListRemove(Heap_FindParentHeap(header), header); +} + +Heap_Header *Heap_FindBlock(const void *memBlock) { + return Heap_FindBlockInternal(&gHeapList, memBlock); +} + +void Heap_InitList(Heap_LinkedList *list, u16 offset) { + list->head = NULL; + list->tail = NULL; + list->numElements = 0; + list->offset = offset; +} + +void Heap_ListSetFirst(Heap_LinkedList *list, void *object) { + Heap_LinkedObject *link; + + link = ((Heap_LinkedObject *) ((u32) (object) + list->offset)); + link->next = NULL; + link->prev = NULL; + list->head = object; + list->tail = object; + list->numElements++; +} + +void Heap_ListAppend(Heap_LinkedList *list, void *object) { + if (list->head == NULL) { + Heap_ListSetFirst(list, object); + } else { + Heap_LinkedObject *link = ((Heap_LinkedObject *) ((u32) (object) + list->offset)); + + link->prev = list->tail; + link->next = NULL; + + ((Heap_LinkedObject *) ((u32) (list->tail) + list->offset))->next = object; + list->tail = object; + list->numElements++; + } +} + +void Heap_ListPrepend(Heap_LinkedList *list, void *object) { + if (list->head == NULL) { + Heap_ListSetFirst(list, object); + } else { + Heap_LinkedObject *link = ((Heap_LinkedObject *) ((u32) (object) + list->offset)); + link->prev = NULL; + link->next = list->head; + ((Heap_LinkedObject *) ((u32) (list->head) + list->offset))->prev = object; + list->head = object; + list->numElements++; + } +} + +void Heap_ListInsertBefore(Heap_LinkedList *list, void *target, void *object) { + if (target == NULL) { + Heap_ListAppend(list, object); + } else if (target == list->head) { + Heap_ListPrepend(list, object); + } else { + Heap_LinkedObject *link = ((Heap_LinkedObject *) ((u32) (object) + list->offset)); + void *prevObj = ((Heap_LinkedObject *) ((u32) (target) + list->offset))->prev; + Heap_LinkedObject *prevLnk = ((Heap_LinkedObject *) ((u32) (prevObj) + list->offset)); + + link->prev = prevObj; + link->next = target; + prevLnk->next = object; + ((Heap_LinkedObject *) ((u32) (target) + list->offset))->prev = object; + list->numElements++; + } +} + +void Heap_ListRemove(Heap_LinkedList *list, void *object) { + Heap_LinkedObject *link; + + link = ((Heap_LinkedObject *) ((u32) (object) + list->offset)); + + if (link->prev == NULL) { + list->head = link->next; + } else { + ((Heap_LinkedObject *) ((u32) (link->prev) + list->offset))->next = link->next; + } + if (link->next == NULL) { + list->tail = link->prev; + } else { + ((Heap_LinkedObject *) ((u32) (link->next) + list->offset))->prev = link->prev; + } + link->prev = NULL; + link->next = NULL; + list->numElements--; +} + +void *Heap_ListNext(Heap_LinkedList *list, void *object) { + if (object == NULL) { + return list->head; + } + return ((Heap_LinkedObject *) ((u32) (object) + list->offset))->next; +} + +void *Heap_ListPrev(Heap_LinkedList *list, void *object) { + if (object == NULL) { + return list->tail; + } + return ((Heap_LinkedObject *) ((u32) (object) + list->offset))->prev; } \ No newline at end of file From 75e7f5dd9650ad1301cf7070b3261319d7ad9f71 Mon Sep 17 00:00:00 2001 From: enzo Date: Wed, 3 Jun 2026 10:50:41 -0300 Subject: [PATCH 4/6] add unth heap --- config/eur/arm9/delinks.txt | 2 +- config/eur/arm9/symbols.txt | 8 ++--- config/usa/arm9/delinks.txt | 2 +- config/usa/arm9/symbols.txt | 8 ++--- libs/nds/include/nds/heap.h | 21 +++++++++++-- libs/nds/src/heap.c | 61 +++++++++++++++++++++++++++++++++++-- 6 files changed, 87 insertions(+), 15 deletions(-) diff --git a/config/eur/arm9/delinks.txt b/config/eur/arm9/delinks.txt index b8dfa295c..06d41c9ec 100644 --- a/config/eur/arm9/delinks.txt +++ b/config/eur/arm9/delinks.txt @@ -91,5 +91,5 @@ libs/nds/src/sbc.c: .bss start:0x0205ae08 end:0x0205db08 libs/nds/src/heap.c: - .text start:0x02017034 end:0x020178fc + .text start:0x02017034 end:0x020179ac .bss start:0x0205ade4 end:0x0205adf4 \ No newline at end of file diff --git a/config/eur/arm9/symbols.txt b/config/eur/arm9/symbols.txt index 264ae6420..8bce01a88 100644 --- a/config/eur/arm9/symbols.txt +++ b/config/eur/arm9/symbols.txt @@ -707,7 +707,7 @@ Heap_FRMHFreeEmpty kind:function(thumb,size=0x1c) addr:0x020176f4 Heap_FindBlockInternal kind:function(thumb,size=0x3e) addr:0x02017710 Heap_FindParentHeap kind:function(thumb,size=0x1c) addr:0x02017750 Heap_InitHeader kind:function(thumb,size=0x5c) addr:0x0201776c -Heap_Destroy kind:function(thumb,size=0x10) addr:0x020177c8 +Heap_DestroyInternal kind:function(thumb,size=0x10) addr:0x020177c8 Heap_FindBlock kind:function(thumb,size=0x10) addr:0x020177d8 Heap_InitList kind:function(thumb,size=0xc) addr:0x020177e8 Heap_ListSetFirst kind:function(thumb,size=0x1a) addr:0x020177f4 @@ -717,9 +717,9 @@ Heap_ListInsertBefore kind:function(thumb,size=0x36) addr:0x02017868 Heap_ListRemove kind:function(thumb,size=0x3a) addr:0x020178a0 Heap_ListNext kind:function(thumb,size=0x10) addr:0x020178dc Heap_ListPrev kind:function(thumb,size=0xe) addr:0x020178ec -func_020178fc kind:function(thumb,size=0x98) addr:0x020178fc -func_02017994 kind:function(thumb,size=0x8) addr:0x02017994 -func_0201799c kind:function(thumb,size=0x10) addr:0x0201799c +Heap_UNTHCreate kind:function(thumb,size=0x98) addr:0x020178fc +Heap_Destroy kind:function(thumb,size=0x8) addr:0x02017994 +Heap_UNTHSize kind:function(thumb,size=0x10) addr:0x0201799c func_020179ac kind:function(arm,size=0x20) addr:0x020179ac func_020179cc kind:function(arm,size=0x18) addr:0x020179cc func_020179e4 kind:function(arm,size=0x14) addr:0x020179e4 diff --git a/config/usa/arm9/delinks.txt b/config/usa/arm9/delinks.txt index 2a1153776..869cdd5a6 100644 --- a/config/usa/arm9/delinks.txt +++ b/config/usa/arm9/delinks.txt @@ -87,5 +87,5 @@ libs/nds/src/sbc.c: .bss start:0x0205ada8 end:0x0205daa8 libs/nds/src/heap.c: - .text start:0x02017034 end:0x020178fc + .text start:0x02017034 end:0x020179ac .bss start:0x0205ad84 end:0x0205ad94 \ No newline at end of file diff --git a/config/usa/arm9/symbols.txt b/config/usa/arm9/symbols.txt index bc6d36b4a..da6d58f01 100644 --- a/config/usa/arm9/symbols.txt +++ b/config/usa/arm9/symbols.txt @@ -707,7 +707,7 @@ Heap_FRMHFreeEmpty kind:function(thumb,size=0x1c) addr:0x020176f4 Heap_FindBlockInternal kind:function(thumb,size=0x3e) addr:0x02017710 Heap_FindParentHeap kind:function(thumb,size=0x1c) addr:0x02017750 Heap_InitHeader kind:function(thumb,size=0x5c) addr:0x0201776c -Heap_Destroy kind:function(thumb,size=0x10) addr:0x020177c8 +Heap_DestroyInternal kind:function(thumb,size=0x10) addr:0x020177c8 Heap_FindBlock kind:function(thumb,size=0x10) addr:0x020177d8 Heap_InitList kind:function(thumb,size=0xc) addr:0x020177e8 Heap_ListSetFirst kind:function(thumb,size=0x1a) addr:0x020177f4 @@ -717,9 +717,9 @@ Heap_ListInsertBefore kind:function(thumb,size=0x36) addr:0x02017868 Heap_ListRemove kind:function(thumb,size=0x3a) addr:0x020178a0 Heap_ListNext kind:function(thumb,size=0x10) addr:0x020178dc Heap_ListPrev kind:function(thumb,size=0xe) addr:0x020178ec -func_020178fc kind:function(thumb,size=0x98) addr:0x020178fc -func_02017994 kind:function(thumb,size=0x8) addr:0x02017994 -func_0201799c kind:function(thumb,size=0x10) addr:0x0201799c +Heap_UNTHCreate kind:function(thumb,size=0x98) addr:0x020178fc +Heap_Destroy kind:function(thumb,size=0x8) addr:0x02017994 +Heap_UNTHSize kind:function(thumb,size=0x10) addr:0x0201799c func_020179ac kind:function(arm,size=0x20) addr:0x020179ac func_020179cc kind:function(arm,size=0x18) addr:0x020179cc func_020179e4 kind:function(arm,size=0x14) addr:0x020179e4 diff --git a/libs/nds/include/nds/heap.h b/libs/nds/include/nds/heap.h index d3a6fc05d..d67ceff46 100644 --- a/libs/nds/include/nds/heap.h +++ b/libs/nds/include/nds/heap.h @@ -70,8 +70,25 @@ typedef struct Heap_FRMHHeader_ { } Heap_FRMHHeader; void Heap_InitHeader(Heap_Header *pHeapHd, u32 signature, void *heapStart, void *heapEnd, u16 optFlag); -void Heap_Destroy(Heap_Header *pHeapHd); +void Heap_DestroyInternal(Heap_Header *pHeapHd); void Heap_InitList(Heap_LinkedList *list, u16 offset); void Heap_ListAppend(Heap_LinkedList *list, void *object); void Heap_ListRemove(Heap_LinkedList *list, void *object); -void *Heap_ListNext(Heap_LinkedList *list, void *object); \ No newline at end of file +void *Heap_ListNext(Heap_LinkedList *list, void *object); + +// rename +typedef struct Heap_UNTHBlockHeader_ { + /* 00 */ struct Heap_UNTHBlockHeader_ *next; + /* 04 */ +} Heap_UNTHBlockHeader; + +typedef struct Heap_UNTHBlockList_ { + /* 00 */ Heap_UNTHBlockHeader *head; + /* 04 */ +} Heap_UNTHBlockList; + +typedef struct Heap_UNTHHeader_ { + /* 00 */ Heap_UNTHBlockList mbFreeList; + /* 04 */ u32 mBlkSize; + /* 08 */ +} Heap_UNTHHeader; \ No newline at end of file diff --git a/libs/nds/src/heap.c b/libs/nds/src/heap.c index 85d295518..9b3d8e8cc 100644 --- a/libs/nds/src/heap.c +++ b/libs/nds/src/heap.c @@ -260,7 +260,7 @@ Heap_Header *Heap_EXPHCreate(void *startAddress, u32 size, u16 optFlag) { } void Heap_EXPHDestroy(Heap_Header *heap) { - Heap_Destroy(heap); + Heap_DestroyInternal(heap); } void *Heap_EXPHNew(Heap_Header *heap, u32 size, int alignment) { @@ -474,7 +474,7 @@ Heap_Header *Heap_FRMHCreate(void *startAddress, u32 size, u16 optFlag) { } void Heap_FRMHDestroy(Heap_Header *heap) { - Heap_Destroy(heap); + Heap_DestroyInternal(heap); } void *Heap_FRMHNew(Heap_Header *heap, u32 size, int alignment) { @@ -619,7 +619,7 @@ void Heap_InitHeader(Heap_Header *header, u32 stamp, void *heapStart, void *heap Heap_ListAppend(Heap_FindParentHeap(header), header); } -void Heap_Destroy(Heap_Header *header) { +void Heap_DestroyInternal(Heap_Header *header) { Heap_ListRemove(Heap_FindParentHeap(header), header); } @@ -723,4 +723,59 @@ void *Heap_ListPrev(Heap_LinkedList *list, void *object) { return list->tail; } return ((Heap_LinkedObject *) ((u32) (object) + list->offset))->prev; +} + +Heap_Header *Heap_UNTHCreate(void *startAddress, u32 heapSize, u32 memBlockSize, int alignment, u16 optFlag) { + Heap_Header *header; + void *heapEnd; + Heap_UNTHHeader *pUntHeapHd; + void *heapStart; + u32 elementNum; + + header = (void *) ((u32) startAddress + 3 & ~3); + heapEnd = (void *) ((u32) AddU32_inline(startAddress, heapSize) & ~3); + + if ((const u8 *) header - (const u8 *) heapEnd > 0) { + return 0; + } + + memBlockSize = memBlockSize + (alignment - 1) & ~(alignment - 1); + pUntHeapHd = (void *) (sizeof(Heap_Header) + (u32) header); + heapStart = (void *) (((u32) AddU32_inline(pUntHeapHd, sizeof(Heap_UNTHHeader)) + (alignment - 1)) & ~(alignment - 1)); + + if ((u8 *) heapStart - (u8 *) heapEnd > 0) { + return 0; + } + + elementNum = (heapEnd - heapStart) / memBlockSize; + if (elementNum == 0) { + return 0; + } + + heapEnd = AddU32_inline(heapStart, elementNum * memBlockSize); + Heap_InitHeader(header, 'UNTH', heapStart, heapEnd, optFlag); + pUntHeapHd->mbFreeList.head = heapStart; + pUntHeapHd->mBlkSize = memBlockSize; + + { + Heap_UNTHBlockHeader *pMBlkHd = pUntHeapHd->mbFreeList.head; + int i; + + for (i = 0; i < elementNum - 1; ++i, pMBlkHd = pMBlkHd->next) { + pMBlkHd->next = AddU32_inline(pMBlkHd, memBlockSize); + } + + pMBlkHd->next = NULL; + } + + return header; +} + +void Heap_Destroy(Heap_Header *heap) { + Heap_DestroyInternal(heap); +} + +u32 Heap_UNTHSize(u32 memBlockSize, u32 memBlockNum, int alignment) { + return sizeof(Heap_Header) + sizeof(Heap_UNTHHeader) + (alignment - 4) + + memBlockNum * (((memBlockSize) + (alignment - 1)) & ~(alignment - 1)); } \ No newline at end of file From f140fc06acb2e67fbb78c64e0a0624c8cb63d181 Mon Sep 17 00:00:00 2001 From: enzo Date: Wed, 3 Jun 2026 10:54:54 -0300 Subject: [PATCH 5/6] link heap.c --- config/eur/arm9/delinks.txt | 1 + config/eur/arm9/symbols.txt | 4 ++-- config/usa/arm9/delinks.txt | 1 + config/usa/arm9/symbols.txt | 4 ++-- 4 files changed, 6 insertions(+), 4 deletions(-) diff --git a/config/eur/arm9/delinks.txt b/config/eur/arm9/delinks.txt index 06d41c9ec..0967ac8d4 100644 --- a/config/eur/arm9/delinks.txt +++ b/config/eur/arm9/delinks.txt @@ -91,5 +91,6 @@ libs/nds/src/sbc.c: .bss start:0x0205ae08 end:0x0205db08 libs/nds/src/heap.c: + complete .text start:0x02017034 end:0x020179ac .bss start:0x0205ade4 end:0x0205adf4 \ No newline at end of file diff --git a/config/eur/arm9/symbols.txt b/config/eur/arm9/symbols.txt index 8bce01a88..ad6e44cc6 100644 --- a/config/eur/arm9/symbols.txt +++ b/config/eur/arm9/symbols.txt @@ -3014,8 +3014,8 @@ data_0205ada8 kind:bss addr:0x0205ada8 data_0205adac kind:bss addr:0x0205adac data_0205adc0 kind:bss addr:0x0205adc0 data_0205ade0 kind:bss addr:0x0205ade0 -gHeapListInitialized kind:bss addr:0x0205ade4 -gHeapList kind:bss addr:0x0205ade8 +gHeapListInitialized kind:bss addr:0x0205ade4 local +gHeapList kind:bss addr:0x0205ade8 local data_0205adf4 kind:bss addr:0x0205adf4 data_0205ae08 kind:bss addr:0x0205ae08 data_0205db08 kind:bss addr:0x0205db08 diff --git a/config/usa/arm9/delinks.txt b/config/usa/arm9/delinks.txt index 869cdd5a6..0a591ebc8 100644 --- a/config/usa/arm9/delinks.txt +++ b/config/usa/arm9/delinks.txt @@ -87,5 +87,6 @@ libs/nds/src/sbc.c: .bss start:0x0205ada8 end:0x0205daa8 libs/nds/src/heap.c: + complete .text start:0x02017034 end:0x020179ac .bss start:0x0205ad84 end:0x0205ad94 \ No newline at end of file diff --git a/config/usa/arm9/symbols.txt b/config/usa/arm9/symbols.txt index da6d58f01..893edec5d 100644 --- a/config/usa/arm9/symbols.txt +++ b/config/usa/arm9/symbols.txt @@ -3014,8 +3014,8 @@ data_0205ada8 kind:bss addr:0x0205ad48 data_0205adac kind:bss addr:0x0205ad4c data_0205adc0 kind:bss addr:0x0205ad60 data_0205ade0 kind:bss addr:0x0205ad80 -gHeapListInitialized kind:bss addr:0x0205ad84 -gHeapList kind:bss addr:0x0205ad88 +gHeapListInitialized kind:bss addr:0x0205ad84 local +gHeapList kind:bss addr:0x0205ad88 local data_0205adf4 kind:bss addr:0x0205ad94 data_0205ae08 kind:bss addr:0x0205ada8 data_0205db08 kind:bss addr:0x0205daa8 From 550c55f09b650ef203cc6f40bda4661e5f7e445f Mon Sep 17 00:00:00 2001 From: enzo Date: Wed, 3 Jun 2026 13:02:45 -0300 Subject: [PATCH 6/6] fix external references --- include/Actor/ActorManager.hpp | 1 + libs/nds/include/nds/heap.h | 32 ++++++++++++++++++--------- libs/nds/src/heap.c | 6 ++--- src/04_Load/Actor/ActorManager_04.cpp | 6 ++--- src/08_GameStart/Init.cpp | 7 +++--- 5 files changed, 30 insertions(+), 22 deletions(-) diff --git a/include/Actor/ActorManager.hpp b/include/Actor/ActorManager.hpp index 0b3b2677b..bbfada47b 100644 --- a/include/Actor/ActorManager.hpp +++ b/include/Actor/ActorManager.hpp @@ -4,6 +4,7 @@ #include "types.h" #include "lib/files.hpp" +#include "nds/heap.h" #include "Actor/Actor.hpp" #include "Actor/ActorRef.hpp" diff --git a/libs/nds/include/nds/heap.h b/libs/nds/include/nds/heap.h index d67ceff46..221bac8a1 100644 --- a/libs/nds/include/nds/heap.h +++ b/libs/nds/include/nds/heap.h @@ -1,6 +1,10 @@ #include "global.h" #include "types.h" +#ifdef __cplusplus +extern "C" { +#endif + typedef struct Heap_Region_ { /* 00 */ void *start; /* 04 */ void *end; @@ -69,14 +73,6 @@ typedef struct Heap_FRMHHeader_ { /* 0c */ } Heap_FRMHHeader; -void Heap_InitHeader(Heap_Header *pHeapHd, u32 signature, void *heapStart, void *heapEnd, u16 optFlag); -void Heap_DestroyInternal(Heap_Header *pHeapHd); -void Heap_InitList(Heap_LinkedList *list, u16 offset); -void Heap_ListAppend(Heap_LinkedList *list, void *object); -void Heap_ListRemove(Heap_LinkedList *list, void *object); -void *Heap_ListNext(Heap_LinkedList *list, void *object); - -// rename typedef struct Heap_UNTHBlockHeader_ { /* 00 */ struct Heap_UNTHBlockHeader_ *next; /* 04 */ @@ -88,7 +84,21 @@ typedef struct Heap_UNTHBlockList_ { } Heap_UNTHBlockList; typedef struct Heap_UNTHHeader_ { - /* 00 */ Heap_UNTHBlockList mbFreeList; - /* 04 */ u32 mBlkSize; + /* 00 */ Heap_UNTHBlockList freeBlocks; + /* 04 */ u32 blockSize; /* 08 */ -} Heap_UNTHHeader; \ No newline at end of file +} Heap_UNTHHeader; + +// function declarations +void *Heap_EXPHNew(Heap_Header *heap, u32 size, int alignment); +void Heap_EXPHFreeBlock(Heap_Header *heap, void *memBlock); +void Heap_InitHeader(Heap_Header *pHeapHd, u32 signature, void *heapStart, void *heapEnd, u16 optFlag); +void Heap_DestroyInternal(Heap_Header *pHeapHd); +void Heap_InitList(Heap_LinkedList *list, u16 offset); +void Heap_ListAppend(Heap_LinkedList *list, void *object); +void Heap_ListRemove(Heap_LinkedList *list, void *object); +void *Heap_ListNext(Heap_LinkedList *list, void *object); + +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/libs/nds/src/heap.c b/libs/nds/src/heap.c index 9b3d8e8cc..35188b0e2 100644 --- a/libs/nds/src/heap.c +++ b/libs/nds/src/heap.c @@ -754,11 +754,11 @@ Heap_Header *Heap_UNTHCreate(void *startAddress, u32 heapSize, u32 memBlockSize, heapEnd = AddU32_inline(heapStart, elementNum * memBlockSize); Heap_InitHeader(header, 'UNTH', heapStart, heapEnd, optFlag); - pUntHeapHd->mbFreeList.head = heapStart; - pUntHeapHd->mBlkSize = memBlockSize; + pUntHeapHd->freeBlocks.head = heapStart; + pUntHeapHd->blockSize = memBlockSize; { - Heap_UNTHBlockHeader *pMBlkHd = pUntHeapHd->mbFreeList.head; + Heap_UNTHBlockHeader *pMBlkHd = pUntHeapHd->freeBlocks.head; int i; for (i = 0; i < elementNum - 1; ++i, pMBlkHd = pMBlkHd->next) { diff --git a/src/04_Load/Actor/ActorManager_04.cpp b/src/04_Load/Actor/ActorManager_04.cpp index fdf8fe763..497f0208d 100644 --- a/src/04_Load/Actor/ActorManager_04.cpp +++ b/src/04_Load/Actor/ActorManager_04.cpp @@ -129,7 +129,6 @@ THUMB void ActorManager::func_ov004_0210532c() { return; } -extern "C" void Heap_EXPHFreeBlock(u32 *, void *); extern "C" void func_ov017_02168a90(); extern "C" void func_ov025_0216d6dc(); extern "C" void func_ov029_0216d6f0(unk32 *); @@ -147,7 +146,7 @@ THUMB void ActorManager::func_ov004_021053dc() { this->DeleteActor(i, true); } } - Heap_EXPHFreeBlock(data_027e0ce0[1], this->mActorTable); + Heap_EXPHFreeBlock((Heap_Header *) data_027e0ce0[1], this->mActorTable); this->mActorTable = NULL; delete this->mUnk_14; this->mUnk_14 = NULL; @@ -179,7 +178,6 @@ THUMB void ActorManager::func_ov004_021053dc() { } extern "C" void func_ov000_020c3388(unk32); -extern "C" void *Heap_EXPHNew(u32 *id, s32 length, s32 param_3); THUMB void ActorManager::func_ov004_021054a4(FileEntryFlag *param1, s32 param2, unk32 param3) { u16 sVar1; u16 sVar2; @@ -205,7 +203,7 @@ THUMB void ActorManager::func_ov004_021054a4(FileEntryFlag *param1, s32 param2, } param1->vfunc_0c(); func_ov000_020c3388(sVar2); - this->mActorTable = (Actor **) Heap_EXPHNew(data_027e0ce0[1], this->mMaxActors * 4, 4); + this->mActorTable = (Actor **) Heap_EXPHNew((Heap_Header *) data_027e0ce0[1], this->mMaxActors * 4, 4); Fill256(0, this->mActorTable, this->mMaxActors * 4); this->mUnk_14 = new(data_027e0ce0[1], 4) ActorManager_Unk14(this->mMaxActors); } diff --git a/src/08_GameStart/Init.cpp b/src/08_GameStart/Init.cpp index 3251c45b5..ce835be9d 100644 --- a/src/08_GameStart/Init.cpp +++ b/src/08_GameStart/Init.cpp @@ -15,6 +15,7 @@ #include "Unknown/UnkStruct_027e0d54.hpp" #include "Unknown/UnkStruct_027e0dbc.hpp" #include "Unknown/UnkStruct_027e0f88.hpp" +#include "nds/heap.h" extern "C" { void func_0200a23c(); @@ -22,9 +23,7 @@ void func_0200a318(u8 *); unk32 func_0200dd94(); unk32 func_0200a284(u8 *); u16 func_ov001_020efdac(); -void *Heap_EXPHNew(char *id, s32 length, s32 param_3); unk32 func_ov000_020773c0(); -void Heap_EXPHFreeBlock(u32 *, void *); void func_0201f378(); void func_0202019c(void *, const char *, u32 *, unk32); void func_020213f0(u32 *); @@ -165,13 +164,13 @@ ARM UnkStruct_020ee698::UnkStruct_020ee698() : mUnk_02(0), mUnk_04(func_ov001_020efdac()), mUnk_08(0x0D) { - void *newHeap = Heap_EXPHNew((char *) data_027e0ce0[1], 0x700, 0x20); + void *newHeap = Heap_EXPHNew((Heap_Header *) data_027e0ce0[1], 0x700, 0x20); if (func_ov000_020773c0() == 3) { this->mUnk_00 = 1; } - Heap_EXPHFreeBlock(data_027e0ce0[1], newHeap); + Heap_EXPHFreeBlock((Heap_Header *) data_027e0ce0[1], newHeap); } // --- data_ov000_020ee734 ---