diff --git a/config/GMPE01_00/splits.txt b/config/GMPE01_00/splits.txt index 7e961f99..d864a28b 100644 --- a/config/GMPE01_00/splits.txt +++ b/config/GMPE01_00/splits.txt @@ -13,6 +13,15 @@ Sections: .sdata2 type:rodata .sbss2 type:bss +game/malloc.c: + .text start:0x8000A558 end:0x8000A938 + .data start:0x80121F50 end:0x80121FC8 + .bss start:0x80145A80 end:0x80145A98 + +game/memory.c: + .text start:0x8000A938 end:0x8000AEF0 + .data start:0x80121FC8 end:0x80122140 + Runtime.PPCEABI.H/global_destructor_chain.c: .text start:0x800E2008 end:0x800E2068 .dtors start:0x8011DCE8 end:0x8011DCEC diff --git a/config/GMPE01_00/symbols.txt b/config/GMPE01_00/symbols.txt index 7aeba886..7b255f4e 100644 --- a/config/GMPE01_00/symbols.txt +++ b/config/GMPE01_00/symbols.txt @@ -101,29 +101,29 @@ fn_8000A1A4 = .text:0x8000A1A4; // type:function size:0x6C fn_8000A210 = .text:0x8000A210; // type:function size:0x254 fn_8000A464 = .text:0x8000A464; // type:function size:0x74 fn_8000A4D8 = .text:0x8000A4D8; // type:function size:0x80 -fn_8000A558 = .text:0x8000A558; // type:function size:0x12C -fn_8000A684 = .text:0x8000A684; // type:function size:0x30 -fn_8000A6B4 = .text:0x8000A6B4; // type:function size:0x2C -fn_8000A6E0 = .text:0x8000A6E0; // type:function size:0x54 -fn_8000A734 = .text:0x8000A734; // type:function size:0x64 -fn_8000A798 = .text:0x8000A798; // type:function size:0x6C -fn_8000A804 = .text:0x8000A804; // type:function size:0x38 -fn_8000A83C = .text:0x8000A83C; // type:function size:0x54 -fn_8000A890 = .text:0x8000A890; // type:function size:0x3C -fn_8000A8CC = .text:0x8000A8CC; // type:function size:0x3C -fn_8000A908 = .text:0x8000A908; // type:function size:0x18 -fn_8000A920 = .text:0x8000A920; // type:function size:0x18 -fn_8000A938 = .text:0x8000A938; // type:function size:0x4C -fn_8000A984 = .text:0x8000A984; // type:function size:0x40 -fn_8000A9C4 = .text:0x8000A9C4; // type:function size:0x3C -fn_8000AA00 = .text:0x8000AA00; // type:function size:0x108 -fn_8000AB08 = .text:0x8000AB08; // type:function size:0x7C -fn_8000AB84 = .text:0x8000AB84; // type:function size:0x12C -fn_8000ACB0 = .text:0x8000ACB0; // type:function size:0x48 -fn_8000ACF8 = .text:0x8000ACF8; // type:function size:0x44 -fn_8000AD3C = .text:0x8000AD3C; // type:function size:0xC -fn_8000AD48 = .text:0x8000AD48; // type:function size:0x158 -fn_8000AEA0 = .text:0x8000AEA0; // type:function size:0x50 +HuMemInitAll = .text:0x8000A558; // type:function size:0x12C +HuMemInit = .text:0x8000A684; // type:function size:0x30 +HuMemDCFlushAll = .text:0x8000A6B4; // type:function size:0x2C +HuMemDCFlush = .text:0x8000A6E0; // type:function size:0x54 +HuMemDirectMalloc = .text:0x8000A734; // type:function size:0x64 +HuMemDirectMallocNum = .text:0x8000A798; // type:function size:0x6C +HuMemDirectFree = .text:0x8000A804; // type:function size:0x38 +HuMemDirectFreeNum = .text:0x8000A83C; // type:function size:0x54 +HuMemUsedMallocSizeGet = .text:0x8000A890; // type:function size:0x3C +HuMemUsedMallocBlockGet = .text:0x8000A8CC; // type:function size:0x3C +HuMemHeapSizeGet = .text:0x8000A908; // type:function size:0x18 +HuMemHeapPtrGet = .text:0x8000A920; // type:function size:0x18 +HuMemHeapInit = .text:0x8000A938; // type:function size:0x4C +HuMemMemoryAllocNum = .text:0x8000A984; // type:function size:0x40 +HuMemMemoryAlloc = .text:0x8000A9C4; // type:function size:0x3C +HuMemMemoryAlloc2 = .text:0x8000AA00; // type:function size:0x108 scope:local +HuMemMemoryFreeNum = .text:0x8000AB08; // type:function size:0x7C +HuMemMemoryFree = .text:0x8000AB84; // type:function size:0x12C +HuMemUsedMemorySizeGet = .text:0x8000ACB0; // type:function size:0x48 +HuMemUsedMemoryBlockGet = .text:0x8000ACF8; // type:function size:0x44 +HuMemMemoryAllocSizeGet = .text:0x8000AD3C; // type:function size:0xC +HuMemHeapDump = .text:0x8000AD48; // type:function size:0x158 +HuMemMemorySizeGet = .text:0x8000AEA0; // type:function size:0x50 fn_8000AEF0 = .text:0x8000AEF0; // type:function size:0x64 fn_8000AF54 = .text:0x8000AF54; // type:function size:0xA0 fn_8000AFF4 = .text:0x8000AFF4; // type:function size:0x15C @@ -2053,13 +2053,13 @@ OSCancelAlarm = .text:0x800B5008; // type:function size:0x11C DecrementerExceptionCallback = .text:0x800B5124; // type:function size:0x230 scope:local DecrementerExceptionHandler = .text:0x800B5354; // type:function size:0x50 scope:local fn_800B53A4 = .text:0x800B53A4; // type:function size:0xAC -fn_800B5450 = .text:0x800B5450; // type:function size:0xFC +OSAllocFromHeap = .text:0x800B5450; // type:function size:0xFC fn_800B554C = .text:0x800B554C; // type:function size:0x284 fn_800B57D0 = .text:0x800B57D0; // type:function size:0x7C OSSetCurrentHeap = .text:0x800B584C; // type:function size:0x10 OSInitAlloc = .text:0x800B585C; // type:function size:0x70 OSCreateHeap = .text:0x800B58CC; // type:function size:0x6C -fn_800B5938 = .text:0x800B5938; // type:function size:0x360 +OSCheckHeap = .text:0x800B5938; // type:function size:0x360 fn_800B5C98 = .text:0x800B5C98; // type:function size:0x104 OSGetArenaHi = .text:0x800B5D9C; // type:function size:0x8 scope:global OSGetArenaLo = .text:0x800B5DA4; // type:function size:0x8 scope:global @@ -4840,10 +4840,10 @@ lbl_8011FCBE = .data:0x8011FCBE; // type:object size:0x122 lbl_8011FDE0 = .data:0x8011FDE0; // type:object size:0x20 lbl_8011FE00 = .data:0x8011FE00; // type:object size:0x2000 lbl_80121E00 = .data:0x80121E00; // type:object size:0x150 -lbl_80121F50 = .data:0x80121F50; // type:object size:0x78 +HeapSizeTbl = .data:0x80121F50; // type:object size:0x78 scope:local lbl_80121FC8 = .data:0x80121FC8; // type:object size:0x50 lbl_80122018 = .data:0x80122018; // type:object size:0x128 -fcoltbl = .data:0x80122140; // type:object size:0x40 +fcoltbl = .data:0x80122140; // type:object size:0x40 align:32 lbl_80122180 = .data:0x80122180; // type:object size:0x1F data:string lbl_8012219F = .data:0x8012219F; // type:object size:0x31 lbl_801221D0 = .data:0x801221D0; // type:object size:0x12 @@ -5356,7 +5356,7 @@ RumbleData = .bss:0x80142810; // type:object size:0x30 ReadDataStat = .bss:0x80142840; // type:object size:0x2E00 data:4byte TextBuffer = .bss:0x80145640; // type:object size:0x400 lbl_80145A40 = .bss:0x80145A40; // type:object size:0x40 -lbl_80145A80 = .bss:0x80145A80; // type:object size:0x18 +HeapTbl = .bss:0x80145A80; // type:object size:0x14 scope:local lbl_80145A98 = .bss:0x80145A98; // type:object size:0x6800 lbl_8014C298 = .bss:0x8014C298; // type:object size:0x100 data:byte lbl_8014C398 = .bss:0x8014C398; // type:object size:0xF8 @@ -5840,7 +5840,7 @@ lbl_801D38B0 = .sdata:0x801D38B0; // type:object size:0x2 data:2byte lbl_801D38B2 = .sdata:0x801D38B2; // type:object size:0x2 data:2byte lbl_801D38B4 = .sdata:0x801D38B4; // type:object size:0x2 data:2byte lbl_801D38B6 = .sdata:0x801D38B6; // type:object size:0x2 data:2byte -lbl_801D38B8 = .sdata:0x801D38B8; // type:object size:0x8 data:4byte +__OSCurrHeap = .sdata:0x801D38B8; // type:object size:0x8 data:4byte __OSArenaLo = .sdata:0x801D38C0; // type:object size:0x4 scope:local data:4byte @32 = .sdata:0x801D38C8; // type:object size:0x2 scope:local data:string lbl_801D38D0 = .sdata:0x801D38D0; // type:object size:0x8 data:2byte @@ -5952,7 +5952,7 @@ lbl_801D3B0C = .sbss:0x801D3B0C; // type:object size:0x4 data:4byte lbl_801D3B10 = .sbss:0x801D3B10; // type:object size:0x4 data:4byte lbl_801D3B14 = .sbss:0x801D3B14; // type:object size:0x4 data:4byte lbl_801D3B18 = .sbss:0x801D3B18; // type:object size:0x4 data:4byte -lbl_801D3B1C = .sbss:0x801D3B1C; // type:object size:0x4 data:4byte +currentHeapHandle = .sbss:0x801D3B1C; // type:object size:0x4 data:4byte lbl_801D3B20 = .sbss:0x801D3B20; // type:object size:0x8 data:4byte lbl_801D3B28 = .sbss:0x801D3B28; // type:object size:0x4 data:4byte lbl_801D3B2C = .sbss:0x801D3B2C; // type:object size:0x2 data:2byte diff --git a/configure.py b/configure.py index 74dfe46a..c86dab57 100755 --- a/configure.py +++ b/configure.py @@ -177,6 +177,12 @@ cflags_rel = [ "-sdata2 0", ] +# Game flags +cflags_game = [ + *cflags_base, + "-O0,p", +] + config.linker_version = "GC/2.6" config.rel_strip_partial = False config.rel_empty_file = "REL/empty.c" @@ -210,6 +216,16 @@ NonMatching = False config.warn_missing_config = True config.warn_missing_source = False config.libs = [ + { + "lib": "Game", + "mw_version": config.linker_version, + "cflags": cflags_game, + "host": False, + "objects": [ + Object(Matching, "game/malloc.c"), + Object(Matching, "game/memory.c"), + ], + }, { "lib": "Runtime.PPCEABI.H", "mw_version": config.linker_version, diff --git a/include/functions.h b/include/functions.h index 6d8168d0..29afc607 100644 --- a/include/functions.h +++ b/include/functions.h @@ -5,6 +5,9 @@ #include "common_structs.h" void OSReport(const char * format, ...); +void* OSAllocFromHeap(int heap, u32 size); +s32 OSCheckHeap(int heap); +void DCFlushRangeNoSync(void *addr, u32 size); void* HuPrcCreate(void (*), s32, s32, s32); void Hu3DBGColorSet(u8, u8, u8); void Hu3DCameraCreate(s16); @@ -18,4 +21,30 @@ void fn_80045F74(s16, s32); s32 fn_800578E4(void); void fn_1_26C(void); + +void HuMemInitAll(void); +void *HuMemInit(void *ptr, s32 size); +void HuMemDCFlushAll(); +void HuMemDCFlush(int heap); +void *HuMemDirectMalloc(int heap, s32 size); +void *HuMemDirectMallocNum(int heap, s32 size, u32 num); +void HuMemDirectFree(void *ptr); +void HuMemDirectFreeNum(int heap, u32 num); +s32 HuMemUsedMallocSizeGet(int heap); +s32 HuMemUsedMallocBlockGet(int heap); +u32 HuMemHeapSizeGet(int heap); +void *HuMemHeapPtrGet(int heap); + +void *HuMemHeapInit(void *ptr, s32 size); +void *HuMemMemoryAlloc(void *heap_ptr, s32 size, u32 retaddr); +void *HuMemMemoryAllocNum(void *heap_ptr, s32 size, u32 num, u32 retaddr); +void HuMemMemoryFree(void *ptr, u32 retaddr); +void HuMemMemoryFreeNum(void *heap_ptr, u32 num, u32 retaddr); +s32 HuMemUsedMemorySizeGet(void *heap_ptr); +s32 HuMemUsedMemoryBlockGet(void *heap_ptr); +s32 HuMemMemoryAllocSizeGet(s32 size); +void HuMemHeapDump(void *heap_ptr, s16 status); + + + #endif \ No newline at end of file diff --git a/include/types.h b/include/types.h index 71c28167..388ebfcc 100644 --- a/include/types.h +++ b/include/types.h @@ -1,6 +1,7 @@ #ifndef _TYPES_H_ #define _TYPES_H_ +#define NULL ((void *)0) typedef unsigned char u8; typedef unsigned short u16; typedef unsigned long u32; diff --git a/src/game/malloc.c b/src/game/malloc.c new file mode 100644 index 00000000..08910376 --- /dev/null +++ b/src/game/malloc.c @@ -0,0 +1,105 @@ +#include "common.h" + +extern int __OSCurrHeap; +extern int currentHeapHandle; + +static u32 HeapSizeTbl[5] = { 0x240000, 0x140000, 0xA80000, 0x580000, 0 }; +static void *HeapTbl[5]; + +void HuMemInitAll(void) +{ + int i; + void *ptr; + u32 free_size; + for(i=0; i<4; i++) { + ptr = OSAllocFromHeap(__OSCurrHeap, HeapSizeTbl[i]); + if(ptr == NULL) { + OSReport("HuMem> Failed OSAlloc Size:%d\n", HeapSizeTbl[i]); + return; + } + HeapTbl[i] = HuMemInit(ptr, HeapSizeTbl[i]); + } + free_size = OSCheckHeap(currentHeapHandle); + OSReport("HuMem> left memory space %dKB(%d)\n", free_size/1024, free_size); + ptr = OSAllocFromHeap(__OSCurrHeap, free_size); + if(ptr == NULL) { + OSReport("HuMem> Failed OSAlloc left space\n"); + return; + } + HeapTbl[4] = HuMemInit(ptr, free_size); + HeapSizeTbl[4] = free_size; +} + +void *HuMemInit(void *ptr, s32 size) +{ + return HuMemHeapInit(ptr, size); +} + +void HuMemDCFlushAll() +{ + HuMemDCFlush(2); + HuMemDCFlush(0); +} + +void HuMemDCFlush(int heap) +{ + DCFlushRangeNoSync(HeapTbl[heap], HeapSizeTbl[heap]); +} + +void *HuMemDirectMalloc(int heap, s32 size) +{ + register u32 retaddr; + asm { + mflr retaddr + } + size = (size+31) & 0xFFFFFFE0; + return HuMemMemoryAlloc(HeapTbl[heap], size, retaddr); +} + +void *HuMemDirectMallocNum(int heap, s32 size, u32 num) +{ + register u32 retaddr; + asm { + mflr retaddr + } + size = (size+31) & 0xFFFFFFE0; + return HuMemMemoryAllocNum(HeapTbl[heap], size, num, retaddr); +} + +void HuMemDirectFree(void *ptr) +{ + register u32 retaddr; + asm { + mflr retaddr + } + HuMemMemoryFree(ptr, retaddr); +} + +void HuMemDirectFreeNum(int heap, u32 num) +{ + register u32 retaddr; + asm { + mflr retaddr + } + HuMemMemoryFreeNum(HeapTbl[heap], num, retaddr); +} + +s32 HuMemUsedMallocSizeGet(int heap) +{ + return HuMemUsedMemorySizeGet(HeapTbl[heap]); +} + +s32 HuMemUsedMallocBlockGet(int heap) +{ + return HuMemUsedMemoryBlockGet(HeapTbl[heap]); +} + +u32 HuMemHeapSizeGet(int heap) +{ + return HeapSizeTbl[heap]; +} + +void *HuMemHeapPtrGet(int heap) +{ + return HeapTbl[heap]; +} \ No newline at end of file diff --git a/src/game/memory.c b/src/game/memory.c new file mode 100644 index 00000000..990c70db --- /dev/null +++ b/src/game/memory.c @@ -0,0 +1,202 @@ +#include "common.h" + +#define DATA_GET_BLOCK(ptr) ((struct memory_block *)(((char *)(ptr))-32)) +#define BLOCK_GET_DATA(block) (((char *)(block))+32) + +#define MEM_ALLOC_SIZE(size) (((size)+63) & 0xFFFFFFE0) + +struct memory_block { + s32 size; + u8 magic; + u8 flag; + struct memory_block *prev; + struct memory_block *next; + u32 num; + u32 retaddr; +}; + +static void *HuMemMemoryAlloc2(void *heap_ptr, s32 size, u32 num, u32 retaddr); + +void *HuMemHeapInit(void *ptr, s32 size) +{ + struct memory_block *block = ptr; + block->size = size; + block->magic = 205; + block->flag = 0; + block->prev = block; + block->next = block; + block->num = -256; + block->retaddr = 0xCDCDCDCD; + return block; +} + +void *HuMemMemoryAllocNum(void *heap_ptr, s32 size, u32 num, u32 retaddr) +{ + return HuMemMemoryAlloc2(heap_ptr, size, num, retaddr); +} + +void *HuMemMemoryAlloc(void *heap_ptr, s32 size, u32 retaddr) +{ + return HuMemMemoryAlloc2(heap_ptr, size, -256, retaddr); +} + +static void *HuMemMemoryAlloc2(void *heap_ptr, s32 size, u32 num, u32 retaddr) +{ + s32 alloc_size = MEM_ALLOC_SIZE(size); + struct memory_block *block = heap_ptr; + do { + if(!block->flag && block->size >= alloc_size) { + if(block->size-alloc_size > 32u) { + struct memory_block *new_block = (struct memory_block *)(((u32)block)+alloc_size); + new_block->size = block->size-alloc_size; + new_block->magic = 205; + new_block->flag = 0; + new_block->retaddr = retaddr; + block->next->prev = new_block; + new_block->next = block->next; + block->next = new_block; + new_block->prev = block; + block->size = alloc_size; + } + block->flag = 1; + block->magic = 165; + block->num = num; + block->retaddr = retaddr; + return BLOCK_GET_DATA(block); + } + block = block->next; + } while(block != heap_ptr); + OSReport("HuMem>memory alloc error %08x(%08X): Call %08x\n", size, num, retaddr); + HuMemHeapDump(heap_ptr, -1); + return NULL; +} + +void HuMemMemoryFreeNum(void *heap_ptr, u32 num, u32 retaddr) +{ + struct memory_block *block = heap_ptr; + do { + struct memory_block *block_next = block->next; + if(block->flag && block->num == num) { + HuMemMemoryFree(BLOCK_GET_DATA(block), retaddr); + } + block = block_next; + } while(block != heap_ptr); + +} + +static void HuMemTailMemoryAlloc2() //Required for string literal +{ + OSReport("memory allocation(tail) error.\n"); +} + +void HuMemMemoryFree(void *ptr, u32 retaddr) +{ + struct memory_block *block; + if(!ptr) { + return; + } + block = DATA_GET_BLOCK(ptr); + if(block->magic != 165) { + OSReport("HuMem>memory free error. %08x( call %08x)\n", ptr, retaddr); + return; + } + if(block->prev < block && !block->prev->flag) { + block->flag = 0; + block->magic = 205; + block->next->prev = block->prev; + block->prev->next = block->next; + block->prev->size += block->size; + block = block->prev; + } + if(block->next > block && !block->next->flag) { + block->next->next->prev = block; + block->size += block->next->size; + block->next = block->next->next; + } + block->flag = 0; + block->magic = 205; + block->retaddr = retaddr; +} + +s32 HuMemUsedMemorySizeGet(void *heap_ptr) +{ + struct memory_block *block = heap_ptr; + s32 size = 0; + do { + if(block->flag == 1) { + size += block->size; + } + block = block->next; + } while(block != heap_ptr); + return size; +} + +s32 HuMemUsedMemoryBlockGet(void *heap_ptr) +{ + struct memory_block *block = heap_ptr; + s32 num_blocks = 0; + do { + if(block->flag == 1) { + num_blocks++; + } + block = block->next; + } while(block != heap_ptr); + return num_blocks; +} + +s32 HuMemMemoryAllocSizeGet(s32 size) +{ + return MEM_ALLOC_SIZE(size); +} + +void HuMemHeapDump(void *heap_ptr, s16 status) +{ + struct memory_block *block = heap_ptr; + s32 size = 0; + s32 inactive_size = 0; + s32 num_blocks = 0; + s32 num_unused_blocks = 0; + u8 dump_type; + + if(status < 0) { + dump_type = 10; + } else if(status == 0) { + dump_type = 0; + } else { + dump_type = 1; + } + OSReport("======== HuMem heap dump %08x ========\n", heap_ptr); + OSReport("MCB-----+Size----+MG+FL+Prev----+Next----+UNum----+Body----+Call----\n"); + do { + if(dump_type == 10 || block->flag == dump_type) { + OSReport("%08x %08x %02x %02x %08x %08x %08x %08x %08x\n", block, block->size, block->magic, block->flag, + block->prev, block->next, block->num, BLOCK_GET_DATA(block), block->retaddr); + } + if(block->flag == 1) { + size += block->size; + num_blocks++; + } else { + inactive_size += block->size; + num_unused_blocks++; + } + + block = block->next; + } while(block != heap_ptr); + OSReport("MCB:%d(%d/%d) MEM:%08x(%08x/%08x)\n", num_blocks+num_unused_blocks, num_blocks, num_unused_blocks, + size+inactive_size, size, inactive_size); + OSReport("======== HuMem heap dump %08x end =====\n", heap_ptr); +} + +s32 HuMemMemorySizeGet(void *ptr) +{ + struct memory_block *block; + if(!ptr) { + return 0; + } + block = DATA_GET_BLOCK(ptr); + if(block->flag == 1 && block->magic == 165) { + return block->size-32; + } else { + return 0; + } +}