From a88ef2fde041e5d733b5cbe2728b15ca149d1671 Mon Sep 17 00:00:00 2001 From: mrb0nk500 Date: Sat, 28 Jan 2023 09:31:59 -0400 Subject: Initial commit --- include/__ppc_eabi_linker.h | 75 +++ include/__start.h | 46 ++ include/dolphin/OSReset.h | 1 + include/dolphin/PPCArch.h | 502 +++++++++++++++++++++ include/dolphin/__ppc_eabi_init.h | 21 + include/dolphin/__start.h | 6 + include/dolphin/types.h | 92 ++++ include/pso/TObject.h | 117 +++++ include/static_assert.hpp | 35 ++ include/types.h | 30 ++ ldscript.lcf | 33 ++ 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 + .../mwcc_compiler/1.3.2/place-compiler-files-here | 0 20 files changed, 1519 insertions(+) create mode 100644 include/__ppc_eabi_linker.h create mode 100644 include/__start.h create mode 100644 include/dolphin/OSReset.h create mode 100644 include/dolphin/PPCArch.h create mode 100644 include/dolphin/__ppc_eabi_init.h create mode 100644 include/dolphin/__start.h create mode 100644 include/dolphin/types.h create mode 100644 include/pso/TObject.h create mode 100644 include/static_assert.hpp create mode 100644 include/types.h create mode 100644 ldscript.lcf 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 create mode 100644 tools/mwcc_compiler/1.3.2/place-compiler-files-here 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 +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 +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 +#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 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 -- cgit v1.2.3-13-gbd6f