diff options
author | sceptillion <33798691+sceptillion@users.noreply.github.com> | 2017-12-18 00:47:25 -0800 |
---|---|---|
committer | sceptillion <33798691+sceptillion@users.noreply.github.com> | 2017-12-18 00:47:25 -0800 |
commit | d1437d30f7e6071f62d1a7842400d6732c7313b7 (patch) | |
tree | 35b574a2e7a07b4778c7a3a1343c8aead5e40cf2 | |
parent | 4265e3617426639577df510c6d659e6a9cd13b19 (diff) |
decompile malloc
-rw-r--r-- | asm/malloc.s | 423 | ||||
-rw-r--r-- | data/data.s | 21 | ||||
-rw-r--r-- | include/gba/isagbprint.h | 14 | ||||
-rw-r--r-- | ld_script.txt | 3 | ||||
-rw-r--r-- | src/malloc.c | 224 | ||||
-rw-r--r-- | sym_bss.txt | 7 | ||||
-rw-r--r-- | sym_ewram.txt | 9 |
7 files changed, 242 insertions, 459 deletions
diff --git a/asm/malloc.s b/asm/malloc.s deleted file mode 100644 index 03432dc2b..000000000 --- a/asm/malloc.s +++ /dev/null @@ -1,423 +0,0 @@ - .include "asm/macros.inc" - .include "constants/constants.inc" - - .syntax unified - - .text - - thumb_func_start PutMemBlockHeader -PutMemBlockHeader: @ 800292C - push {r4,lr} - movs r4, 0 - strh r4, [r0] - ldr r4, _08002944 @ =0x0000a3a3 - strh r4, [r0, 0x2] - str r3, [r0, 0x4] - str r1, [r0, 0x8] - str r2, [r0, 0xC] - pop {r4} - pop {r0} - bx r0 - .align 2, 0 -_08002944: .4byte 0x0000a3a3 - thumb_func_end PutMemBlockHeader - - thumb_func_start PutFirstMemBlockHeader -PutFirstMemBlockHeader: @ 8002948 - push {lr} - adds r2, r0, 0 - adds r3, r1, 0 - subs r3, 0x10 - adds r1, r2, 0 - bl PutMemBlockHeader - pop {r0} - bx r0 - thumb_func_end PutFirstMemBlockHeader - - thumb_func_start sub_800295C -sub_800295C: @ 800295C - push {r4-r7,lr} - adds r5, r1, 0 - ldr r2, _08002998 @ =gUnknown_2020004 - str r0, [r2] - ldr r1, _0800299C @ =gUnknown_2020008 - str r0, [r1] - movs r0, 0x3 - ands r0, r5 - cmp r0, 0 - beq _08002976 - lsrs r0, r5, 2 - adds r0, 0x1 - lsls r5, r0, 2 -_08002976: - adds r6, r1, 0 - ldr r7, _080029A0 @ =gUnknown_202000C -_0800297A: - ldr r4, [r6] - ldrh r0, [r4] - cmp r0, 0 - bne _080029DC - ldr r3, [r4, 0x4] - cmp r3, r5 - bcc _080029DC - subs r0, r3, r5 - cmp r0, 0x1F - bhi _080029A4 - movs r0, 0x1 - strh r0, [r4] - adds r0, r4, 0 - adds r0, 0x10 - b _080029F8 - .align 2, 0 -_08002998: .4byte gUnknown_2020004 -_0800299C: .4byte gUnknown_2020008 -_080029A0: .4byte gUnknown_202000C -_080029A4: - subs r3, 0x10 - subs r3, r5 - adds r0, r5, 0 - adds r0, 0x10 - adds r0, r4, r0 - str r0, [r7] - movs r1, 0x1 - strh r1, [r4] - str r5, [r4, 0x4] - ldr r2, [r4, 0xC] - adds r1, r4, 0 - bl PutMemBlockHeader - ldr r0, [r6] - ldr r1, [r7] - str r1, [r0, 0xC] - ldr r0, _080029D8 @ =gUnknown_2020004 - ldr r2, [r1, 0xC] - ldr r0, [r0] - cmp r2, r0 - beq _080029D0 - str r1, [r2, 0x8] -_080029D0: - ldr r0, [r6] - adds r0, 0x10 - b _080029F8 - .align 2, 0 -_080029D8: .4byte gUnknown_2020004 -_080029DC: - ldr r0, [r1] - ldr r3, [r0, 0xC] - ldr r0, [r2] - cmp r3, r0 - beq _080029EA - str r3, [r1] - b _0800297A -_080029EA: - ldr r0, _08002A00 @ =gUnknown_81E9F68 - movs r1, 0xAE - ldr r2, _08002A04 @ =gUnknown_81E9FA0 - movs r3, 0x1 - bl AGBAssert - movs r0, 0 -_080029F8: - pop {r4-r7} - pop {r1} - bx r1 - .align 2, 0 -_08002A00: .4byte gUnknown_81E9F68 -_08002A04: .4byte gUnknown_81E9FA0 - thumb_func_end sub_800295C - - thumb_func_start sub_8002A08 -sub_8002A08: @ 8002A08 - push {r4-r7,lr} - cmp r1, 0 - bne _08002A24 - ldr r0, _08002A1C @ =gUnknown_81E9F68 - ldr r2, _08002A20 @ =gUnknown_81E9FA4 - movs r1, 0xC3 - movs r3, 0x1 - bl AGBAssert - b _08002ACA - .align 2, 0 -_08002A1C: .4byte gUnknown_81E9F68 -_08002A20: .4byte gUnknown_81E9FA4 -_08002A24: - adds r6, r0, 0 - adds r4, r1, 0 - subs r4, 0x10 - ldrh r0, [r4, 0x2] - ldr r7, _08002AD0 @ =0x0000a3a3 - cmp r0, r7 - beq _08002A3E - ldr r0, _08002AD4 @ =gUnknown_81E9F68 - ldr r2, _08002AD8 @ =gUnknown_81E9FB0 - movs r1, 0xCC - movs r3, 0x1 - bl AGBAssert -_08002A3E: - ldrh r0, [r4] - cmp r0, 0x1 - beq _08002A50 - ldr r0, _08002AD4 @ =gUnknown_81E9F68 - ldr r2, _08002ADC @ =gUnknown_81E9FD8 - movs r1, 0xCD - movs r3, 0x1 - bl AGBAssert -_08002A50: - movs r0, 0 - strh r0, [r4] - ldr r0, [r4, 0xC] - cmp r0, r6 - beq _08002A8C - ldrh r5, [r0] - cmp r5, 0 - bne _08002A8C - ldrh r0, [r0, 0x2] - cmp r0, r7 - beq _08002A72 - ldr r0, _08002AD4 @ =gUnknown_81E9F68 - ldr r2, _08002AE0 @ =gUnknown_81E9FEC - movs r1, 0xD3 - movs r3, 0x1 - bl AGBAssert -_08002A72: - ldr r0, [r4, 0x4] - adds r0, 0x10 - ldr r2, [r4, 0xC] - ldr r1, [r2, 0x4] - adds r0, r1 - str r0, [r4, 0x4] - strh r5, [r2, 0x2] - ldr r0, [r4, 0xC] - ldr r0, [r0, 0xC] - str r0, [r4, 0xC] - cmp r0, r6 - beq _08002A8C - str r4, [r0, 0x8] -_08002A8C: - cmp r4, r6 - beq _08002ACA - ldr r0, [r4, 0x8] - ldrh r5, [r0] - cmp r5, 0 - bne _08002ACA - ldrh r1, [r0, 0x2] - ldr r0, _08002AD0 @ =0x0000a3a3 - cmp r1, r0 - beq _08002AAC - ldr r0, _08002AD4 @ =gUnknown_81E9F68 - ldr r2, _08002AE4 @ =gUnknown_81EA018 - movs r1, 0xE4 - movs r3, 0x1 - bl AGBAssert -_08002AAC: - ldr r1, [r4, 0x8] - ldr r0, [r4, 0xC] - str r0, [r1, 0xC] - ldr r1, [r4, 0xC] - cmp r1, r6 - beq _08002ABC - ldr r0, [r4, 0x8] - str r0, [r1, 0x8] -_08002ABC: - strh r5, [r4, 0x2] - ldr r0, [r4, 0x8] - ldr r1, [r0, 0x4] - adds r1, 0x10 - ldr r2, [r4, 0x4] - adds r1, r2 - str r1, [r0, 0x4] -_08002ACA: - pop {r4-r7} - pop {r0} - bx r0 - .align 2, 0 -_08002AD0: .4byte 0x0000a3a3 -_08002AD4: .4byte gUnknown_81E9F68 -_08002AD8: .4byte gUnknown_81E9FB0 -_08002ADC: .4byte gUnknown_81E9FD8 -_08002AE0: .4byte gUnknown_81E9FEC -_08002AE4: .4byte gUnknown_81EA018 - thumb_func_end sub_8002A08 - - thumb_func_start AllocZeroedInternal -AllocZeroedInternal: @ 8002AE8 - push {r4,r5,lr} - sub sp, 0x4 - adds r4, r1, 0 - bl sub_800295C - adds r5, r0, 0 - cmp r5, 0 - beq _08002B1C - movs r0, 0x3 - ands r0, r4 - cmp r0, 0 - beq _08002B06 - lsrs r0, r4, 2 - adds r0, 0x1 - lsls r4, r0, 2 -_08002B06: - movs r0, 0 - str r0, [sp] - lsls r2, r4, 9 - lsrs r2, 11 - movs r0, 0xA0 - lsls r0, 19 - orrs r2, r0 - mov r0, sp - adds r1, r5, 0 - bl CpuSet -_08002B1C: - adds r0, r5, 0 - add sp, 0x4 - pop {r4,r5} - pop {r1} - bx r1 - thumb_func_end AllocZeroedInternal - - thumb_func_start CheckMemBlockInternal -CheckMemBlockInternal: @ 8002B28 - push {r4,r5,lr} - adds r5, r0, 0 - adds r3, r1, 0 - subs r3, 0x10 - ldrh r2, [r3, 0x2] - ldr r0, _08002B74 @ =0x0000a3a3 - cmp r2, r0 - bne _08002B6E - ldr r0, [r3, 0xC] - ldrh r1, [r0, 0x2] - adds r4, r0, 0 - cmp r1, r2 - bne _08002B6E - cmp r4, r5 - beq _08002B4C - ldr r0, [r4, 0x8] - cmp r0, r3 - bne _08002B6E -_08002B4C: - ldr r2, [r3, 0x8] - ldrh r1, [r2, 0x2] - ldr r0, _08002B74 @ =0x0000a3a3 - cmp r1, r0 - bne _08002B6E - cmp r2, r5 - beq _08002B60 - ldr r0, [r2, 0xC] - cmp r0, r3 - bne _08002B6E -_08002B60: - cmp r4, r5 - beq _08002B78 - ldr r0, [r3, 0x4] - adds r0, 0x10 - adds r0, r3, r0 - cmp r4, r0 - beq _08002B78 -_08002B6E: - movs r0, 0 - b _08002B7A - .align 2, 0 -_08002B74: .4byte 0x0000a3a3 -_08002B78: - movs r0, 0x1 -_08002B7A: - pop {r4,r5} - pop {r1} - bx r1 - thumb_func_end CheckMemBlockInternal - - thumb_func_start InitHeap -InitHeap: @ 8002B80 - push {lr} - ldr r2, _08002B94 @ =gUnknown_3000A38 - str r0, [r2] - ldr r2, _08002B98 @ =gUnknown_3000A3C - str r1, [r2] - bl PutFirstMemBlockHeader - pop {r0} - bx r0 - .align 2, 0 -_08002B94: .4byte gUnknown_3000A38 -_08002B98: .4byte gUnknown_3000A3C - thumb_func_end InitHeap - - thumb_func_start Alloc -Alloc: @ 8002B9C - push {lr} - adds r1, r0, 0 - ldr r0, _08002BAC @ =gUnknown_3000A38 - ldr r0, [r0] - bl sub_800295C - pop {r1} - bx r1 - .align 2, 0 -_08002BAC: .4byte gUnknown_3000A38 - thumb_func_end Alloc - - thumb_func_start AllocZeroed -AllocZeroed: @ 8002BB0 - push {lr} - adds r1, r0, 0 - ldr r0, _08002BC0 @ =gUnknown_3000A38 - ldr r0, [r0] - bl AllocZeroedInternal - pop {r1} - bx r1 - .align 2, 0 -_08002BC0: .4byte gUnknown_3000A38 - thumb_func_end AllocZeroed - - thumb_func_start Free -Free: @ 8002BC4 - push {lr} - adds r1, r0, 0 - ldr r0, _08002BD4 @ =gUnknown_3000A38 - ldr r0, [r0] - bl sub_8002A08 - pop {r0} - bx r0 - .align 2, 0 -_08002BD4: .4byte gUnknown_3000A38 - thumb_func_end Free - - thumb_func_start CheckMemBlock -CheckMemBlock: @ 8002BD8 - push {lr} - adds r1, r0, 0 - ldr r0, _08002BE8 @ =gUnknown_3000A38 - ldr r0, [r0] - bl CheckMemBlockInternal - pop {r1} - bx r1 - .align 2, 0 -_08002BE8: .4byte gUnknown_3000A38 - thumb_func_end CheckMemBlock - - thumb_func_start CheckHeap -CheckHeap: @ 8002BEC - push {r4,r5,lr} - ldr r0, _08002C10 @ =gUnknown_3000A38 - ldr r4, [r0] - adds r5, r0, 0 -_08002BF4: - ldr r0, [r5] - adds r1, r4, 0 - adds r1, 0x10 - bl CheckMemBlockInternal - cmp r0, 0 - beq _08002C14 - ldr r4, [r4, 0xC] - ldr r0, [r5] - cmp r4, r0 - bne _08002BF4 - movs r0, 0x1 - b _08002C16 - .align 2, 0 -_08002C10: .4byte gUnknown_3000A38 -_08002C14: - movs r0, 0 -_08002C16: - pop {r4,r5} - pop {r1} - bx r1 - thumb_func_end CheckHeap - - .align 2, 0 @ Don't pad with nop. diff --git a/data/data.s b/data/data.s index bca0e3455..600fb2392 100644 --- a/data/data.s +++ b/data/data.s @@ -1,26 +1,5 @@ .section .rodata -gUnknown_81E9F68:: @ 81E9F68 - .incbin "baserom.gba", 0x1E9F68, 0x38 - -gUnknown_81E9FA0:: @ 81E9FA0 - .incbin "baserom.gba", 0x1E9FA0, 0x4 - -gUnknown_81E9FA4:: @ 81E9FA4 - .incbin "baserom.gba", 0x1E9FA4, 0xC - -gUnknown_81E9FB0:: @ 81E9FB0 - .incbin "baserom.gba", 0x1E9FB0, 0x28 - -gUnknown_81E9FD8:: @ 81E9FD8 - .incbin "baserom.gba", 0x1E9FD8, 0x14 - -gUnknown_81E9FEC:: @ 81E9FEC - .incbin "baserom.gba", 0x1E9FEC, 0x2C - -gUnknown_81EA018:: @ 81EA018 - .incbin "baserom.gba", 0x1EA018, 0x2C - gUnknown_81EA044:: @ 81EA044 .incbin "baserom.gba", 0x1EA044, 0x100 diff --git a/include/gba/isagbprint.h b/include/gba/isagbprint.h index ce547928c..c5eb456c3 100644 --- a/include/gba/isagbprint.h +++ b/include/gba/isagbprint.h @@ -33,4 +33,18 @@ void AGBAssert(const char *pFile, int nLine, const char *pExpression, int nStopP #define AGB_WARNING(exp) (exp) ? ((void*)0) : AGBAssert(__FILE__, __LINE__, #exp, 0); #endif +// for matching purposes + +#ifdef NDEBUG +#define AGB_ASSERT_EX(exp, file, line) +#else +#define AGB_ASSERT_EX(exp, file, line) (exp) ? ((void*)0) : AGBAssert(file, line, #exp, 1); +#endif + +#ifdef NDEBUG +#define AGB_WARNING_EX(exp, file, line) +#else +#define AGB_WARNING_EX(exp, file, line) (exp) ? ((void*)0) : AGBAssert(file, line, #exp, 0); +#endif + #endif // GUARD_GBA_ISAGBPRINT_H diff --git a/ld_script.txt b/ld_script.txt index 18af439bd..66f696f70 100644 --- a/ld_script.txt +++ b/ld_script.txt @@ -86,7 +86,7 @@ SECTIONS { src/gpu_regs.o(.text); src/dma3_manager.o(.text); src/bg.o(.text); - asm/malloc.o(.text); + src/malloc.o(.text); asm/text_printer.o(.text); asm/window.o(.text); asm/blit.o(.text); @@ -393,6 +393,7 @@ SECTIONS { { src/main.o(.rodata); src/bg.o(.rodata); + src/malloc.o(.rodata); data/data.o(.rodata); src/m4a_tables.o(.rodata); data/sound_data.o(.rodata); diff --git a/src/malloc.c b/src/malloc.c new file mode 100644 index 000000000..4768721ba --- /dev/null +++ b/src/malloc.c @@ -0,0 +1,224 @@ +#include "global.h" + +static void *sHeapStart; +static u32 sHeapSize; + +static EWRAM_DATA struct MemBlock *head = NULL; +static EWRAM_DATA struct MemBlock *pos = NULL; +static EWRAM_DATA struct MemBlock *splitBlock = NULL; + +#define MALLOC_SYSTEM_ID 0xA3A3 + +struct MemBlock { + // Whether this block is currently allocated. + bool16 flag; + + // Magic number used for error checking. Should equal MALLOC_SYSTEM_ID. + u16 magic_number; + + // Size of the block (not including this header struct). + u32 size; + + // Previous block pointer. Equals sHeapStart if this is the first block. + struct MemBlock *prev; + + // Next block pointer. Equals sHeapStart if this is the last block. + struct MemBlock *next; + + // Data in the memory block. (Arrays of length 0 are a GNU extension.) + u8 data[0]; +}; + +void PutMemBlockHeader(void *block, struct MemBlock *prev, struct MemBlock *next, u32 size) +{ + struct MemBlock *header = (struct MemBlock *)block; + + header->flag = FALSE; + header->magic_number = MALLOC_SYSTEM_ID; + header->size = size; + header->prev = prev; + header->next = next; +} + +void PutFirstMemBlockHeader(void *block, u32 size) +{ + PutMemBlockHeader(block, (struct MemBlock *)block, (struct MemBlock *)block, size - sizeof(struct MemBlock)); +} + +void *AllocInternal(void *heapStart, u32 size) +{ + u32 foundBlockSize; + + head = (struct MemBlock *)heapStart; + pos = head; + + // Alignment + if (size & 3) + size = 4 * ((size / 4) + 1); + + for (;;) { + // Loop through the blocks looking for unused block that's big enough. + + if (!pos->flag) { + foundBlockSize = pos->size; + + if (foundBlockSize >= size) { + if (foundBlockSize - size < 2 * sizeof(struct MemBlock)) { + // The block isn't much bigger than the requested size, + // so just use it. + pos->flag = TRUE; + return pos->data; + } else { + // The block is significantly bigger than the requested + // size, so split the rest into a separate block. + int splitBlockSize = foundBlockSize; + splitBlockSize -= sizeof(struct MemBlock); + splitBlockSize -= size; + + splitBlock = (struct MemBlock *)(pos->data + size); + + pos->flag = TRUE; + pos->size = size; + + PutMemBlockHeader(splitBlock, pos, pos->next, splitBlockSize); + + pos->next = splitBlock; + + if (splitBlock->next != head) + splitBlock->next->prev = splitBlock; + return pos->data; + } + } + } + + if (pos->next == head) + { + AGB_ASSERT_EX(0, "C:/WORK/POKeFRLG/src/pm_lgfr_ose/source/gflib/malloc.c", 174); + return NULL; + } + + pos = pos->next; + } +} + +void FreeInternal(void *heapStart, void *p) +{ + AGB_ASSERT_EX(p != NULL, "C:/WORK/POKeFRLG/src/pm_lgfr_ose/source/gflib/malloc.c", 195); + + if (p) { + struct MemBlock *head = (struct MemBlock *)heapStart; + struct MemBlock *pos = (struct MemBlock *)((u8 *)p - sizeof(struct MemBlock)); + AGB_ASSERT_EX(pos->magic_number == MALLOC_SYSTEM_ID, "C:/WORK/POKeFRLG/src/pm_lgfr_ose/source/gflib/malloc.c", 204); + AGB_ASSERT_EX(pos->flag == TRUE, "C:/WORK/POKeFRLG/src/pm_lgfr_ose/source/gflib/malloc.c", 205); + pos->flag = FALSE; + + // If the freed block isn't the last one, merge with the next block + // if it's not in use. + if (pos->next != head) { + if (!pos->next->flag) { + AGB_ASSERT_EX(pos->next->magic_number == MALLOC_SYSTEM_ID, "C:/WORK/POKeFRLG/src/pm_lgfr_ose/source/gflib/malloc.c", 211); + pos->size += sizeof(struct MemBlock) + pos->next->size; + pos->next->magic_number = 0; + pos->next = pos->next->next; + if (pos->next != head) + pos->next->prev = pos; + } + } + + // If the freed block isn't the first one, merge with the previous block + // if it's not in use. + if (pos != head) { + if (!pos->prev->flag) { + AGB_ASSERT_EX(pos->prev->magic_number == MALLOC_SYSTEM_ID, "C:/WORK/POKeFRLG/src/pm_lgfr_ose/source/gflib/malloc.c", 228); + + pos->prev->next = pos->next; + + if (pos->next != head) + pos->next->prev = pos->prev; + + pos->magic_number = 0; + pos->prev->size += sizeof(struct MemBlock) + pos->size; + } + } + } +} + +void *AllocZeroedInternal(void *heapStart, u32 size) +{ + void *mem = AllocInternal(heapStart, size); + + if (mem != NULL) { + if (size & 3) + size = 4 * ((size / 4) + 1); + + CpuFill32(0, mem, size); + } + + return mem; +} + +bool32 CheckMemBlockInternal(void *heapStart, void *pointer) +{ + struct MemBlock *head = (struct MemBlock *)heapStart; + struct MemBlock *block = (struct MemBlock *)((u8 *)pointer - sizeof(struct MemBlock)); + + if (block->magic_number != MALLOC_SYSTEM_ID) + return FALSE; + + if (block->next->magic_number != MALLOC_SYSTEM_ID) + return FALSE; + + if (block->next != head && block->next->prev != block) + return FALSE; + + if (block->prev->magic_number != MALLOC_SYSTEM_ID) + return FALSE; + + if (block->prev != head && block->prev->next != block) + return FALSE; + + if (block->next != head && block->next != (struct MemBlock *)(block->data + block->size)) + return FALSE; + + return TRUE; +} + +void InitHeap(void *heapStart, u32 heapSize) +{ + sHeapStart = heapStart; + sHeapSize = heapSize; + PutFirstMemBlockHeader(heapStart, heapSize); +} + +void *Alloc(u32 size) +{ + AllocInternal(sHeapStart, size); +} + +void *AllocZeroed(u32 size) +{ + AllocZeroedInternal(sHeapStart, size); +} + +void Free(void *pointer) +{ + FreeInternal(sHeapStart, pointer); +} + +bool32 CheckMemBlock(void *pointer) +{ + return CheckMemBlockInternal(sHeapStart, pointer); +} + +bool32 CheckHeap() +{ + struct MemBlock *pos = (struct MemBlock *)sHeapStart; + + do { + if (!CheckMemBlockInternal(sHeapStart, pos->data)) + return FALSE; + pos = pos->next; + } while (pos != (struct MemBlock *)sHeapStart); + + return TRUE; +} diff --git a/sym_bss.txt b/sym_bss.txt index 069cfff4d..25c9155da 100644 --- a/sym_bss.txt +++ b/sym_bss.txt @@ -7,14 +7,9 @@ .space 0x4 .include "src/bg.o" + .include "src/malloc.o" .align 2 -gUnknown_3000A38: @ 3000A38 - .space 0x4 - -gUnknown_3000A3C: @ 3000A3C - .space 0x4 - gUnknown_3000A40: @ 3000A40 .space 0xA2 diff --git a/sym_ewram.txt b/sym_ewram.txt index 3f109f231..8ca6b2afd 100644 --- a/sym_ewram.txt +++ b/sym_ewram.txt @@ -28,14 +28,7 @@ gUnknown_201FF00: @ 201FF00 gTrainerId: @ 2020000 .space 0x4 -gUnknown_2020004: @ 2020004 - .space 0x4 - -gUnknown_2020008: @ 2020008 - .space 0x4 - -gUnknown_202000C: @ 202000C - .space 0x4 + .include "src/malloc.o" gUnknown_2020010: @ 2020010 .space 0x24 |