From 08cfada6bdf8603253f81aedb0c38bb03f51f2b3 Mon Sep 17 00:00:00 2001 From: RevoSucks Date: Sat, 26 Aug 2023 18:44:11 -0400 Subject: [PATCH] document and rename intro_loader to memory --- include/functions.h | 9 +- include/ultra64.h | 2 +- splat.yaml | 2 +- src/3A80.c | 84 +++---- src/E1C0.c | 19 +- {include => src}/controller.h | 0 src/crash_screen.c | 19 +- {include => src}/crash_screen.h | 0 {include => src}/dma.h | 0 src/hal_libc.c | 7 +- {include => src}/hal_libc.h | 2 +- src/intro_loader.c | 319 --------------------------- src/intro_loader.h | 51 ----- {include => src}/memmap.h | 0 src/memory.c | 373 ++++++++++++++++++++++++++++++++ src/memory.h | 52 +++++ {include => src}/rsp.h | 0 tools/symbol_addrs.txt | 21 +- 18 files changed, 519 insertions(+), 441 deletions(-) rename {include => src}/controller.h (100%) rename {include => src}/crash_screen.h (100%) rename {include => src}/dma.h (100%) rename {include => src}/hal_libc.h (79%) delete mode 100644 src/intro_loader.c delete mode 100644 src/intro_loader.h rename {include => src}/memmap.h (100%) create mode 100644 src/memory.c create mode 100644 src/memory.h rename {include => src}/rsp.h (100%) diff --git a/include/functions.h b/include/functions.h index c77f4f1..fae8153 100644 --- a/include/functions.h +++ b/include/functions.h @@ -1,5 +1,5 @@ -#ifndef _FUNCTIONS_H -#define _FUNCTIONS_H +#ifndef _FUNCTIONS_H_ +#define _FUNCTIONS_H_ #include "ultra64.h" @@ -12,10 +12,11 @@ extern void _bcopy(void *, void *, u32); // 3640.s extern void* func_80002AF8(s32, void*); -// 3A80.s +// 3A80.c +extern uintptr_t convert_addr_to_virt_addr(uintptr_t addr); extern void func_80002F58(void); extern void *func_80002FDC(s32); -extern void func_80003004(void *); // type unknown +extern void func_80003004(void *); // 3FB0.s extern void func_80003B30(void *, s32, s32, s32); // types unknown diff --git a/include/ultra64.h b/include/ultra64.h index bd4f939..d309e52 100644 --- a/include/ultra64.h +++ b/include/ultra64.h @@ -40,8 +40,8 @@ #include "ultra64/thread.h" -#include "functions.h" #include "macros.h" +#include "functions.h" #include "variables.h" #endif diff --git a/splat.yaml b/splat.yaml index 08c95d5..0eb07e9 100644 --- a/splat.yaml +++ b/splat.yaml @@ -36,7 +36,7 @@ segments: - [0x1F70, bin, noppad_1F70] # Extra nop align like earlier. Weird - [0x1F80, c, dp_intro] # dp intro code - [0x28E0, c, memmap] - - [0x2EC0, c, intro_loader] # intro loader + - [0x2EC0, c, memory] - [0x3640, asm] # - [0x3A80, c] - [0x3FB0, asm] # PRES-JPEG decoder diff --git a/src/3A80.c b/src/3A80.c index c484fcf..7c77042 100644 --- a/src/3A80.c +++ b/src/3A80.c @@ -1,6 +1,6 @@ #include #include "memmap.h" -#include "intro_loader.h" +#include "memory.h" extern s32 D_80068B90; extern u8 D_80104BB0[]; @@ -11,23 +11,33 @@ s32 func_80002A40(s32, s32); void func_80002BD0(s32, void *); // type unknown s32 func_80007A58(void); -uintptr_t func_80002E80(uintptr_t addr) { - uintptr_t retaddr = 0x00000000; +/* + * Convert any valid address to its virtual (KSEG0) counterpart. + */ +uintptr_t convert_addr_to_virt_addr(uintptr_t addr) { + uintptr_t retaddr = 0x00000000; // any invalid cases are treated as NULL return. + // convert physical (in installed memory range) to virtual. if (addr < (size_t) osMemSize) { retaddr = addr | 0x80000000; + // convert segmented to virtual. } else if (addr < 0x10000000U) { retaddr = Memmap_GetSegmentVaddr(addr); + // convert a fragment pre-relocated address to a post-relocated virtual address. } else if ((addr >= 0x81000000U) && (addr < 0x90000000U)) { // is the address in fragment space? convert it to its post-relocated address. retaddr = Memmap_GetFragmentVaddr(addr); + // pass-through addresses that are already virtual (in installed memory range) } else if ((addr >= 0x80000000U) && (addr < (uintptr_t) (osMemSize + 0x80000000U))) { retaddr = addr; } + return retaddr; } -// HAL memcpy? -void func_80002F28(u32* dest, u32* src, int size) { +/* + * Copy memory from one address to the other. (why is this function not in HAL_libc?) + */ +void HAL_Memcpy(u32* dest, u32* src, int size) { while (size --> 0) { *(dest++) = *(src++); } @@ -36,9 +46,9 @@ void func_80002F28(u32* dest, u32* src, int size) { void func_80002F58(void) { // wat? mem sizes are only ever 0x400000 or 0x800000. This check makes no sense. if ((D_80068B90 != 0) && ((u32) osMemSize > 0x600000U)) { - func_800022C0(&D_80104BB0, 0x80600000); + main_pool_init(&D_80104BB0, 0x80600000); } else { - func_800022C0(&D_80104BB0, 0x80400000); + main_pool_init(&D_80104BB0, 0x80400000); D_80068B90 = 0; } func_80003860(); @@ -53,8 +63,7 @@ void func_80003004(void *arg0) { func_80002BD0(D_800A60B0, arg0); } -// HAL_DrawRect -void func_8000302C(Gfx** dlist, s32 ulx, s32 lrx, u16 color) { +void HAL_DrawRect(Gfx** dlist, s32 ulx, s32 lrx, u16 color) { s32 uly = 0xF; s32 lry = 0x11; Gfx *gfx = *dlist; @@ -72,48 +81,49 @@ void func_8000302C(Gfx** dlist, s32 ulx, s32 lrx, u16 color) { *dlist = gfx; } -void func_8000310C(Gfx** dlist) -{ - struct Unk800A6070 * sp54 = func_80002A30(); - s32 temp_s1 = func_80002764() - D_80068B90; +void func_8000310C(Gfx** dlist) { + struct MainPool *pool = main_pool_get_pool(); + s32 temp_s1 = main_pool_get_available() - D_80068B90; if (temp_s1 >= 0) { - u32 coord = 0x1E; - s32 sp48 = ((u32) ( K0_TO_PHYS(sp54->unk20)) >> 0xF) + coord; - s32 sp44 = ((u32) ( K0_TO_PHYS(sp54->unk28)) >> 0xF) + coord; - s32 sp40 = ((u32) ( K0_TO_PHYS(sp54->unk2C) - D_80068B90) >> 0xF) + coord; - s32 sp3C = ((u32) ( K0_TO_PHYS(sp54->unk24) - D_80068B90) >> 0xF) + coord; + s32 base = 30; + s32 sp48 = ((u32) ( K0_TO_PHYS(pool->start)) >> 15) + base; + s32 sp44 = ((u32) ( K0_TO_PHYS(pool->listHeadL)) >> 15) + base; + s32 sp40 = ((u32) ( K0_TO_PHYS(pool->listHeadR) - D_80068B90) >> 15) + base; + s32 sp3C = ((u32) ( K0_TO_PHYS(pool->end) - D_80068B90) >> 15) + base; - func_8000302C(dlist, coord, sp48, 0xFBCB); - func_8000302C(dlist, sp48, sp44, 0xFFCB); - func_8000302C(dlist, sp44, sp40, 0x2ABF); - func_8000302C(dlist, sp40, sp3C, 0xFFCB); - HAL_Printf(coord, 0x14, "MEM: +%XH (+%dK)", temp_s1, temp_s1 / 1024); + HAL_DrawRect(dlist, base, sp48, 0xFBCB); + HAL_DrawRect(dlist, sp48, sp44, 0xFFCB); + HAL_DrawRect(dlist, sp44, sp40, 0x2ABF); + HAL_DrawRect(dlist, sp40, sp3C, 0xFFCB); + HAL_Printf(base, 0x14, "MEM: +%XH (+%dK)", temp_s1, temp_s1 / 1024); } else { - u32 coord = 0x1E; - s32 sp34 = ((u32) ( K0_TO_PHYS(sp54->unk20)) >> 0xF) + coord; - s32 sp30 = ((u32) ( K0_TO_PHYS(sp54->unk28)) >> 0xF) + coord; - s32 sp2C = ((u32) ( K0_TO_PHYS(sp54->unk2C) - D_80068B90) >> 0xF) + coord; - s32 sp28 = ((u32) ( K0_TO_PHYS(sp54->unk24) - D_80068B90) >> 0xF) + coord; - func_8000302C(dlist, coord, sp34, 0xFBCB); - func_8000302C(dlist, sp34, sp2C, 0xFFCB); - func_8000302C(dlist, sp2C, sp30, 0xF94B); - func_8000302C(dlist, sp30, sp28, 0xFFCB); - HAL_Printf(coord, 0x14, "MEM: -%XH (-%dK)", -temp_s1, -temp_s1 / 1024); + s32 base = 30; + s32 sp34 = ((u32) ( K0_TO_PHYS(pool->start)) >> 15) + base; + s32 sp30 = ((u32) ( K0_TO_PHYS(pool->listHeadL)) >> 15) + base; + s32 sp2C = ((u32) ( K0_TO_PHYS(pool->listHeadR) - D_80068B90) >> 15) + base; + s32 sp28 = ((u32) ( K0_TO_PHYS(pool->end) - D_80068B90) >> 15) + base; + HAL_DrawRect(dlist, base, sp34, 0xFBCB); + HAL_DrawRect(dlist, sp34, sp2C, 0xFFCB); + HAL_DrawRect(dlist, sp2C, sp30, 0xF94B); + HAL_DrawRect(dlist, sp30, sp28, 0xFFCB); + HAL_Printf(base, 0x14, "MEM: -%XH (-%dK)", -temp_s1, -temp_s1 / 1024); } } -void func_8000330C(u64 * dest, u32 arg1) { - while( arg1 --> 0 ) { +/* + * Clear memory address area. + */ +void HAL_Memclear(u64* dest, u32 size) { + while( size --> 0 ) { *(dest++) = -1; } } -s32 func_80003348(u64* arg0) -{ +s32 func_80003348(u64* arg0) { s32 ret = 0; while (*(arg0++) == 0x8040000080400000) diff --git a/src/E1C0.c b/src/E1C0.c index 2540e31..c943004 100644 --- a/src/E1C0.c +++ b/src/E1C0.c @@ -2,7 +2,7 @@ #include #include "dp_intro.h" #include "fragments.h" -#include "intro_loader.h" +#include "memory.h" #include "dp_intro.h" struct UnkInputStruct8000D738 { @@ -40,9 +40,6 @@ void func_81206D9C(void); void func_81206E64(void); void func_81206F38(void); -// from 3A80.c -extern uintptr_t func_80002E80(uintptr_t addr); - void func_80005370(struct UnkStruct800AA660 *); void func_80004454(u32, void *, void *); char func_8000B318(char); @@ -50,7 +47,7 @@ s32 func_800044F4(void *, void *, s32, s32); s32 func_8000484C(s32, s32); void func_8000D5C0(void* unused) { - void (*func)(void *) = func_80002E80(&func_81206F38); + void (*func)(void *) = convert_addr_to_virt_addr(&func_81206F38); __osSetFpcCsr(0x01000C01); func_80004CC0(D_800AA664, 0, 1); @@ -66,8 +63,8 @@ void func_8000D5C0(void* unused) { } void func_8000D678(void *unused) { - void (*func1)(void *func) = func_80002E80(&func_81206D9C); - void (*func2)(void *func) = func_80002E80(&func_81206E64); + void (*func1)(void *func) = convert_addr_to_virt_addr(&func_81206D9C); + void (*func2)(void *func) = convert_addr_to_virt_addr(&func_81206E64); __osSetFpcCsr(0x01000C01); func_80004CC0(D_800AA660, 0, 1); @@ -87,9 +84,9 @@ void func_8000D678(void *unused) { void func_8000D738(struct UnkInputStruct8000D738* arg0) { s32 temp_v0; - func_80002784(0x4742454D); - D_800AA660 = (void*)func_800025C4(0x2210, 0); - D_800AA664 = (void*)func_800025C4(0x21E0, 0); + main_pool_push_state('GBEM'); + D_800AA660 = (void*)main_pool_alloc_node_no_func(0x2210, 0); + D_800AA664 = (void*)main_pool_alloc_node_no_func(0x21E0, 0); func_80004454(((u32) ((u32) &fragment1_TEXT_START & 0x0FF00000) >> 0x14) - 0x10, &fragment1_ROM_START, &fragment1_ROM_END); temp_v0 = func_800044F4(&D_3BA190, &D_3CB130, 1, 1); D_800AA660->unk21FC = func_8000484C(temp_v0, 0); @@ -118,5 +115,5 @@ void func_8000D8DC(struct UnkInputStruct8000D738* arg0) { func_80005370(D_800AA664); osDestroyThread(&D_800AA660->thread); osDestroyThread(&D_800AA664->thread); - func_80002838(0x4742454D); + main_pool_pop_state('GBEM'); } diff --git a/include/controller.h b/src/controller.h similarity index 100% rename from include/controller.h rename to src/controller.h diff --git a/src/crash_screen.c b/src/crash_screen.c index fb64a19..d02945c 100644 --- a/src/crash_screen.c +++ b/src/crash_screen.c @@ -79,7 +79,8 @@ u16 gCrashScreenUnlockInputs[] = { }; void crash_screen_sleep(s32 ms) { - u64 cycles = (ms * 1000LL) * 3000ULL / 64ULL; + u64 cycles = OS_USEC_TO_CYCLES(ms * 1000LL); // why not just do OS_NSEC_TO_CYCLES and not multiply by 1000LL? + osSetTime(0); while (osGetTime() < cycles) { } @@ -222,22 +223,18 @@ void crash_screen_print_fpr(s32 x, s32 y, s32 regNum, void *addr) { } } -void crash_screen_print_fpcsr(u32 value) { +void crash_screen_print_fpcsr(u32 fpcsr) { s32 i; - u32 flag = 0x20000; + u32 bit = 1 << 17; - crash_screen_printf(30, 155, "FPCSR:%08XH", value); + crash_screen_printf(30, 155, "FPCSR:%08XH", fpcsr); - for (i = 0; i < 6;) { - if (value & flag) { + for (i = 0; i < 6; i++) { + if (fpcsr & bit) { crash_screen_printf(132, 155, "(%s)", gFPCSRFaultCauses[i]); break; - - do {} while (0); } - - i++; - flag >>= 1; + bit >>= 1; } } diff --git a/include/crash_screen.h b/src/crash_screen.h similarity index 100% rename from include/crash_screen.h rename to src/crash_screen.h diff --git a/include/dma.h b/src/dma.h similarity index 100% rename from include/dma.h rename to src/dma.h diff --git a/src/hal_libc.c b/src/hal_libc.c index fd421c0..ca3ed85 100644 --- a/src/hal_libc.c +++ b/src/hal_libc.c @@ -53,12 +53,11 @@ size_t HAL_Strcmp(char* dest, char* src) { * this value for every byte across a given specified size. Return the original * pointer used. */ -char* HAL_Memset(char* dest, s32 c, s32 nsize) { +char* HAL_Memset(char* dest, s32 c, u32 nsize) { char* newDest = dest; - // While the size is not 0, keep decrementing. Oddly, HAL seems to have - // xor'd the result instead of checking the logical result. - while((nsize-- == 0) ^ 1) { + // While the size is not 0, keep decrementing. + while( nsize --> 0 ) { *newDest++ = c; } return dest; diff --git a/include/hal_libc.h b/src/hal_libc.h similarity index 79% rename from include/hal_libc.h rename to src/hal_libc.h index fa8122c..8d339a8 100644 --- a/include/hal_libc.h +++ b/src/hal_libc.h @@ -4,6 +4,6 @@ char* HAL_Strcpy(char* dest, char* src); char* HAL_Strcpy2(char *dest, char* src); size_t HAL_Strcmp(char* dest, char* src); -char* HAL_Memset(char* dest, s32 c, s32 nsize); +char* HAL_Memset(char* dest, s32 c, u32 nsize); #endif // _HAL_LIBC_ diff --git a/src/intro_loader.c b/src/intro_loader.c deleted file mode 100644 index 03f4eee..0000000 --- a/src/intro_loader.c +++ /dev/null @@ -1,319 +0,0 @@ -#include -#include -#include "intro_loader.h" - -// local to this file -extern struct Unk800A6070 D_800A6070; - - -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wunknown-pragmas" - -void func_800022C0(void *arg0, void *arg1) { - D_800A6070.unk20 = (void *)(ALIGN16((uintptr_t)arg0) + 0x10); - D_800A6070.unk24 = (void *)(((uintptr_t)arg1 & ~0xF) - 0x10); - D_800A6070.unk1C = (uintptr_t)D_800A6070.unk24 - (uintptr_t)D_800A6070.unk20; - D_800A6070.unk30 = NULL; - - D_800A6070.unk28 = D_800A6070.unk20 - 1; - D_800A6070.unk28->unk00 = NULL; - D_800A6070.unk28->unk04 = NULL; - D_800A6070.unk28->unk08 = NULL; - D_800A6070.unk28->unk0C = 0; - - D_800A6070.unk2C = D_800A6070.unk24; - D_800A6070.unk2C->unk00 = NULL; - D_800A6070.unk2C->unk04 = NULL; - D_800A6070.unk28->unk08 = NULL; - D_800A6070.unk28->unk0C = 0; - - osCreateMesgQueue(&D_800A6070.queue, D_800A6070.msgs, ARRAY_COUNT(D_800A6070.msgs)); - osSendMesg(&D_800A6070.queue, NULL, OS_MESG_NOBLOCK); -} - -struct UnkNodeThing *func_80002380(u32 arg0, s32 arg1) { - struct UnkNodeThing *node; - struct UnkNodeThing *ret; - - arg0 = ALIGN16(arg0) + sizeof(struct UnkNodeThing); - ret = NULL; - if ((arg0 != 0) && (D_800A6070.unk1C >= (uintptr_t)arg0)) { - if (arg1 == 0) { - D_800A6070.unk1C -= (uintptr_t)arg0; - node = (void *)((uintptr_t)D_800A6070.unk28 + (uintptr_t)arg0); - D_800A6070.unk28->unk04 = node; - node->unk00 = D_800A6070.unk28; - node->unk04 = NULL; - node->unk08 = 0; - node->unk0C = 0; - ret = D_800A6070.unk28; - D_800A6070.unk28 = node; - ret = ret + 1; - } else if (arg1 == 1) { - D_800A6070.unk1C -= (uintptr_t)arg0; - node = (void *)((uintptr_t)D_800A6070.unk2C - (uintptr_t)arg0); - D_800A6070.unk2C->unk00 = node; - node->unk04 = D_800A6070.unk2C; - node->unk00 = NULL; - node->unk08 = 0; - node->unk0C = 0; - D_800A6070.unk2C = node; - ret = node + 1; - } - } - return ret; -} - - -uintptr_t func_80002430(struct UnkNodeThing *arg0, s32 arg1); - -#ifdef NON_MATCHING -uintptr_t func_80002430(struct UnkNodeThing *arg0, s32 arg1) { - // struct UnkNodeThing *node; - struct UnkNodeThing *otherNode; - struct UnkNodeThing *prev; - uintptr_t priorAddr; - - priorAddr = (uintptr_t)(arg0 - 1); // v1 - - if (priorAddr < (uintptr_t)D_800A6070.unk28) { - do { - prev = D_800A6070.unk28->unk00; // t6 - D_800A6070.unk28 = prev; - if (arg1) { - if (prev->unk08 != NULL) { - prev->unk08(prev + 1, prev->unk0C); - } - } - D_800A6070.unk1C = D_800A6070.unk1C + (uintptr_t)D_800A6070.unk28->unk04 - (uintptr_t)D_800A6070.unk28; - D_800A6070.unk28->unk04 = NULL; - } while (priorAddr != (uintptr_t)D_800A6070.unk28); - } else { - otherNode = D_800A6070.unk2C; - if (priorAddr >= (uintptr_t)otherNode && priorAddr >= (uintptr_t)otherNode) { - do { - if (arg1) { - if (otherNode->unk08 != NULL) { - otherNode->unk08(otherNode + 1, otherNode->unk0C); - otherNode = D_800A6070.unk2C; - } - } - prev = otherNode->unk04; - D_800A6070.unk2C = prev; - D_800A6070.unk1C = D_800A6070.unk1C + (uintptr_t)prev - (uintptr_t)prev->unk00; - prev->unk00 = NULL; - otherNode = D_800A6070.unk2C; - } while (priorAddr >= (uintptr_t)otherNode); - } - } - - return func_80002764(); -} - -#else -#pragma GLOBAL_ASM("asm/nonmatchings/intro_loader/func_80002430.s") -#endif - -struct UnkNodeThing *func_8000254C(u32 arg0, s32 arg1, s32 arg2, void *arg3) { - struct UnkNodeThing *node; - - osRecvMesg(&D_800A6070.queue, NULL, OS_MESG_BLOCK); - node = func_80002380(arg0, arg1); - if (node != NULL) { - func_80002A14(node, arg2, arg3); - } - osSendMesg(&D_800A6070.queue, NULL, OS_MESG_NOBLOCK); - - return node; -} - -struct UnkNodeThing *func_800025C4(u32 arg0, s32 arg1) { - struct UnkNodeThing *node; - - osRecvMesg(&D_800A6070.queue, NULL, OS_MESG_BLOCK); - node = func_80002380(arg0, arg1); - osSendMesg(&D_800A6070.queue, NULL, OS_MESG_NOBLOCK); - return node; -} - -void func_80002620(struct UnkNodeThing *arg0) { - if (arg0 != NULL) { - osRecvMesg(&D_800A6070.queue, NULL, OS_MESG_BLOCK); - func_80002430(arg0, 1); - osSendMesg(&D_800A6070.queue, NULL, OS_MESG_NOBLOCK); - } - func_80002764(); -} - -#ifdef NON_MATCHING -struct UnkNodeThing *func_80002680(struct UnkNodeThing *arg0, uintptr_t arg1) { - uintptr_t diff; - struct UnkNodeThing *sp28; - struct UnkNodeThing *prior; - struct UnkNodeThing *priorPrev; - s32 sp20; - void *sp1C; - - - sp28 = NULL; - osRecvMesg(&D_800A6070.queue, NULL, OS_MESG_BLOCK); - // temp_v1 = arg0 - 0x10; - prior = arg0 - 1; - // temp_a0 = temp_v1->unk4; - priorPrev = prior->unk04; - // temp_v0 = temp_a0 - arg0; - diff = (uintptr_t)priorPrev - (uintptr_t)arg0; - - if (D_800A6070.unk28 == priorPrev) { - // uintptr_t aligned; - - // temp_a3 = (arg1 + 0xF) & ~0xF; - // aligned = ALIGN16(arg1); - arg1 = ALIGN16(arg1); - // if (temp_v0 < temp_a3) { - if (diff >= arg1 || D_800A6070.unk1C >= (arg1 - diff)) { - sp20 = prior->unk0C; - sp1C = prior->unk08; - func_80002430(arg0, 0); - sp28 = func_80002380(arg1, 0); - func_80002A14(sp28, sp20, sp1C); - } - } - osSendMesg(&D_800A6070.queue, NULL, OS_MESG_NOBLOCK); - return sp28; -} -#else -#pragma GLOBAL_ASM("asm/nonmatchings/intro_loader/func_80002680.s") -#endif - -// this is a weird type, so maybe it should be cast into UnkNodeThing? -uintptr_t func_80002764(void) { - s32 val = (s32)D_800A6070.unk1C - sizeof(struct UnkNodeThing); - - if (val < 0) { - val = 0; - } - - return val; -} - -void func_80002784(s32 arg0) { - struct UnkNodeThing *node; - struct UnkNodeThing *sp20; // prev? - struct UnkNodeThing *sp1C; // data? - uintptr_t sp18; // next? - - osRecvMesg(&D_800A6070.queue, NULL, OS_MESG_BLOCK); - sp18 = D_800A6070.unk1C; - sp20 = D_800A6070.unk28; - sp1C = D_800A6070.unk2C; - node = func_80002380(0x10, 0); - if (node != NULL) { - (node-1)->unk0C = arg0; - node->unk0C = (uintptr_t)D_800A6070.unk30; - node->unk00 = (struct UnkNodeThing *) sp18; - node->unk04 = sp20; - node->unk08 = (void *) sp1C; - D_800A6070.unk30 = node; - } - osSendMesg(&D_800A6070.queue, NULL, OS_MESG_NOBLOCK); - func_80002764(); -} - -void func_80002838(struct UnkNodeThing *arg0) { - struct UnkNodeThing *node; - struct UnkNodeThing *s0; - void *s2, *s3; - - s0 = arg0; - osRecvMesg(&D_800A6070.queue, NULL, OS_MESG_BLOCK); - while (TRUE) { - node = D_800A6070.unk30; - s2 = node->unk04; - s3 = node->unk08; - D_800A6070.unk1C = (uintptr_t)node->unk00; - D_800A6070.unk30 = INT2VOID(node->unk0C); - - if (s0 == NULL) { break; } - // odd non-matching, but it works - node = node - 1; - if ((uintptr_t)s0 == (uintptr_t)node->unk0C) { break; } - if (D_800A6070.unk30 == NULL) { break; } - } - - s0 = D_800A6070.unk2C; - while ((uintptr_t)s3 > (uintptr_t)s0) { - if (s0->unk08 != NULL) { - s0->unk08(s0 + 1, s0->unk0C); - } - s0 = s0->unk04; - } - - s0 = D_800A6070.unk28->unk00; - while ((uintptr_t)s2 <= (uintptr_t)s0) { - if (s0->unk08 != NULL) { - s0->unk08(s0 + 1, s0->unk0C); - } - s0 = s0->unk00; - } - - D_800A6070.unk28 = s2; - D_800A6070.unk2C = s3; - osSendMesg(&D_800A6070.queue, NULL, OS_MESG_NOBLOCK); - func_80002764(); -} - -#ifdef MIPS_TO_C -// unused function? -struct UnkNodeThing *func_80002960(uintptr_t arg0, s32 *arg1) { - struct UnkNodeThing *node; // v0? - struct UnkNodeThing *otherNode; - - node = D_800A6070.unk28->unk00; - while (node != NULL) { - otherNode = node->unk04; - if (arg0 >= (uintptr_t)(node + 1) && arg0 < (uintptr_t)otherNode) { - if (arg1 != NULL) { - *arg1 = node->unk0C; - } - return (node + 1); - } - node = node->unk00; - } - // L800029B8 - node = D_800A6070.unk2C; - otherNode = node->unk04; - while (otherNode != NULL) { - if (arg0 >= (uintptr_t)(node + 1) && arg0 < (uintptr_t)otherNode) { - if (arg1 != NULL) { - *arg1 = node->unk0C; - } - return node + 1; - } - node = otherNode; - otherNode = otherNode->unk04; - } - // L80002A08 - return NULL; -} -#else -#pragma GLOBAL_ASM("asm/nonmatchings/intro_loader/func_80002960.s") -#endif - -void func_80002A14(struct UnkNodeThing *arg0, s32 arg1, void *arg2) { - struct UnkNodeThing *node = INT2VOID((uintptr_t)arg0 - sizeof(struct UnkNodeThing)); - node->unk08 = arg2; - node->unk0C = arg1; -} - -uintptr_t func_80002A24(struct UnkNodeThing *arg0) { - struct UnkNodeThing *prior = arg0 - 1; - - return (uintptr_t)prior->unk04 - (uintptr_t)arg0; -} - -struct Unk800A6070 *func_80002A30(void) { - return &D_800A6070; -} - -#pragma GCC diagnostic pop diff --git a/src/intro_loader.h b/src/intro_loader.h deleted file mode 100644 index e5c9dd9..0000000 --- a/src/intro_loader.h +++ /dev/null @@ -1,51 +0,0 @@ -#ifndef _SRC_INTRO_LOADER_H_ -#define _SRC_INTRO_LOADER_H_ - -#include -#include -#include - -struct UnkNodeThing { - /* 0x00 */ struct UnkNodeThing *unk00; - /* 0x04 */ struct UnkNodeThing *unk04; - // this looks like it can be any type of pointer? - // or are there multiple list node types in a union? - /* 0x08 */ void (*unk08)(struct UnkNodeThing *, s32); - /* 0x0C */ s32 unk0C; -}; // sizeof == 0x10 - -// "known" types for +08 and +0C: -// fn pointer -// void (*unk08)(struct UnkNodeThing *, s32 -// s32 unk0C -// more nodes -// struct UnkNodeThing *unk08 -// struct UnkNodeThing *unk0C - -struct Unk800A6070 { - /* 0x00 */ OSMesg msgs[1]; - /* 0x04 */ OSMesgQueue queue; - /* 0x1C */ uintptr_t unk1C; - // these pointers might be to different variants of this struct - // or, they could be to different lists... - /* 0x20 */ struct UnkNodeThing *unk20; - /* 0x24 */ struct UnkNodeThing *unk24; - /* 0x28 */ struct UnkNodeThing *unk28; - /* 0x2C */ struct UnkNodeThing *unk2C; - /* 0x30 */ struct UnkNodeThing *unk30; -}; // sizeof >= 0x34 - -// functions -void func_800022C0(void *arg0, void *arg1); -struct UnkNodeThing *func_8000254C(u32 arg0, s32 arg1, s32 arg2, void *arg3); -struct UnkNodeThing *func_800025C4(u32 arg0, s32 arg1); -void func_80002620(struct UnkNodeThing *arg0); -struct UnkNodeThing *func_80002680(struct UnkNodeThing *arg0, uintptr_t arg1); -uintptr_t func_80002764(void); -void func_80002784(s32 arg0); -void func_80002838(struct UnkNodeThing *arg0); -void func_80002A14(struct UnkNodeThing *, s32, void *); -uintptr_t func_80002A24(struct UnkNodeThing *arg0); -struct Unk800A6070 *func_80002A30(void); - -#endif /* _SRC_INTRO_LOADER_H_ */ diff --git a/include/memmap.h b/src/memmap.h similarity index 100% rename from include/memmap.h rename to src/memmap.h diff --git a/src/memory.c b/src/memory.c new file mode 100644 index 0000000..bb1213b --- /dev/null +++ b/src/memory.c @@ -0,0 +1,373 @@ +#include +#include +#include "memory.h" + +extern struct MainPool gMemPool; // gMemPool + +/** + * Initialize the main memory pool. This pool is conceptually a pair of stacks + * that grow inward from the left and right. It therefore only supports + * freeing the object that was most recently allocated from a side. + */ +void main_pool_init(void *start, void *end) { + gMemPool.start = (void *)(ALIGN16((uintptr_t)start) + 16); + gMemPool.end = (void *)(ALIGN16((uintptr_t)end - 15) - 16); + gMemPool.available = (uintptr_t)gMemPool.end - (uintptr_t)gMemPool.start; + gMemPool.mainState = NULL; + + gMemPool.listHeadL = ((u8*)gMemPool.start - sizeof(struct MainPoolBlock)); + gMemPool.listHeadL->prev = NULL; + gMemPool.listHeadL->next = NULL; + gMemPool.listHeadL->func = NULL; + gMemPool.listHeadL->arg = 0; + + gMemPool.listHeadR = gMemPool.end; + gMemPool.listHeadR->prev = NULL; + gMemPool.listHeadR->next = NULL; + gMemPool.listHeadL->func = NULL; + gMemPool.listHeadL->arg = 0; + + osCreateMesgQueue(&gMemPool.queue, gMemPool.msgs, ARRAY_COUNT(gMemPool.msgs)); + osSendMesg(&gMemPool.queue, NULL, OS_MESG_NOBLOCK); +} + +/** + * Allocate a block of memory from the pool of given size, and from the + * specified side of the pool (MEMORY_POOL_LEFT or MEMORY_POOL_RIGHT). + * If there is not enough space, return NULL. + */ +struct MainPoolBlock *main_pool_alloc(u32 size, u32 side) { + struct MainPoolBlock *newListHead; + void *addr = NULL; + + size = ALIGN16(size) + sizeof(struct MainPoolBlock); + if (size != 0 && gMemPool.available >= size) { + if (side == MEMORY_POOL_LEFT) { + gMemPool.available -= size; + newListHead = (void *)((uintptr_t)gMemPool.listHeadL + size); + gMemPool.listHeadL->next = newListHead; + newListHead->prev = gMemPool.listHeadL; + newListHead->next = NULL; + newListHead->func = 0; + newListHead->arg = 0; + addr = ((u8*)gMemPool.listHeadL + sizeof(struct MainPoolBlock)); + gMemPool.listHeadL = newListHead; + } else if (side == MEMORY_POOL_RIGHT) { + gMemPool.available -= size; + newListHead = (void *)((uintptr_t)gMemPool.listHeadR - size); + gMemPool.listHeadR->prev = newListHead; + newListHead->next = gMemPool.listHeadR; + newListHead->prev = NULL; + newListHead->func = 0; + newListHead->arg = 0; + gMemPool.listHeadR = newListHead; + addr = ((u8*)newListHead + sizeof(struct MainPoolBlock)); + } + } + return addr; +} + +/** + * Free a block of memory that was allocated from the pool. The block must be + * the most recently allocated block from its end of the pool, otherwise all + * newer blocks are freed as well. + * Return the amount of free space left in the pool. + */ +u32 main_pool_free(void *addr, u32 runBlockFunc) { + struct MainPoolBlock *block = (struct MainPoolBlock *)((u8 *)addr - sizeof(struct MainPoolBlock)); + struct MainPoolBlock *oldListHead = (struct MainPoolBlock *)((u8 *)addr - sizeof(struct MainPoolBlock)); + + if (oldListHead < gMemPool.listHeadL) { + do { + block = (gMemPool.listHeadL = gMemPool.listHeadL->prev); + if (runBlockFunc) { + // TODO: Fakematch + void (*func)(struct MainPoolBlock *, u32) = block->func; + if (func != 0) { + block->func(block + 1, block->arg); + // TODO: fake here too + if ((!(&gMemPool)) && (!(&gMemPool))) + { + } + } + } + gMemPool.available += ((uintptr_t)gMemPool.listHeadL->next - (uintptr_t)gMemPool.listHeadL); + gMemPool.listHeadL->next = NULL; + } while (oldListHead != gMemPool.listHeadL); + } else { + block = gMemPool.listHeadR; + if (oldListHead >= block && oldListHead >= block) { + do { + if (runBlockFunc) { + void (*func)(struct MainPoolBlock *, u32) = block->func; + if (func != NULL) { + func(block + 1, block->arg); + block = gMemPool.listHeadR; + } + } + block = (gMemPool.listHeadR = block->next); + gMemPool.available += ((uintptr_t)block - (uintptr_t)block->prev); + block->prev = NULL; + block = gMemPool.listHeadR; + } while (oldListHead >= gMemPool.listHeadR); + } + } + + return main_pool_get_available(); +} + +/** + * Manually allocate and initialize a block given a size and side and its + * function+arguments. + */ +struct MainPoolBlock *main_pool_alloc_node(u32 size, s32 side, s32 arg, void *func) { + struct MainPoolBlock *node; + + osRecvMesg(&gMemPool.queue, NULL, OS_MESG_BLOCK); + node = main_pool_alloc(size, side); + if (node != NULL) { + main_pool_set_func(node, arg, func); + } + osSendMesg(&gMemPool.queue, NULL, OS_MESG_NOBLOCK); + + return node; +} + +/** + * Same as above but no function/argument is set. + */ +struct MainPoolBlock *main_pool_alloc_node_no_func(u32 size, s32 side) { + struct MainPoolBlock *node; + + osRecvMesg(&gMemPool.queue, NULL, OS_MESG_BLOCK); + node = main_pool_alloc(size, side); + osSendMesg(&gMemPool.queue, NULL, OS_MESG_NOBLOCK); + + return node; +} + +/** + * Tries to free a block of memory that was allocated from the pool. Return + * the new available amount of the pool. + */ +u32 main_pool_try_free(struct MainPoolBlock *addr) { + if (addr != NULL) { + osRecvMesg(&gMemPool.queue, NULL, OS_MESG_BLOCK); + main_pool_free(addr, 1); + osSendMesg(&gMemPool.queue, NULL, OS_MESG_NOBLOCK); + } + + return main_pool_get_available(); +} + +/** + * Resize a block of memory that was allocated from the left side of the pool. + * If the block is increasing in size, it must be the most recently allocated + * block from the left side. + * The block does not move. + */ +struct MainPoolBlock *main_pool_realloc(void *addr, size_t size) { + struct MainPoolBlock *prior = (struct MainPoolBlock *)((u8 *)addr - sizeof(struct MainPoolBlock)); + void *newaddr = NULL; + + osRecvMesg(&gMemPool.queue, NULL, OS_MESG_BLOCK); + + if (prior->next == gMemPool.listHeadL) { + size_t diff = ((uintptr_t)prior->next - (uintptr_t)addr); + size = ALIGN16(size); + if (diff >= size || gMemPool.available >= (size - diff)) { + s32 arg = prior->arg; + void *func = prior->func; + main_pool_free(addr, 0); + newaddr = main_pool_alloc(size, 0); + main_pool_set_func(newaddr, arg, func); + } + } + osSendMesg(&gMemPool.queue, NULL, OS_MESG_NOBLOCK); + return newaddr; +} + +/** + * Return the amount of available memory to use in the pool. + */ +u32 main_pool_get_available(void) { + s32 available = gMemPool.available - sizeof(struct MainPoolBlock); + + if (available < 0) { + available = 0; + } + + return available; +} + +/** + * Push pool state, to be restored later. Return the amount of free space left + * in the pool. + */ +u32 main_pool_push_state(u32 arg) { + struct MainPoolState *state; + struct MainPoolBlock *listHeadL; + struct MainPoolBlock *listHeadR; + uintptr_t available; + + osRecvMesg(&gMemPool.queue, NULL, OS_MESG_BLOCK); + + // retrieve the space and head pointers. + available = gMemPool.available; + listHeadL = gMemPool.listHeadL; + listHeadR = gMemPool.listHeadR; + + state = (void*)main_pool_alloc(sizeof(struct MainPoolState), 0); + if (state != NULL) { + /** + * Why is this line here? What this line is doing is backing the pointer up to the + * previous block before this one. in the block alloc function, addr is determined + * by the head plus the size of the block struct, meaning it is returning the + * pointer to the head. + */ + ((struct MainPoolBlock *)((u8*)state-sizeof(struct MainPoolBlock)))->arg = arg; + + // now that the previous block's argument is set, set the newly allocated state's + // fields. + state->prev = gMemPool.mainState; + state->freeSpace = available; + state->listHeadL = listHeadL; + state->listHeadR = listHeadR; + + // add the newly allocated state. + gMemPool.mainState = state; + } + osSendMesg(&gMemPool.queue, NULL, OS_MESG_NOBLOCK); + return main_pool_get_available(); +} + +/** + * Restore pool state from a previous call to main_pool_push_state. Return the + * amount of free space left in the pool. + */ +u32 main_pool_pop_state(u32 arg) { + struct MainPoolState *node; + struct MainPoolBlock *argptr; + void *listHeadL; + void *listHeadR; + struct MainPoolState *state; + + argptr = (u32)arg; + osRecvMesg(&gMemPool.queue, NULL, OS_MESG_BLOCK); + + do { + node = gMemPool.mainState; + listHeadL = node->listHeadL; + listHeadR = node->listHeadR; + gMemPool.available = node->freeSpace; + gMemPool.mainState = node->prev; + + // was the argument passed in 0? + if (argptr == 0) { + break; + } + + // odd reuse of the variable, but what this is doing is backing the ptr up to the + // pool block. Thus, to check the arg variable on the pool block located before the state, + // we will need to cast the next if check. + node = (void*)((u8*)node - sizeof(struct MainPoolState)); + + if ((uintptr_t)argptr == (uintptr_t)((struct MainPoolBlock *)node)->arg) { + // we found the block with the matching string! break. + break; + } + } while(gMemPool.mainState != NULL); + + argptr = gMemPool.listHeadR; + while ((uintptr_t)listHeadR > (uintptr_t)argptr) { + if (argptr->func != NULL) { + argptr->func(argptr + 1, argptr->arg); + } + argptr = argptr->next; + } + + argptr = gMemPool.listHeadL->prev; + while ((uintptr_t)listHeadL <= (uintptr_t)argptr) { + if (argptr->func != NULL) { + argptr->func(argptr + 1, argptr->arg); + } + argptr = argptr->prev; + } + + gMemPool.listHeadL = listHeadL; + gMemPool.listHeadR = listHeadR; + osSendMesg(&gMemPool.queue, NULL, OS_MESG_NOBLOCK); + return main_pool_get_available(); +} + +/* + * Unused function. Seems at first glance to check for an address within some + * range, and then return the pointer to its data after the block. Perhaps? + * Without this being called, its hard to tell the correct context of this + * function. + */ +void *main_pool_search(uintptr_t addr, s32 *argPtr) { + struct MainPoolBlock *node; + struct MainPoolBlock *otherNode; + + node = gMemPool.listHeadL->prev; + while (node != NULL) { + int isAddrLater = (addr >= ((uintptr_t) ((u8*)node + sizeof(struct MainPoolBlock)))); + otherNode = node->next; + // seems to be checking for an addr within a block region? Since this function + // is unused, we wont be able to check for the intended context of what could + // call this function. + if (isAddrLater && addr < ((uintptr_t)otherNode & 0xFFFFFFFF)) { + if (argPtr != NULL) { + *argPtr = node->arg; + } + // return the pointer to its block contents. + return (void*)((u8*)(node) + sizeof(struct MainPoolBlock)); + } + node = node->prev; + } + + // we've searched thr prev linked list. Now lets go through the next linked list. + node = gMemPool.listHeadR; + otherNode = node->next; + while (otherNode != NULL) { + int isAddrLater = (addr >= ((uintptr_t) ((u8*)node + sizeof(struct MainPoolBlock)))); + struct MainPoolBlock *new_var = otherNode; // bit of a fakematch to force the move reload. + // same as above. + if (isAddrLater && (addr < ((uintptr_t)new_var & 0xFFFFFFFF))) { + if (argPtr != NULL) { + *argPtr = node->arg; + } + // return the pointer to its block contents. + return (void*)((u8*)(node) + sizeof(struct MainPoolBlock)); + } + otherNode = (node = otherNode)->next; + } + + return NULL; +} + +/** + * Set the block function and its argument(s) for a given block. + */ +void main_pool_set_func(void *block, s32 arg, void *func) { + struct MainPoolBlock *node = (void*)((uintptr_t)block - sizeof(struct MainPoolBlock)); + node->func = func; + node->arg = arg; +} + +/** + * Get the distance offset from the block's state listHeadL pointer to the current block. + */ +uintptr_t main_pool_get_block_dist(struct MainPoolBlock *block) { + struct MainPoolState *state = ((u8*)block - sizeof(struct MainPoolBlock)); + + return (uintptr_t)state->listHeadL - (uintptr_t)block; +} + +/** + * Return the pointer to the static memory pool area. + */ +struct MainPool *main_pool_get_pool(void) { + return &gMemPool; +} diff --git a/src/memory.h b/src/memory.h new file mode 100644 index 0000000..73e3256 --- /dev/null +++ b/src/memory.h @@ -0,0 +1,52 @@ +#ifndef _MEMORY_H_ +#define _MEMORY_H_ + +#include +#include +#include + +#define MEMORY_POOL_LEFT 0 +#define MEMORY_POOL_RIGHT 1 + +struct MainPoolState { + /* 0x00 */ u32 freeSpace; + /* 0x04 */ struct MainPoolBlock *listHeadL; + /* 0x08 */ struct MainPoolBlock *listHeadR; + /* 0x0C */ struct MainPoolState *prev; +}; + +struct MainPoolBlock { + /* 0x00 */ struct MainPoolBlock *prev; + /* 0x04 */ struct MainPoolBlock *next; + /* 0x08 */ void (*func)(struct MainPoolBlock *block, s32 arg); + /* 0x0C */ s32 arg; // passed into func as the 2nd argument. +}; + +struct MainPool { + /* 0x00 */ OSMesg msgs[1]; + /* 0x04 */ OSMesgQueue queue; + /* 0x1C */ size_t available; + /* 0x20 */ struct MainPoolBlock *start; + /* 0x24 */ struct MainPoolBlock *end; + /* 0x28 */ struct MainPoolBlock *listHeadL; + /* 0x2C */ struct MainPoolBlock *listHeadR; + /* 0x30 */ struct MainPoolState *mainState; +}; + +// functions +void main_pool_init(void *start, void *end); +struct MainPoolBlock *main_pool_alloc(u32 size, u32 side); +u32 main_pool_free(void *addr, u32 runBlockFunc); +struct MainPoolBlock *main_pool_alloc_node(u32 size, s32 side, s32 arg, void *func); +struct MainPoolBlock *main_pool_alloc_node_no_func(u32 size, s32 side); +u32 main_pool_try_free(struct MainPoolBlock *addr); +struct MainPoolBlock *main_pool_realloc(void *addr, size_t size); +u32 main_pool_get_available(void); +u32 main_pool_push_state(u32 arg); +u32 main_pool_pop_state(u32 arg); +void *main_pool_search(uintptr_t addr, s32 *argPtr); +void main_pool_set_func(void *block, s32 arg, void *func); +uintptr_t main_pool_get_block_dist(struct MainPoolBlock *block); +struct MainPool *main_pool_get_pool(void); + +#endif /* _MEMORY_H_ */ diff --git a/include/rsp.h b/src/rsp.h similarity index 100% rename from include/rsp.h rename to src/rsp.h diff --git a/tools/symbol_addrs.txt b/tools/symbol_addrs.txt index ea189cf..3139bd1 100644 --- a/tools/symbol_addrs.txt +++ b/tools/symbol_addrs.txt @@ -563,4 +563,23 @@ HAL_Printf = 0x80008154; print_profiler_metrics = 0x8000A0FC; clear_profiler_data = 0x8000A21C; draw_profiler_bar_cpu_keep_max = 0x80009630; -Yay0_Decompress = 0x8000B7F0; \ No newline at end of file +Yay0_Decompress = 0x8000B7F0; +convert_addr_to_virt_addr = 0x80002E80; +HAL_Memcpy = 0x80002F28; +HAL_DrawRect = 0x8000302C; +HAL_Memclear = 0x8000330C; +UnkHeapThing = 0x80104BC0; +gMemPool = 0x800A6070; +main_pool_alloc = 0x80002380; +main_pool_get_available = 0x80002764; +main_pool_free = 0x80002430; +main_pool_set_func = 0x80002A14; +main_pool_alloc_node = 0x8000254C; +main_pool_alloc_node_no_func = 0x800025C4; +main_pool_try_free = 0x80002620; +main_pool_realloc = 0x80002680; +main_pool_push_state = 0x80002784; +main_pool_pop_state = 0x80002838; +main_pool_get_pool = 0x80002A30; +main_pool_get_block_dist = 0x80002A24; +main_pool_search = 0x80002960; \ No newline at end of file