summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormrb0nk500 <b0nk@b0nk.xyz>2023-01-28 09:31:59 -0400
committermrb0nk500 <b0nk@b0nk.xyz>2023-01-28 19:04:05 -0400
commita88ef2fde041e5d733b5cbe2728b15ca149d1671 (patch)
treeb4b01c75a640810f6549c485a382242d25a19a97
Initial commit
-rw-r--r--include/__ppc_eabi_linker.h75
-rw-r--r--include/__start.h46
-rw-r--r--include/dolphin/OSReset.h1
-rw-r--r--include/dolphin/PPCArch.h502
-rw-r--r--include/dolphin/__ppc_eabi_init.h21
-rw-r--r--include/dolphin/__start.h6
-rw-r--r--include/dolphin/types.h92
-rw-r--r--include/pso/TObject.h117
-rw-r--r--include/static_assert.hpp35
-rw-r--r--include/types.h30
-rw-r--r--ldscript.lcf33
-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
-rw-r--r--tools/mwcc_compiler/1.3.2/place-compiler-files-here0
20 files changed, 1519 insertions, 0 deletions
diff --git a/include/__ppc_eabi_linker.h b/include/__ppc_eabi_linker.h
new file mode 100644
index 0000000..bdcb743
--- /dev/null
+++ b/include/__ppc_eabi_linker.h
@@ -0,0 +1,75 @@
+// This file was taken from the Metroid Prime decompilation project.
+// https://github.com/PrimeDecomp/prime/blob/main/include/__ppc_eabi_linker.h
+#ifndef __PPC_EABI_LINKER
+#define __PPC_EABI_LINKER
+
+__declspec(section ".init") extern char _stack_addr[];
+__declspec(section ".init") extern char _stack_end[];
+__declspec(section ".init") extern char _heap_addr[];
+__declspec(section ".init") extern char _heap_end[];
+__declspec(section ".init") extern const char _fextabindex_rom[];
+__declspec(section ".init") extern char _fextabindex[];
+__declspec(section ".init") extern char _eextabindex[];
+
+__declspec(section ".init") extern char _SDA_BASE_[];
+
+__declspec(section ".init") extern char _SDA2_BASE_[];
+
+typedef struct __rom_copy_info {
+ char* rom;
+ char* addr;
+ unsigned int size;
+} __rom_copy_info;
+
+__declspec(section ".init") extern __rom_copy_info _rom_copy_info[];
+
+typedef struct __bss_init_info {
+ char* addr;
+ unsigned int size;
+} __bss_init_info;
+
+__declspec(section ".init") extern __bss_init_info _bss_init_info[];
+
+typedef struct __eti_init_info {
+ void* eti_start;
+ void* eti_end;
+ void* code_start;
+ unsigned long code_size;
+} __eti_init_info;
+
+__declspec(section ".init") extern __eti_init_info _eti_init_info[];
+__declspec(section ".init") extern const char _f_init_rom[];
+__declspec(section ".init") extern char _f_init[];
+__declspec(section ".init") extern char _e_init[];
+__declspec(section ".init") extern const char _f_text_rom[];
+__declspec(section ".init") extern char _f_text[];
+__declspec(section ".init") extern char _e_text[];
+__declspec(section ".init") extern const char _f_rodata_rom[];
+__declspec(section ".init") extern char _f_rodata[];
+__declspec(section ".init") extern char _e_rodata[];
+__declspec(section ".init") extern const char _fextab_rom[];
+__declspec(section ".init") extern char _fextab[];
+__declspec(section ".init") extern char _eextab[];
+__declspec(section ".init") extern const char _f_data_rom[];
+__declspec(section ".init") extern char _f_data[];
+__declspec(section ".init") extern char _e_data[];
+__declspec(section ".init") extern char _f_bss[];
+__declspec(section ".init") extern char _e_bss[];
+__declspec(section ".init") extern const char _f_sdata_rom[];
+__declspec(section ".init") extern char _f_sdata[];
+__declspec(section ".init") extern char _e_sdata[];
+__declspec(section ".init") extern char _f_sbss[];
+__declspec(section ".init") extern char _e_sbss[];
+__declspec(section ".init") extern const char _f_sdata2_rom[];
+__declspec(section ".init") extern char _f_sdata2[];
+__declspec(section ".init") extern char _e_sdata2[];
+__declspec(section ".init") extern char _f_sbss2[];
+__declspec(section ".init") extern char _e_sbss2[];
+__declspec(section ".init") extern const char _f_PPC_EMB_sdata0_rom[];
+__declspec(section ".init") extern char _f_PPC_EMB_sdata0[];
+__declspec(section ".init") extern char _e_PPC_EMB_sdata0[];
+__declspec(section ".init") extern char _f_PPC_EMB_sbss0[];
+__declspec(section ".init") extern char _e_PPC_EMB_sbss0[];
+
+
+#endif // __PPC_EABI_LINKER
diff --git a/include/__start.h b/include/__start.h
new file mode 100644
index 0000000..1cf3da4
--- /dev/null
+++ b/include/__start.h
@@ -0,0 +1,46 @@
+// This file was taken from the Metroid Prime decompilation project.
+// https://github.com/PrimeDecomp/prime/blob/main/include/dolphin/__start.h
+#ifndef _DOLPHIN__START
+#define _DOLPHIN__START
+
+#include "dolphin/db.h"
+#include "types.h"
+
+#define PAD3_BUTTON_ADDR 0x800030E4
+#define OS_RESET_RESTART 0
+#define EXCEPTIONMASK_ADDR 0x80000044
+#define BOOTINFO2_ADDR 0x800000F4
+#define OS_BI2_DEBUGFLAG_OFFSET 0xC
+#define ARENAHI_ADDR 0x80000034
+#define DEBUGFLAG_ADDR 0x800030E8
+#define DVD_DEVICECODE_ADDR 0x800030E6
+
+#define MSR_FP 0x2000
+
+extern void InitMetroTRK();
+
+u16 Pad3Button : PAD3_BUTTON_ADDR;
+static u8 Debug_BBA = 0;
+
+extern void memset(void*, int, int);
+extern int main(int argc, char* argv[]);
+extern void exit(int);
+extern void __init_user(void);
+extern void OSInit(void);
+extern void DBInit(void);
+extern void OSResetSystem(BOOL reset, u32 resetCode, BOOL forceMenu);
+extern void __OSCacheInit(void);
+extern void __OSPSInit(void);
+
+__declspec(section ".init") extern void __check_pad3(void);
+__declspec(section ".init") extern void __start(void);
+__declspec(section ".init") extern void __init_registers(void);
+__declspec(section ".init") extern void __init_data(void);
+__declspec(section ".init") extern void __init_hardware(void);
+__declspec(section ".init") extern void __flush_cache(void* address, unsigned int size);
+
+__declspec(section ".init") extern char _stack_addr[];
+__declspec(section ".init") extern char _SDA_BASE_[];
+__declspec(section ".init") extern char _SDA2_BASE_[];
+
+#endif // _DOLPHIN__START
diff --git a/include/dolphin/OSReset.h b/include/dolphin/OSReset.h
new file mode 100644
index 0000000..e8c8bed
--- /dev/null
+++ b/include/dolphin/OSReset.h
@@ -0,0 +1 @@
+extern void OSResetSystem(int reset, unsigned int resetCode, int forceMenu);
diff --git a/include/dolphin/PPCArch.h b/include/dolphin/PPCArch.h
new file mode 100644
index 0000000..9ffbd5c
--- /dev/null
+++ b/include/dolphin/PPCArch.h
@@ -0,0 +1,502 @@
+// This file was taken from the Metroid Prime decompilation project.
+// https://github.com/PrimeDecomp/prime/blob/main/include/dolphin/PPCArch.h
+#ifndef _DOLPHIN_PPCARCH
+#define _DOLPHIN_PPCARCH
+
+#include "types.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define CTR 9
+#define XER 1
+#define LR 8
+
+#define UPMC1 937
+#define UPMC2 938
+#define UPMC3 941
+#define UPMC4 942
+
+#define USIA 939
+
+#define UMMCR0 936
+#define UMMCR1 940
+
+#define HID0 1008
+#define HID1 1009
+
+#define PVR 287
+
+#define IBAT0U 528
+#define IBAT0L 529
+#define IBAT1U 530
+#define IBAT1L 531
+#define IBAT2U 532
+#define IBAT2L 533
+#define IBAT3U 534
+#define IBAT3L 535
+
+#define DBAT0U 536
+#define DBAT0L 537
+#define DBAT1U 538
+#define DBAT1L 539
+#define DBAT2U 540
+#define DBAT2L 541
+#define DBAT3U 542
+#define DBAT3L 543
+
+#define SDR1 25
+
+#define SPRG0 272
+#define SPRG1 273
+#define SPRG2 274
+#define SPRG3 275
+
+#define DAR 19
+#define DSISR 18
+
+#define SRR0 26
+#define SRR1 27
+
+#define EAR 282
+
+#define DABR 1013
+
+#define TBL 284
+#define TBU 285
+
+#define L2CR 1017
+
+#define DEC 22
+
+#define IABR 1010
+
+#define PMC1 953
+#define PMC2 954
+#define PMC3 957
+#define PMC4 958
+
+#define SIA 955
+
+#define MMCR0 952
+#define MMCR1 956
+
+#define THRM1 1020
+#define THRM2 1021
+#define THRM3 1022
+
+#define ICTC 1019
+
+#define GQR0 912
+#define GQR1 913
+#define GQR2 914
+#define GQR3 915
+#define GQR4 916
+#define GQR5 917
+#define GQR6 918
+#define GQR7 919
+
+#define HID2 920
+
+#define WPAR 921
+
+#define DMA_U 922
+#define DMA_L 923
+
+#define MSR_POW 0x00040000 // Power Management
+#define MSR_ILE 0x00010000 // Interrupt Little Endian
+#define MSR_EE 0x00008000 // external interrupt
+#define MSR_PR 0x00004000 // privilege level(should be 0)
+#define MSR_FP 0x00002000 // floating point available
+#define MSR_ME 0x00001000 // machine check enable
+#define MSR_FE0 0x00000800 // floating point exception enable
+#define MSR_SE 0x00000400 // single step trace enable
+#define MSR_BE 0x00000200 // branch trace enable
+#define MSR_FE1 0x00000100 // floating point exception enable
+#define MSR_IP 0x00000040 // Exception prefix
+#define MSR_IR 0x00000020 // instruction relocate
+#define MSR_DR 0x00000010 // data relocate
+#define MSR_PM 0x00000004 // Performance monitor marked mode
+#define MSR_RI 0x00000002 // Recoverable interrupt
+#define MSR_LE 0x00000001 // Little Endian
+
+#define MSR_POW_BIT 13 // Power Management
+#define MSR_ILE_BIT 15 // Interrupt Little Endian
+#define MSR_EE_BIT 16 // external interrupt
+#define MSR_PR_BIT 17 // privilege level (should be 0)
+#define MSR_FP_BIT 18 // floating point available
+#define MSR_ME_BIT 19 // machine check enable
+#define MSR_FE0_BIT 20 // floating point exception enable
+#define MSR_SE_BIT 21 // single step trace enable
+#define MSR_BE_BIT 22 // branch trace enable
+#define MSR_FE1_BIT 23 // floating point exception enable
+#define MSR_IP_BIT 25 // Exception prefix
+#define MSR_IR_BIT 26 // instruction relocate
+#define MSR_DR_BIT 27 // data relocate
+#define MSR_PM_BIT 29 // Performance monitor marked mode
+#define MSR_RI_BIT 30 // Recoverable interrupt
+#define MSR_LE_BIT 31 // Little Endian
+
+/*---------------------------------------------------------------------------*
+ HID0 bits
+ *---------------------------------------------------------------------------*/
+#define HID0_EMCP 0x80000000 // Enable MCP
+#define HID0_DBP 0x40000000 // Enable 60x bus address and data parity chk
+#define HID0_EBA 0x20000000 // Enable 60x address parity checking
+#define HID0_EBD 0x10000000 // Enable 60x data parity checking
+#define HID0_BCLK 0x08000000 // CLK_OUT output enable and clk selection
+#define HID0_ECLK 0x02000000 // CLK_OUT output enable and clk selection
+#define HID0_PAR 0x01000000 // Disable !ARTRY precharge
+#define HID0_DOZE 0x00800000 // Doze mode enable
+#define HID0_NAP 0x00400000 // Nap mode enable
+#define HID0_SLEEP 0x00200000 // Sleep mode enable
+#define HID0_DPM 0x00100000 // Dynamic power management enable
+#define HID0_NHR 0x00010000 // Not hard reset (0 hard reset if s/w set it)
+#define HID0_ICE 0x00008000 // Instruction cache enable
+#define HID0_DCE 0x00004000 // Data cache enable
+#define HID0_ILOCK 0x00002000 // ICache lock
+#define HID0_DLOCK 0x00001000 // DCache lock
+#define HID0_ICFI 0x00000800 // ICache flash invalidate
+#define HID0_DCFI 0x00000400 // DCache flash invalidate
+#define HID0_SPD 0x00000200 // Speculative cache access enable (0 enable)
+#define HID0_IFEM 0x00000100 // Enable M bit on bus for Ifetch
+#define HID0_SGE 0x00000080 // Store gathering enable
+#define HID0_DCFA 0x00000040 // DCache flush assist - set before a flush
+#define HID0_BTIC 0x00000020 // Branch target icache enable
+#define HID0_ABE 0x00000008 // Address bcast enable
+#define HID0_BHT 0x00000004 // Branch history table enable
+#define HID0_NOOPTI 0x00000001 // No-op Dcache touch instructions
+
+#define HID0_ICE_BIT 16 // Instruction cache enable
+#define HID0_DCE_BIT 17 // Data cache enable
+#define HID0_ILOCK_BIT 18 // ICache lock
+#define HID0_DLOCK_BIT 19 // DCache lock
+
+#define HID2_LSQE 0x80000000 // L/S quantize enable
+#define HID2_WPE 0x40000000 // Write pipe enable
+#define HID2_PSE 0x20000000 // Paired single enable
+#define HID2_LCE 0x10000000 // Locked cache enable
+
+#define HID2_DCHERR 0x00800000 // ERROR: dcbz_l cache hit
+#define HID2_DNCERR 0x00400000 // ERROR: DMA access to normal cache
+#define HID2_DCMERR 0x00200000 // ERROR: DMA cache miss error
+#define HID2_DQOERR 0x00100000 // ERROR: DMA queue overflow
+#define HID2_DCHEE 0x00080000 // dcbz_l cache hit error enable
+#define HID2_DNCEE 0x00040000 // DMA access to normal cache error enable
+#define HID2_DCMEE 0x00020000 // DMA cache miss error error enable
+#define HID2_DQOEE 0x00010000 // DMA queue overflow error enable
+
+#define HID2_DMAQL_MASK 0x0F000000 // DMA queue length mask
+#define HID2_DMAQL_SHIFT 24 // DMA queue shift
+
+#define HID2_LSQE_BIT 0
+#define HID2_WPE_BIT 1
+#define HID2_PSE_BIT 2
+#define HID2_LCE_BIT 3
+
+#define HID2_DCHERR_BIT 8
+#define HID2_DNCERR_BIT 9
+#define HID2_DCMERR_BIT 10
+#define HID2_DQOERR_BIT 11
+#define HID2_DCHEE_BIT 12
+#define HID2_DNCEE_BIT 13
+#define HID2_DCMEE_BIT 14
+#define HID2_DQOEE_BIT 15
+
+#define GQR_LOAD_SCALE_MASK 0x3F000000 // load scale field
+#define GQR_LOAD_TYPE_MASK 0x00070000 // load type field
+#define GQR_STORE_SCALE_MASK 0x00003F00 // store scale field
+#define GQR_STORE_TYPE_MASK 0x00000007 // store type field
+
+typedef struct
+{
+ u32 _pad0 :2;
+ u32 loadScale :6;
+ u32 _pad1 :5;
+ u32 loadType :3;
+ u32 _pad2 :2;
+ u32 storeScale :6;
+ u32 _pad3 :5;
+ u32 storeType :3;
+} PPC_GQR_t;
+
+typedef union
+{
+ u32 val;
+ PPC_GQR_t f;
+} PPC_GQR_u;
+
+
+#define DMA_U_ADDR_MASK 0xFFFFFFE0 // Start addr in memory
+#define DMA_U_LEN_U_MASK 0x0000001F // lines to transfer (U)
+
+#define DMA_L_LC_ADDR_MASK 0xFFFFFFE0 // Start addr in LC
+#define DMA_L_LOAD 0x00000010 // 0 - store, 1 - load
+#define DMA_L_STORE 0x00000000 // 0 - store, 1 - load
+#define DMA_L_LEN_MASK 0x0000000C // lines to transfer (L)
+#define DMA_L_TRIGGER 0x00000002 // 0 - cmd inactive, 1 - cmd rdy
+#define DMA_L_FLUSH 0x00000001 // 1 - Flush DMA queue
+
+typedef struct
+{
+ u32 memAddr :27;
+ u32 dmaLenU :5;
+} PPC_DMA_U_t;
+
+typedef union
+{
+ u32 val;
+ PPC_DMA_U_t f;
+} PPC_DMA_U_u;
+
+
+typedef struct
+{
+ u32 lcAddr :27;
+ u32 dmaLd :1;
+ u32 dmaLenL :2;
+ u32 dmaTrigger :1;
+ u32 dmaFlush :1;
+} PPC_DMA_L_t;
+
+
+typedef union
+{
+ u32 val;
+ PPC_DMA_L_t f;
+} PPC_DMA_L_u;
+
+
+#define WPAR_ADDR 0xFFFFFFE0 // 32byte gather address
+#define WPAR_BNE 0x00000001 // Buffer not empty (R)
+
+#define SRR1_DMA_BIT 0x00200000
+#define SRR1_L2DP_BIT 0x00100000
+
+#define L2CR_L2E 0x80000000 // L2 Enable
+#define L2CR_L2PE 0x40000000 // L2 data parity generation and checking enable
+
+#define L2CR_L2SIZ_256K 0x10000000 // L2 size 256K
+#define L2CR_L2SIZ_512K 0x20000000 // L2 size 512
+#define L2CR_L2SIZ_1M 0x30000000 // L2 size 1M
+
+#define L2CR_L2CLK_1_0 0x02000000 // L2 clock ratio 1
+#define L2CR_L2CLK_1_5 0x04000000 // L2 clock ratio 1.5
+#define L2CR_L2CLK_2_0 0x08000000 // L2 clock ratio 2
+#define L2CR_L2CLK_2_5 0x0A000000 // L2 clock ratio 2.5
+#define L2CR_L2CLK_3_0 0x0C000000 // L2 clock ratio 3
+
+#define L2CR_RAM_FLOW_THRU_BURST 0x00000000 // L2 RAM type flow-through sync. burst SRAM
+#define L2CR_RAM_PIPELINE_BURST 0x01000000 // L2 RAM type pipelined sync. burst SRAM
+#define L2CR_RAM_PIPELINE_LATE 0x01800000 // L2 RAM type pipelined sync. late-write SRAM
+
+#define L2CR_L2DO 0x00400000 // Data only
+#define L2CR_L2I 0x00200000 // Global invalidate
+#define L2CR_L2CTL 0x00100000 // ZZ enable
+#define L2CR_L2WT 0x00080000 // L2 write through
+#define L2CR_L2TS 0x00040000 // L2 test support
+
+#define L2CR_L2OH_0_5 0x00000000 // L2 output hold 0.5 ns
+#define L2CR_L2OH_1_0 0x00010000 // L2 output hold 1.0 ns
+
+#define L2CR_L2SL 0x00008000 // L2 DLL slow
+#define L2CR_L2DF 0x00004000 // L2 differential clock
+#define L2CR_L2BYP 0x00002000 // L2 DLL bypass
+#define L2CR_L2CS 0x00000200 // L2 clock stop
+#define L2CR_L2DRO 0x00000100 // L2 DLL rollover checkstop enable
+#define L2CR_L2CTR_MASK 0x000000FE // L2 counter value mask
+#define L2CR_L2IP 0x00000001 // L2 global invalidate in progress
+
+#define MMCR0_DIS 0x80000000 // Disables counting unconditionally
+#define MMCR0_DP 0x40000000 // Disables counting while in supervisor mode
+#define MMCR0_DU 0x20000000 // Disables counting while in user mode
+#define MMCR0_DMS 0x10000000 // Disables counting while MSR[PM] is set
+#define MMCR0_DMR 0x08000000 // Disables counting while MSR[PM] is zero
+#define MMCR0_ENINT 0x04000000 // Enables performance monitor interrupt signaling
+#define MMCR0_DISCOUNT 0x02000000 // Disables counting of PMCn when a performance monitor interrupt is signaled or...
+#define MMCR0_RTCSELECT_MASK 0x01800000 // 64-bit time base, bit selection enable
+#define MMCR0_RTCSELECT_63 0x00000000 // Pick bit 63 to count
+#define MMCR0_RTCSELECT_55 0x00800000 // Pick bit 55 to count
+#define MMCR0_RTCSELECT_51 0x01000000 // Pick bit 51 to count
+#define MMCR0_RTCSELECT_47 0x01800000 // Pick bit 47 to count
+#define MMCR0_INTONBITTRANS 0x00400000 // Causes interrupt signaling on bit transition from off to on
+#define MMCR0_THRESHOLD_MASK 0x003F0000 // Threshold value
+#define MMCR0_THRESHOLD(n) ((n) << 16) // Threshold value (0 - 63)
+#define MMCR0_PMC1INTCONTROL 0x00008000 // Enables interrupt signaling due to PMC1 counter overflow
+#define MMCR0_PMC2INTCONTROL 0x00004000 // Enables interrupt signaling due to PMC2-PMC4 counter overflow
+#define MMCR0_PMCTRIGGER 0x00002000 // Can be used to trigger counting of PMC2-PMC4 after PMC1 has overflowed or...
+#define MMCR0_PMC1SELECT_MASK 0x00001FC0 // PMC1 input selector
+#define MMCR0_PMC2SELECT_MASK 0x0000003F // PMC2 input selector
+
+#define MMCR1_PMC3SELECT_MASK 0xF8000000 // PMC3 input selector
+#define MMCR1_PMC4SELECT_MASK 0x07C00000 // PMC4 input selector
+
+#define PMC1_OV 0x80000000 // Overflow
+#define PMC1_COUNTER 0x7FFFFFFF // Counter value
+#define PMC2_OV 0x80000000 // Overflow
+#define PMC2_COUNTER 0x7FFFFFFF // Counter value
+#define PMC3_OV 0x80000000 // Overflow
+#define PMC3_COUNTER 0x7FFFFFFF // Counter value
+#define PMC4_OV 0x80000000 // Overflow
+#define PMC4_COUNTER 0x7FFFFFFF // Counter value
+
+/*---------------------------------------------------------------------------*
+ PMC1 Events
+ *---------------------------------------------------------------------------*/
+#define MMCR0_PMC1_HOLD 0x00000000 // Register holds current value
+#define MMCR0_PMC1_CYCLE 0x00000040 // Processor cycles
+#define MMCR0_PMC1_INSTRUCTION 0x00000080 // # of instructions completed.
+#define MMCR0_PMC1_TRANSITION 0x000000C0 // # of transitions for 0 to 1
+#define MMCR0_PMC1_DISPATCHED 0x00000100 // # of instructions dispatched
+#define MMCR0_PMC1_EIEIO 0x00000140 // # of eieio instructions completed
+#define MMCR0_PMC1_ITLB_CYCLE 0x00000180 // # of cycles spent performing table search op. for the ITLB
+#define MMCR0_PMC1_L2_HIT 0x000001C0 // # of access that hit the L2.
+#define MMCR0_PMC1_EA 0x00000200 // # of valid instruction EAs delivered to the memory subsystem
+#define MMCR0_PMC1_IABR 0x00000240 // # of time the address of an instruction matches the IABR
+#define MMCR0_PMC1_L1_MISS 0x00000280 // # of loads that miss the L1
+#define MMCR0_PMC1_Bx_UNRESOLVED 0x000002C0 // # of branches that are unresolved when processed
+#define MMCR0_PMC1_Bx_STALL_CYCLE 0x00000300 // # of cycles that dispatcher stalls due to a second
+ // unresolved branch in the instruction stream
+#define MMCR0_PMC1_IC_FETCH_MISS 0x00000340 // # of times an instruction fetch missed the L1 Icache
+#define MMCR0_PMC2_HOLD 0x00000000 // Register holds current value
+#define MMCR0_PMC2_CYCLE 0x00000001 // Processor cycles
+#define MMCR0_PMC2_INSTRUCTION 0x00000002 // # of instructions completed
+#define MMCR0_PMC2_TRANSITION 0x00000003 // # of time-base (lower) bit transitions
+#define MMCR0_PMC2_DISPATCHED 0x00000004 // # of instructions dispatched
+#define MMCR0_PMC2_IC_MISS 0x00000005 // # of L1 instruction cache misses
+#define MMCR0_PMC2_ITLB_MISS 0x00000006 // # of ITLB misses
+#define MMCR0_PMC2_L2_I_MISS 0x00000007 // # of L2 instruction misses
+#define MMCR0_PMC2_Bx_FALL_TROUGH 0x00000008 // # of fall-through branches
+#define MMCR0_PMC2_PR_SWITCH 0x00000009 // # of MSR[PR] bit toggles
+#define MMCR0_PMC2_RESERVED_LOAD 0x0000000A // # of reserved loads completed
+#define MMCR0_PMC2_LOAD_STORE 0x0000000B // # of completed loads and stores
+#define MMCR0_PMC2_SNOOP 0x0000000C // # of snoops
+#define MMCR0_PMC2_L1_CASTOUT 0x0000000D // # of L1 castouts to L2
+#define MMCR0_PMC2_SYSTEM 0x0000000E // # of completed system unit instructions
+#define MMCR0_PMC2_IC_FETCH_MISS 0x0000000F // # of instruction fetch misses in the L1
+#define MMCR0_PMC2_Bx_OUT_OF_ORDER 0x00000010 // # of branches allowing out-of-order execution
+
+/*---------------------------------------------------------------------------*
+ PMC3 Events
+ *---------------------------------------------------------------------------*/
+#define MMCR1_PMC3_HOLD 0x00000000 // Register holds current value
+#define MMCR1_PMC3_CYCLE 0x08000000 // Processor cycles
+#define MMCR1_PMC3_INSTRUCTION 0x10000000 // # of instructions completed
+#define MMCR1_PMC3_TRANSITION 0x18000000 // # of time-base (lower) bit transitions
+#define MMCR1_PMC3_DISPATCHED 0x20000000 // # of instructions dispatched
+#define MMCR1_PMC3_DC_MISS 0x28000000 // # of L1 data cache misses
+#define MMCR1_PMC3_DTLB_MISS 0x30000000 // # of DTLB misses
+#define MMCR1_PMC3_L2_D_MISS 0x38000000 // # of L2 data misses
+#define MMCR1_PMC3_Bx_TAKEN 0x40000000 // # predicted branches that were taken
+#define MMCR1_PMC3_PM_SWITCH 0x48000000 // # of transitions between marked and unmarked processes
+#define MMCR1_PMC3_COND_STORE 0x50000000 // # of store conditional instructions completed
+#define MMCR1_PMC3_FPU 0x58000000 // # of instructions completed from the FPU
+#define MMCR1_PMC3_L2_SNOOP_CASTOUT 0x60000000 // # of L2 castout caused by snoops to modified lines
+#define MMCR1_PMC3_L2_HIT 0x68000000 // # of cache operations that hit in the L2 cache
+#define MMCR1_PMC3_L1_MISS_CYCLE 0x78000000 // # of cycles generated by L1 load misses
+#define MMCR1_PMC3_Bx_SECOND 0x80000000 // # of branches in the second speculative branch
+ // resolved correctly
+#define MMCR1_PMC3_BPU_LR_CR 0x88000000 // # of cycles the BPU stalls due to LR or CR unresolved
+ // dependencies
+
+#define MMCR1_PMC4_HOLD 0x00000000 // Register holds current value
+#define MMCR1_PMC4_CYCLE 0x00400000 // Processor cycles
+#define MMCR1_PMC4_INSTRUCTION 0x00800000 // # of instructions completed
+#define MMCR1_PMC4_TRANSITION 0x00C00000 // # of time-base (lower) bit transitions
+#define MMCR1_PMC4_DISPATCHED 0x01000000 // # of instructions dispatched
+#define MMCR1_PMC4_L2_CASTOUT 0x01400000 // # of L2 castouts
+#define MMCR1_PMC4_DTLB_CYCLE 0x01800000 // # of cycles spent performing table searches for DTLB accesses
+#define MMCR1_PMC4_Bx_MISSED 0x02000000 // # of mispredicted branches
+#define MMCR1_PMC4_COND_STORE_INT 0x02800000 // # of store conditional instructions completed
+ // with reservation intact
+#define MMCR1_PMC4_SYNC 0x02C00000 // # of completed sync instructions
+#define MMCR1_PMC4_SNOOP_RETRY 0x03000000 // # of snoop request retries
+#define MMCR1_PMC4_INTEGER 0x03400000 // # of completed integer operations
+#define MMCR1_PMC4_BPU_THIRD 0x03800000 // # of cycles the BPU cannot process new branches
+ // due to having two unresolved branches
+#define MMCR1_PMC4_DC_MISS 0x07C00000 // # of L1 data cache misses
+
+/*---------------------------------------------------------------------------*
+ FPSCR bits
+ *---------------------------------------------------------------------------*/
+#ifndef FPSCR_FX
+#define FPSCR_FX 0x80000000 // Exception summary
+#define FPSCR_FEX 0x40000000 // Enabled exception summary
+#define FPSCR_VX 0x20000000 // Invalid operation
+#define FPSCR_OX 0x10000000 // Overflow exception
+#define FPSCR_UX 0x08000000 // Underflow exception
+#define FPSCR_ZX 0x04000000 // Zero divide exception
+#define FPSCR_XX 0x02000000 // Inexact exception
+#define FPSCR_VXSNAN 0x01000000 // SNaN
+#define FPSCR_VXISI 0x00800000 // Infinity - Infinity
+#define FPSCR_VXIDI 0x00400000 // Infinity / Infinity
+#define FPSCR_VXZDZ 0x00200000 // 0 / 0
+#define FPSCR_VXIMZ 0x00100000 // Infinity * 0
+#define FPSCR_VXVC 0x00080000 // Invalid compare
+#define FPSCR_FR 0x00040000 // Fraction rounded
+#define FPSCR_FI 0x00020000 // Fraction inexact
+#define FPSCR_VXSOFT 0x00000400 // Software request
+#define FPSCR_VXSQRT 0x00000200 // Invalid square root
+#define FPSCR_VXCVI 0x00000100 // Invalid integer convert
+#define FPSCR_VE 0x00000080 // Invalid operation exception enable
+#define FPSCR_OE 0x00000040 // Overflow exception enable
+#define FPSCR_UE 0x00000020 // Underflow exception enable
+#define FPSCR_ZE 0x00000010 // Zero divide exception enable
+#define FPSCR_XE 0x00000008 // Inexact exception enable
+#define FPSCR_NI 0x00000004 // Non-IEEE mode
+#endif
+
+#ifndef FPSCR_FX_BIT
+#define FPSCR_FX_BIT 0 // Exception summary
+#define FPSCR_FEX_BIT 1 // Enabled exception summary
+#define FPSCR_VX_BIT 2 // Invalid operation
+#define FPSCR_OX_BIT 3 // Overflow exception
+#define FPSCR_UX_BIT 4 // Underflow exception
+#define FPSCR_ZX_BIT 5 // Zero divide exception
+#define FPSCR_XX_BIT 6 // Inexact exception
+#define FPSCR_VXSNAN_BIT 7 // SNaN
+#define FPSCR_VXISI_BIT 8 // Infinity - Infinity
+#define FPSCR_VXIDI_BIT 9 // Infinity / Infinity
+#define FPSCR_VXZDZ_BIT 10 // 0 / 0
+#define FPSCR_VXIMZ_BIT 11 // Infinity * 0
+#define FPSCR_VXVC_BIT 12 // Invalid compare
+#define FPSCR_FR_BIT 13 // Fraction rounded
+#define FPSCR_FI_BIT 14 // Fraction inexact
+#define FPSCR_VXSOFT_BIT 21 // Software request
+#define FPSCR_VXSQRT_BIT 22 // Invalid square root
+#define FPSCR_VXCVI_BIT 23 // Invalid integer convert
+#define FPSCR_VE_BIT 24 // Invalid operation exception enable
+#define FPSCR_OE_BIT 25 // Overflow exception enable
+#define FPSCR_UE_BIT 26 // Underflow exception enable
+#define FPSCR_ZE_BIT 27 // Zero divide exception enable
+#define FPSCR_XE_BIT 28 // Inexact exception enable
+#define FPSCR_NI_BIT 29 // Non-IEEE mode
+#endif
+
+u32 PPCMfmsr();
+void PPCMtmsr(u32 newMSR);
+u32 PPCOrMsr(u32 value);
+u32 PPCMfhid0();
+void PPCMthid0(u32 newHID0);
+u32 PPCMfl2cr();
+void PPCMtl2cr(u32 newL2cr);
+void PPCMtdec(u32 newDec);
+void PPCSync();
+void PPCHalt();
+u32 PPCMffpscr();
+void PPCMtfpscr(u32 newFPSCR);
+u32 PPCMfhid2();
+void PPCMthid2(u32 newhid2);
+u32 PPCMfwpar();
+void PPCMtwpar(u32 newwpar);
+void PPCEnableSpeculation();
+void PPCDisableSpeculation();
+void PPCSetFpIEEEMode();
+void PPCSetFpNonIEEEMode();
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // _DOLPHIN_PPCARCH
diff --git a/include/dolphin/__ppc_eabi_init.h b/include/dolphin/__ppc_eabi_init.h
new file mode 100644
index 0000000..6349ce9
--- /dev/null
+++ b/include/dolphin/__ppc_eabi_init.h
@@ -0,0 +1,21 @@
+// This file was taken from the Metroid Prime decompilation project.
+// https://github.com/PrimeDecomp/prime/blob/main/include/dolphin/__ppc_eabi_init.h
+#ifndef _DOLPHIN__PPC_EABI_INIT
+#define _DOLPHIN__PPC_EABI_INIT
+
+#include "types.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+__declspec(section ".init") void __init_hardware(void);
+__declspec(section ".init") void __flush_cache(register void* address, register unsigned int size);
+
+void __init_user(void);
+void __init_cpp(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // _DOLPHIN__PPC_EABI_INIT
diff --git a/include/dolphin/__start.h b/include/dolphin/__start.h
new file mode 100644
index 0000000..07bb2bf
--- /dev/null
+++ b/include/dolphin/__start.h
@@ -0,0 +1,6 @@
+unsigned short Pad3Button : 0x800030e4;
+
+extern int main(int argc, char **argv);
+
+__declspec(section ".init") void __check_pad3(void);
+__declspec(section ".init") void __start(void);
diff --git a/include/dolphin/types.h b/include/dolphin/types.h
new file mode 100644
index 0000000..77e1053
--- /dev/null
+++ b/include/dolphin/types.h
@@ -0,0 +1,92 @@
+// This file was taken from the Metroid Prime decompilation project.
+// https://github.com/PrimeDecomp/prime/blob/main/include/dolphin/types.h
+#ifndef _DOLPHIN_TYPES
+#define _DOLPHIN_TYPES
+
+#ifdef TARGET_PC
+#include <stdint.h>
+typedef int8_t s8;
+typedef int16_t s16;
+typedef int32_t s32;
+typedef int64_t s64;
+typedef uint8_t u8;
+typedef uint16_t u16;
+typedef uint32_t u32;
+typedef uint64_t u64;
+#else
+typedef signed char s8;
+typedef signed short int s16;
+typedef signed long s32;
+typedef signed long long int s64;
+typedef unsigned char u8;
+typedef unsigned short int u16;
+typedef unsigned long u32;
+typedef unsigned long long int u64;
+#endif
+
+typedef volatile u8 vu8;
+typedef volatile u16 vu16;
+typedef volatile u32 vu32;
+typedef volatile u64 vu64;
+
+typedef volatile s8 vs8;
+typedef volatile s16 vs16;
+typedef volatile s32 vs32;
+typedef volatile s64 vs64;
+
+typedef float f32;
+typedef double f64;
+
+typedef volatile f32 vf32;
+typedef volatile f64 vf64;
+
+#if defined(TARGET_PC) && !defined(_WIN32)
+#include <stdbool.h>
+typedef bool BOOL;
+#ifndef FALSE
+#define FALSE false
+#endif
+#ifndef TRUE
+#define TRUE true
+#endif
+#else
+typedef int BOOL;
+#ifndef FALSE
+#define FALSE 0
+#endif
+#ifndef TRUE
+#define TRUE 1
+#endif
+#endif
+
+#ifdef TARGET_PC
+#include <stddef.h>
+#else
+#ifndef NULL
+#define NULL 0
+#endif
+#endif
+#if !defined(__cplusplus) || __cplusplus < 201103L
+#ifndef nullptr
+#define nullptr NULL
+#endif
+
+#if defined(__MWERKS__)
+#ifndef override
+#define override
+#endif
+#endif
+
+#endif
+
+#ifndef ATTRIBUTE_ALIGN
+#if defined(__MWERKS__) || defined(__GNUC__)
+#define ATTRIBUTE_ALIGN(num) __attribute__((aligned(num)))
+#elif defined(_MSC_VER)
+#define ATTRIBUTE_ALIGN(num)
+#else
+#error unknown compiler
+#endif
+#endif
+
+#endif // _DOLPHIN_TYPES
diff --git a/include/pso/TObject.h b/include/pso/TObject.h
new file mode 100644
index 0000000..a24b32a
--- /dev/null
+++ b/include/pso/TObject.h
@@ -0,0 +1,117 @@
+#pragma once
+typedef unsigned char u8;
+typedef unsigned short u16;
+typedef unsigned int u32;
+
+#define NULL 0
+#define OBJECT_NAMES \
+ o(TObject)
+
+
+/*#define CREATE_CTOR(type, parent_type) \
+ const char *type##_name = #type; \
+ type::type(parent_type *parent)*/
+
+class TObject {
+public:
+ const char *name;
+ u16 flags;
+ u16 id;
+ TObject *prev;
+ TObject *next;
+ TObject *up;
+ TObject *down;
+public:
+ void set_flag_0();
+ void set_flag_9();
+ u32 get_flag_9();
+ void clear_flag_9();
+
+ TObject(TObject *parent = NULL);
+ virtual ~TObject();
+
+ void *operator new (unsigned long size) { return alloc(size); };
+ void operator delete(void *ptr) { free(ptr); };
+
+ void delete_children();
+ void set_flag_0_for_each_node();
+ void run_tasks();
+ void call_func_0x10_for_each_node();
+ void call_func_0x14_for_each_node();
+ void call_func_0x10_for_each_node2();
+ void empty_func();
+ void set_parent(TObject *parent);
+
+ virtual void run_task();
+ virtual void func_0x10();
+ virtual void func_0x14();
+
+ void empty_func2();
+ void log(const char *str);
+ int get_node_count();
+ bool is_flag_0_clear_for_all_parents();
+ static void *alloc(unsigned long size);
+ static void free(void *ptr);
+ bool toggle_flag_9_if_flag_10_is_clear();
+
+private:
+ void _delete_children() {
+ while (this->down != NULL) {
+ delete this->down;
+ }
+ };
+ void add_parent(TObject *parent, bool set_parent) {
+ if (set_parent) {
+ up = parent;
+ }
+ TObject *child;
+ if (parent == NULL) {
+ this->prev = this;
+ this->next = NULL;
+ return;
+ }
+ child = parent->down;
+ if (child != NULL) {
+ this->prev = child->next;
+ this->next = NULL;
+ child->prev->next = this;
+ child->prev = this;
+ } else {
+ this->prev = this;
+ parent->down = this;
+ this->next = NULL;
+ }
+ };
+ void remove_parent() {
+ if (this->up != NULL) {
+ if (this->prev == this) {
+ this->up->down = NULL;
+ } else if (this->up->down == this) {
+ this->up->down = this->prev;
+ this->prev->next = NULL;
+ if (this->next != NULL) {
+ this->next->prev = this->next;
+ }
+ } else {
+ this->prev->next = this->next;
+ if (this->next != NULL) {
+ this->next->prev = this->prev;
+ } else {
+ this->up->down->prev = this->prev;
+ }
+ }
+ }
+ };
+
+ void set_flags(u16 flags) {
+ this->flags |= flags;
+ }
+
+ void clear_flags(u16 flags) {
+ this->flags &= ~flags;
+ }
+
+ u32 get_flags(u16 flags) {
+ return this->flags & flags;
+ };
+};
diff --git a/include/static_assert.hpp b/include/static_assert.hpp
new file mode 100644
index 0000000..daccdd3
--- /dev/null
+++ b/include/static_assert.hpp
@@ -0,0 +1,35 @@
+// This file was taken from the Metroid Prime decompilation project.
+// https://github.com/PrimeDecomp/prime/blob/main/include/static_assert.hpp
+// C++98 static assert
+
+struct false_type {
+ static const int value = 0;
+};
+
+struct true_type {
+ static const int value = 1;
+};
+
+template < int A, int B >
+struct _n_is_equal : false_type {};
+
+template < int A >
+struct _n_is_equal< A, A > : true_type {};
+
+template < class T, int N >
+struct check_sizeof : _n_is_equal< sizeof(T), N > {};
+
+#ifdef __MWERKS__
+#ifndef offsetof
+typedef unsigned long size_t;
+#define offsetof(type, member) ((size_t) & (((type*)0)->member))
+#endif
+#define CHECK_SIZEOF(cls, size) extern int cls##_check[check_sizeof< cls, size >::value];
+#define NESTED_CHECK_SIZEOF(parent, cls, size) extern int cls##_check[check_sizeof< parent::cls, size >::value];
+#define CHECK_OFFSETOF(cls, member, offset) \
+ extern int cls##_check_offset##[_n_is_equal< offsetof(cls, member), offset >::value];
+#else
+#define CHECK_SIZEOF(cls, size)
+#define NESTED_CHECK_SIZEOF(parent, cls, size)
+#define CHECK_OFFSETOF(cls, member, offset)
+#endif
diff --git a/include/types.h b/include/types.h
new file mode 100644
index 0000000..c5322e5
--- /dev/null
+++ b/include/types.h
@@ -0,0 +1,30 @@
+// This file was taken from the Metroid Prime decompilation project.
+// https://github.com/PrimeDecomp/prime/blob/main/include/types.h
+#ifndef _TYPES
+#define _TYPES
+
+#ifdef __cplusplus
+#include "static_assert.hpp"
+
+extern "C" {
+#endif
+
+#include <dolphin/types.h>
+
+// Dolphin u32 is unsigned long
+typedef unsigned int uint;
+typedef unsigned short ushort;
+typedef unsigned char uchar;
+
+// Pointer to unknown, to be determined at a later date.
+typedef void* unkptr;
+
+#define SBig(x) x
+
+#define ARRAY_SIZE(arr) static_cast< int >(sizeof(arr) / sizeof(arr[0]))
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // _TYPES
diff --git a/ldscript.lcf b/ldscript.lcf
new file mode 100644
index 0000000..fc61429
--- /dev/null
+++ b/ldscript.lcf
@@ -0,0 +1,33 @@
+MEMORY
+{
+ text : origin = 0x8000c000
+}
+
+SECTIONS
+{
+ GROUP:
+ {
+ .init ALIGN(0x20):{}
+ extab ALIGN(0x20):{}
+ extabindex ALIGN(0x20):{}
+ .text ALIGN(0x20):{}
+ .ctors ALIGN(0x20):{}
+ .dtors ALIGN(0x20):{}
+ .rodata ALIGN(0x20):{}
+ .data ALIGN(0x20):{}
+ .bss ALIGN(0x20):{}
+ .sdata ALIGN(0x20):{}
+ .sbss ALIGN(0x20):{}
+ .sdata2 ALIGN(0x20):{}
+ .sbss2 ALIGN(0x20):{}
+ .stack ALIGN(0x100):{}
+ } > text
+
+
+ _stack_addr = (_f_sbss2 + SIZEOF(.sbss2) + 65535 + 3073 + 0x7) & ~0x7;
+ _stack_end = _f_sbss2 + SIZEOF(.sbss2);
+ _db_stack_addr = (_stack_addr + 0x2000);
+ _db_stack_end = _stack_addr;
+ __ArenaLo = (_db_stack_addr + 0x1f) & ~0x1f;
+ __ArenaHi = 0x81700000;
+}
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;
+}
diff --git a/tools/mwcc_compiler/1.3.2/place-compiler-files-here b/tools/mwcc_compiler/1.3.2/place-compiler-files-here
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tools/mwcc_compiler/1.3.2/place-compiler-files-here