diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/Dolphin/os/OSReset.c | 5 | ||||
| -rw-r--r-- | src/Dolphin/os/__ppc_eabi_init.cpp | 67 | ||||
| -rw-r--r-- | src/Dolphin/os/__start.c | 163 | ||||
| -rw-r--r-- | src/Runtime/NMWException.h | 16 | ||||
| -rw-r--r-- | src/Runtime/abort_exit.c | 17 | ||||
| -rw-r--r-- | src/Runtime/global_destructor_chain.c | 22 | ||||
| -rw-r--r-- | src/TObject.cpp | 266 | ||||
| -rw-r--r-- | src/main.cpp | 5 | 
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; +} | 
