mirror of
https://github.com/pret/pokestadium.git
synced 2026-09-11 04:45:33 -05:00
document and rename intro_loader to memory
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -40,8 +40,8 @@
|
||||
|
||||
#include "ultra64/thread.h"
|
||||
|
||||
#include "functions.h"
|
||||
#include "macros.h"
|
||||
#include "functions.h"
|
||||
#include "variables.h"
|
||||
|
||||
#endif
|
||||
|
||||
@@ -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
|
||||
|
||||
84
src/3A80.c
84
src/3A80.c
@@ -1,6 +1,6 @@
|
||||
#include <ultra64.h>
|
||||
#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)
|
||||
|
||||
19
src/E1C0.c
19
src/E1C0.c
@@ -2,7 +2,7 @@
|
||||
#include <PR/os_internal_reg.h>
|
||||
#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');
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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_
|
||||
@@ -1,319 +0,0 @@
|
||||
#include <ultra64.h>
|
||||
#include <macros.h>
|
||||
#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
|
||||
@@ -1,51 +0,0 @@
|
||||
#ifndef _SRC_INTRO_LOADER_H_
|
||||
#define _SRC_INTRO_LOADER_H_
|
||||
|
||||
#include <PR/ultratypes.h>
|
||||
#include <PR/os.h>
|
||||
#include <macros.h>
|
||||
|
||||
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_ */
|
||||
373
src/memory.c
Normal file
373
src/memory.c
Normal file
@@ -0,0 +1,373 @@
|
||||
#include <ultra64.h>
|
||||
#include <macros.h>
|
||||
#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;
|
||||
}
|
||||
52
src/memory.h
Normal file
52
src/memory.h
Normal file
@@ -0,0 +1,52 @@
|
||||
#ifndef _MEMORY_H_
|
||||
#define _MEMORY_H_
|
||||
|
||||
#include <PR/ultratypes.h>
|
||||
#include <PR/os.h>
|
||||
#include <macros.h>
|
||||
|
||||
#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_ */
|
||||
@@ -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;
|
||||
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;
|
||||
Reference in New Issue
Block a user