diff --git a/lib/NitroSystem/asm/fnd/expheap.s b/lib/NitroSystem/asm/fnd/expheap.s deleted file mode 100644 index 9872921d5d..0000000000 --- a/lib/NitroSystem/asm/fnd/expheap.s +++ /dev/null @@ -1,577 +0,0 @@ - .include "macros/function.inc" - .include "include/expheap.inc" - - - - .text - - - arm_func_start GetRegionOfMBlock -GetRegionOfMBlock: ; 0x020A4F0C - ldrh r2, [r1, #2] - add r3, r1, #0x10 - mov r2, r2, asr #8 - and r2, r2, #0x7f - mov r2, r2, lsl #0x10 - sub r2, r1, r2, lsr #16 - str r2, [r0, #0] - ldr r1, [r1, #4] - add r1, r1, r3 - str r1, [r0, #4] - bx lr - arm_func_end GetRegionOfMBlock - - arm_func_start RemoveMBlock -RemoveMBlock: ; 0x020A4F38 - ldr r2, [r1, #8] - ldr r1, [r1, #0xc] - cmp r2, #0 - strne r1, [r2, #0xc] - streq r1, [r0] - cmp r1, #0 - strne r2, [r1, #8] - streq r2, [r0, #4] - mov r0, r2 - bx lr - arm_func_end RemoveMBlock - - arm_func_start InsertMBlock -InsertMBlock: ; 0x020A4F60 - str r2, [r1, #8] - cmp r2, #0 - ldrne r3, [r2, #0xc] - strne r1, [r2, #0xc] - ldreq r3, [r0] - streq r1, [r0] - str r3, [r1, #0xc] - cmp r3, #0 - strne r1, [r3, #8] - streq r1, [r0, #4] - mov r0, r1 - bx lr - arm_func_end InsertMBlock - - arm_func_start InitMBlock -InitMBlock: ; 0x020A4F90 - ldr r3, [r0, #0] - mov r2, #0 - strh r1, [r3] - strh r2, [r3, #2] - ldr r1, [r0, #4] - add r0, r3, #0x10 - sub r0, r1, r0 - stmib r3, {r0, r2} - mov r0, r3 - str r2, [r3, #0xc] - bx lr - arm_func_end InitMBlock - - arm_func_start InitExpHeap -InitExpHeap: ; 0x020A4FBC - stmfd sp!, {r3, r4, lr} - sub sp, sp, #0xc - mov r3, r1 - mov r4, r0 - str r2, [sp] - ldr r1, _020A5028 ; =0x45585048 - add r2, r4, #0x38 - bl NNSi_FndInitHeapHead - mov r0, #0 - strh r0, [r4, #0x34] - bic r0, r0, #1 - strh r0, [r4, #0x36] - ldr r1, [r4, #0x18] - add r0, sp, #4 - str r1, [sp, #4] - ldr r2, [r4, #0x1c] - ldr r1, _020A502C ; =0x00004652 - str r2, [sp, #8] - bl InitMBlock - str r0, [r4, #0x24] - str r0, [r4, #0x28] - mov r1, #0 - str r1, [r4, #0x2c] - mov r0, r4 - str r1, [r4, #0x30] - add sp, sp, #0xc - ldmia sp!, {r3, r4, pc} - ; .align 2, 0 -_020A5028: .word 0x45585048 -_020A502C: .word 0x00004652 - arm_func_end InitExpHeap - - arm_func_start AllocUsedBlockFromFreeBlock -AllocUsedBlockFromFreeBlock: ; 0x020A5030 - stmfd sp!, {r4, r5, r6, r7, r8, lr} - sub sp, sp, #0x18 - mov r7, r0 - add r0, sp, #0x10 - mov r8, r1 - mov r6, r2 - mov r4, r3 - bl GetRegionOfMBlock - ldr r3, [sp, #0x14] - sub r5, r6, #0x10 - add r2, r4, r6 - mov r0, r7 - mov r1, r8 - str r5, [sp, #0x14] - str r3, [sp, #0xc] - str r2, [sp, #8] - bl RemoveMBlock - ldr r2, [sp, #0x10] - ldr r1, [sp, #0x14] - mov r4, r0 - sub r0, r1, r2 - cmp r0, #0x14 - strlo r2, [sp, #0x14] - blo _020A50B0 - ldr r1, _020A51A8 ; =0x00004652 - add r0, sp, #0x10 - bl InitMBlock - mov r1, r0 - mov r0, r7 - mov r2, r4 - bl InsertMBlock - mov r4, r0 -_020A50B0: - ldr r1, [sp, #0xc] - ldr r0, [sp, #8] - sub r0, r1, r0 - cmp r0, #0x14 - strlo r1, [sp, #8] - blo _020A50E4 - ldr r1, _020A51A8 ; =0x00004652 - add r0, sp, #8 - bl InitMBlock - mov r1, r0 - mov r0, r7 - mov r2, r4 - bl InsertMBlock -_020A50E4: - ldr r0, [r7, #-4] - ldr r1, [sp, #0x14] - ldr r2, [sp, #8] - and r0, r0, #0xff - tst r0, #1 - sub r2, r2, r1 - beq _020A5108 - mov r0, #0 - bl MIi_CpuClear32 -_020A5108: - ldr r2, [sp, #8] - ldr r1, _020A51AC ; =0x00005544 - add r0, sp, #0 - str r5, [sp] - str r2, [sp, #4] - bl InitMBlock - mov r1, r0 - ldrh r3, [r1, #2] - ldrh r2, [sp, #0x30] - add r0, r7, #8 - bic r3, r3, #0x8000 - strh r3, [r1, #2] - ldrh r3, [r1, #2] - mov r2, r2, lsl #0x1f - orr r2, r3, r2, lsr #16 - strh r2, [r1, #2] - ldrh r2, [r1, #2] - ldr r3, [sp, #0x14] - bic r2, r2, #0x7f00 - strh r2, [r1, #2] - sub r2, r1, r3 - mov r2, r2, lsl #0x10 - mov r2, r2, lsr #0x10 - ldrh r3, [r1, #2] - mov r2, r2, lsl #0x19 - orr r2, r3, r2, lsr #17 - strh r2, [r1, #2] - ldrh r2, [r1, #2] - ldrh r3, [r7, #0x10] - bic r2, r2, #0xff - strh r2, [r1, #2] - ldrh r2, [r1, #2] - and r3, r3, #0xff - orr r2, r2, r3 - strh r2, [r1, #2] - ldr r2, [r7, #0xc] - bl InsertMBlock - mov r0, r6 - add sp, sp, #0x18 - ldmia sp!, {r4, r5, r6, r7, r8, pc} - ; .align 2, 0 -_020A51A8: .word 0x00004652 -_020A51AC: .word 0x00005544 - arm_func_end AllocUsedBlockFromFreeBlock - - arm_func_start AllocFromHead_dup1 -AllocFromHead_dup1: ; 0x020A51B0 - stmfd sp!, {r3, r4, r5, r6, r7, r8, sb, lr} - ldrh r4, [r0, #0x36] - mov r3, r1 - ldr ip, [r0, #0x24] - and r1, r4, #1 - mov r1, r1, lsl #0x10 - movs r1, r1, lsr #0x10 - mov r1, #0 - moveq r6, #1 - movne r6, #0 - mov r4, r1 - cmp ip, #0 - sub lr, r1, #1 - beq _020A5240 - sub r2, r2, #1 - mvn r5, r2 -_020A51F0: - add r8, ip, #0x10 - add r7, r2, r8 - and sb, r5, r7 - sub r7, sb, r8 - ldr r8, [ip, #4] - add r7, r3, r7 - cmp r8, r7 - blo _020A5234 - cmp lr, r8 - bls _020A5234 - mov r1, ip - mov lr, r8 - mov r4, sb - cmp r6, #0 - bne _020A5240 - cmp r8, r3 - beq _020A5240 -_020A5234: - ldr ip, [ip, #0xc] - cmp ip, #0 - bne _020A51F0 -_020A5240: - cmp r1, #0 - moveq r0, #0 - ldmeqia sp!, {r3, r4, r5, r6, r7, r8, sb, pc} - mov r5, #0 - mov r2, r4 - add r0, r0, #0x24 - str r5, [sp] - bl AllocUsedBlockFromFreeBlock - ldmia sp!, {r3, r4, r5, r6, r7, r8, sb, pc} - arm_func_end AllocFromHead_dup1 - - arm_func_start AllocFromTail_dup1 -AllocFromTail_dup1: ; 0x020A5264 - stmfd sp!, {r3, r4, r5, r6, r7, r8, sb, lr} - ldrh r4, [r0, #0x36] - mov r3, r1 - ldr ip, [r0, #0x28] - and r1, r4, #1 - mov r1, r1, lsl #0x10 - movs r1, r1, lsr #0x10 - mov r1, #0 - moveq r5, #1 - movne r5, #0 - mov r4, r1 - cmp ip, #0 - sub lr, r1, #1 - beq _020A52F0 - sub r2, r2, #1 - mvn r2, r2 -_020A52A4: - ldr r8, [ip, #4] - add sb, ip, #0x10 - add r6, r8, sb - sub r6, r6, r3 - and r7, r2, r6 - subs r6, r7, sb - bmi _020A52E4 - cmp lr, r8 - bls _020A52E4 - mov r1, ip - mov lr, r8 - mov r4, r7 - cmp r5, #0 - bne _020A52F0 - cmp r8, r3 - beq _020A52F0 -_020A52E4: - ldr ip, [ip, #8] - cmp ip, #0 - bne _020A52A4 -_020A52F0: - cmp r1, #0 - moveq r0, #0 - ldmeqia sp!, {r3, r4, r5, r6, r7, r8, sb, pc} - mov r5, #1 - mov r2, r4 - add r0, r0, #0x24 - str r5, [sp] - bl AllocUsedBlockFromFreeBlock - ldmia sp!, {r3, r4, r5, r6, r7, r8, sb, pc} - arm_func_end AllocFromTail_dup1 - - arm_func_start RecycleRegion -RecycleRegion: ; 0x020A5314 - stmfd sp!, {r4, r5, r6, lr} - sub sp, sp, #8 - mov r5, r1 - ldr r2, [r5, #0] - ldr r1, [r5, #4] - mov r6, r0 - str r2, [sp] - str r1, [sp, #4] - ldr r1, [r6, #0] - mov r4, #0 - cmp r1, #0 - beq _020A5388 - ldr r0, [r5, #0] -_020A5348: - cmp r1, r0 - movlo r4, r1 - blo _020A537C - ldr r0, [r5, #4] - cmp r1, r0 - bne _020A5388 - ldr r2, [r1, #4] - add r0, r1, #0x10 - add r2, r2, r0 - mov r0, r6 - str r2, [sp, #4] - bl RemoveMBlock - b _020A5388 -_020A537C: - ldr r1, [r1, #0xc] - cmp r1, #0 - bne _020A5348 -_020A5388: - cmp r4, #0 - beq _020A53BC - ldr r2, [r4, #4] - add r1, r4, #0x10 - ldr r0, [r5, #0] - add r1, r2, r1 - cmp r1, r0 - bne _020A53BC - mov r0, r6 - mov r1, r4 - str r4, [sp] - bl RemoveMBlock - mov r4, r0 -_020A53BC: - ldr r1, [sp, #4] - ldr r0, [sp] - sub r0, r1, r0 - cmp r0, #0x10 - addlo sp, sp, #8 - movlo r0, #0 - ldmloia sp!, {r4, r5, r6, pc} - ldr r1, _020A5400 ; =0x00004652 - add r0, sp, #0 - bl InitMBlock - mov r1, r0 - mov r0, r6 - mov r2, r4 - bl InsertMBlock - mov r0, #1 - add sp, sp, #8 - ldmia sp!, {r4, r5, r6, pc} - ; .align 2, 0 -_020A5400: .word 0x00004652 - arm_func_end RecycleRegion - - arm_func_start NNS_FndCreateExpHeapEx -NNS_FndCreateExpHeapEx: ; 0x020A5404 - stmfd sp!, {r3, lr} - add r1, r1, r0 - add r0, r0, #3 - bic r1, r1, #3 - bic r0, r0, #3 - cmp r0, r1 - bhi _020A542C - sub r3, r1, r0 - cmp r3, #0x4c - bhs _020A5434 -_020A542C: - mov r0, #0 - ldmia sp!, {r3, pc} -_020A5434: - bl InitExpHeap - ldmia sp!, {r3, pc} - arm_func_end NNS_FndCreateExpHeapEx - - arm_func_start NNS_FndDestroyExpHeap -NNS_FndDestroyExpHeap: ; 0x020A543C - ldr ip, _020A5444 ; =NNSi_FndFinalizeHeap - bx ip - ; .align 2, 0 -_020A5444: .word NNSi_FndFinalizeHeap - arm_func_end NNS_FndDestroyExpHeap - - arm_func_start NNS_FndAllocFromExpHeapEx -NNS_FndAllocFromExpHeapEx: ; 0x020A5448 - stmfd sp!, {r3, lr} - cmp r1, #0 - moveq r1, #1 - add r1, r1, #3 - cmp r2, #0 - bic r1, r1, #3 - blt _020A546C - bl AllocFromHead_dup1 - ldmia sp!, {r3, pc} -_020A546C: - rsb r2, r2, #0 - bl AllocFromTail_dup1 - ldmia sp!, {r3, pc} - arm_func_end NNS_FndAllocFromExpHeapEx - - arm_func_start NNS_FndResizeForMBlockExpHeap -NNS_FndResizeForMBlockExpHeap: ; 0x020A5478 - stmfd sp!, {r3, r4, r5, r6, r7, r8, sb, lr} - sub sp, sp, #0x10 - mov r4, r1 - mov sb, r2 - sub r8, r4, #0x10 - add r1, sb, #3 - ldr r7, [r8, #4] - bic sb, r1, #3 - cmp sb, r7 - mov r5, r0 - addeq sp, sp, #0x10 - moveq r0, sb - ldmeqia sp!, {r3, r4, r5, r6, r7, r8, sb, pc} - bls _020A5598 - ldr r6, [r5, #0x24] - add r0, r8, #0x10 - cmp r6, #0 - add r0, r7, r0 - beq _020A54D4 -_020A54C4: - cmp r6, r0 - ldrne r6, [r6, #0xc] - cmpne r6, #0 - bne _020A54C4 -_020A54D4: - cmp r6, #0 - beq _020A54F0 - ldr r0, [r6, #4] - add r1, r7, #0x10 - add r0, r1, r0 - cmp sb, r0 - bls _020A54FC -_020A54F0: - add sp, sp, #0x10 - mov r0, #0 - ldmia sp!, {r3, r4, r5, r6, r7, r8, sb, pc} -_020A54FC: - add r0, sp, #8 - mov r1, r6 - bl GetRegionOfMBlock - mov r1, r6 - add r0, r5, #0x24 - bl RemoveMBlock - ldr r2, [sp, #0xc] - add r3, sb, r4 - ldr r6, [sp, #8] - sub r1, r2, r3 - str r3, [sp, #8] - cmp r1, #0x10 - strlo r2, [sp, #8] - mov r7, r0 - ldr r0, [sp, #8] - sub r0, r0, r4 - str r0, [r8, #4] - ldr r1, [sp, #0xc] - ldr r0, [sp, #8] - sub r0, r1, r0 - cmp r0, #0x10 - blo _020A5570 - ldr r1, _020A55D4 ; =0x00004652 - add r0, sp, #8 - bl InitMBlock - mov r1, r0 - mov r2, r7 - add r0, r5, #0x24 - bl InsertMBlock -_020A5570: - ldr r0, [r5, #0x20] - ldr r1, [sp, #8] - and r0, r0, #0xff - tst r0, #1 - sub r2, r1, r6 - beq _020A55C8 - mov r1, r6 - mov r0, #0 - bl MIi_CpuClear32 - b _020A55C8 -_020A5598: - add r0, sb, r4 - str r0, [sp] - ldr r1, [r8, #4] - add r0, r8, #0x10 - add r0, r1, r0 - str r0, [sp, #4] - add r1, sp, #0 - add r0, r5, #0x24 - str sb, [r8, #4] - bl RecycleRegion - cmp r0, #0 - streq r7, [r8, #4] -_020A55C8: - ldr r0, [r8, #4] - add sp, sp, #0x10 - ldmia sp!, {r3, r4, r5, r6, r7, r8, sb, pc} - ; .align 2, 0 -_020A55D4: .word 0x00004652 - arm_func_end NNS_FndResizeForMBlockExpHeap - - arm_func_start NNS_FndFreeToExpHeap -NNS_FndFreeToExpHeap: ; 0x020A55D8 - stmfd sp!, {r3, r4, r5, lr} - sub sp, sp, #8 - sub r4, r1, #0x10 - mov r5, r0 - add r0, sp, #0 - mov r1, r4 - bl GetRegionOfMBlock - mov r1, r4 - add r0, r5, #0x2c - bl RemoveMBlock - add r1, sp, #0 - add r0, r5, #0x24 - bl RecycleRegion - add sp, sp, #8 - ldmia sp!, {r3, r4, r5, pc} - arm_func_end NNS_FndFreeToExpHeap - - arm_func_start NNS_FndGetTotalFreeSizeForExpHeap -NNS_FndGetTotalFreeSizeForExpHeap: ; 0x020A5614 - ldr r2, [r0, #0x24] - mov r0, #0 - cmp r2, #0 - bxeq lr -_020A5624: - ldr r1, [r2, #4] - ldr r2, [r2, #0xc] - add r0, r0, r1 - cmp r2, #0 - bne _020A5624 - bx lr - arm_func_end NNS_FndGetTotalFreeSizeForExpHeap - - arm_func_start NNS_FndSetGroupIDForExpHeap -NNS_FndSetGroupIDForExpHeap: ; 0x020A563C - ldrh r2, [r0, #0x34] - strh r1, [r0, #0x34] - mov r0, r2 - bx lr - arm_func_end NNS_FndSetGroupIDForExpHeap - - arm_func_start NNS_FndGetSizeForMBlockExpHeap -NNS_FndGetSizeForMBlockExpHeap: ; 0x020A564C - ldr r0, [r0, #-0xc] - bx lr - arm_func_end NNS_FndGetSizeForMBlockExpHeap - - arm_func_start NNS_FndGetGroupIDForMBlockExpHeap -NNS_FndGetGroupIDForMBlockExpHeap: ; 0x020A5654 - ldrh r0, [r0, #-0xe] - and r0, r0, #0xff - bx lr - arm_func_end NNS_FndGetGroupIDForMBlockExpHeap \ No newline at end of file diff --git a/lib/NitroSystem/asm/fnd/frameheap.s b/lib/NitroSystem/asm/fnd/frameheap.s deleted file mode 100644 index 254d07d34f..0000000000 --- a/lib/NitroSystem/asm/fnd/frameheap.s +++ /dev/null @@ -1,223 +0,0 @@ - .include "macros/function.inc" - .include "include/frameheap.inc" - - - - .text - - - arm_func_start InitFrameHeap -InitFrameHeap: ; 0x020A5660 - stmfd sp!, {r3, r4, lr} - sub sp, sp, #4 - mov r3, r1 - mov r4, r0 - str r2, [sp] - ldr r1, _020A56A4 ; =0x46524D48 - add r2, r4, #0x30 - bl NNSi_FndInitHeapHead - ldr r0, [r4, #0x18] - mov r1, #0 - str r0, [r4, #0x24] - ldr r2, [r4, #0x1c] - mov r0, r4 - str r2, [r4, #0x28] - str r1, [r4, #0x2c] - add sp, sp, #4 - ldmia sp!, {r3, r4, pc} - ; .align 2, 0 -_020A56A4: .word 0x46524D48 - arm_func_end InitFrameHeap - - arm_func_start AllocFromHead_dup2 -AllocFromHead_dup2: ; 0x020A56A8 - stmfd sp!, {r4, r5, r6, lr} - mov r4, r0 - ldr r3, [r4, #0] - sub r0, r2, #1 - mvn r2, r0 - add r0, r0, r3 - and r5, r2, r0 - ldr r0, [r4, #4] - add r6, r1, r5 - cmp r6, r0 - movhi r0, #0 - ldmhiia sp!, {r4, r5, r6, pc} - ldr r0, [r4, #-4] - sub r2, r6, r3 - and r0, r0, #0xff - tst r0, #1 - beq _020A56F8 - mov r1, r3 - mov r0, #0 - bl MIi_CpuClear32 -_020A56F8: - mov r0, r5 - str r6, [r4, #0] - ldmia sp!, {r4, r5, r6, pc} - arm_func_end AllocFromHead_dup2 - - arm_func_start AllocFromTail_dup2 -AllocFromTail_dup2: ; 0x020A5704 - stmfd sp!, {r3, r4, r5, lr} - mov r4, r0 - ldr r3, [r4, #4] - sub r0, r2, #1 - mvn r2, r0 - sub r1, r3, r1 - ldr r0, [r4, #0] - and r5, r2, r1 - cmp r5, r0 - movlo r0, #0 - ldmloia sp!, {r3, r4, r5, pc} - ldr r0, [r4, #-4] - sub r2, r3, r5 - and r0, r0, #0xff - tst r0, #1 - beq _020A5750 - mov r1, r5 - mov r0, #0 - bl MIi_CpuClear32 -_020A5750: - mov r0, r5 - str r5, [r4, #4] - ldmia sp!, {r3, r4, r5, pc} - arm_func_end AllocFromTail_dup2 - - arm_func_start FreeHead -FreeHead: ; 0x020A575C - ldr r2, [r0, #0x18] - mov r1, #0 - str r2, [r0, #0x24] - str r1, [r0, #0x2c] - bx lr - arm_func_end FreeHead - - arm_func_start FreeTail -FreeTail: ; 0x020A5770 - ldr r2, [r0, #0x2c] - cmp r2, #0 - beq _020A5790 -_020A577C: - ldr r1, [r0, #0x1c] - str r1, [r2, #8] - ldr r2, [r2, #0xc] - cmp r2, #0 - bne _020A577C -_020A5790: - ldr r1, [r0, #0x1c] - str r1, [r0, #0x28] - bx lr - arm_func_end FreeTail - - arm_func_start NNS_FndCreateFrmHeapEx -NNS_FndCreateFrmHeapEx: ; 0x020A579C - stmfd sp!, {r3, lr} - add r1, r1, r0 - add r0, r0, #3 - bic r1, r1, #3 - bic r0, r0, #3 - cmp r0, r1 - bhi _020A57C4 - sub r3, r1, r0 - cmp r3, #0x30 - bhs _020A57CC -_020A57C4: - mov r0, #0 - ldmia sp!, {r3, pc} -_020A57CC: - bl InitFrameHeap - ldmia sp!, {r3, pc} - arm_func_end NNS_FndCreateFrmHeapEx - - arm_func_start NNS_FndDestroyFrmHeap -NNS_FndDestroyFrmHeap: ; 0x020A57D4 - ldr ip, _020A57DC ; =NNSi_FndFinalizeHeap - bx ip - ; .align 2, 0 -_020A57DC: .word NNSi_FndFinalizeHeap - arm_func_end NNS_FndDestroyFrmHeap - - arm_func_start NNS_FndAllocFromFrmHeapEx -NNS_FndAllocFromFrmHeapEx: ; 0x020A57E0 - stmfd sp!, {r3, lr} - cmp r1, #0 - moveq r1, #1 - add r1, r1, #3 - cmp r2, #0 - bic r1, r1, #3 - add r0, r0, #0x24 - blt _020A5808 - bl AllocFromHead_dup2 - ldmia sp!, {r3, pc} -_020A5808: - rsb r2, r2, #0 - bl AllocFromTail_dup2 - ldmia sp!, {r3, pc} - arm_func_end NNS_FndAllocFromFrmHeapEx - - arm_func_start NNS_FndFreeToFrmHeap -NNS_FndFreeToFrmHeap: ; 0x020A5814 - stmfd sp!, {r3, r4, r5, lr} - mov r4, r1 - mov r5, r0 - tst r4, #1 - beq _020A582C - bl FreeHead -_020A582C: - tst r4, #2 - ldmeqia sp!, {r3, r4, r5, pc} - mov r0, r5 - bl FreeTail - ldmia sp!, {r3, r4, r5, pc} - arm_func_end NNS_FndFreeToFrmHeap - - arm_func_start NNS_FndRecordStateForFrmHeap -NNS_FndRecordStateForFrmHeap: ; 0x020A5840 - stmfd sp!, {r4, r5, r6, lr} - mov r6, r0 - ldr r4, [r6, #0x24] - mov r5, r1 - add r0, r6, #0x24 - mov r1, #0x10 - mov r2, #4 - bl AllocFromHead_dup2 - cmp r0, #0 - moveq r0, #0 - ldmeqia sp!, {r4, r5, r6, pc} - str r5, [r0, #0] - str r4, [r0, #4] - ldr r1, [r6, #0x28] - str r1, [r0, #8] - ldr r1, [r6, #0x2c] - str r1, [r0, #0xc] - str r0, [r6, #0x2c] - mov r0, #1 - ldmia sp!, {r4, r5, r6, pc} - arm_func_end NNS_FndRecordStateForFrmHeap - - arm_func_start NNS_FndFreeByStateToFrmHeap -NNS_FndFreeByStateToFrmHeap: ; 0x020A5890 - ldr r3, [r0, #0x2c] - cmp r1, #0 - cmpne r3, #0 - beq _020A58B4 -_020A58A0: - ldr r2, [r3, #0] - cmp r2, r1 - ldrne r3, [r3, #0xc] - cmpne r3, #0 - bne _020A58A0 -_020A58B4: - cmp r3, #0 - moveq r0, #0 - bxeq lr - ldr r1, [r3, #4] - str r1, [r0, #0x24] - ldr r1, [r3, #8] - str r1, [r0, #0x28] - ldr r1, [r3, #0xc] - str r1, [r0, #0x2c] - mov r0, #1 - bx lr - arm_func_end NNS_FndFreeByStateToFrmHeap \ No newline at end of file diff --git a/lib/NitroSystem/asm/fnd/heapcommon.s b/lib/NitroSystem/asm/fnd/heapcommon.s deleted file mode 100644 index a854564ed9..0000000000 --- a/lib/NitroSystem/asm/fnd/heapcommon.s +++ /dev/null @@ -1,116 +0,0 @@ - .include "macros/function.inc" - .include "include/heapcommon.inc" - - .extern Unk_021C3AA0 - .extern Unk_021C3AA4 - - - .text - - - arm_func_start FindContainHeap -FindContainHeap: ; 0x020A4DE8 - stmfd sp!, {r4, r5, r6, lr} - mov r5, r1 - mov r1, #0 - mov r6, r0 - bl NNS_FndGetNextListObject - movs r4, r0 - beq _020A4E48 -_020A4E04: - ldr r0, [r4, #0x18] - cmp r0, r5 - bhi _020A4E34 - ldr r0, [r4, #0x1c] - cmp r5, r0 - bhs _020A4E34 - mov r1, r5 - add r0, r4, #0xc - bl FindContainHeap - cmp r0, #0 - moveq r0, r4 - ldmia sp!, {r4, r5, r6, pc} -_020A4E34: - mov r0, r6 - mov r1, r4 - bl NNS_FndGetNextListObject - movs r4, r0 - bne _020A4E04 -_020A4E48: - mov r0, #0 - ldmia sp!, {r4, r5, r6, pc} - arm_func_end FindContainHeap - - arm_func_start FindListContainHeap -FindListContainHeap: ; 0x020A4E50 - stmfd sp!, {r4, lr} - ldr r4, _020A4E74 ; =0x021C3AA4 - mov r1, r0 - mov r0, r4 - bl FindContainHeap - cmp r0, #0 - addne r4, r0, #0xc - mov r0, r4 - ldmia sp!, {r4, pc} - ; .align 2, 0 -_020A4E74: .word Unk_021C3AA4 - arm_func_end FindListContainHeap - - arm_func_start NNSi_FndInitHeapHead -NNSi_FndInitHeapHead: ; 0x020A4E78 - stmfd sp!, {r4, lr} - mov r4, r0 - ldrh r0, [sp, #8] - str r1, [r4, #0] - mov ip, #0 - str r2, [r4, #0x18] - bic r1, ip, #0xff - and r0, r0, #0xff - orr r2, r1, r0 - str r3, [r4, #0x1c] - add r0, r4, #0xc - mov r1, #4 - str r2, [r4, #0x20] - bl NNS_FndInitList - ldr r0, _020A4EEC ; =0x021C3AA0 - ldr r0, [r0, #0] - cmp r0, #0 - bne _020A4ED8 - ldr r0, _020A4EF0 ; =0x021C3AA4 - mov r1, #4 - bl NNS_FndInitList - ldr r0, _020A4EEC ; =0x021C3AA0 - mov r1, #1 - str r1, [r0, #0] -_020A4ED8: - mov r0, r4 - bl FindListContainHeap - mov r1, r4 - bl NNS_FndAppendListObject - ldmia sp!, {r4, pc} - ; .align 2, 0 -_020A4EEC: .word Unk_021C3AA0 -_020A4EF0: .word Unk_021C3AA4 - arm_func_end NNSi_FndInitHeapHead - - arm_func_start NNSi_FndFinalizeHeap -NNSi_FndFinalizeHeap: ; 0x020A4EF4 - stmfd sp!, {r4, lr} - mov r4, r0 - bl FindListContainHeap - mov r1, r4 - bl NNS_FndRemoveListObject - ldmia sp!, {r4, pc} - arm_func_end NNSi_FndFinalizeHeap - - .bss - - - .global Unk_021C3AA0 -Unk_021C3AA0: ; 0x021C3AA0 - .space 0x4 - - .global Unk_021C3AA4 -Unk_021C3AA4: ; 0x021C3AA4 - .space 0xC - diff --git a/lib/NitroSystem/asm/fnd/include/expheap.inc b/lib/NitroSystem/asm/fnd/include/expheap.inc deleted file mode 100644 index e27bc02d42..0000000000 --- a/lib/NitroSystem/asm/fnd/include/expheap.inc +++ /dev/null @@ -1,12 +0,0 @@ -.public NNSi_FndInitHeapHead -.public NNSi_FndFinalizeHeap -.public GetRegionOfMBlock -.public RemoveMBlock -.public InsertMBlock -.public InitMBlock -.public InitExpHeap -.public AllocUsedBlockFromFreeBlock -.public AllocFromHead_dup1 -.public AllocFromTail_dup1 -.public RecycleRegion -.public MIi_CpuClear32 diff --git a/lib/NitroSystem/asm/fnd/include/frameheap.inc b/lib/NitroSystem/asm/fnd/include/frameheap.inc deleted file mode 100644 index 98b02354b4..0000000000 --- a/lib/NitroSystem/asm/fnd/include/frameheap.inc +++ /dev/null @@ -1,8 +0,0 @@ -.public NNSi_FndInitHeapHead -.public NNSi_FndFinalizeHeap -.public InitFrameHeap -.public AllocFromHead_dup2 -.public AllocFromTail_dup2 -.public FreeHead -.public FreeTail -.public MIi_CpuClear32 diff --git a/lib/NitroSystem/asm/fnd/include/heapcommon.inc b/lib/NitroSystem/asm/fnd/include/heapcommon.inc deleted file mode 100644 index bff440a9ed..0000000000 --- a/lib/NitroSystem/asm/fnd/include/heapcommon.inc +++ /dev/null @@ -1,6 +0,0 @@ -.public NNS_FndInitList -.public NNS_FndAppendListObject -.public NNS_FndRemoveListObject -.public NNS_FndGetNextListObject -.public FindContainHeap -.public FindListContainHeap diff --git a/lib/NitroSystem/asm/fnd/include/list_nnsfnd.inc b/lib/NitroSystem/asm/fnd/include/list_nnsfnd.inc deleted file mode 100644 index a7e2a41693..0000000000 --- a/lib/NitroSystem/asm/fnd/include/list_nnsfnd.inc +++ /dev/null @@ -1,3 +0,0 @@ -.public SetFirstObject -.public NNS_FndAppendListObject -.public NNS_FndPrependListObject diff --git a/lib/NitroSystem/asm/fnd/include/unitheap.inc b/lib/NitroSystem/asm/fnd/include/unitheap.inc deleted file mode 100644 index d0d07203f4..0000000000 --- a/lib/NitroSystem/asm/fnd/include/unitheap.inc +++ /dev/null @@ -1,2 +0,0 @@ -.public PopMBlock -.public MIi_CpuClear32 diff --git a/lib/NitroSystem/asm/fnd/list_nnsfnd.s b/lib/NitroSystem/asm/fnd/list_nnsfnd.s deleted file mode 100644 index 22baeab6df..0000000000 --- a/lib/NitroSystem/asm/fnd/list_nnsfnd.s +++ /dev/null @@ -1,161 +0,0 @@ - .include "macros/function.inc" - .include "include/list_nnsfnd.inc" - - - - .text - - - arm_func_start NNS_FndInitList -NNS_FndInitList: ; 0x020A4C10 - mov r2, #0 - str r2, [r0, #0] - str r2, [r0, #4] - strh r2, [r0, #8] - strh r1, [r0, #0xa] - bx lr - arm_func_end NNS_FndInitList - - arm_func_start SetFirstObject -SetFirstObject: ; 0x020A4C28 - ldrh r3, [r0, #0xa] - mov r2, #0 - add ip, r1, r3 - str r2, [ip, #4] - str r2, [r1, r3] - str r1, [r0, #0] - str r1, [r0, #4] - ldrh r1, [r0, #8] - add r1, r1, #1 - strh r1, [r0, #8] - bx lr - arm_func_end SetFirstObject - - arm_func_start NNS_FndAppendListObject -NNS_FndAppendListObject: ; 0x020A4C54 - stmfd sp!, {r3, lr} - ldr r2, [r0, #0] - cmp r2, #0 - bne _020A4C6C - bl SetFirstObject - ldmia sp!, {r3, pc} -_020A4C6C: - ldrh ip, [r0, #0xa] - ldr r3, [r0, #4] - mov r2, #0 - str r3, [r1, ip] - add r3, r1, ip - str r2, [r3, #4] - ldrh r2, [r0, #0xa] - ldr r3, [r0, #4] - add r2, r3, r2 - str r1, [r2, #4] - str r1, [r0, #4] - ldrh r1, [r0, #8] - add r1, r1, #1 - strh r1, [r0, #8] - ldmia sp!, {r3, pc} - arm_func_end NNS_FndAppendListObject - - arm_func_start NNS_FndPrependListObject -NNS_FndPrependListObject: ; 0x020A4CA8 - stmfd sp!, {r3, lr} - ldr r2, [r0, #0] - cmp r2, #0 - bne _020A4CC0 - bl SetFirstObject - ldmia sp!, {r3, pc} -_020A4CC0: - ldrh r3, [r0, #0xa] - mov r2, #0 - str r2, [r1, r3] - ldr r2, [r0, #0] - add r3, r1, r3 - str r2, [r3, #4] - ldrh r2, [r0, #0xa] - ldr r3, [r0, #0] - str r1, [r3, r2] - str r1, [r0, #0] - ldrh r1, [r0, #8] - add r1, r1, #1 - strh r1, [r0, #8] - ldmia sp!, {r3, pc} - arm_func_end NNS_FndPrependListObject - - arm_func_start NNS_FndInsertListObject -NNS_FndInsertListObject: ; 0x020A4CF8 - stmfd sp!, {r3, lr} - cmp r1, #0 - bne _020A4D10 - mov r1, r2 - bl NNS_FndAppendListObject - ldmia sp!, {r3, pc} -_020A4D10: - ldr r3, [r0, #0] - cmp r1, r3 - bne _020A4D28 - mov r1, r2 - bl NNS_FndPrependListObject - ldmia sp!, {r3, pc} -_020A4D28: - ldrh lr, [r0, #0xa] - ldr r3, [r1, lr] - add ip, r2, lr - str r3, [r2, lr] - str r1, [ip, #4] - add r3, r3, lr - str r2, [r3, #4] - ldrh r3, [r0, #0xa] - str r2, [r1, r3] - ldrh r1, [r0, #8] - add r1, r1, #1 - strh r1, [r0, #8] - ldmia sp!, {r3, pc} - arm_func_end NNS_FndInsertListObject - - arm_func_start NNS_FndRemoveListObject -NNS_FndRemoveListObject: ; 0x020A4D5C - stmfd sp!, {r3, lr} - ldrh ip, [r0, #0xa] - ldr r3, [r1, ip] - add lr, r1, ip - cmp r3, #0 - ldreq r1, [lr, #4] - streq r1, [r0] - ldrne r2, [lr, #4] - addne r1, r3, ip - strne r2, [r1, #4] - ldr r3, [lr, #4] - cmp r3, #0 - ldreq r1, [lr] - streq r1, [r0, #4] - ldrneh r1, [r0, #0xa] - ldrne r2, [lr] - strne r2, [r3, r1] - mov r1, #0 - str r1, [lr] - str r1, [lr, #4] - ldrh r1, [r0, #8] - sub r1, r1, #1 - strh r1, [r0, #8] - ldmia sp!, {r3, pc} - arm_func_end NNS_FndRemoveListObject - - arm_func_start NNS_FndGetNextListObject -NNS_FndGetNextListObject: ; 0x020A4DBC - cmp r1, #0 - ldreq r0, [r0] - ldrneh r0, [r0, #0xa] - addne r0, r1, r0 - ldrne r0, [r0, #4] - bx lr - arm_func_end NNS_FndGetNextListObject - - arm_func_start NNS_FndGetPrevListObject -NNS_FndGetPrevListObject: ; 0x020A4DD4 - cmp r1, #0 - ldreq r0, [r0, #4] - ldrneh r0, [r0, #0xa] - ldrne r0, [r1, r0] - bx lr - arm_func_end NNS_FndGetPrevListObject \ No newline at end of file diff --git a/lib/NitroSystem/asm/fnd/unitheap.s b/lib/NitroSystem/asm/fnd/unitheap.s deleted file mode 100644 index bc8776c223..0000000000 --- a/lib/NitroSystem/asm/fnd/unitheap.s +++ /dev/null @@ -1,46 +0,0 @@ - .include "macros/function.inc" - .include "include/unitheap.inc" - - - - .text - - - arm_func_start PopMBlock -PopMBlock: ; 0x020A58E0 - ldr r2, [r0, #0] - cmp r2, #0 - ldrne r1, [r2] - strne r1, [r0] - mov r0, r2 - bx lr - arm_func_end PopMBlock - - arm_func_start NNS_FndAllocFromUnitHeap -NNS_FndAllocFromUnitHeap: ; 0x020A58F8 - stmfd sp!, {r3, r4, r5, lr} - mov r5, r0 - add r0, r5, #0x24 - bl PopMBlock - movs r4, r0 - beq _020A5930 - ldr r0, [r5, #0x20] - ldr r2, [r5, #0x28] - and r0, r0, #0xff - tst r0, #1 - beq _020A5930 - mov r1, r4 - mov r0, #0 - bl MIi_CpuClear32 -_020A5930: - mov r0, r4 - ldmia sp!, {r3, r4, r5, pc} - arm_func_end NNS_FndAllocFromUnitHeap - - arm_func_start NNS_FndFreeToUnitHeap -NNS_FndFreeToUnitHeap: ; 0x020A5938 - ldr r2, [r0, #0x24] - str r2, [r1, #0] - str r1, [r0, #0x24] - bx lr - arm_func_end NNS_FndFreeToUnitHeap \ No newline at end of file diff --git a/lib/NitroSystem/src/fnd/expheap.c b/lib/NitroSystem/src/fnd/expheap.c new file mode 100644 index 0000000000..a29575cc2c --- /dev/null +++ b/lib/NitroSystem/src/fnd/expheap.c @@ -0,0 +1,975 @@ + +#include +#include +#include +#include + +#include "include/heapcommoni.h" + +#define MBLOCK_FREE_SIGNATURE ('FR') +#define MBLOCK_USED_SIGNATURE ('UD') +#define MAX_GROUPID 0xff +#define DEFAULT_GROUPID 0 +#define MIN_ALIGNMENT 4 +#define DEFAULT_ALLOC_MODE NNS_FND_EXPHEAP_ALLOC_MODE_FIRST +#define MIN_FREE_BLOCK_SIZE 4 + +typedef struct NNSiMemRegion NNSiMemRegion; + +struct NNSiMemRegion { + void * start; + void * end; +}; + +#if !defined(NNS_FINALROM) + + #define HEAP_WARNING(exp, ...) \ + (void)((exp) && (OS_Printf(__VA_ARGS__), 0)) + +#endif + +static NNS_FND_INLINE void * MaxPtr (void * a, void * b) { + return NNSiGetUIntPtr(a) > NNSiGetUIntPtr(b) ? a: b; +} + +static NNS_FND_INLINE BOOL IsValidExpHeapHandle (NNSFndHeapHandle handle) { + if (handle == NNS_FND_HEAP_INVALID_HANDLE) { + return FALSE; + } + + { + NNSiFndHeapHead * pHeapHd = handle; + return pHeapHd->signature == NNSI_EXPHEAP_SIGNATURE; + } +} + +static NNS_FND_INLINE NNSiFndExpHeapHead * GetExpHeapHeadPtrFromHeapHead (NNSiFndHeapHead * pHHead) { + return AddU32ToPtr(pHHead, sizeof(NNSiFndHeapHead)); +} + +static NNS_FND_INLINE NNSiFndHeapHead * GetHeapHeadPtrFromExpHeapHead (NNSiFndExpHeapHead * pEHHead) { + return SubU32ToPtr(pEHHead, sizeof(NNSiFndHeapHead)); +} + +static NNS_FND_INLINE NNSiFndExpHeapHead * GetExpHeapHeadPtrFromHandle (NNSFndHeapHandle heap) { + return GetExpHeapHeadPtrFromHeapHead(heap); +} + +static NNS_FND_INLINE void * GetMemPtrForMBlock (NNSiFndExpHeapMBlockHead * pMBlkHd) { + return AddU32ToPtr(pMBlkHd, sizeof(NNSiFndExpHeapMBlockHead)); +} + +static NNS_FND_INLINE const void * GetMemCPtrForMBlock (const NNSiFndExpHeapMBlockHead * pMBlkHd) { + return AddU32ToCPtr(pMBlkHd, sizeof(NNSiFndExpHeapMBlockHead)); +} + +static NNS_FND_INLINE NNSiFndExpHeapMBlockHead * GetMBlockHeadPtr (void * memBlock) { + return SubU32ToPtr(memBlock, sizeof(NNSiFndExpHeapMBlockHead)); +} + +static NNS_FND_INLINE const NNSiFndExpHeapMBlockHead * GetMBlockHeadCPtr (const void * memBlock) { + return SubU32ToCPtr(memBlock, sizeof(NNSiFndExpHeapMBlockHead)); +} + +static NNS_FND_INLINE void * GetMBlockEndAddr (NNSiFndExpHeapMBlockHead * pMBHead) { + return AddU32ToPtr(GetMemPtrForMBlock(pMBHead), pMBHead->blockSize); +} + +static NNS_FND_INLINE u16 GetAlignmentForMBlock (const NNSiFndExpHeapMBlockHead * pMBlkHd) { + return (u16)NNSi_FndGetBitValue(pMBlkHd->attribute, 8, 7); +} + +static NNS_FND_INLINE void SetAlignmentForMBlock (NNSiFndExpHeapMBlockHead * pMBlkHd, u16 alignment) { + NNSi_FndSetBitValue(pMBlkHd->attribute, 8, 7, alignment); +} + +static NNS_FND_INLINE u16 GetGroupIDForMBlock (const NNSiFndExpHeapMBlockHead * pMBHead) { + return (u16)NNSi_FndGetBitValue(pMBHead->attribute, 0, 8); +} + +static NNS_FND_INLINE void SetGroupIDForMBlock (NNSiFndExpHeapMBlockHead * pMBHead, u16 id) { + NNSi_FndSetBitValue(pMBHead->attribute, 0, 8, id); +} + +static NNS_FND_INLINE u16 GetAllocDirForMBlock (const NNSiFndExpHeapMBlockHead * pMBHead) { + return (u16)NNSi_FndGetBitValue(pMBHead->attribute, 15, 1); +} + +static NNS_FND_INLINE void SetAllocDirForMBlock (NNSiFndExpHeapMBlockHead * pMBHead, u16 mode) { + NNSi_FndSetBitValue(pMBHead->attribute, 15, 1, mode); +} + +static NNS_FND_INLINE u16 GetAllocMode (NNSiFndExpHeapHead * pEHHead) { + return (u16)NNSi_FndGetBitValue(pEHHead->feature, 0, 1); +} + +static NNS_FND_INLINE void SetAllocMode (NNSiFndExpHeapHead * pEHHead, u16 mode) { + NNSi_FndSetBitValue(pEHHead->feature, 0, 1, mode); +} + +static void GetRegionOfMBlock (NNSiMemRegion * region, NNSiFndExpHeapMBlockHead * block) { + region->start = SubU32ToPtr(block, GetAlignmentForMBlock(block)); + region->end = GetMBlockEndAddr(block); +} + +static NNSiFndExpHeapMBlockHead * RemoveMBlock (NNSiFndExpMBlockList * list, NNSiFndExpHeapMBlockHead * block) { + NNSiFndExpHeapMBlockHead * const prev = block->pMBHeadPrev; + NNSiFndExpHeapMBlockHead * const next = block->pMBHeadNext; + + if (prev) { + prev->pMBHeadNext = next; + } else { + list->head = next; + } + + if (next) { + next->pMBHeadPrev = prev; + } else { + list->tail = prev; + } + + return prev; +} + +static NNSiFndExpHeapMBlockHead * InsertMBlock (NNSiFndExpMBlockList * list, NNSiFndExpHeapMBlockHead * target, NNSiFndExpHeapMBlockHead * prev) { + NNSiFndExpHeapMBlockHead * next; + + target->pMBHeadPrev = prev; + if (prev) { + next = prev->pMBHeadNext; + prev->pMBHeadNext = target; + } else { + next = list->head; + list->head = target; + } + + target->pMBHeadNext = next; + if (next) { + next->pMBHeadPrev = target; + } else { + list->tail = target; + } + + return target; +} + +static NNS_FND_INLINE void AppendMBlock (NNSiFndExpMBlockList * list, NNSiFndExpHeapMBlockHead * block) { + (void)InsertMBlock(list, block, list->tail); +} + +static 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; +} + +static NNS_FND_INLINE NNSiFndExpHeapMBlockHead * InitFreeMBlock (const NNSiMemRegion * pRegion) { + return InitMBlock(pRegion, MBLOCK_FREE_SIGNATURE); +} + +static NNSiFndHeapHead * InitExpHeap (void * startAddress, void * endAddress, u16 optFlag) { + NNSiFndHeapHead * pHeapHd = startAddress; + NNSiFndExpHeapHead * pExpHeapHd = GetExpHeapHeadPtrFromHeapHead(pHeapHd); + + NNSi_FndInitHeapHead( + pHeapHd, + NNSI_EXPHEAP_SIGNATURE, + AddU32ToPtr(pExpHeapHd, sizeof(NNSiFndExpHeapHead)), + endAddress, + optFlag + ); + + pExpHeapHd->groupID = DEFAULT_GROUPID; + pExpHeapHd->feature = 0; + SetAllocMode(pExpHeapHd, DEFAULT_ALLOC_MODE); + + { + NNSiFndExpHeapMBlockHead * pMBHead; + NNSiMemRegion region; + region.start = pHeapHd->heapStart; + region.end = pHeapHd->heapEnd; + pMBHead = InitFreeMBlock(®ion); + + pExpHeapHd->mbFreeList.head = pMBHead; + pExpHeapHd->mbFreeList.tail = pMBHead; + pExpHeapHd->mbUsedList.head = NULL; + pExpHeapHd->mbUsedList.tail = NULL; + + return pHeapHd; + } +} + +static void * AllocUsedBlockFromFreeBlock (NNSiFndExpHeapHead * pEHHead, NNSiFndExpHeapMBlockHead * pMBHeadFree, void * mblock, u32 size, u16 direction) { + NNSiMemRegion freeRgnT; + NNSiMemRegion freeRgnB; + NNSiFndExpHeapMBlockHead * pMBHeadFreePrev; + + GetRegionOfMBlock(&freeRgnT, pMBHeadFree); + freeRgnB.end = freeRgnT.end; + freeRgnB.start = AddU32ToPtr(mblock, size); + freeRgnT.end = SubU32ToPtr(mblock, sizeof(NNSiFndExpHeapMBlockHead)); + + pMBHeadFreePrev = RemoveMBlock(&pEHHead->mbFreeList, pMBHeadFree); + + if (GetOffsetFromPtr(freeRgnT.start, freeRgnT.end) < sizeof(NNSiFndExpHeapMBlockHead) + MIN_FREE_BLOCK_SIZE) { + freeRgnT.end = freeRgnT.start; + } else { + pMBHeadFreePrev = InsertMBlock(&pEHHead->mbFreeList, InitFreeMBlock(&freeRgnT), pMBHeadFreePrev); + } + + if (GetOffsetFromPtr(freeRgnB.start, freeRgnB.end) < sizeof(NNSiFndExpHeapMBlockHead) + MIN_FREE_BLOCK_SIZE) { + freeRgnB.start = freeRgnB.end; + } else { + (void)InsertMBlock(&pEHHead->mbFreeList, InitFreeMBlock(&freeRgnB), pMBHeadFreePrev); + } + + FillAllocMemory(GetHeapHeadPtrFromExpHeapHead(pEHHead), freeRgnT.end, GetOffsetFromPtr(freeRgnT.end, freeRgnB.start)); + + { + NNSiFndExpHeapMBlockHead * pMBHeadNewUsed; + NNSiMemRegion region; + + region.start = SubU32ToPtr(mblock, sizeof(NNSiFndExpHeapMBlockHead)); + region.end = freeRgnB.start; + + pMBHeadNewUsed = InitMBlock(®ion, MBLOCK_USED_SIGNATURE); + SetAllocDirForMBlock(pMBHeadNewUsed, direction); + SetAlignmentForMBlock(pMBHeadNewUsed, (u16)GetOffsetFromPtr(freeRgnT.end, pMBHeadNewUsed)); + SetGroupIDForMBlock(pMBHeadNewUsed, pEHHead->groupID); + AppendMBlock(&pEHHead->mbUsedList, pMBHeadNewUsed); + } + + return mblock; +} + +static void * AllocFromHead (NNSiFndHeapHead * pHeapHd, u32 size, int alignment) { + NNSiFndExpHeapHead * pExpHeapHd = GetExpHeapHeadPtrFromHeapHead(pHeapHd); + + const BOOL bAllocFirst = GetAllocMode(pExpHeapHd) == NNS_FND_EXPHEAP_ALLOC_MODE_FIRST; + + NNSiFndExpHeapMBlockHead * pMBlkHd = NULL; + NNSiFndExpHeapMBlockHead * pMBlkHdFound = NULL; + u32 foundSize = 0xffffffff; + void * foundMBlock = NULL; + + for (pMBlkHd = pExpHeapHd->mbFreeList.head; pMBlkHd; pMBlkHd = pMBlkHd->pMBHeadNext) { + void * const mblock = GetMemPtrForMBlock(pMBlkHd); + void * const reqMBlock = NNSi_FndRoundUpPtr(mblock, alignment); + const u32 offset = GetOffsetFromPtr(mblock, reqMBlock); + + if (pMBlkHd->blockSize >= size + offset + && foundSize > pMBlkHd->blockSize) { + pMBlkHdFound = pMBlkHd; + foundSize = pMBlkHd->blockSize; + foundMBlock = reqMBlock; + + if (bAllocFirst || foundSize == size) { + break; + } + } + } + + if (!pMBlkHdFound) { + return NULL; + } + + return AllocUsedBlockFromFreeBlock( + pExpHeapHd, + pMBlkHdFound, + foundMBlock, + size, + NNS_FND_EXPHEAP_ALLOC_DIR_FRONT + ); +} + +static void * AllocFromTail (NNSiFndHeapHead * pHeapHd, u32 size, int alignment) { + NNSiFndExpHeapHead * pExpHeapHd = GetExpHeapHeadPtrFromHeapHead(pHeapHd); + + const BOOL bAllocFirst = GetAllocMode(pExpHeapHd) == NNS_FND_EXPHEAP_ALLOC_MODE_FIRST; + + NNSiFndExpHeapMBlockHead * pMBlkHd = NULL; + NNSiFndExpHeapMBlockHead * pMBlkHdFound = NULL; + u32 foundSize = 0xffffffff; + void * foundMBlock = NULL; + + for (pMBlkHd = pExpHeapHd->mbFreeList.tail; pMBlkHd; pMBlkHd = pMBlkHd->pMBHeadPrev) { + void * const mblock = GetMemPtrForMBlock(pMBlkHd); + void * const mblockEnd = AddU32ToPtr(mblock, pMBlkHd->blockSize); + void * const reqMBlock = NNSi_FndRoundDownPtr(SubU32ToPtr(mblockEnd, size), alignment); + + if (ComparePtr(reqMBlock, mblock) >= 0 + && foundSize > pMBlkHd->blockSize) { + pMBlkHdFound = pMBlkHd; + foundSize = pMBlkHd->blockSize; + foundMBlock = reqMBlock; + + if (bAllocFirst || foundSize == size) { + break; + } + } + } + + if (!pMBlkHdFound) { + return NULL; + } + + return AllocUsedBlockFromFreeBlock( + pExpHeapHd, + pMBlkHdFound, + foundMBlock, + size, + NNS_FND_EXPHEAP_ALLOC_DIR_REAR + ); +} + +static BOOL RecycleRegion (NNSiFndExpHeapHead * pEHHead, const NNSiMemRegion * pRegion) { + NNSiFndExpHeapMBlockHead * pBlkPrFree = NULL; + NNSiMemRegion freeRgn = *pRegion; + + { + NNSiFndExpHeapMBlockHead * pBlk; + + for (pBlk = pEHHead->mbFreeList.head; pBlk; pBlk = pBlk->pMBHeadNext) { + if (pBlk < pRegion->start) { + pBlkPrFree = pBlk; + continue; + } + + if (pBlk == pRegion->end) { + freeRgn.end = GetMBlockEndAddr(pBlk); + (void)RemoveMBlock(&pEHHead->mbFreeList, pBlk); + + FillNoUseMemory(GetHeapHeadPtrFromExpHeapHead(pEHHead), pBlk, sizeof(NNSiFndExpHeapMBlockHead)); + } + break; + } + } + + if (pBlkPrFree && GetMBlockEndAddr(pBlkPrFree) == pRegion->start) { + freeRgn.start = pBlkPrFree; + pBlkPrFree = RemoveMBlock(&pEHHead->mbFreeList, pBlkPrFree); + } + + if (GetOffsetFromPtr(freeRgn.start, freeRgn.end) < sizeof(NNSiFndExpHeapMBlockHead)) { + return FALSE; + } + + FillFreeMemory(GetHeapHeadPtrFromExpHeapHead(pEHHead), pRegion->start, GetOffsetFromPtr(pRegion->start, pRegion->end)); + + (void)InsertMBlock( + &pEHHead->mbFreeList, + InitFreeMBlock(&freeRgn), + pBlkPrFree + ); + + return TRUE; +} + +#if !defined(NNS_FINALROM) + +static BOOL CheckMBlock (const NNSiFndExpHeapMBlockHead * pMBHead, NNSiFndHeapHead * pHeapHd, u16 signature, const char * heapType, u32 flag) { + const BOOL bPrint = 0 != (flag & NNS_FND_HEAP_ERROR_PRINT); + const void * const memBlock = GetMemCPtrForMBlock(pMBHead); + + if (pHeapHd) { + if (NNSiGetUIntPtr(pMBHead) < NNSiGetUIntPtr(pHeapHd->heapStart) + || NNSiGetUIntPtr(memBlock) > NNSiGetUIntPtr(pHeapHd->heapEnd) + ) { + HEAP_WARNING( + bPrint, "[NNS Foundation " "Exp" " Heap]" " Bad %s memory block address. - address %08X, heap area [%08X - %08X)\n", + heapType, memBlock, pHeapHd->heapStart, pHeapHd->heapEnd + ); + return FALSE; + } + } else { + if (NNSiGetUIntPtr(pMBHead) >= 0x11000000) { + HEAP_WARNING( + bPrint, "[NNS Foundation " "Exp" " Heap]" " Bad %s memory block address. - address %08X\n", + heapType, memBlock + ); + return FALSE; + } + } + + if (pMBHead->signature != signature) { + HEAP_WARNING( + bPrint, "[NNS Foundation " "Exp" " Heap]" " Bad %s memory block signature. - address %08X, signature %04X\n", + heapType, memBlock, pMBHead->signature + ); + return FALSE; + } + + if (pMBHead->blockSize >= 0x01000000) { + HEAP_WARNING( + bPrint, "[NNS Foundation " "Exp" " Heap]" " Too large %s memory block. - address %08X, block size %08X\n", + heapType, memBlock, pMBHead->blockSize + ); + return FALSE; + } + + if (pHeapHd) { + if (NNSiGetUIntPtr(memBlock) + pMBHead->blockSize > NNSiGetUIntPtr(pHeapHd->heapEnd)) { + HEAP_WARNING( + bPrint, "[NNS Foundation " "Exp" " Heap]" " wrong size %s memory block. - address %08X, block size %08X\n", + heapType, memBlock, pMBHead->blockSize + ); + return FALSE; + } + } + + return TRUE; +} + +#endif + +#if !defined(NNS_FINALROM) + +static NNS_FND_INLINE BOOL CheckUsedMBlock (const NNSiFndExpHeapMBlockHead * pMBHead, NNSiFndHeapHead * pHeapHd, u32 flag) { + return CheckMBlock(pMBHead, pHeapHd, MBLOCK_USED_SIGNATURE, "used", flag); +} + +#endif + +#if !defined(NNS_FINALROM) + +static NNS_FND_INLINE BOOL CheckFreeMBlock (const NNSiFndExpHeapMBlockHead * pMBHead, NNSiFndHeapHead * pHeapHd, u32 flag) { + return CheckMBlock(pMBHead, pHeapHd, MBLOCK_FREE_SIGNATURE, "free", flag); +} + +#endif + +#if !defined(NNS_FINALROM) + +static BOOL CheckMBlockPrevPtr (const NNSiFndExpHeapMBlockHead * pMBHead, const NNSiFndExpHeapMBlockHead * pMBHeadPrev, u32 flag) { + const BOOL bPrint = 0 != (flag & NNS_FND_HEAP_ERROR_PRINT); + + if (pMBHead->pMBHeadPrev != pMBHeadPrev) { + HEAP_WARNING( + bPrint, "[NNS Foundation " "Exp" " Heap]" " Wrong link memory block. - address %08X, previous address %08X != %08X\n", + GetMemCPtrForMBlock(pMBHead), pMBHead->pMBHeadPrev, pMBHeadPrev + ); + return FALSE; + } + + return TRUE; +} + +#endif + +#if !defined(NNS_FINALROM) + +static BOOL CheckMBlockNextPtr (const NNSiFndExpHeapMBlockHead * pMBHead, const NNSiFndExpHeapMBlockHead * pMBHeadNext, u32 flag) { + const BOOL bPrint = 0 != (flag & NNS_FND_HEAP_ERROR_PRINT); + + if (pMBHead->pMBHeadNext != pMBHeadNext) { + HEAP_WARNING( + bPrint, "[NNS Foundation " "Exp" " Heap]" " Wrong link memory block. - address %08X, next address %08X != %08X\n", + GetMemCPtrForMBlock(pMBHead), pMBHead->pMBHeadNext, pMBHeadNext + ); + return FALSE; + } + + return TRUE; +} + +#endif + +#if !defined(NNS_FINALROM) + +static BOOL CheckMBlockLinkTail (const NNSiFndExpHeapMBlockHead * pMBHead, const NNSiFndExpHeapMBlockHead * pMBHeadTail, const char * heapType, u32 flag) { + const BOOL bPrint = 0 != (flag & NNS_FND_HEAP_ERROR_PRINT); + + if (pMBHead != pMBHeadTail) { + HEAP_WARNING( + bPrint, "[NNS Foundation " "Exp" " Heap]" " Wrong memory brock list %s pointer. - address %08X, %s address %08X != %08X\n", + heapType, GetMemCPtrForMBlock(pMBHead), heapType, pMBHead, pMBHeadTail + ); + return FALSE; + } + + return TRUE; +} + +#endif + +#if !defined(NNS_FINALROM) + +static BOOL IsValidUsedMBlock (const void * memBlock, NNSFndHeapHandle heap) { + NNSiFndHeapHead * pHeapHd = heap; + + if (!memBlock) { + return FALSE; + } + + return CheckUsedMBlock(GetMBlockHeadCPtr(memBlock), pHeapHd, 0); +} + +#endif + +#if !defined(NNS_FINALROM) + +void NNSi_FndDumpExpHeap (NNSFndHeapHandle heap) { + NNS_ASSERT(IsValidExpHeapHandle(heap)); + + { + u32 usedSize = 0; + u32 usedCnt = 0; + u32 freeSize = 0; + u32 freeCnt = 0; + + NNSiFndHeapHead * pHeapHd = heap; + NNSiFndExpHeapHead * pExpHeapHd = GetExpHeapHeadPtrFromHandle(pHeapHd); + + NNSi_FndDumpHeapHead(pHeapHd); + + OS_Printf(" attr address: size gid aln prev_ptr next_ptr\n"); + + OS_Printf(" (Used Blocks)\n"); + + if (pExpHeapHd->mbUsedList.head == NULL) { + OS_Printf(" NONE\n"); + } else { + NNSiFndExpHeapMBlockHead * pMBHead; + + for (pMBHead = pExpHeapHd->mbUsedList.head; pMBHead; pMBHead = pMBHead->pMBHeadNext) { + if (pMBHead->signature != MBLOCK_USED_SIGNATURE) { + OS_Printf(" xxxxx %08x: -------- --- --- (-------- --------)\nabort\n", pMBHead); + break; + } + + OS_Printf( + " %s %08x: %8d %3d %3d (%08x %08x)\n", + GetAllocDirForMBlock(pMBHead) == NNS_FND_EXPHEAP_ALLOC_DIR_REAR ? " rear" : "front", + GetMemPtrForMBlock(pMBHead), + pMBHead->blockSize, + GetGroupIDForMBlock(pMBHead), + GetAlignmentForMBlock(pMBHead), + pMBHead->pMBHeadPrev ? GetMemPtrForMBlock(pMBHead->pMBHeadPrev): NULL, + pMBHead->pMBHeadNext ? GetMemPtrForMBlock(pMBHead->pMBHeadNext): NULL + ); + + usedSize += sizeof(NNSiFndExpHeapMBlockHead) + pMBHead->blockSize + GetAlignmentForMBlock(pMBHead); + + usedCnt++; + } + } + + OS_Printf(" (Free Blocks)\n"); + + if (pExpHeapHd->mbFreeList.head == NULL) { + OS_Printf(" NONE\n"); + } else { + NNSiFndExpHeapMBlockHead * pMBHead; + + for (pMBHead = pExpHeapHd->mbFreeList.head; pMBHead; pMBHead = pMBHead->pMBHeadNext) { + if (pMBHead->signature != MBLOCK_FREE_SIGNATURE) { + OS_Printf(" xxxxx %08x: -------- --- --- (-------- --------)\nabort\n", pMBHead); + break; + } + + OS_Printf( + " %s %08x: %8d %3d %3d (%08x %08x)\n", + " free", + GetMemPtrForMBlock(pMBHead), + pMBHead->blockSize, + GetGroupIDForMBlock(pMBHead), + GetAlignmentForMBlock(pMBHead), + pMBHead->pMBHeadPrev ? GetMemPtrForMBlock(pMBHead->pMBHeadPrev): NULL, + pMBHead->pMBHeadNext ? GetMemPtrForMBlock(pMBHead->pMBHeadNext): NULL + ); + + freeCnt++; + } + } + + OS_Printf("\n"); + + { + u32 heapSize = GetOffsetFromPtr(pHeapHd->heapStart, pHeapHd->heapEnd); + OS_Printf( + " %d / %d bytes (%6.2f%%) used (U:%d F:%d)\n", + usedSize, heapSize, 100.0 * usedSize / heapSize, usedCnt, freeCnt + ); + } + + OS_Printf("\n"); + } +} + +#endif + +NNSFndHeapHandle NNS_FndCreateExpHeapEx (void * startAddress, u32 size, u16 optFlag) { + void * endAddress; + + SDK_NULL_ASSERT(startAddress); + + endAddress = NNSi_FndRoundDownPtr(AddU32ToPtr(startAddress, size), MIN_ALIGNMENT); + startAddress = NNSi_FndRoundUpPtr(startAddress, MIN_ALIGNMENT); + + if (NNSiGetUIntPtr(startAddress) > NNSiGetUIntPtr(endAddress) + || GetOffsetFromPtr(startAddress, endAddress) < sizeof(NNSiFndHeapHead) + sizeof(NNSiFndExpHeapHead) + + sizeof(NNSiFndExpHeapMBlockHead) + MIN_ALIGNMENT + ) { + return NNS_FND_HEAP_INVALID_HANDLE; + } + + { + NNSiFndHeapHead * pHeapHd = InitExpHeap(startAddress, endAddress, optFlag); + return pHeapHd; + } +} + +void NNS_FndDestroyExpHeap (NNSFndHeapHandle heap) { + NNS_ASSERT(IsValidExpHeapHandle(heap)); + + NNSi_FndFinalizeHeap(heap); +} + +void * NNS_FndAllocFromExpHeapEx (NNSFndHeapHandle heap, u32 size, int alignment) { + void * memory = NULL; + + NNS_ASSERT(IsValidExpHeapHandle(heap)); + + NNS_ASSERT(alignment % MIN_ALIGNMENT == 0); + NNS_ASSERT(MIN_ALIGNMENT <= abs(alignment) && abs(alignment) <= 32); + + if (size == 0) { + size = 1; + } + + size = NNSi_FndRoundUp(size, MIN_ALIGNMENT); + + if (alignment >= 0) { + memory = AllocFromHead(heap, size, alignment); + } else { + memory = AllocFromTail(heap, size, -alignment); + } + + return memory; +} + +u32 NNS_FndResizeForMBlockExpHeap (NNSFndHeapHandle heap, void * memBlock, u32 size) { + NNSiFndExpHeapHead * pEHHead; + NNSiFndExpHeapMBlockHead * pMBHead; + + NNS_ASSERT(IsValidExpHeapHandle(heap)); + NNS_ASSERT(IsValidUsedMBlock(memBlock, heap)); + + pEHHead = GetExpHeapHeadPtrFromHandle(heap); + pMBHead = GetMBlockHeadPtr(memBlock); + + size = NNSi_FndRoundUp(size, MIN_ALIGNMENT); + 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; +} + +void NNS_FndFreeToExpHeap (NNSFndHeapHandle heap, void * memBlock) { + NNS_ASSERT(IsValidExpHeapHandle(heap)); + + { + NNSiFndHeapHead * pHeapHd = heap; + NNSiFndExpHeapHead * pExpHeapHd = GetExpHeapHeadPtrFromHandle(pHeapHd); + NNSiFndExpHeapMBlockHead * pMBHead = GetMBlockHeadPtr(memBlock); + NNSiMemRegion region; + + NNS_ASSERT(pHeapHd->heapStart <= memBlock && memBlock < pHeapHd->heapEnd); + + GetRegionOfMBlock(®ion, pMBHead); + (void)RemoveMBlock(&pExpHeapHd->mbUsedList, pMBHead); + (void)RecycleRegion(pExpHeapHd, ®ion); + } +} + +u32 NNS_FndGetTotalFreeSizeForExpHeap (NNSFndHeapHandle heap) { + NNS_ASSERT(IsValidExpHeapHandle(heap)); + + { + u32 sumSize = 0; + NNSiFndExpHeapHead * pEHHead = GetExpHeapHeadPtrFromHandle(heap); + NNSiFndExpHeapMBlockHead * pMBHead; + + for(pMBHead = pEHHead->mbFreeList.head; pMBHead; pMBHead = pMBHead->pMBHeadNext) { + sumSize += pMBHead->blockSize; + } + + return sumSize; + } +} + +u32 NNS_FndGetAllocatableSizeForExpHeapEx (NNSFndHeapHandle heap, int alignment) { + NNS_ASSERT(IsValidExpHeapHandle(heap)); + + NNS_ASSERT(alignment % MIN_ALIGNMENT == 0); + NNS_ASSERT(MIN_ALIGNMENT <= abs(alignment) && abs(alignment) <= 32); + + alignment = abs(alignment); + + { + NNSiFndExpHeapHead * pEHHead = GetExpHeapHeadPtrFromHandle(heap); + u32 maxSize = 0; + u32 offsetMin = 0xFFFFFFFF; + NNSiFndExpHeapMBlockHead * pMBlkHd; + + for (pMBlkHd = pEHHead->mbFreeList.head; pMBlkHd; pMBlkHd = pMBlkHd->pMBHeadNext) { + void * baseAddress = NNSi_FndRoundUpPtr(GetMemPtrForMBlock(pMBlkHd), alignment); + + if (NNSiGetUIntPtr(baseAddress) < NNSiGetUIntPtr(GetMBlockEndAddr(pMBlkHd))) { + const u32 blockSize = GetOffsetFromPtr(baseAddress, GetMBlockEndAddr(pMBlkHd)); + + const u32 offset = GetOffsetFromPtr(GetMemPtrForMBlock(pMBlkHd), baseAddress); + + if (maxSize < blockSize + || (maxSize == blockSize && offsetMin > offset) + ) { + maxSize = blockSize; + offsetMin = offset; + } + } + } + + return maxSize; + } +} + +u16 NNS_FndSetAllocModeForExpHeap (NNSFndHeapHandle heap, u16 mode) { + NNS_ASSERT(IsValidExpHeapHandle(heap)); + + { + NNSiFndExpHeapHead * const pEHHead = GetExpHeapHeadPtrFromHandle(heap); + u16 oldMode = GetAllocMode(pEHHead); + SetAllocMode(pEHHead, mode); + + return oldMode; + } +} + +u16 NNS_FndGetAllocModeForExpHeap (NNSFndHeapHandle heap) { + NNS_ASSERT(IsValidExpHeapHandle(heap)); + return GetAllocMode(GetExpHeapHeadPtrFromHandle(heap)); +} + +u16 NNS_FndSetGroupIDForExpHeap (NNSFndHeapHandle heap, u16 groupID) { + NNS_ASSERT(IsValidExpHeapHandle(heap)); + NNS_ASSERT(groupID <= MAX_GROUPID); + + { + NNSiFndExpHeapHead * pEHHead = GetExpHeapHeadPtrFromHandle(heap); + u16 oldGroupID = pEHHead->groupID; + pEHHead->groupID = groupID; + + return oldGroupID; + } +} + +u16 NNS_FndGetGroupIDForExpHeap (NNSFndHeapHandle heap) { + NNS_ASSERT(IsValidExpHeapHandle(heap)); + + return GetExpHeapHeadPtrFromHandle(heap)->groupID; +} + +void NNS_FndVisitAllocatedForExpHeap (NNSFndHeapHandle heap, NNSFndHeapVisitor visitor, u32 userParam) { + NNS_ASSERT(IsValidExpHeapHandle(heap)); + SDK_NULL_ASSERT(visitor); + + { + NNSiFndExpHeapMBlockHead * pMBHead = GetExpHeapHeadPtrFromHandle(heap)->mbUsedList.head; + + while (pMBHead) { + NNSiFndExpHeapMBlockHead * pMBHeadNext = pMBHead->pMBHeadNext; + (*visitor)(GetMemPtrForMBlock(pMBHead), heap, userParam); + pMBHead = pMBHeadNext; + } + } +} + +u32 NNS_FndGetSizeForMBlockExpHeap (const void * memBlock) { + NNS_ASSERT(IsValidUsedMBlock(memBlock, NULL)); + + return GetMBlockHeadCPtr(memBlock)->blockSize; +} + +u16 NNS_FndGetGroupIDForMBlockExpHeap (const void * memBlock) { + NNS_ASSERT(IsValidUsedMBlock(memBlock, NULL)); + + return GetGroupIDForMBlock(GetMBlockHeadCPtr(memBlock)); +} + +u16 NNS_FndGetAllocDirForMBlockExpHeap (const void * memBlock) { + NNS_ASSERT(IsValidUsedMBlock(memBlock, NULL)); + + return GetAllocDirForMBlock(GetMBlockHeadCPtr(memBlock)); +} + +#if !defined(NNS_FINALROM) + +BOOL NNS_FndCheckExpHeap (NNSFndHeapHandle heap, u32 optFlag) { + const BOOL bPrint = 0 != (optFlag & NNS_FND_HEAP_ERROR_PRINT); + u32 totalBytes = 0; + + if (!IsValidExpHeapHandle(heap)) { + HEAP_WARNING(bPrint, "[NNS Foundation " "Exp" " Heap]" " Invalid heap handle. - %08X\n", heap); + return FALSE; + } + + { + NNSiFndHeapHead * const pHeapHd = heap; + NNSiFndExpHeapHead * const pExpHeapHd = GetExpHeapHeadPtrFromHeapHead(pHeapHd); + NNSiFndExpHeapMBlockHead * pMBHead = NULL; + NNSiFndExpHeapMBlockHead * pMBHeadPrev = NULL; + + for (pMBHead = pExpHeapHd->mbUsedList.head; pMBHead; pMBHeadPrev = pMBHead, pMBHead = pMBHead->pMBHeadNext) { + if (!CheckUsedMBlock(pMBHead, pHeapHd, optFlag) + || !CheckMBlockPrevPtr(pMBHead, pMBHeadPrev, optFlag) + ) { + return FALSE; + } + + totalBytes += sizeof(NNSiFndExpHeapMBlockHead) + pMBHead->blockSize + GetAlignmentForMBlock(pMBHead); + } + + if (!CheckMBlockLinkTail(pMBHeadPrev, pExpHeapHd->mbUsedList.tail, "tail", optFlag)) { + return FALSE; + } + + pMBHead = NULL; + pMBHeadPrev = NULL; + for (pMBHead = pExpHeapHd->mbFreeList.head; pMBHead; pMBHeadPrev = pMBHead, pMBHead = pMBHead->pMBHeadNext) { + if (!CheckFreeMBlock(pMBHead, pHeapHd, optFlag) + || !CheckMBlockPrevPtr(pMBHead, pMBHeadPrev, optFlag) + ) { + return FALSE; + } + + totalBytes += sizeof(NNSiFndExpHeapMBlockHead) + pMBHead->blockSize; + } + + if (!CheckMBlockLinkTail(pMBHeadPrev, pExpHeapHd->mbFreeList.tail, "tail", optFlag)) { + return FALSE; + } + + if (totalBytes != GetOffsetFromPtr(pHeapHd->heapStart, pHeapHd->heapEnd)) { + HEAP_WARNING( + bPrint, "[NNS Foundation " "Exp" " Heap]" " Incorrect total memory block size. - heap size %08X, sum size %08X\n", + GetOffsetFromPtr(pHeapHd->heapStart, pHeapHd->heapEnd), totalBytes + ); + return FALSE; + } + + return TRUE; + } +} + +#endif + +#if !defined(NNS_FINALROM) + +BOOL NNS_FndCheckForMBlockExpHeap (const void * memBlock, NNSFndHeapHandle heap, u32 optFlag) { + const NNSiFndExpHeapMBlockHead * pMBHead = NULL; + NNSiFndHeapHead * const pHeapHd = heap; + + if (!memBlock) { + return FALSE; + } + + pMBHead = GetMBlockHeadCPtr(memBlock); + + if (!CheckUsedMBlock(pMBHead, pHeapHd, optFlag)) { + return FALSE; + } + + if (pMBHead->pMBHeadPrev) { + if (!CheckUsedMBlock(pMBHead->pMBHeadPrev, pHeapHd, optFlag) + || !CheckMBlockNextPtr(pMBHead->pMBHeadPrev, pMBHead, optFlag) + ) { + return FALSE; + } + } else { + if (pHeapHd) { + if (!CheckMBlockLinkTail(pMBHead, GetExpHeapHeadPtrFromHeapHead(pHeapHd)->mbUsedList.head, "head", optFlag)) { + return FALSE; + } + } + } + + if (pMBHead->pMBHeadNext) { + if (!CheckUsedMBlock(pMBHead->pMBHeadNext, pHeapHd, optFlag) + || !CheckMBlockPrevPtr(pMBHead->pMBHeadNext, pMBHead, optFlag) + ) { + return FALSE; + } + } else { + if (pHeapHd) { + if (!CheckMBlockLinkTail(pMBHead, GetExpHeapHeadPtrFromHeapHead(pHeapHd)->mbUsedList.tail, "tail", optFlag)) { + return FALSE; + } + } + } + + return TRUE; +} + +#endif diff --git a/lib/NitroSystem/src/fnd/frameheap.c b/lib/NitroSystem/src/fnd/frameheap.c new file mode 100644 index 0000000000..2c8c52f20b --- /dev/null +++ b/lib/NitroSystem/src/fnd/frameheap.c @@ -0,0 +1,373 @@ + +#include +#include +#include +#include + +#include "include/heapcommoni.h" + +#define MIN_ALIGNMENT 4 + +static NNS_FND_INLINE BOOL IsValidFrmHeapHandle (NNSFndHeapHandle handle) { + if (handle == NNS_FND_HEAP_INVALID_HANDLE) { + return FALSE; + } + + { + NNSiFndHeapHead * pHeapHd = handle; + return pHeapHd->signature == NNSI_FRMHEAP_SIGNATURE; + } +} + +static NNS_FND_INLINE NNSiFndFrmHeapHead * GetFrmHeapHeadPtrFromHeapHead (NNSiFndHeapHead * pHHead) { + return AddU32ToPtr(pHHead, sizeof(NNSiFndHeapHead)); +} + +static NNS_FND_INLINE NNSiFndHeapHead * GetHeapHeadPtrFromFrmHeapHead (NNSiFndFrmHeapHead * pFrmHeapHd) { + return SubU32ToPtr(pFrmHeapHd, sizeof(NNSiFndHeapHead)); +} + +static NNSiFndHeapHead * InitFrameHeap (void * startAddress, void * endAddress, u16 optFlag) { + NNSiFndHeapHead * pHeapHd = startAddress; + NNSiFndFrmHeapHead * pFrmHeapHd = GetFrmHeapHeadPtrFromHeapHead(pHeapHd); + + NNSi_FndInitHeapHead( + pHeapHd, + NNSI_FRMHEAP_SIGNATURE, + AddU32ToPtr(pFrmHeapHd, sizeof(NNSiFndFrmHeapHead)), + endAddress, + optFlag + ); + + pFrmHeapHd->headAllocator = pHeapHd->heapStart; + pFrmHeapHd->tailAllocator = pHeapHd->heapEnd; + + pFrmHeapHd->pState = NULL; + + return pHeapHd; +} + +static void * AllocFromHead (NNSiFndFrmHeapHead * pFrmHeapHd, u32 size, int alignment) { + void * newBlock = NNSi_FndRoundUpPtr(pFrmHeapHd->headAllocator, alignment); + void * endAddress = AddU32ToPtr(newBlock, size); + + if (NNSiGetUIntPtr(endAddress) > NNSiGetUIntPtr(pFrmHeapHd->tailAllocator)) { + return NULL; + } + + FillAllocMemory( + GetHeapHeadPtrFromFrmHeapHead(pFrmHeapHd), + pFrmHeapHd->headAllocator, + GetOffsetFromPtr(pFrmHeapHd->headAllocator, endAddress) + ); + + pFrmHeapHd->headAllocator = endAddress; + + return newBlock; +} + +static void * AllocFromTail (NNSiFndFrmHeapHead * pFrmHeapHd, u32 size, int alignment) { + void * newBlock = NNSi_FndRoundDownPtr(SubU32ToPtr(pFrmHeapHd->tailAllocator, size), alignment); + + if (NNSiGetUIntPtr(newBlock) < NNSiGetUIntPtr(pFrmHeapHd->headAllocator)) { + return NULL; + } + + FillAllocMemory( + GetHeapHeadPtrFromFrmHeapHead(pFrmHeapHd), + newBlock, + GetOffsetFromPtr(newBlock, pFrmHeapHd->tailAllocator) + ); + + pFrmHeapHd->tailAllocator = newBlock; + + return newBlock; +} + +static void FreeHead (NNSiFndHeapHead * pHeapHd) { + NNSiFndFrmHeapHead * pFrmHeapHd = GetFrmHeapHeadPtrFromHeapHead(pHeapHd); + + FillFreeMemory( + pHeapHd, + pHeapHd->heapStart, + GetOffsetFromPtr(pHeapHd->heapStart, pFrmHeapHd->headAllocator) + ); + + pFrmHeapHd->headAllocator = pHeapHd->heapStart; + pFrmHeapHd->pState = NULL; +} + +static void FreeTail (NNSiFndHeapHead * pHeapHd) { + NNSiFndFrmHeapHead * pFrmHeapHd = GetFrmHeapHeadPtrFromHeapHead(pHeapHd); + + FillFreeMemory( + pHeapHd, + pFrmHeapHd->tailAllocator, + GetOffsetFromPtr(pFrmHeapHd->tailAllocator, pHeapHd->heapEnd) + ); + + { + NNSiFndFrmHeapState * pState; + for (pState = pFrmHeapHd->pState; pState; pState = pState->pPrevState) { + pState->tailAllocator = pHeapHd->heapEnd; + } + } + + pFrmHeapHd->tailAllocator = pHeapHd->heapEnd; +} + +#if !defined(NNS_FINALROM) + +static void PrintSize (u32 size, u32 wholeSize) { + OS_Printf("%9d (%6.2f%%)", size, 100.0 * size / wholeSize); +} + +#endif + +void * NNSi_FndGetFreeStartForFrmHeap (NNSFndHeapHandle heap) { + NNS_ASSERT(IsValidFrmHeapHandle(heap)); + return GetFrmHeapHeadPtrFromHeapHead(heap)->headAllocator; +} + +void * NNSi_FndGetFreeEndForFrmHeap (NNSFndHeapHandle heap) { + NNS_ASSERT(IsValidFrmHeapHandle(heap)); + return GetFrmHeapHeadPtrFromHeapHead(heap)->tailAllocator; +} + +#if !defined(NNS_FINALROM) + +void NNSi_FndDumpFrmHeap (NNSFndHeapHandle heap) { + NNS_ASSERT(IsValidFrmHeapHandle(heap)); + + { + NNSiFndHeapHead * const pHeapHd = heap; + NNSiFndFrmHeapHead * const pFrmHeapHd = GetFrmHeapHeadPtrFromHeapHead(pHeapHd); + const u32 heapSize = GetOffsetFromPtr(pHeapHd->heapStart, pHeapHd->heapEnd); + + NNSi_FndDumpHeapHead(pHeapHd); + + OS_Printf(" head [%p - %p) ", pHeapHd->heapStart, pFrmHeapHd->headAllocator); + PrintSize(GetOffsetFromPtr(pHeapHd->heapStart, pFrmHeapHd->headAllocator), heapSize); + OS_Printf("\n free "); + PrintSize(GetOffsetFromPtr(pFrmHeapHd->headAllocator, pFrmHeapHd->tailAllocator), heapSize); + OS_Printf("\n tail [%p - %p) ", pFrmHeapHd->tailAllocator, pHeapHd->heapEnd); + PrintSize(GetOffsetFromPtr(pFrmHeapHd->tailAllocator, pHeapHd->heapEnd), heapSize); + OS_Printf("\n"); + + if (pFrmHeapHd->pState) { + NNSiFndFrmHeapState * pState; + + OS_Printf(" state : [tag] [head] [tail]\n"); + + for (pState = pFrmHeapHd->pState; pState; pState = pState->pPrevState) { + OS_Printf( + " '%c%c%c%c' : %p %p\n", pState->tagName >> 24, (pState->tagName >> 16) & 0xFF, (pState->tagName >> 8) & 0xFF, pState->tagName & 0xFF, + pState->headAllocator, pState->tailAllocator + ); + } + } + + OS_Printf("\n"); + } +} + +#endif + +NNSFndHeapHandle NNS_FndCreateFrmHeapEx (void * startAddress, u32 size, u16 optFlag) { + void * endAddress; + + SDK_NULL_ASSERT(startAddress); + + endAddress = NNSi_FndRoundDownPtr(AddU32ToPtr(startAddress, size), MIN_ALIGNMENT); + startAddress = NNSi_FndRoundUpPtr(startAddress, MIN_ALIGNMENT); + + if (NNSiGetUIntPtr(startAddress) > NNSiGetUIntPtr(endAddress) + || GetOffsetFromPtr(startAddress, endAddress) < sizeof(NNSiFndHeapHead) + sizeof(NNSiFndFrmHeapHead) + ) { + return NNS_FND_HEAP_INVALID_HANDLE; + } + + { + NNSiFndHeapHead * pHHead = InitFrameHeap(startAddress, endAddress, optFlag); + return pHHead; + } +} + +void NNS_FndDestroyFrmHeap (NNSFndHeapHandle heap) { + NNS_ASSERT(IsValidFrmHeapHandle(heap)); + NNSi_FndFinalizeHeap(heap); +} + +void * NNS_FndAllocFromFrmHeapEx (NNSFndHeapHandle heap, u32 size, int alignment) { + void * memory = NULL; + NNSiFndFrmHeapHead * pFrmHeapHd; + + NNS_ASSERT(IsValidFrmHeapHandle(heap)); + + NNS_ASSERT(alignment % MIN_ALIGNMENT == 0); + NNS_ASSERT(MIN_ALIGNMENT <= abs(alignment) && abs(alignment) <= 32); + + pFrmHeapHd = GetFrmHeapHeadPtrFromHeapHead(heap); + + if (size == 0) { + size = 1; + } + + size = NNSi_FndRoundUp(size, MIN_ALIGNMENT); + + if (alignment >= 0) { + memory = AllocFromHead(pFrmHeapHd, size, alignment); + } else { + memory = AllocFromTail(pFrmHeapHd, size, -alignment); + } + + return memory; +} + +void NNS_FndFreeToFrmHeap (NNSFndHeapHandle heap, int mode) { + NNS_ASSERT(IsValidFrmHeapHandle(heap)); + + if (mode & NNS_FND_FRMHEAP_FREE_HEAD) { + FreeHead(heap); + } + + if (mode & NNS_FND_FRMHEAP_FREE_TAIL) { + FreeTail(heap); + } +} + +u32 NNS_FndGetAllocatableSizeForFrmHeapEx (NNSFndHeapHandle heap, int alignment) { + NNS_ASSERT(IsValidFrmHeapHandle(heap)); + + NNS_ASSERT(alignment % MIN_ALIGNMENT == 0); + NNS_ASSERT(MIN_ALIGNMENT <= abs(alignment) && abs(alignment) <= 32); + + alignment = abs(alignment); + + { + const NNSiFndFrmHeapHead * pFrmHeapHd = GetFrmHeapHeadPtrFromHeapHead(heap); + const void * block = NNSi_FndRoundUpPtr(pFrmHeapHd->headAllocator, alignment); + + if (NNSiGetUIntPtr(block) > NNSiGetUIntPtr(pFrmHeapHd->tailAllocator)) { + return 0; + } + + return GetOffsetFromPtr(block, pFrmHeapHd->tailAllocator); + } +} + +BOOL NNS_FndRecordStateForFrmHeap (NNSFndHeapHandle heap, u32 tagName) { + NNS_ASSERT(IsValidFrmHeapHandle(heap)); + + { + NNSiFndFrmHeapHead * pFrmHeapHd = GetFrmHeapHeadPtrFromHeapHead(heap); + void * oldHeadAllocator = pFrmHeapHd->headAllocator; + + NNSiFndFrmHeapState * pState = AllocFromHead(pFrmHeapHd, sizeof(NNSiFndFrmHeapState), MIN_ALIGNMENT); + if (!pState) { + return FALSE; + } + + pState->tagName = tagName; + pState->headAllocator = oldHeadAllocator; + pState->tailAllocator = pFrmHeapHd->tailAllocator; + pState->pPrevState = pFrmHeapHd->pState; + + pFrmHeapHd->pState = pState; + + return TRUE; + } +} + +BOOL NNS_FndFreeByStateToFrmHeap (NNSFndHeapHandle heap, u32 tagName) { + NNS_ASSERT(IsValidFrmHeapHandle(heap)); + + { + NNSiFndFrmHeapHead * pFrmHeapHd = GetFrmHeapHeadPtrFromHeapHead(heap); + NNSiFndFrmHeapState * pState = pFrmHeapHd->pState; + + if (tagName != 0) { + for (; pState; pState = pState->pPrevState) { + if (pState->tagName == tagName) { + break; + } + } + } + + if (!pState) { + return FALSE; + } + + pFrmHeapHd->headAllocator = pState->headAllocator; + pFrmHeapHd->tailAllocator = pState->tailAllocator; + + pFrmHeapHd->pState = pState->pPrevState; + + return TRUE; + } +} + +u32 NNS_FndAdjustFrmHeap (NNSFndHeapHandle heap) { + NNS_ASSERT(IsValidFrmHeapHandle(heap)); + + { + NNSiFndHeapHead * pHeapHd = heap; + NNSiFndFrmHeapHead * pFrmHeapHd = GetFrmHeapHeadPtrFromHeapHead(pHeapHd); + + if (0 < GetOffsetFromPtr(pFrmHeapHd->tailAllocator, pHeapHd->heapEnd)) { + return 0; + } + + pFrmHeapHd->tailAllocator = pHeapHd->heapEnd = pFrmHeapHd->headAllocator; + + return GetOffsetFromPtr(heap, pHeapHd->heapEnd); + } +} + +u32 NNS_FndResizeForMBlockFrmHeap (NNSFndHeapHandle heap, void * memBlock, u32 newSize) { + NNSiFndHeapHead * pHeapHd = NULL; + NNSiFndFrmHeapHead * pFrmHeapHd = NULL; + + NNS_ASSERT(IsValidFrmHeapHandle(heap)); + NNS_ASSERT(memBlock == NNSi_FndRoundDownPtr(memBlock, MIN_ALIGNMENT)); + + pHeapHd = heap; + pFrmHeapHd = GetFrmHeapHeadPtrFromHeapHead(pHeapHd); + + NNS_ASSERT( + ComparePtr(pHeapHd->heapStart, memBlock) <= 0 + && ComparePtr(pFrmHeapHd->headAllocator, memBlock) > 0 + ); + NNS_ASSERT( + pFrmHeapHd->pState == NULL + || ComparePtr(pFrmHeapHd->pState, memBlock) < 0 + ); + + if (newSize == 0) { + newSize = 1; + } + newSize = NNSi_FndRoundUp(newSize, MIN_ALIGNMENT); + + { + const u32 oldSize = GetOffsetFromPtr(memBlock, pFrmHeapHd->headAllocator); + void * endAddress = AddU32ToPtr(memBlock, newSize); + + if (newSize == oldSize) { + return newSize; + } + + if (newSize > oldSize) { + if (ComparePtr(endAddress, pFrmHeapHd->tailAllocator) > 0) { + return 0; + } + + FillAllocMemory(heap, pFrmHeapHd->headAllocator, newSize - oldSize); + } else { + FillFreeMemory(heap, endAddress, oldSize - newSize); + } + + pFrmHeapHd->headAllocator = endAddress; + + return newSize; + } +} diff --git a/lib/NitroSystem/src/fnd/heapcommon.c b/lib/NitroSystem/src/fnd/heapcommon.c new file mode 100644 index 0000000000..38c8a2fb27 --- /dev/null +++ b/lib/NitroSystem/src/fnd/heapcommon.c @@ -0,0 +1,146 @@ +#include +#include +#include +#include +#include +#include +#include + +#include "include/heapcommoni.h" + +static NNSFndList sRootList; +static BOOL sRootListInitialized = FALSE; + +#if !defined(NNS_FINALROM) + +static u32 sFillVals[NNS_FND_HEAP_FILL_MAX] = { + 0xC3C3C3C3, + 0xF3F3F3F3, + 0xD3D3D3D3, +}; + +#endif + +static NNSiFndHeapHead * FindContainHeap (NNSFndList * pList, const void * memBlock) { + NNSiFndHeapHead * pHeapHd = NULL; + while (NULL != (pHeapHd = NNS_FndGetNextListObject(pList, pHeapHd))) { + if (NNSiGetUIntPtr(pHeapHd->heapStart) <= NNSiGetUIntPtr(memBlock) + && NNSiGetUIntPtr(memBlock) < NNSiGetUIntPtr(pHeapHd->heapEnd) + ) { + NNSiFndHeapHead * pChildHeapHd = FindContainHeap(&pHeapHd->childList, memBlock); + if (pChildHeapHd) { + return pChildHeapHd; + } + + return pHeapHd; + } + } + + return NULL; +} + +static NNSFndList * FindListContainHeap (NNSiFndHeapHead * pHeapHd) { + NNSFndList * pList = &sRootList; + + NNSiFndHeapHead * pContainHeap = FindContainHeap(&sRootList, pHeapHd); + + if (pContainHeap) { + pList = &pContainHeap->childList; + } + + return pList; +} + +static NNS_FND_INLINE void DumpHeapList (void) { + return; +} + +void NNSi_FndInitHeapHead (NNSiFndHeapHead * pHeapHd, u32 signature, void * heapStart, void * heapEnd, u16 optFlag) { + pHeapHd->signature = signature; + + pHeapHd->heapStart = heapStart; + pHeapHd->heapEnd = heapEnd; + + pHeapHd->attribute = 0; + SetOptForHeap(pHeapHd, optFlag); + + FillNoUseMemory( + pHeapHd, + heapStart, + GetOffsetFromPtr(heapStart, heapEnd) + ); + + NNS_FND_INIT_LIST(&pHeapHd->childList, NNSiFndHeapHead, link); + + if (!sRootListInitialized) { + NNS_FND_INIT_LIST(&sRootList, NNSiFndHeapHead, link); + sRootListInitialized = TRUE; + } + + NNS_FndAppendListObject(FindListContainHeap(pHeapHd), pHeapHd); + DumpHeapList(); +} + +void NNSi_FndFinalizeHeap (NNSiFndHeapHead * pHeapHd) { + NNS_FndRemoveListObject(FindListContainHeap(pHeapHd), pHeapHd); + DumpHeapList(); +} + +void NNSi_FndDumpHeapHead (NNSiFndHeapHead * pHeapHd) { + OS_Printf("[NNS Foundation "); + + switch (pHeapHd->signature) { + case NNSI_EXPHEAP_SIGNATURE: OS_Printf("Exp"); break; + case NNSI_FRMHEAP_SIGNATURE: OS_Printf("Frame"); break; + case NNSI_UNTHEAP_SIGNATURE: OS_Printf("Unit"); break; + default: + NNS_ASSERT(FALSE); + } + + OS_Printf(" Heap]\n"); + + OS_Printf(" whole [%p - %p)\n", pHeapHd, pHeapHd->heapEnd); +} + +NNSFndHeapHandle NNS_FndFindContainHeap (const void * memBlock) { + return FindContainHeap(&sRootList, memBlock); +} + +#if !defined(NNS_FINALROM) + +void NNS_FndDumpHeap (NNSFndHeapHandle heap) { + NNSiFndHeapHead * pHeapHd = heap; + switch (pHeapHd->signature) { + case NNSI_EXPHEAP_SIGNATURE: NNSi_FndDumpExpHeap(heap); break; + case NNSI_FRMHEAP_SIGNATURE: NNSi_FndDumpFrmHeap(heap); break; + case NNSI_UNTHEAP_SIGNATURE: NNSi_FndDumpUnitHeap(heap); break; + default: + OS_Printf("[NNS Foundation] dump heap : unknown heap. - %p\n", heap); + } +} + +#endif + +#if !defined(NNS_FINALROM) + +u32 NNS_FndSetFillValForHeap (int type, u32 val) { + NNS_ASSERT(type < NNS_FND_HEAP_FILL_MAX); + + { + u32 oldVal = sFillVals[type]; + sFillVals[type] = val; + return oldVal; + } +} + +#endif + +#if !defined(NNS_FINALROM) + +u32 NNS_FndGetFillValForHeap (int type) { + NNS_ASSERT(type < NNS_FND_HEAP_FILL_MAX); + + return sFillVals[type]; +} + +#endif diff --git a/lib/NitroSystem/src/fnd/include/heapcommoni.h b/lib/NitroSystem/src/fnd/include/heapcommoni.h new file mode 100644 index 0000000000..f979176109 --- /dev/null +++ b/lib/NitroSystem/src/fnd/include/heapcommoni.h @@ -0,0 +1,154 @@ +#ifndef NNS_FND_HEAPCOMMONI_H_ +#define NNS_FND_HEAPCOMMONI_H_ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef s32 NNSiIntPtr; +typedef u32 NNSiUIntPtr; + +#define NNSi_FndRoundUp(value, alignment) \ + (((value) + (alignment - 1)) & ~(alignment - 1)) + +#define NNSi_FndRoundUpPtr(ptr, alignment) \ + ((void *)NNSi_FndRoundUp(NNSiGetUIntPtr(ptr), alignment)) + +#define NNSi_FndRoundDown(value, alignment) \ + ((value) & ~(alignment - 1)) + +#define NNSi_FndRoundDownPtr(ptr, alignment) \ + ((void *)NNSi_FndRoundDown(NNSiGetUIntPtr(ptr), alignment)) + +#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); + +NNS_FND_INLINE NNSiUIntPtr NNSiGetUIntPtr (const void * ptr) +{ + return (NNSiUIntPtr)ptr; +} + +NNS_FND_INLINE u32 GetOffsetFromPtr (const void * start, const void * end) +{ + return NNSiGetUIntPtr(end) - NNSiGetUIntPtr(start); +} + +NNS_FND_INLINE void * AddU32ToPtr (void * ptr, u32 val) +{ + return (void *)(NNSiGetUIntPtr(ptr) + val); +} + +NNS_FND_INLINE const void * AddU32ToCPtr (const void * ptr, u32 val) +{ + return (const void *)(NNSiGetUIntPtr(ptr) + val); +} + +NNS_FND_INLINE void * SubU32ToPtr (void * ptr, u32 val) +{ + return (void *)(NNSiGetUIntPtr(ptr) - val); +} + +NNS_FND_INLINE const void * SubU32ToCPtr (const void * ptr, u32 val) +{ + return (const void *)(NNSiGetUIntPtr(ptr) - val); +} + +NNS_FND_INLINE int ComparePtr (const void * a, const void * b) +{ + const u8 * wa = a; + const u8 * wb = b; + + return wa - wb; +} + +NNS_FND_INLINE u16 GetOptForHeap (const NNSiFndHeapHead * pHeapHd) +{ + return (u16)NNSi_FndGetBitValue(pHeapHd->attribute, 0, 8); +} + +NNS_FND_INLINE void SetOptForHeap ( + NNSiFndHeapHead * pHeapHd, + u16 optFlag +) +{ + NNSi_FndSetBitValue(pHeapHd->attribute, 0, 8, optFlag); +} + +NNS_FND_INLINE void FillAllocMemory ( + NNSiFndHeapHead * pHeapHd, + void * address, + u32 size +) +{ + if (GetOptForHeap(pHeapHd) & NNS_FND_HEAP_OPT_0_CLEAR) { + MI_CpuFill32(address, 0, size); + } else { + #if !defined(NNS_FINALROM) + if (GetOptForHeap(pHeapHd) & NNS_FND_HEAP_OPT_DEBUG_FILL) { + MI_CpuFill32(address, NNS_FndGetFillValForHeap(NNS_FND_HEAP_FILL_ALLOC), size); + } + #endif + } +} + +#if defined(NNS_FINALROM) + #define FillFreeMemory(pHeapHd, address, size) ((void)0) +#else +NNS_FND_INLINE void FillFreeMemory ( + NNSiFndHeapHead * pHeapHd, + void * address, + u32 size +) +{ + if (GetOptForHeap(pHeapHd) & NNS_FND_HEAP_OPT_DEBUG_FILL) { + MI_CpuFill32(address, NNS_FndGetFillValForHeap(NNS_FND_HEAP_FILL_FREE), size); + } +} +#endif + +#if defined(NNS_FINALROM) + #define FillNoUseMemory(pHeapHd, address, size) ((void)0) +#else +NNS_FND_INLINE void FillNoUseMemory ( + NNSiFndHeapHead * pHeapHd, + void * address, + u32 size +) +{ + if (GetOptForHeap(pHeapHd) & NNS_FND_HEAP_OPT_DEBUG_FILL) { + MI_CpuFill32(address, NNS_FndGetFillValForHeap(NNS_FND_HEAP_FILL_NOUSE), size); + } +} +#endif + +void NNSi_FndInitHeapHead( + NNSiFndHeapHead * pHeapHd, + u32 signature, + void * heapStart, + void * heapEnd, + u16 optFlag); + +void NNSi_FndFinalizeHeap( + NNSiFndHeapHead * pHeapHd); + +void NNSi_FndDumpHeapHead( + NNSiFndHeapHead * pHeapHd); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/NitroSystem/src/fnd/list_nnsfnd.c b/lib/NitroSystem/src/fnd/list_nnsfnd.c new file mode 100644 index 0000000000..1018f70cae --- /dev/null +++ b/lib/NitroSystem/src/fnd/list_nnsfnd.c @@ -0,0 +1,141 @@ +#include +#include + +#define OBJ_TO_LINK(list, obj) ((NNSFndLink *)(((u32)(obj)) + (list)->offset)) + +void NNS_FndInitList (NNSFndList * list, u16 offset) { + NNS_NULL_ASSERT(list); + + list->headObject = NULL; + list->tailObject = NULL; + list->numObjects = 0; + list->offset = offset; +} + +static void SetFirstObject (NNSFndList * list, void * object) { + NNSFndLink * link; + + NNS_NULL_ASSERT(list); + NNS_NULL_ASSERT(object); + + link = OBJ_TO_LINK(list, object); + + link->nextObject = NULL; + link->prevObject = NULL; + list->headObject = object; + list->tailObject = object; + list->numObjects++; +} + +void NNS_FndAppendListObject (NNSFndList * list, void * object) { + NNS_NULL_ASSERT(list); + NNS_NULL_ASSERT(object); + + if (list->headObject == NULL) { + SetFirstObject(list, object); + } else { + NNSFndLink * link = OBJ_TO_LINK(list, object); + + link->prevObject = list->tailObject; + link->nextObject = NULL; + + OBJ_TO_LINK(list, list->tailObject)->nextObject = object; + list->tailObject = object; + list->numObjects++; + } +} + +void NNS_FndPrependListObject (NNSFndList * list, void * object) { + NNS_NULL_ASSERT(list); + NNS_NULL_ASSERT(object); + + if (list->headObject == NULL) { + SetFirstObject(list, object); + } else { + NNSFndLink * link = OBJ_TO_LINK(list, object); + + link->prevObject = NULL; + link->nextObject = list->headObject; + + OBJ_TO_LINK(list, list->headObject)->prevObject = object; + list->headObject = object; + list->numObjects++; + } +} + +void NNS_FndInsertListObject (NNSFndList * list, void * target, void * object) { + NNS_NULL_ASSERT(list); + NNS_NULL_ASSERT(object); + + if (target == NULL) { + NNS_FndAppendListObject(list, object); + } else if (target == list->headObject) { + NNS_FndPrependListObject(list, object); + } else { + NNSFndLink * link = OBJ_TO_LINK(list, object); + void * prevObj = OBJ_TO_LINK(list, target)->prevObject; + NNSFndLink * prevLnk = OBJ_TO_LINK(list, prevObj); + + link->prevObject = prevObj; + link->nextObject = target; + prevLnk->nextObject = object; + OBJ_TO_LINK(list, target)->prevObject = object; + list->numObjects++; + } +} + +void NNS_FndRemoveListObject (NNSFndList * list, void * object) { + NNSFndLink * link; + + NNS_NULL_ASSERT(list); + NNS_NULL_ASSERT(object); + + link = OBJ_TO_LINK(list, object); + + if (link->prevObject == NULL) { + list->headObject = link->nextObject; + } else { + OBJ_TO_LINK(list, link->prevObject)->nextObject = link->nextObject; + } + if (link->nextObject == NULL) { + list->tailObject = link->prevObject; + } else { + OBJ_TO_LINK(list, link->nextObject)->prevObject = link->prevObject; + } + link->prevObject = NULL; + link->nextObject = NULL; + list->numObjects--; +} + +void * NNS_FndGetNextListObject (NNSFndList * list, void * object) { + NNS_NULL_ASSERT(list); + + if (object == NULL) { + return list->headObject; + } + return OBJ_TO_LINK(list, object)->nextObject; +} + +void * NNS_FndGetPrevListObject (NNSFndList * list, void * object) { + NNS_NULL_ASSERT(list); + + if (object == NULL) { + return list->tailObject; + } + return OBJ_TO_LINK(list, object)->prevObject; +} + +void * NNS_FndGetNthListObject (NNSFndList * list, u16 index) { + int count = 0; + NNSFndLink * object = NULL; + + NNS_NULL_ASSERT(list); + + while ((object = NNS_FndGetNextListObject(list, object)) != NULL) { + if (index == count) { + return object; + } + count++; + } + return NULL; +} diff --git a/lib/NitroSystem/src/fnd/unitheap.c b/lib/NitroSystem/src/fnd/unitheap.c new file mode 100644 index 0000000000..d4c17cf3ae --- /dev/null +++ b/lib/NitroSystem/src/fnd/unitheap.c @@ -0,0 +1,172 @@ +#include +#include +#include +#include + +#include "include/heapcommoni.h" + +#define MIN_ALIGNMENT 4 + +static NNSiFndUntHeapMBlockHead * PopMBlock (NNSiFndUntMBlockList * list) { + NNSiFndUntHeapMBlockHead * block = list->head; + if (block) { + list->head = block->pMBlkHdNext; + } + + return block; +} + +static NNS_FND_INLINE void PushMBlock (NNSiFndUntMBlockList * list, NNSiFndUntHeapMBlockHead * block) { + block->pMBlkHdNext = list->head; + list->head = block; +} + +static NNS_FND_INLINE NNSiFndUntHeapHead * GetUnitHeapHeadPtrFromHeapHead (NNSiFndHeapHead * pHeapHd) { + return AddU32ToPtr(pHeapHd, sizeof(NNSiFndHeapHead)); +} + +static NNS_FND_INLINE BOOL IsValidUnitHeapHandle (NNSFndHeapHandle handle) { + if (handle == NNS_FND_HEAP_INVALID_HANDLE) { + return FALSE; + } + + { + NNSiFndHeapHead * pHeapHd = handle; + return pHeapHd->signature == NNSI_UNTHEAP_SIGNATURE; + } +} + +#if !defined(NNS_FINALROM) + +void NNSi_FndDumpUnitHeap (NNSFndHeapHandle heap) { + NNS_ASSERT(IsValidUnitHeapHandle(heap)); + + { + NNSiFndHeapHead * const pHeapHd = heap; + NNSiFndUntHeapHead * const pUnitHeapHd = GetUnitHeapHeadPtrFromHeapHead(pHeapHd); + const u32 heapSize = GetOffsetFromPtr(pHeapHd->heapStart, pHeapHd->heapEnd); + + const u32 freeSize = NNS_FndCountFreeBlockForUnitHeap(heap) * pUnitHeapHd->mBlkSize; + const u32 usedSize = heapSize - freeSize; + + NNSi_FndDumpHeapHead(pHeapHd); + + OS_Printf( + " %d / %d bytes (%6.2f%%) used\n", + usedSize, heapSize, 100.0f * usedSize / heapSize + ); + } +} + +#endif + +NNSFndHeapHandle NNS_FndCreateUnitHeapEx (void * startAddress, u32 heapSize, u32 memBlockSize, int alignment, u16 optFlag) { + NNSiFndHeapHead * pHeapHd; + void * heapEnd; + + SDK_NULL_ASSERT(startAddress); + + NNS_ASSERT(alignment % MIN_ALIGNMENT == 0); + NNS_ASSERT(MIN_ALIGNMENT <= alignment && alignment <= 32); + + pHeapHd = NNSi_FndRoundUpPtr(startAddress, MIN_ALIGNMENT); + heapEnd = NNSi_FndRoundDownPtr(AddU32ToPtr(startAddress, heapSize), MIN_ALIGNMENT); + + if (ComparePtr(pHeapHd, heapEnd) > 0) { + return NNS_FND_HEAP_INVALID_HANDLE; + } + + memBlockSize = NNSi_FndRoundUp(memBlockSize, alignment); + + { + NNSiFndUntHeapHead * pUntHeapHd = GetUnitHeapHeadPtrFromHeapHead(pHeapHd); + void * heapStart = NNSi_FndRoundUpPtr(AddU32ToPtr(pUntHeapHd, sizeof(NNSiFndUntHeapHead)), alignment); + u32 elementNum; + + if (ComparePtr(heapStart, heapEnd) > 0) { + return NNS_FND_HEAP_INVALID_HANDLE; + } + + elementNum = GetOffsetFromPtr(heapStart, heapEnd) / memBlockSize; + if (elementNum == 0) { + return NNS_FND_HEAP_INVALID_HANDLE; + } + + heapEnd = AddU32ToPtr(heapStart, elementNum * memBlockSize); + + NNSi_FndInitHeapHead( + pHeapHd, + NNSI_UNTHEAP_SIGNATURE, + heapStart, + heapEnd, + optFlag + ); + + pUntHeapHd->mbFreeList.head = heapStart; + pUntHeapHd->mBlkSize = memBlockSize; + + { + NNSiFndUntHeapMBlockHead * pMBlkHd = pUntHeapHd->mbFreeList.head; + int i; + + for (i = 0; i < elementNum - 1; ++i, pMBlkHd = pMBlkHd->pMBlkHdNext) { + pMBlkHd->pMBlkHdNext = AddU32ToPtr(pMBlkHd, memBlockSize); + } + + pMBlkHd->pMBlkHdNext = NULL; + } + + return pHeapHd; + } +} + +void NNS_FndDestroyUnitHeap (NNSFndHeapHandle heap) { + NNS_ASSERT(IsValidUnitHeapHandle(heap)); + NNSi_FndFinalizeHeap(heap); +} + +void * NNS_FndAllocFromUnitHeap (NNSFndHeapHandle heap) { + NNS_ASSERT(IsValidUnitHeapHandle(heap)); + + { + NNSiFndUntHeapHead * pUntHeapHd = GetUnitHeapHeadPtrFromHeapHead(heap); + NNSiFndUntHeapMBlockHead * pMBlkHd = PopMBlock(&pUntHeapHd->mbFreeList); + + if (pMBlkHd) { + FillAllocMemory(heap, pMBlkHd, pUntHeapHd->mBlkSize); + } + + return pMBlkHd; + } +} + +void NNS_FndFreeToUnitHeap (NNSFndHeapHandle heap, void * memBlock) { + NNS_ASSERT(IsValidUnitHeapHandle(heap)); + + { + NNSiFndUntHeapHead * pUntHeapHd = GetUnitHeapHeadPtrFromHeapHead(heap); + + FillFreeMemory(heap, memBlock, pUntHeapHd->mBlkSize); + PushMBlock(&pUntHeapHd->mbFreeList, memBlock); + } +} + +u32 NNS_FndCountFreeBlockForUnitHeap (NNSFndHeapHandle heap) { + NNS_ASSERT(IsValidUnitHeapHandle(heap)); + + { + NNSiFndUntHeapHead * pUntHeapHd = GetUnitHeapHeadPtrFromHeapHead(heap); + NNSiFndUntHeapMBlockHead * pMBlkHd = pUntHeapHd->mbFreeList.head; + u32 cnt = 0; + + for (; pMBlkHd; pMBlkHd = pMBlkHd->pMBlkHdNext) { + ++cnt; + } + + return cnt; + } +} + +u32 NNS_FndCalcHeapSizeForUnitHeap (u32 memBlockSize, u32 memBlockNum, int alignment) { + return sizeof(NNSiFndHeapHead) + sizeof(NNSiFndUntHeapHead) + (alignment - 4) + memBlockNum * NNSi_FndRoundUp(memBlockSize, alignment); +} diff --git a/main.lsf b/main.lsf index db7a07efe2..804ff4ffa0 100644 --- a/main.lsf +++ b/main.lsf @@ -379,11 +379,11 @@ Static main Object lib/NitroDWC/asm/base/dwc_account.o Object asm/unk_020A490C.o Object asm/unk_020A4A34.o - Object lib/NitroSystem/asm/fnd/list_nnsfnd.o - Object lib/NitroSystem/asm/fnd/heapcommon.o - Object lib/NitroSystem/asm/fnd/expheap.o - Object lib/NitroSystem/asm/fnd/frameheap.o - Object lib/NitroSystem/asm/fnd/unitheap.o + Object lib/NitroSystem/src/fnd/list_nnsfnd.o + Object lib/NitroSystem/src/fnd/heapcommon.o + Object lib/NitroSystem/src/fnd/expheap.o + Object lib/NitroSystem/src/fnd/frameheap.o + Object lib/NitroSystem/src/fnd/unitheap.o Object lib/NitroSystem/src/fnd/allocator.o Object lib/NitroSystem/asm/gfd/gfd_texvramman.o Object lib/NitroSystem/asm/gfd/gfd_plttvramman.o