From a88ef2fde041e5d733b5cbe2728b15ca149d1671 Mon Sep 17 00:00:00 2001 From: mrb0nk500 Date: Sat, 28 Jan 2023 09:31:59 -0400 Subject: Initial commit --- src/Dolphin/os/OSReset.c | 5 + src/Dolphin/os/__ppc_eabi_init.cpp | 67 +++++++++ src/Dolphin/os/__start.c | 163 +++++++++++++++++++++ src/Runtime/NMWException.h | 16 ++ src/Runtime/abort_exit.c | 17 +++ src/Runtime/global_destructor_chain.c | 22 +++ src/TObject.cpp | 266 ++++++++++++++++++++++++++++++++++ src/main.cpp | 5 + 8 files changed, 561 insertions(+) create mode 100644 src/Dolphin/os/OSReset.c create mode 100644 src/Dolphin/os/__ppc_eabi_init.cpp create mode 100644 src/Dolphin/os/__start.c create mode 100644 src/Runtime/NMWException.h create mode 100644 src/Runtime/abort_exit.c create mode 100644 src/Runtime/global_destructor_chain.c create mode 100644 src/TObject.cpp create mode 100644 src/main.cpp (limited to 'src') diff --git a/src/Dolphin/os/OSReset.c b/src/Dolphin/os/OSReset.c new file mode 100644 index 0000000..a9cc186 --- /dev/null +++ b/src/Dolphin/os/OSReset.c @@ -0,0 +1,5 @@ +#include "dolphin/OSReset.h" + +void OSResetSystem(int reset, unsigned int resetCode, int forceMenu) { + +} diff --git a/src/Dolphin/os/__ppc_eabi_init.cpp b/src/Dolphin/os/__ppc_eabi_init.cpp new file mode 100644 index 0000000..a0e7574 --- /dev/null +++ b/src/Dolphin/os/__ppc_eabi_init.cpp @@ -0,0 +1,67 @@ +// This file was taken from the Metroid Prime decompilation project. +// https://github.com/PrimeDecomp/prime/blob/main/src/Dolphin/os/__ppc_eabi_init.cpp +#include "dolphin/__ppc_eabi_init.h" +#include "dolphin/PPCArch.h" + +#ifdef __cplusplus +extern "C" { +#endif +void __OSPSInit(); +void __OSCacheInit(); + +asm void __init_hardware(void) { + nofralloc + mfmsr r0 + ori r0, r0, 0x2000 + mtmsr r0 + + mflr r31 + bl __OSPSInit + bl __OSCacheInit + mtlr r31 + blr +} + +asm void __flush_cache(register void* address, register unsigned int size) { + // clang-format off + nofralloc + lis r5, ~0 + ori r5, r5, ~14 + and r5, r5, r3 + subf r3, r5, r3 + add r4, r4, r3 + +loop: + dcbst r0, r5 + sync + icbi r0, r5 + addic r5, r5, 8 + subic. r4, r4, 8 + bge loop + isync + blr + // clang-format on +} + +void __init_user() { __init_cpp(); } + +typedef void (*voidfunctionptr)(void); // pointer to function returning void +__declspec(section ".init") extern voidfunctionptr _ctors[]; +__declspec(section ".init") extern voidfunctionptr _dtors[]; + +void __init_cpp(void) { + voidfunctionptr* constructor; + + /* + * call static initializers + */ + for (constructor = _ctors; *constructor; constructor++) { + (*constructor)(); + } +} + +void _ExitProcess(void) { PPCHalt(); } + +#ifdef __cplusplus +} +#endif diff --git a/src/Dolphin/os/__start.c b/src/Dolphin/os/__start.c new file mode 100644 index 0000000..1113e15 --- /dev/null +++ b/src/Dolphin/os/__start.c @@ -0,0 +1,163 @@ +// This file was taken from the Metroid Prime decompilation project. +// https://github.com/PrimeDecomp/prime/blob/main/src/Dolphin/os/__start.c +#include "dolphin/__start.h" +#include "__ppc_eabi_linker.h" + +void __check_pad3(void) { + if ((Pad3Button & 0x0eef) == 0x0eef) { + OSResetSystem(OS_RESET_RESTART, 0, FALSE); + } + return; +} + +__declspec(weak) asm void __start(void) { + // clang-format off + nofralloc + bl __init_registers + bl __init_hardware + li r0, -1 + stwu r1, -8(r1) + stw r0, 4(r1) + stw r0, 0(r1) + bl __init_data + li r0, 0 + lis r6, EXCEPTIONMASK_ADDR@ha + addi r6, r6, EXCEPTIONMASK_ADDR@l + stw r0, 0(r6) + lis r6, BOOTINFO2_ADDR@ha + addi r6, r6, BOOTINFO2_ADDR@l + lwz r6, 0(r6) + +_check_TRK: + cmplwi r6, 0 + beq _load_lomem_debug_flag + lwz r7, OS_BI2_DEBUGFLAG_OFFSET(r6) + b _check_debug_flag + +_load_lomem_debug_flag: + lis r5, ARENAHI_ADDR@ha + addi r5, r5, ARENAHI_ADDR@l + lwz r5, 0(r5) + cmplwi r5, 0 + beq _goto_main + lis r7, DEBUGFLAG_ADDR@ha + addi r7, r7, DEBUGFLAG_ADDR@l + lwz r7, 0(r7) + +_check_debug_flag: + li r5, 0 + cmplwi r7, 2 + beq _goto_inittrk + cmplwi r7, 3 + bne _goto_main + li r5, 1 + +_goto_inittrk: + lis r6, InitMetroTRK@ha + addi r6, r6, InitMetroTRK@l + mtlr r6 + blrl + +_goto_main: + lis r6, BOOTINFO2_ADDR@ha + addi r6, r6, BOOTINFO2_ADDR@l + lwz r5, 0(r6) + cmplwi r5, 0 + beq+ _no_args + lwz r6, 8(r5) + cmplwi r6, 0 + beq+ _no_args + add r6, r5, r6 + lwz r14, 0(r6) + cmplwi r14, 0 + beq _no_args + addi r15, r6, 4 + mtctr r14 + +_loop: + addi r6, r6, 4 + lwz r7, 0(r6) + add r7, r7, r5 + stw r7, 0(r6) + bdnz _loop + lis r5, ARENAHI_ADDR@ha + addi r5, r5, ARENAHI_ADDR@l + rlwinm r7, r15, 0, 0, 0x1a + stw r7, 0(r5) + b _end_of_parseargs + +_no_args: + li r14, 0 + li r15, 0 + +_end_of_parseargs: + bl DBInit + bl OSInit + lis r4, DVD_DEVICECODE_ADDR@ha + addi r4, r4, DVD_DEVICECODE_ADDR@l + lhz r3, 0(r4) + andi. r5, r3, 0x8000 + beq _check_pad3 + andi. r3, r3, 0x7fff + cmplwi r3, 1 + bne _goto_skip_init_bba + +_check_pad3: + bl __check_pad3 + +_goto_skip_init_bba: + bl __init_user + mr r3, r14 + mr r4, r15 + bl main + b exit + // clang-format on +} + +asm static void __init_registers(void) { + // clang-format off + nofralloc + lis r1, _stack_addr@h + ori r1, r1, _stack_addr@l + lis r2, _SDA2_BASE_@h + ori r2, r2, _SDA2_BASE_@l + lis r13, _SDA_BASE_@h + ori r13, r13, _SDA_BASE_@l + blr + // clang-format on +} + +inline static void __copy_rom_section(void* dst, const void* src, unsigned long size) { + if (size && (dst != src)) { + memcpy(dst, src, size); + __flush_cache(dst, size); + } +} + +inline static void __init_bss_section(void* dst, unsigned long size) { + if (size) { + memset(dst, 0, size); + } +} + +#pragma scheduling off +void __init_data(void) { + __rom_copy_info* dci; + __bss_init_info* bii; + + dci = _rom_copy_info; + while (TRUE) { + if (dci->size == 0) + break; + __copy_rom_section(dci->addr, dci->rom, dci->size); + dci++; + } + + bii = _bss_init_info; + while (TRUE) { + if (bii->size == 0) + break; + __init_bss_section(bii->addr, bii->size); + bii++; + } +} diff --git a/src/Runtime/NMWException.h b/src/Runtime/NMWException.h new file mode 100644 index 0000000..49b623e --- /dev/null +++ b/src/Runtime/NMWException.h @@ -0,0 +1,16 @@ +#ifndef NMWEXCEPTION_H +#define NMWEXCEPTION_H + +typedef void (dtor_func)(void *object, int free_object); +typedef struct destructor_chain dtor_chain; + +struct destructor_chain { + dtor_chain *next; + dtor_func *destructor; + void *object; +}; + +void *__register_global_object(void *object, dtor_func *destructor, dtor_chain *regmem); +void __destroy_global_chain(); + +#endif diff --git a/src/Runtime/abort_exit.c b/src/Runtime/abort_exit.c new file mode 100644 index 0000000..43b1a0c --- /dev/null +++ b/src/Runtime/abort_exit.c @@ -0,0 +1,17 @@ +void __destroy_global_chain(); + +extern void (*_dtors[])(void); + +int __aborting; + + +void exit(int state) { + void (**dtor)(void); + if (!__aborting) { + dtor = _dtors; + while (*dtor != 0) { + (*dtor)(); + dtor++; + } + } +} diff --git a/src/Runtime/global_destructor_chain.c b/src/Runtime/global_destructor_chain.c new file mode 100644 index 0000000..b96c8f3 --- /dev/null +++ b/src/Runtime/global_destructor_chain.c @@ -0,0 +1,22 @@ +#include "NMWException.h" + +dtor_chain *__global_destructor_chain; + +extern void *__register_global_object(void *object, dtor_func *destructor, dtor_chain *regmem) { + regmem->next = __global_destructor_chain; + regmem->destructor = destructor; + regmem->object = object; + __global_destructor_chain = regmem; + return object; +} + +extern void __destroy_global_chain() { + dtor_chain *iter = __global_destructor_chain; + while (__global_destructor_chain != 0) { + iter = __global_destructor_chain; + __global_destructor_chain = __global_destructor_chain->next; + iter->destructor(iter->object, -1); + } +} + +__declspec(section ".dtors") static void* const __destroy_global_chain_reference = __destroy_global_chain; diff --git a/src/TObject.cpp b/src/TObject.cpp new file mode 100644 index 0000000..d133fd7 --- /dev/null +++ b/src/TObject.cpp @@ -0,0 +1,266 @@ +#include "pso/TObject.h" +#define MATCHING + +#define o(name) const char *name##_name = #name; +OBJECT_NAMES +#undef o + +void debug_print(const char *fmt) { + +} + +bool TObject::toggle_flag_9_if_flag_10_is_clear() { + if (get_flags(0x400)) { + return false; + } + if (!get_flag_9()) { + set_flag_9(); + return true; + } else { + clear_flag_9(); + return false; + } +} + +void TObject::free(void *ptr) { + +} + +void *TObject::alloc(unsigned long size) { + return NULL; +} + + +bool TObject::is_flag_0_clear_for_all_parents() { + for (TObject *parent = this; parent != NULL; parent = parent->up) { + if (parent->get_flags(1)) { + return false; + } + } + return true; +} + +int TObject::get_node_count() { + // NOTE: The order of the variable declarations matter for matching. + TObject *child; + int node_count = 0; + for (child = this->down; child != NULL; child = child->next) { + node_count += child->get_node_count() + 1; + } + return node_count; +} + +void TObject::log(const char *str) { + debug_print(str); +} + +void TObject::empty_func2() { + +} + +void TObject::func_0x14() { + +} + +void TObject::func_0x10() { + +} + +void TObject::run_task() { + +} + +void TObject::set_parent(TObject *parent) { + remove_parent(); + add_parent(parent, true); +} + +void TObject::empty_func() { + +} + +void TObject::call_func_0x10_for_each_node2() { + for (TObject *child = this->down; child != NULL; child = child->next) { + if (child->get_flags(0x200)) { + child->func_0x10(); + child->clear_flag_9(); + } + child->call_func_0x10_for_each_node2(); + } +} + +void TObject::call_func_0x14_for_each_node() { + for (TObject *child = this->down; child != NULL; child = child->next) { + if (!child->get_flags(0x100)) { + child->func_0x14(); + child->call_func_0x14_for_each_node(); + } + } +} + +void TObject::call_func_0x10_for_each_node() { + for (TObject *child = this->down; child != NULL; child = child->next) { + if (!child->get_flags(0x10)) { + child->func_0x10(); + child->call_func_0x10_for_each_node(); + } + } +} + +#ifndef MATCHING +// Near perfect match, just a single register allocation issue. +void TObject::run_tasks() { + TObject *child = this->down; + while (this->down != NULL && child != NULL) { + TObject *node = child; + child = child->next; + if (node->get_flags(0x0f)) { + if (node->get_flags(1)) { + node->clear_flags(1); + if (!node->get_flags(0x20)) { + delete node; + } else { + // Clearing child's flags with nothing here + // causes the redundant load to appear. + child->clear_flags(0); + if (node->get_flags(2)) { + node->delete_children(); + node->run_task(); + node->clear_flags(2); + } + + if (!node->get_flags(4)) { + // Adding this here somehow causes the + // dead code to be compiled. + + // Register allocation still wrong. + + // If `node` was used, it'd use the + // proper register, but it'd also add + // an unwanted `sth`. + child->clear_flags(0); + } + } + } + } else { + node->run_task(); + node->run_tasks(); + } + } +} +#else +asm void TObject::run_tasks() { + nofralloc + /* 80229828 9421FFE0 */ stwu r1, -0x20(r1) + /* 8022982C 7C0802A6 */ mflr r0 + /* 80229830 90010024 */ stw r0, 0x24(r1) + /* 80229834 BFA10014 */ stmw r29, 0x14(r1) + /* 80229838 7C7D1B78 */ mr r29, r3 + /* 8022983C 83E30014 */ lwz r31, 0x14(r3) + /* 80229840 480000B8 */ b lbl_802298f8 + lbl_80229844: + /* 80229844 7FFEFB78 */ mr r30, r31 + /* 80229848 83FF000C */ lwz r31, 0xc(r31) + /* 8022984C A07E0004 */ lhz r3, 4(r30) + /* 80229850 5460073F */ clrlwi. r0, r3, 0x1c + /* 80229854 41820088 */ beq- lbl_802298dc + /* 80229858 546007FF */ clrlwi. r0, r3, 0x1f + /* 8022985C 4182003C */ beq- lbl_80229898 + /* 80229860 5460043C */ rlwinm r0, r3, 0, 0x10, 0x1e + /* 80229864 B01E0004 */ sth r0, 4(r30) + /* 80229868 A01E0004 */ lhz r0, 4(r30) + /* 8022986C 540006B5 */ rlwinm. r0, r0, 0, 0x1a, 0x1a + /* 80229870 40820028 */ bne- lbl_80229898 + /* 80229874 281E0000 */ cmplwi r30, 0 + /* 80229878 41820080 */ beq- lbl_802298f8 + /* 8022987C 7FC3F378 */ mr r3, r30 + /* 80229880 38800001 */ li r4, 0x1 + /* 80229884 819E0018 */ lwz r12, 0x18(r30) + /* 80229888 818C0008 */ lwz r12, 8(r12) + /* 8022988C 7D8903A6 */ mtctr r12 + /* 80229890 4E800421 */ bctrl + /* 80229894 48000064 */ b lbl_802298f8 + lbl_80229898: + /* 80229898 A01E0004 */ lhz r0, 4(r30) + /* 8022989C 540007BD */ rlwinm. r0, r0, 0, 0x1e, 0x1e + /* 802298A0 4182002C */ beq- lbl_802298cc + /* 802298A4 7FC3F378 */ mr r3, r30 + /* 802298A8 480000C1 */ bl delete_children + /* 802298AC 7FC3F378 */ mr r3, r30 + /* 802298B0 819E0018 */ lwz r12, 0x18(r30) + /* 802298B4 818C000C */ lwz r12, 0xc(r12) + /* 802298B8 7D8903A6 */ mtctr r12 + /* 802298BC 4E800421 */ bctrl + /* 802298C0 A01E0004 */ lhz r0, 4(r30) + /* 802298C4 540007FA */ rlwinm r0, r0, 0, 0x1f, 0x1d + /* 802298C8 B01E0004 */ sth r0, 4(r30) + lbl_802298cc: + /* 802298CC A07E0004 */ lhz r3, 4(r30) + /* 802298D0 5460077B */ rlwinm. r0, r3, 0, 0x1d, 0x1d + /* 802298D4 40820024 */ bne- lbl_802298f8 + /* 802298D8 48000020 */ b lbl_802298f8 + lbl_802298dc: + /* 802298DC 7FC3F378 */ mr r3, r30 + /* 802298E0 819E0018 */ lwz r12, 0x18(r30) + /* 802298E4 818C000C */ lwz r12, 0xc(r12) + /* 802298E8 7D8903A6 */ mtctr r12 + /* 802298EC 4E800421 */ bctrl + /* 802298F0 7FC3F378 */ mr r3, r30 + /* 802298F4 4BFFFF35 */ bl run_tasks + lbl_802298f8: + /* 802298F8 801D0014 */ lwz r0, 0x14(r29) + /* 802298FC 28000000 */ cmplwi r0, 0 + /* 80229900 4182000C */ beq- lbl_8022990c + /* 80229904 281F0000 */ cmplwi r31, 0 + /* 80229908 4082FF3C */ bne+ lbl_80229844 + lbl_8022990c: + /* 8022990C BBA10014 */ lmw r29, 0x14(r1) + /* 80229910 80010024 */ lwz r0, 0x24(r1) + /* 80229914 7C0803A6 */ mtlr r0 + /* 80229918 38210020 */ addi r1, r1, 0x20 + /* 8022991C 4E800020 */ blr +} +#endif + +void TObject::set_flag_0_for_each_node() { + for (TObject *child = this->down; child != NULL; child = child->next) { + child->set_flag_0(); + child->set_flag_0_for_each_node(); + } +} + +void TObject::delete_children() { + _delete_children(); +} + +TObject::~TObject() { + if (!get_flags(0x20)) { + set_flags(0x20); + _delete_children(); + remove_parent(); + } +} + +TObject::TObject(TObject *parent) { + flags = 0; + up = parent; + down = NULL; + name = TObject_name; + add_parent(parent, false); +} + +void TObject::clear_flag_9() { + clear_flags(0x200); +} + +void TObject::set_flag_9() { + set_flags(0x200); +} + +u32 TObject::get_flag_9() { + return get_flags(0x200); +} + +void TObject::set_flag_0() { + set_flags(1); +} diff --git a/src/main.cpp b/src/main.cpp new file mode 100644 index 0000000..6c004d2 --- /dev/null +++ b/src/main.cpp @@ -0,0 +1,5 @@ +#include "pso/TObject.h" + +int main(int argc, char **argv) { + return 0; +} -- cgit v1.2.3-13-gbd6f