summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/NMWException.h26
-rw-r--r--obj_files.mk3
-rw-r--r--src/Runtime/Gecko_ExceptionPPC.cpp42
-rw-r--r--src/Runtime/__init_cpp_exceptions.cpp52
-rw-r--r--src/Runtime/global_destructor_chain.c2
5 files changed, 124 insertions, 1 deletions
diff --git a/include/NMWException.h b/include/NMWException.h
new file mode 100644
index 0000000..9cf7e48
--- /dev/null
+++ b/include/NMWException.h
@@ -0,0 +1,26 @@
+#ifndef NMWEXCEPTION_H
+#define NMWEXCEPTION_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+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 __unregister_fragment(int fragmentID);
+int __register_fragment(struct __eti_init_info *info, char *TOC);
+void *__register_global_object(void *object, dtor_func *destructor, dtor_chain *regmem);
+void __destroy_global_chain();
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/obj_files.mk b/obj_files.mk
index 2e65fa0..4677312 100644
--- a/obj_files.mk
+++ b/obj_files.mk
@@ -2,5 +2,8 @@ O_FILES := $(BUILD_DIR)/src/main.o \
$(BUILD_DIR)/src/pso/TMainTask.o \
$(BUILD_DIR)/src/pso/TObject.o \
$(BUILD_DIR)/src/Runtime/global_destructor_chain.o \
+ $(BUILD_DIR)/src/Runtime/Gecko_ExceptionPPC.o \
+ $(BUILD_DIR)/src/Runtime/__init_cpp_exceptions.o \
+ $(BUILD_DIR)/src/Runtime/abort_exit.o \
$(BUILD_DIR)/src/Dolphin/os/__start.o \
$(BUILD_DIR)/src/Dolphin/os/__ppc_eabi_init.o
diff --git a/src/Runtime/Gecko_ExceptionPPC.cpp b/src/Runtime/Gecko_ExceptionPPC.cpp
new file mode 100644
index 0000000..693aa25
--- /dev/null
+++ b/src/Runtime/Gecko_ExceptionPPC.cpp
@@ -0,0 +1,42 @@
+// This file was taken from the Metroid Prime decompilation project.
+// https://github.com/PrimeDecomp/prime/blob/main/src/Runtime/Gecko_ExceptionPPC.cpp
+#include "__ppc_eabi_linker.h"
+#include "NMWException.h"
+
+#if __MWERKS__
+#pragma exceptions on
+#endif
+
+typedef struct ProcessInfo {
+ __eti_init_info* exception_info;
+ char* TOC;
+ int active;
+} ProcessInfo;
+
+static ProcessInfo fragmentinfo[1];
+
+int __register_fragment(struct __eti_init_info* info, char* TOC) {
+ ProcessInfo* f;
+ int i;
+
+ for (i = 0, f = fragmentinfo; i < 1; ++i, ++f) {
+ if (f->active == 0) {
+ f->exception_info = info;
+ f->TOC = TOC;
+ f->active = 1;
+ return (i);
+ }
+ }
+
+ return (-1);
+}
+
+void __unregister_fragment(int fragmentId) {
+ ProcessInfo* f;
+ if (fragmentId >= 0 && fragmentId < 1) {
+ f = &fragmentinfo[fragmentId];
+ f->exception_info = 0;
+ f->TOC = 0;
+ f->active = 0;
+ }
+}
diff --git a/src/Runtime/__init_cpp_exceptions.cpp b/src/Runtime/__init_cpp_exceptions.cpp
new file mode 100644
index 0000000..937cc79
--- /dev/null
+++ b/src/Runtime/__init_cpp_exceptions.cpp
@@ -0,0 +1,52 @@
+// This file was taken from the Metroid Prime decompilation project.
+// https://github.com/PrimeDecomp/prime/blob/main/src/Runtime/__init_cpp_exceptions.cpp
+#include "NMWException.h"
+#include "__ppc_eabi_linker.h"
+
+static int fragmentID = -2;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern void __init_cpp_exceptions(void);
+extern void __fini_cpp_exceptions(void);
+extern void suspend(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+/* clang-format off */
+static asm char* GetR2() {
+ nofralloc;
+ mr r3, r2
+ blr
+}
+/* clang-format on */
+
+extern void __init_cpp_exceptions(void) {
+ char* R2;
+ if (fragmentID == -2) {
+
+ R2 = GetR2();
+
+ /* HACK: TODO: _eti_init_info should be _eti_init_info, we can't use the appropriate name yet due to the
+ * linker not being able to generate it*/
+ fragmentID = __register_fragment(_eti_init_info, R2);
+ }
+}
+
+extern void __fini_cpp_exceptions(void) {
+ if (fragmentID != -2) {
+ __unregister_fragment(fragmentID);
+ fragmentID = -2;
+ }
+}
+
+__declspec(section
+ ".ctors") static void* const __init_cpp_exceptions_reference = __init_cpp_exceptions;
+__declspec(section
+ ".dtors") static void* const __destroy_global_chain_reference = __destroy_global_chain;
+__declspec(section
+ ".dtors") static void* const __fini_cpp_exceptions_reference = __fini_cpp_exceptions;
diff --git a/src/Runtime/global_destructor_chain.c b/src/Runtime/global_destructor_chain.c
index b96c8f3..1f3790d 100644
--- a/src/Runtime/global_destructor_chain.c
+++ b/src/Runtime/global_destructor_chain.c
@@ -10,7 +10,7 @@ extern void *__register_global_object(void *object, dtor_func *destructor, dtor_
return object;
}
-extern void __destroy_global_chain() {
+void __destroy_global_chain() {
dtor_chain *iter = __global_destructor_chain;
while (__global_destructor_chain != 0) {
iter = __global_destructor_chain;