diff --git a/asm/non_matching/common/zMalloc.inc b/asm/non_matching/common/zMalloc.inc deleted file mode 100644 index 742dd67cf..000000000 --- a/asm/non_matching/common/zMalloc.inc +++ /dev/null @@ -1,171 +0,0 @@ - .syntax unified - push {r4, r5, r6, r7, lr} - mov r7, sl - mov r6, sb - mov r5, r8 - push {r5, r6, r7} - mov ip, r0 - movs r0, #3 - add ip, r0 - subs r0, #7 - mov r1, ip - ands r1, r0 - mov ip, r1 - ldr r6, _0801D90C @ =gzHeap - mov sb, r6 - ldrh r7, [r6] - movs r5, #1 - movs r3, #0x80 - lsls r3, r3, #5 - add r3, sb - subs r4, r3, r1 - movs r2, #0 - b _0801D926 - .align 2, 0 -_0801D90C: .4byte gzHeap -_0801D910: - cmp r1, r4 - bhi _0801D918 - cmp r3, r0 - bls _0801D952 -_0801D918: - cmp r4, r1 - bhi _0801D920 - cmp r0, r3 - bls _0801D952 -_0801D920: - adds r0, r2, #1 - lsls r0, r0, #0x10 - lsrs r2, r0, #0x10 -_0801D926: - cmp r2, r7 - bhs _0801D94A - lsls r0, r2, #2 - add r0, sb - ldrh r1, [r0, #2] - ldr r6, _0801D95C @ =gzHeap - adds r1, r1, r6 - ldrh r0, [r0, #4] - adds r0, r0, r6 - cmp r1, r4 - bhi _0801D940 - cmp r4, r0 - bls _0801D952 -_0801D940: - cmp r1, r3 - bhi _0801D910 - cmp r3, r0 - bhi _0801D910 - movs r5, #0 -_0801D94A: - lsls r0, r7, #2 - mov sl, r0 - cmp r5, #0 - bne _0801D9D8 -_0801D952: - movs r1, #0 - mov r8, r1 - lsls r6, r7, #2 - mov sl, r6 - b _0801D970 - .align 2, 0 -_0801D95C: .4byte gzHeap -_0801D960: - movs r5, #0 -_0801D962: - mov r0, r8 - adds r0, #1 - lsls r0, r0, #0x10 - lsrs r0, r0, #0x10 - mov r8, r0 - cmp r8, r7 - bhs _0801D9D4 -_0801D970: - mov r1, r8 - lsls r0, r1, #2 - add r0, sb - ldrh r0, [r0, #2] - ldr r6, _0801D994 @ =gzHeap - adds r3, r0, r6 - mov r0, ip - subs r4, r3, r0 - movs r5, #0 - mov r0, sl - adds r0, #2 - add r0, sb - adds r0, #4 - cmp r4, r0 - blo _0801D962 - movs r5, #1 - movs r2, #0 - b _0801D9AE - .align 2, 0 -_0801D994: .4byte gzHeap -_0801D998: - cmp r1, r4 - bhi _0801D9A0 - cmp r3, r0 - bls _0801D960 -_0801D9A0: - cmp r4, r1 - bhi _0801D9A8 - cmp r0, r3 - bls _0801D960 -_0801D9A8: - adds r0, r2, #1 - lsls r0, r0, #0x10 - lsrs r2, r0, #0x10 -_0801D9AE: - cmp r2, r7 - bhs _0801D9D0 - lsls r0, r2, #2 - add r0, sb - ldrh r1, [r0, #2] - adds r1, r1, r6 - ldrh r0, [r0, #4] - adds r0, r0, r6 - cmp r1, r4 - bhi _0801D9C6 - cmp r4, r0 - blo _0801D960 -_0801D9C6: - cmp r1, r3 - bhs _0801D998 - cmp r3, r0 - bhi _0801D998 - movs r5, #0 -_0801D9D0: - cmp r5, #0 - beq _0801D962 -_0801D9D4: - cmp r5, #0 - beq _0801DA00 -_0801D9D8: - ldr r0, _0801D9FC @ =gUnk_02035542 - mov r1, sl - adds r2, r1, r0 - subs r3, r0, #2 - subs r1, r4, r3 - strh r1, [r2] - adds r0, #2 - add r0, sl - add r1, ip - strh r1, [r0] - adds r0, r7, #1 - strh r0, [r3] - adds r0, r4, #0 - mov r1, ip - bl MemClear - adds r0, r4, #0 - b _0801DA02 - .align 2, 0 -_0801D9FC: .4byte gUnk_02035542 -_0801DA00: - movs r0, #0 -_0801DA02: - pop {r3, r4, r5} - mov r8, r3 - mov sb, r4 - mov sl, r5 - pop {r4, r5, r6, r7, pc} - .syntax divided diff --git a/src/common.c b/src/common.c index 604615230..06cb3def3 100644 --- a/src/common.c +++ b/src/common.c @@ -25,6 +25,7 @@ typedef struct { extern u8 gUnk_03003DE0; extern u8 gzHeap[0x1000]; +extern u8 gUnk_02035542[]; extern u32 gUnk_0201AEE0[0x800]; extern s16 gUnk_02018EE0[]; @@ -348,7 +349,111 @@ void sub_0801D898(void* dest, void* src, u32 word, u32 size) { } while (--size); } -ASM_FUNC("asm/non_matching/common/zMalloc.inc", void* zMalloc(u32 size)); +void* zMalloc(u32 size) { + + FORCE_REGISTER(u32 slotFound, r5); + u16* heapStartOffset; + u8* allocatedEntryStartOffset; + u8* allocatedEntryEndOffset; + u8* candidateSlotEndOffset; + u8* candidateSlotStartOffset; + u16 index1, index2; + u16 numEntries; + // align to 4 + size = (size + 3) & ~3; + + heapStartOffset = (u16*)(gzHeap); + numEntries = heapStartOffset[0]; + slotFound = TRUE; + + // Check for a candidate slot at the tail-end of the heap buffer + candidateSlotEndOffset = (u8*)heapStartOffset + sizeof(gzHeap); + candidateSlotStartOffset = candidateSlotEndOffset - size; + for (index2 = 0; index2 < numEntries; index2++) { + + // Check if there is overlap with already allocated slots + allocatedEntryStartOffset = gzHeap + heapStartOffset[(index2 * 2) + 1]; + allocatedEntryEndOffset = gzHeap + heapStartOffset[(index2 * 2) + 2]; + + if ((allocatedEntryStartOffset <= candidateSlotStartOffset && + candidateSlotStartOffset <= allocatedEntryEndOffset)) { + goto other_search; + } + + if ((allocatedEntryStartOffset <= candidateSlotEndOffset && + candidateSlotEndOffset <= allocatedEntryEndOffset)) { + slotFound = FALSE; + break; + } + + if ((allocatedEntryStartOffset <= candidateSlotStartOffset && + candidateSlotEndOffset <= allocatedEntryEndOffset) || + (candidateSlotStartOffset <= allocatedEntryStartOffset && + allocatedEntryEndOffset <= candidateSlotEndOffset)) { + goto other_search; + } + } + + if (!slotFound) { + other_search: + + index1 = 0; + // Start searching for candidate slot from the left side of the heap buffer. + do { + + candidateSlotEndOffset = gzHeap + heapStartOffset[(index1 * 2) + 1]; + candidateSlotStartOffset = candidateSlotEndOffset - size; + slotFound = FALSE; + + // Ensure that the candidate slot doesn't collide with heap offsets section + if (candidateSlotStartOffset >= (u8*)(2 + (u32)heapStartOffset + (numEntries << 2) + 4)) { + slotFound = TRUE; + + // Check if there is overlap with already allocated slots + for (index2 = 0; index2 < numEntries; index2++) { + + allocatedEntryStartOffset = gzHeap + heapStartOffset[(index2 * 2) + 1]; + allocatedEntryEndOffset = gzHeap + heapStartOffset[(index2 * 2) + 2]; + + if ((allocatedEntryStartOffset <= candidateSlotStartOffset && + candidateSlotStartOffset < allocatedEntryEndOffset)) { + goto iter_end; + } + + if ((allocatedEntryStartOffset < candidateSlotEndOffset && + candidateSlotEndOffset <= allocatedEntryEndOffset)) { + slotFound = FALSE; + break; + } + + if ((allocatedEntryStartOffset <= candidateSlotStartOffset && + candidateSlotEndOffset <= allocatedEntryEndOffset) || + (candidateSlotStartOffset <= allocatedEntryStartOffset && + allocatedEntryEndOffset <= candidateSlotEndOffset)) { + goto iter_end; + } + } + if (slotFound) { + break; + } else { + continue; + } + + iter_end: + slotFound = FALSE; + } + } while ((index1 = (u16)(index1 + 1)) < numEntries); + } + if (!slotFound) + return 0; + + // Register successful allocation + *(u16*)(gUnk_02035542 + (numEntries << 2)) = candidateSlotStartOffset - (gUnk_02035542 - 2); + *(u16*)(gUnk_02035542 + (numEntries << 2) + 2) = candidateSlotStartOffset - (gUnk_02035542 - 2) + size; + *(u16*)(gUnk_02035542 - 2) = numEntries + 1; + MemClear(candidateSlotStartOffset, size); + return candidateSlotStartOffset; +} void zFree(void* ptr) { u32 uVar1;