Match the rest of NNS/fnd

This commit is contained in:
Nomura 2023-01-09 11:09:47 +01:00
parent 689360abd3
commit afca00a398
17 changed files with 1966 additions and 1159 deletions

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -1,6 +0,0 @@
.public NNS_FndInitList
.public NNS_FndAppendListObject
.public NNS_FndRemoveListObject
.public NNS_FndGetNextListObject
.public FindContainHeap
.public FindListContainHeap

View File

@ -1,3 +0,0 @@
.public SetFirstObject
.public NNS_FndAppendListObject
.public NNS_FndPrependListObject

View File

@ -1,2 +0,0 @@
.public PopMBlock
.public MIi_CpuClear32

View File

@ -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

View File

@ -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

View File

@ -0,0 +1,975 @@
#include <nitro.h>
#include <nnsys/misc.h>
#include <nnsys/fnd/expheap.h>
#include <nnsys/fnd/config.h>
#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(&region);
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(&region, 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(&region, pMBHead);
(void)RemoveMBlock(&pExpHeapHd->mbUsedList, pMBHead);
(void)RecycleRegion(pExpHeapHd, &region);
}
}
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

View File

@ -0,0 +1,373 @@
#include <nitro.h>
#include <nnsys/misc.h>
#include <nnsys/fnd/frameheap.h>
#include <nnsys/fnd/config.h>
#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;
}
}

View File

@ -0,0 +1,146 @@
#include <nitro.h>
#include <nnsys/misc.h>
#include <nnsys/fnd/heapcommon.h>
#include <nnsys/fnd/expheap.h>
#include <nnsys/fnd/frameheap.h>
#include <nnsys/fnd/unitheap.h>
#include <nnsys/fnd/config.h>
#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

View File

@ -0,0 +1,154 @@
#ifndef NNS_FND_HEAPCOMMONI_H_
#define NNS_FND_HEAPCOMMONI_H_
#include <nitro/types.h>
#include <nnsys/fnd/config.h>
#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

View File

@ -0,0 +1,141 @@
#include <nnsys/misc.h>
#include <nnsys/fnd/list.h>
#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;
}

View File

@ -0,0 +1,172 @@
#include <nitro.h>
#include <nnsys/misc.h>
#include <nnsys/fnd/unitheap.h>
#include <nnsys/fnd/config.h>
#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);
}

View File

@ -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