diff --git a/arm9/arm9.lsf b/arm9/arm9.lsf index 8287f1338..74e31f797 100644 --- a/arm9/arm9.lsf +++ b/arm9/arm9.lsf @@ -358,6 +358,7 @@ Static arm9 ### Nitro System SDK ### Object NNS_FND_list.o Object NNS_FND_heapcommon.o + Object NNS_FND_expheap_s.o Object NNS_FND_expheap.o Object NNS_FND_frameheap.o Object NNS_FND_allocator.o diff --git a/arm9/asm/NNS_FND_expheap.s b/arm9/asm/NNS_FND_expheap_s.s similarity index 89% rename from arm9/asm/NNS_FND_expheap.s rename to arm9/asm/NNS_FND_expheap_s.s index e94dba383..54a26a2f7 100644 --- a/arm9/asm/NNS_FND_expheap.s +++ b/arm9/asm/NNS_FND_expheap_s.s @@ -2,6 +2,10 @@ .include "global.inc" .extern NNSi_FndInitHeapHead .extern NNSi_FndFinalizeHeap + .extern GetRegionOfMBlock + .extern RemoveMBlock + .extern InsertMBlock + .extern InitMBlock .text arm_func_start NNS_FndGetSizeForMBlockExpHeap @@ -520,64 +524,3 @@ InitExpHeap: ; 0x020AE420 _020AE498: .word 0x45585048 _020AE49C: .word 0x00004652 arm_func_end InitExpHeap - - arm_func_start InitMBlock -InitMBlock: ; 0x020AE4A0 - ldr r3, [r0, #0x0] - mov r2, #0x0 - strh r1, [r3, #0x0] - strh r2, [r3, #0x2] - ldr r1, [r0, #0x4] - add r0, r3, #0x10 - sub r0, r1, r0 - str r0, [r3, #0x4] - str r2, [r3, #0x8] - mov r0, r3 - str r2, [r3, #0xc] - bx lr - arm_func_end InitMBlock - - arm_func_start InsertMBlock -InsertMBlock: ; 0x020AE4D0 - str r2, [r1, #0x8] - cmp r2, #0x0 - ldrne r3, [r2, #0xc] - strne r1, [r2, #0xc] - ldreq r3, [r0, #0x0] - streq r1, [r0, #0x0] - str r3, [r1, #0xc] - cmp r3, #0x0 - strne r1, [r3, #0x8] - streq r1, [r0, #0x4] - mov r0, r1 - bx lr - arm_func_end InsertMBlock - - arm_func_start RemoveMBlock -RemoveMBlock: ; 0x020AE500 - ldr r2, [r1, #0x8] - ldr r1, [r1, #0xc] - cmp r2, #0x0 - strne r1, [r2, #0xc] - streq r1, [r0, #0x0] - cmp r1, #0x0 - strne r2, [r1, #0x8] - streq r2, [r0, #0x4] - mov r0, r2 - bx lr - arm_func_end RemoveMBlock - - arm_func_start GetRegionOfMBlock -GetRegionOfMBlock: ; 0x020AE528 - ldrh r2, [r1, #0x2] - add r3, r1, #0x10 - mov r2, r2, asr #0x8 - and r2, r2, #0x7f - mov r2, r2, lsl #0x10 - sub r2, r1, r2, lsr #0x10 - str r2, [r0, #0x0] - ldr r1, [r1, #0x4] - add r1, r1, r3 - str r1, [r0, #0x4] - bx lr - arm_func_end GetRegionOfMBlock diff --git a/arm9/lib/libnns/include/NNS_FND_heapcommon.h b/arm9/lib/libnns/include/NNS_FND_heapcommon.h index e6fab69c8..8128e74bd 100644 --- a/arm9/lib/libnns/include/NNS_FND_heapcommon.h +++ b/arm9/lib/libnns/include/NNS_FND_heapcommon.h @@ -7,6 +7,18 @@ typedef struct NNSiFndHeapHead NNSiFndHeapHead; +typedef s32 NNSiIntPtr; +typedef u32 NNSiUIntPtr; + +#define NNSi_FndGetBitValue(data, st, bits) (((data) >>(st)) & ((1 <<(bits)) -1)) +#define NNSi_FndSetBitValue(data, st, bits, val) do { \ + u32 maskBits = (u32)((1 << (bits)) - 1); \ + u32 newVal = (val) & maskBits; \ + (void)(maskBits <<= st); \ + (data) &= ~maskBits; \ + (data) |= newVal << (st); \ +} while (FALSE); + struct NNSiFndHeapHead { u32 signature; @@ -23,4 +35,56 @@ struct NNSiFndHeapHead typedef NNSiFndHeapHead* NNSFndHeapHandle; // Type to represent heap handle +static inline NNSiUIntPtr NNSiGetUIntPtr(const void* ptr) +{ + return (NNSiUIntPtr)ptr; +} + +static inline u32 GetOffsetFromPtr(const void* start, const void* end) +{ + return NNSiGetUIntPtr(end) - NNSiGetUIntPtr(start); +} + +static inline void* AddU32ToPtr(void* ptr, u32 val) +{ + return (void*)( NNSiGetUIntPtr(ptr) + val ); +} + +static inline const void* AddU32ToCPtr(const void* ptr, u32 val) +{ + return (const void*)( NNSiGetUIntPtr(ptr) + val ); +} + +static inline void* SubU32ToPtr(void* ptr, u32 val) +{ + return (void*)(NNSiGetUIntPtr(ptr) - val); +} + +static inline const void* SubU32ToCPtr(const void* ptr, u32 val) +{ + return (const void*)(NNSiGetUIntPtr(ptr) - val); +} + +static inline int ComparePtr(const void* a, const void* b) +{ + const u8* wa = a; + const u8* wb = b; + + return wa - wb; +} + + +static inline u16 GetOptForHeap(const NNSiFndHeapHead* pHeapHd) +{ + return (u16)NNSi_FndGetBitValue(pHeapHd->attribute, 0, 8); +} + +static inline void SetOptForHeap( + NNSiFndHeapHead* pHeapHd, + u16 optFlag + ) +{ + NNSi_FndSetBitValue(pHeapHd->attribute, 0, 8, optFlag); +} + #endif //GUARD_NNS_FND_HEAPCOMMON_H diff --git a/arm9/lib/libnns/src/NNS_FND_expheap.c b/arm9/lib/libnns/src/NNS_FND_expheap.c new file mode 100644 index 000000000..70e3886ac --- /dev/null +++ b/arm9/lib/libnns/src/NNS_FND_expheap.c @@ -0,0 +1,92 @@ +#include "global.h" +#include "NNS_FND_expheap.h" + +typedef struct NNSiMemRegion { + void* start; + void* end; +} NNSiMemRegion; + +static inline u16 GetAlignmentForMBlock(NNSiFndExpHeapMBlockHead* block) +{ + return NNSi_FndGetBitValue(block->attribute, 8, 7); +} + +static inline void* GetMemPtrForMBlock(NNSiFndExpHeapMBlockHead* block) +{ + return AddU32ToPtr(block, sizeof(NNSiFndExpHeapMBlockHead)); +} + +static inline void* GetMBlockEndAddr(NNSiFndExpHeapMBlockHead* block) +{ + return AddU32ToPtr(GetMemPtrForMBlock(block), block->blockSize); +} + +void GetRegionOfMBlock(NNSiMemRegion* region, NNSiFndExpHeapMBlockHead* block) +{ + region->start = SubU32ToPtr(block, GetAlignmentForMBlock(block)); + region->end = GetMBlockEndAddr(block); +} + +NNSiFndExpHeapMBlockHead* RemoveMBlock(NNSiFndExpMBlockList* list, NNSiFndExpHeapMBlockHead* block) +{ + NNSiFndExpHeapMBlockHead* const prev = block->pMBHeadPrev; + NNSiFndExpHeapMBlockHead* const next = block->pMBHeadNext; + + if (prev != NULL) + { + prev->pMBHeadNext = next; + } + else + { + list->head = next; + } + + if (next != NULL) + { + next->pMBHeadPrev = prev; + } + else + { + list->tail = prev; + } + + return prev; +} + +NNSiFndExpHeapMBlockHead* InsertMBlock(NNSiFndExpMBlockList* list, NNSiFndExpHeapMBlockHead* target, NNSiFndExpHeapMBlockHead* prev) +{ + NNSiFndExpHeapMBlockHead* next; + target->pMBHeadPrev = prev; + if (prev != NULL) + { + next = prev->pMBHeadNext; + prev->pMBHeadNext = target; + } + else + { + next = list->head; + list->head = target; + } + target->pMBHeadNext = next; + if (next != NULL) + { + next->pMBHeadPrev = target; + } + else + { + list->tail = target; + } + + return target; +} + +NNSiFndExpHeapMBlockHead* InitMBlock(const NNSiMemRegion* pRegion, u16 signature) +{ + NNSiFndExpHeapMBlockHead* block = pRegion->start; + block->signature = signature; + block->attribute = 0; + block->blockSize = GetOffsetFromPtr(GetMemPtrForMBlock(block), pRegion->end); + block->pMBHeadPrev = NULL; + block->pMBHeadNext = NULL; + return block; +} diff --git a/arm9/lib/libnns/src/NNS_FND_heapcommon.c b/arm9/lib/libnns/src/NNS_FND_heapcommon.c index 664007f15..07b8e9cf7 100644 --- a/arm9/lib/libnns/src/NNS_FND_heapcommon.c +++ b/arm9/lib/libnns/src/NNS_FND_heapcommon.c @@ -5,12 +5,6 @@ BOOL sRootListInitialized; NNSFndList sRootList; -static inline void NNSi_FndHeapHeadSetOptionFlag(NNSiFndHeapHead *pHead, u8 option_flag) -{ - pHead->attribute &= ~0xFF; - pHead->attribute |= option_flag; -} - void *NNS_FndGetNextListObject(NNSFndList *, void *); static NNSiFndHeapHead* FindContainHeap(NNSFndList * pList, const void * memBlock) @@ -45,7 +39,7 @@ void NNSi_FndInitHeapHead(NNSiFndHeapHead *pHead, u32 signature, void* heapStart pHead->heapStart = heapStart; pHead->heapEnd = heapEnd; pHead->attribute = 0; - NNSi_FndHeapHeadSetOptionFlag(pHead, optionFlag); + SetOptForHeap(pHead, optionFlag); NNS_FndInitList(&pHead->childList, 4); if (!sRootListInitialized) {