From 676ebab3d6ad726b3e154c994c4fcfdbb186ed22 Mon Sep 17 00:00:00 2001 From: PikalaxALT Date: Sat, 21 Aug 2021 11:02:05 -0400 Subject: through NNS_FndAllocFromExpHeapEx --- arm9/asm/NNS_FND_expheap_s.s | 121 +-------------------------- arm9/lib/libnns/include/NNS_FND_expheap.h | 4 +- arm9/lib/libnns/include/NNS_FND_heapcommon.h | 2 + arm9/lib/libnns/src/NNS_FND_expheap.c | 116 +++++++++++++++++++++++++ 4 files changed, 121 insertions(+), 122 deletions(-) diff --git a/arm9/asm/NNS_FND_expheap_s.s b/arm9/asm/NNS_FND_expheap_s.s index d173bef0..d4d958db 100644 --- a/arm9/asm/NNS_FND_expheap_s.s +++ b/arm9/asm/NNS_FND_expheap_s.s @@ -10,6 +10,7 @@ .extern AllocUsedBlockFromFreeBlock .extern AllocFromHead .extern AllocFromTail + .extern RecycleRegion .text arm_func_start NNS_FndGetSizeForMBlockExpHeap @@ -156,123 +157,3 @@ _020ADF90: .balign 4 _020ADF9C: .word 0x00004652 arm_func_end NNS_FndResizeForMBlockExpHeap - - arm_func_start NNS_FndAllocFromExpHeapEx -NNS_FndAllocFromExpHeapEx: ; 0x020ADFA0 - stmdb sp!, {lr} - sub sp, sp, #0x4 - cmp r1, #0x0 - moveq r1, #0x1 - add r1, r1, #0x3 - cmp r2, #0x0 - bic r1, r1, #0x3 - blt _020ADFCC - bl AllocFromHead - add sp, sp, #0x4 - ldmia sp!, {pc} -_020ADFCC: - rsb r2, r2, #0x0 - bl AllocFromTail - add sp, sp, #0x4 - ldmia sp!, {pc} - arm_func_end NNS_FndAllocFromExpHeapEx - - arm_func_start NNS_FndDestroyExpHeap -NNS_FndDestroyExpHeap: ; 0x020ADFDC - ldr ip, _020ADFE4 ; =NNSi_FndFinalizeHeap - bx r12 - .balign 4 -_020ADFE4: .word NNSi_FndFinalizeHeap - arm_func_end NNS_FndDestroyExpHeap - - arm_func_start NNS_FndCreateExpHeapEx -NNS_FndCreateExpHeapEx: ; 0x020ADFE8 - stmdb sp!, {lr} - sub sp, sp, #0x4 - add r1, r1, r0 - add r0, r0, #0x3 - bic r1, r1, #0x3 - bic r0, r0, #0x3 - cmp r0, r1 - bhi _020AE014 - sub r3, r1, r0 - cmp r3, #0x4c - bhs _020AE020 -_020AE014: - add sp, sp, #0x4 - mov r0, #0x0 - ldmia sp!, {pc} -_020AE020: - bl InitExpHeap - add sp, sp, #0x4 - ldmia sp!, {pc} - arm_func_end NNS_FndCreateExpHeapEx - - arm_func_start RecycleRegion -RecycleRegion: - stmdb sp!, {r4-r6,lr} - sub sp, sp, #0x8 - mov r5, r1 - ldr r2, [r5, #0x0] - ldr r1, [r5, #0x4] - mov r6, r0 - str r2, [sp, #0x0] - str r1, [sp, #0x4] - ldr r1, [r6, #0x0] - mov r4, #0x0 - cmp r1, #0x0 - beq _020AE0A0 - ldr r0, [r5, #0x0] -_020AE060: - cmp r1, r0 - movcc r4, r1 - blo _020AE094 - ldr r0, [r5, #0x4] - cmp r1, r0 - bne _020AE0A0 - ldr r2, [r1, #0x4] - add r0, r1, #0x10 - add r2, r2, r0 - mov r0, r6 - str r2, [sp, #0x4] - bl RemoveMBlock - b _020AE0A0 -_020AE094: - ldr r1, [r1, #0xc] - cmp r1, #0x0 - bne _020AE060 -_020AE0A0: - cmp r4, #0x0 - beq _020AE0D4 - ldr r2, [r4, #0x4] - add r1, r4, #0x10 - ldr r0, [r5, #0x0] - add r1, r2, r1 - cmp r1, r0 - bne _020AE0D4 - mov r0, r6 - mov r1, r4 - str r4, [sp, #0x0] - bl RemoveMBlock - mov r4, r0 -_020AE0D4: - ldr r1, [sp, #0x4] - ldr r0, [sp, #0x0] - sub r0, r1, r0 - cmp r0, #0x10 - addcc sp, sp, #0x8 - movcc r0, #0x0 - ldmccia sp!, {r4-r6,pc} - ldr r1, _020AE118 ; =0x00004652 - add r0, sp, #0x0 - bl InitMBlock - mov r1, r0 - mov r0, r6 - mov r2, r4 - bl InsertMBlock - mov r0, #0x1 - add sp, sp, #0x8 - ldmia sp!, {r4-r6,pc} - .balign 4 -_020AE118: .word 0x00004652 - arm_func_end RecycleRegion diff --git a/arm9/lib/libnns/include/NNS_FND_expheap.h b/arm9/lib/libnns/include/NNS_FND_expheap.h index bdc3fcc4..acf33bd4 100644 --- a/arm9/lib/libnns/include/NNS_FND_expheap.h +++ b/arm9/lib/libnns/include/NNS_FND_expheap.h @@ -38,13 +38,13 @@ struct NNSiFndExpHeapHead u16 feature; // Attribute }; -NNSFndHeapHandle NNS_FndCreateExpHeapEx(void *startAddress, u32 size, u32 optFlag); +NNSFndHeapHandle NNS_FndCreateExpHeapEx(void *startAddress, u32 size, u16 optFlag); void *NNS_FndAllocFromExpHeapEx(NNSFndHeapHandle heap, u32 size, int alignment); void NNS_FndDestroyExpHeap(NNSFndHeapHandle heap); void NNS_FndFreeToExpHeap(NNSFndHeapHandle heap, void *memBlock); u32 NNS_FndGetTotalFreeSizeForExpHeap(NNSFndHeapHandle heap); u32 NNS_FndGetSizeForMBlockExpHeap(const void *memBlock); -void NNS_FndResizeForMBlockExpHeap(NNSFndHeapHandle heap, void *memBlock, u32 size); +u32 NNS_FndResizeForMBlockExpHeap(NNSFndHeapHandle heap, void *memBlock, u32 size); #define NNS_FndCreateExpHeap(startAddress, size) \ NNS_FndCreateExpHeapEx(startAddress, size, 0) diff --git a/arm9/lib/libnns/include/NNS_FND_heapcommon.h b/arm9/lib/libnns/include/NNS_FND_heapcommon.h index f35bf097..e3124e81 100644 --- a/arm9/lib/libnns/include/NNS_FND_heapcommon.h +++ b/arm9/lib/libnns/include/NNS_FND_heapcommon.h @@ -98,6 +98,8 @@ static inline void FillAllocMemory(NNSiFndHeapHead* pHeapHd, void* address, u32 void NNSi_FndInitHeapHead(NNSiFndHeapHead *pHead, u32 signature, void* heapStart, void* heapEnd, u16 optionFlag); +void NNSi_FndFinalizeHeap(NNSiFndHeapHead *pHead); + #define NNSi_FndRoundUp(value, alignment) (((value) + (alignment - 1)) & ~(alignment - 1)) #define NNSi_FndRoundUpPtr(ptr, alignment) ((void*)NNSi_FndRoundUp(NNSiGetUIntPtr(ptr), alignment)) diff --git a/arm9/lib/libnns/src/NNS_FND_expheap.c b/arm9/lib/libnns/src/NNS_FND_expheap.c index 31ea5fbe..15657c43 100644 --- a/arm9/lib/libnns/src/NNS_FND_expheap.c +++ b/arm9/lib/libnns/src/NNS_FND_expheap.c @@ -31,6 +31,11 @@ static inline void* GetMemPtrForMBlock(NNSiFndExpHeapMBlockHead* block) return AddU32ToPtr(block, sizeof(NNSiFndExpHeapMBlockHead)); } +static inline void* GetMBlockHeadPtr(void* block) +{ + return SubU32ToPtr(block, sizeof(NNSiFndExpHeapMBlockHead)); +} + static inline void* GetMBlockEndAddr(NNSiFndExpHeapMBlockHead* block) { return AddU32ToPtr(GetMemPtrForMBlock(block), block->blockSize); @@ -51,6 +56,11 @@ static inline NNSiFndExpHeapHead* GetExpHeapHeadPtrFromHeapHead(NNSiFndHeapHead* return AddU32ToPtr(pHHead, sizeof(NNSiFndHeapHead)); } +static inline NNSiFndExpHeapHead* GetExpHeapHeadPtrFromHandle(NNSFndHeapHandle heap) +{ + return GetExpHeapHeadPtrFromHeapHead(heap); +} + static inline NNSiFndHeapHead* GetHeapHeadPtrFromExpHeapHead(NNSiFndExpHeapHead* pEHHead) { return SubU32ToPtr(pEHHead, sizeof(NNSiFndHeapHead)); @@ -267,3 +277,109 @@ void* AllocFromTail(NNSiFndHeapHead* pHeapHd, u32 size, int alignment) return AllocUsedBlockFromFreeBlock(pExpHeapHd, pMBlkHdFound, foundMBlock, size, 1); } + +BOOL RecycleRegion(NNSiFndExpHeapHead* pEHHead, const NNSiMemRegion* pRegion) +{ + NNSiFndExpHeapMBlockHead* pBlkPtrFree = NULL; + NNSiMemRegion freeRgn = *pRegion; + NNSiFndExpHeapMBlockHead* pBlk; + for (pBlk = pEHHead->mbFreeList.head; pBlk; pBlk = pBlk->pMBHeadNext) + { + if (pBlk < (NNSiFndExpHeapMBlockHead*)pRegion->start) + { + pBlkPtrFree = pBlk; + continue; + } + if (pBlk == pRegion->end) + { + freeRgn.end = GetMBlockEndAddr(pBlk); + (void)RemoveMBlock(&pEHHead->mbFreeList, pBlk); + } + break; + } + if (pBlkPtrFree && GetMBlockEndAddr(pBlkPtrFree) == pRegion->start) + { + freeRgn.start = pBlkPtrFree; + pBlkPtrFree = RemoveMBlock(&pEHHead->mbFreeList, pBlkPtrFree); + } + if (GetOffsetFromPtr(freeRgn.start, freeRgn.end) < sizeof(NNSiFndExpHeapMBlockHead)) + return FALSE; + InsertMBlock(&pEHHead->mbFreeList, InitFreeMBlock(&freeRgn), pBlkPtrFree); + return TRUE; +} + +NNSFndHeapHandle NNS_FndCreateExpHeapEx(void *startAddress, u32 size, u16 optFlag) +{ + void* endAddress = NNSi_FndRoundDownPtr(AddU32ToPtr(startAddress, size), 4); + startAddress = NNSi_FndRoundUpPtr(startAddress, 4); + if (NNSiGetUIntPtr(startAddress) > NNSiGetUIntPtr(endAddress) || GetOffsetFromPtr(startAddress, endAddress) < sizeof(NNSiFndHeapHead) + sizeof(NNSiFndExpHeapHead) + sizeof(NNSiFndExpHeapMBlockHead) + 4) + return NULL; + return InitExpHeap(startAddress, endAddress, optFlag); +} + +void NNS_FndDestroyExpHeap(NNSFndHeapHandle handle) +{ + NNSi_FndFinalizeHeap(handle); +} + +void* NNS_FndAllocFromExpHeapEx(NNSFndHeapHandle handle, u32 size, int alignment) +{ + if (size == 0) + size = 1; + size = NNSi_FndRoundUp(size, 4); + if (alignment >= 0) + return AllocFromHead(handle, size, alignment); + else + return AllocFromTail(handle, size, -alignment); +} + +/* +u32 NNS_FndResizeForMBlockExpHeap(NNSFndHeapHandle heap, void *memBlock, u32 size) +{ + NNSiFndExpHeapHead* pEHHead; + NNSiFndExpHeapMBlockHead* pMBHead; + pEHHead = GetExpHeapHeadPtrFromHandle(heap); + pMBHead = GetMBlockHeadPtr(memBlock); + size = NNSi_FndRoundUp(size, 4); + if (size == pMBHead->blockSize) + return size; + if (size > pMBHead->blockSize) + { + void* crUsedEnd = GetMBlockEndAddr(pMBHead); + NNSiFndExpHeapMBlockHead* block; + for (block = pEHHead->mbFreeList.head; block; block = block->pMBHeadNext) + { + if (block == crUsedEnd) + break; + } + if (!block || size > pMBHead->blockSize + sizeof(NNSiFndExpHeapMBlockHead) + block->blockSize) + return 0; + + NNSiMemRegion rgnNewFree; + void* oldFreeStart; + NNSiFndExpHeapMBlockHead* nextBlockPrev; + + GetRegionOfMBlock(&rgnNewFree, block); + nextBlockPrev = RemoveMBlock(&pEHHead->mbFreeList, block); + oldFreeStart = rgnNewFree.start; + rgnNewFree.start = AddU32ToPtr(memBlock, size); + if (GetOffsetFromPtr(rgnNewFree.start, rgnNewFree.end) < sizeof(NNSiFndExpHeapMBlockHead)) + rgnNewFree.start = rgnNewFree.end; + pMBHead->blockSize = GetOffsetFromPtr(memBlock, rgnNewFree.start); + if (GetOffsetFromPtr(rgnNewFree.start, rgnNewFree.end) >= sizeof(NNSiFndExpHeapMBlockHead)) + (void)InsertMBlock(&pEHHead->mbFreeList, InitFreeMBlock(&rgnNewFree), nextBlockPrev); + FillAllocMemory(heap, oldFreeStart, GetOffsetFromPtr(oldFreeStart, rgnNewFree.start)); + } + else + { + NNSiMemRegion rgnNewFree; + const u32 oldBlockSize = pMBHead->blockSize; + rgnNewFree.start = AddU32ToPtr(memBlock, size); + rgnNewFree.end = GetMBlockEndAddr(pMBHead); + pMBHead->blockSize = size; + if (!RecycleRegion(pEHHead, &rgnNewFree)) + pMBHead->blockSize = oldBlockSize; + } + return pMBHead->blockSize; +} +*/ -- cgit v1.2.3