summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Dolphin/os/OSReset.c5
-rw-r--r--src/Dolphin/os/__ppc_eabi_init.cpp67
-rw-r--r--src/Dolphin/os/__start.c163
-rw-r--r--src/Runtime/NMWException.h16
-rw-r--r--src/Runtime/abort_exit.c17
-rw-r--r--src/Runtime/global_destructor_chain.c22
-rw-r--r--src/TObject.cpp266
-rw-r--r--src/main.cpp5
8 files changed, 561 insertions, 0 deletions
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;
+}