From 393303dca7dc131b1a52cbc801fa8d394bc6d738 Mon Sep 17 00:00:00 2001 From: dbalatoni13 Date: Tue, 12 Nov 2024 04:48:22 +0100 Subject: [PATCH 1/3] Fixed dolphin/DEMOPuts.c --- configure.py | 2 +- src/dolphin/demo/DEMOPuts.c | 30 +++++++++++++++--------------- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/configure.py b/configure.py index 7c6f1fe0..5e8750df 100644 --- a/configure.py +++ b/configure.py @@ -523,7 +523,7 @@ config.libs = [ [ Object(Matching, "dolphin/demo/DEMOInit.c"), Object(Matching, "dolphin/demo/DEMOFont.c"), - Object(NonMatching, "dolphin/demo/DEMOPuts.c"), + Object(Matching, "dolphin/demo/DEMOPuts.c"), Object(Matching, "dolphin/demo/DEMOStats.c"), ], ), diff --git a/src/dolphin/demo/DEMOPuts.c b/src/dolphin/demo/DEMOPuts.c index 3b7e84bc..618152e5 100644 --- a/src/dolphin/demo/DEMOPuts.c +++ b/src/dolphin/demo/DEMOPuts.c @@ -37,22 +37,22 @@ void DEMOSetFontType(DMFontType attr) void DEMOLoadFont(enum _GXTexMapID texMap, enum _GXTexMtx texMtx, DMTexFlt texFlt) { - // float fontTMtx[3][4]; - // unsigned short width; - // unsigned short height; + float fontTMtx[3][4]; + unsigned short width; + unsigned short height; - // width = 64; - // height = 0x1800 / width; - // GXInitTexObj(&fontTexObj, (void *)DEMOFontBitmap, width, (u16)height, 0, 0, 0, 0); - // if (texFlt == 0) { - // GXInitTexObjLOD(&fontTexObj, 0, 0, 0, 0, 0, 0.0f, 0.0f, 0.0f); - // fontShift = 0; - // } - // GXLoadTexObj(&fontTexObj, texMap); - // MTXScale(fontTMtx, 1.0f / (width - fontShift), 1.0f / ((u16)height - !fontShift), 1.0f); - // GXLoadTexMtxImm(fontTMtx, texMtx, 1); - // GXSetNumTexGens(1); - // GXSetTexCoordGen(0, 1, 4, texMtx); + width = 64; + height = 0x1800 / width; + GXInitTexObj(&fontTexObj, (void *)DEMOFontBitmap, width, (u16)height, 0, 0, 0, 0); + if (texFlt == 0) { + GXInitTexObjLOD(&fontTexObj, 0, 0, 0, 0, 0, 0.0f, 0.0f, 0.0f); + fontShift = 0; + } + GXLoadTexObj(&fontTexObj, texMap); + MTXScale(fontTMtx, 1.0f / width, 1.0f / height, 1.0f); + GXLoadTexMtxImm(fontTMtx, texMtx, 1); + GXSetNumTexGens(1); + GXSetTexCoordGen(0, 1, 4, texMtx); } void DEMOSetupScrnSpc(long width, long height, float depth) From 023cd9067566efa0e968c9c6e90cabcb43856c21 Mon Sep 17 00:00:00 2001 From: dbalatoni13 Date: Tue, 12 Nov 2024 18:21:21 +0100 Subject: [PATCH 2/3] Correct the length of string symbols --- config/GMPE01_00/rels/E3setupDLL/symbols.txt | 6 +- config/GMPE01_00/rels/m404Dll/symbols.txt | 4 +- config/GMPE01_00/rels/m406Dll/symbols.txt | 4 +- config/GMPE01_00/rels/m410Dll/symbols.txt | 6 +- config/GMPE01_00/rels/m412Dll/symbols.txt | 2 +- config/GMPE01_00/rels/m420dll/symbols.txt | 2 +- config/GMPE01_00/rels/m432Dll/symbols.txt | 10 +-- config/GMPE01_00/rels/m438Dll/symbols.txt | 2 +- config/GMPE01_00/rels/m440Dll/symbols.txt | 2 +- config/GMPE01_00/rels/m442Dll/symbols.txt | 4 +- config/GMPE01_00/rels/m443Dll/symbols.txt | 2 +- config/GMPE01_00/rels/m446dll/symbols.txt | 10 +-- config/GMPE01_00/rels/m450Dll/symbols.txt | 16 ++--- config/GMPE01_00/rels/m453Dll/symbols.txt | 2 +- config/GMPE01_00/rels/mentDll/symbols.txt | 4 +- config/GMPE01_00/rels/mpexDll/symbols.txt | 10 +-- config/GMPE01_00/rels/present/symbols.txt | 6 +- config/GMPE01_00/rels/w05Dll/symbols.txt | 4 +- config/GMPE01_00/rels/w10Dll/symbols.txt | 2 +- config/GMPE01_00/rels/ztardll/symbols.txt | 2 +- config/GMPE01_00/symbols.txt | 68 +++++++++++++++----- src/REL/E3setupDLL/mgselect.c | 6 +- 22 files changed, 104 insertions(+), 70 deletions(-) diff --git a/config/GMPE01_00/rels/E3setupDLL/symbols.txt b/config/GMPE01_00/rels/E3setupDLL/symbols.txt index da0474aa..4089dcf6 100644 --- a/config/GMPE01_00/rels/E3setupDLL/symbols.txt +++ b/config/GMPE01_00/rels/E3setupDLL/symbols.txt @@ -131,11 +131,11 @@ lbl_2_data_151 = .data:0x00000151; // type:object size:0x16 data:string lbl_2_data_167 = .data:0x00000167; // type:object size:0x16 data:string lbl_2_data_17D = .data:0x0000017D; // type:object size:0x16 data:string lbl_2_data_193 = .data:0x00000193; // type:object size:0x16 data:string -lbl_2_data_1A9 = .data:0x000001A9; // type:object size:0x17 data:string +lbl_2_data_1A9 = .data:0x000001A9; // type:object size:0x16 data:string mgNameTestTbl = .data:0x000001C0; // type:object size:0x34 scope:local cursorYOfsTbl = .data:0x000001F4; // type:object size:0x14 scope:local data:float mgPicTbl = .data:0x00000208; // type:object size:0x34 scope:local -startText = .data:0x0000023C; // type:object size:0x14 scope:local data:string +startText = .data:0x0000023C; // type:object size:0x10 scope:local data:string shadowPos = .data:0x00000250; // type:object size:0xC scope:local shadowTarget = .data:0x0000025C; // type:object size:0xC scope:local shadowUp = .data:0x00000268; // type:object size:0xC scope:local @@ -148,7 +148,7 @@ lbl_2_data_31E = .data:0x0000031E; // type:object size:0x8 playerCntMessTbl = .data:0x00000328; // type:object size:0x10 scope:local charPosTbl = .data:0x00000338; // type:object size:0x40 scope:local data:float charComSfxTbl = .data:0x00000378; // type:object size:0x20 scope:local -lbl_2_data_398 = .data:0x00000398; // type:object size:0x10 scope:local data:string +lbl_2_data_398 = .data:0x00000398; // type:object size:0xF scope:local data:string charSpriteTbl = .data:0x000003A8; // type:object size:0x20 scope:local cursorSpriteTbl = .data:0x000003C8; // type:object size:0x14 scope:local hiliteSprTbl = .data:0x000003DC; // type:object size:0x14 scope:local diff --git a/config/GMPE01_00/rels/m404Dll/symbols.txt b/config/GMPE01_00/rels/m404Dll/symbols.txt index 06571197..dd934235 100644 --- a/config/GMPE01_00/rels/m404Dll/symbols.txt +++ b/config/GMPE01_00/rels/m404Dll/symbols.txt @@ -113,7 +113,7 @@ lbl_1_data_77C = .data:0x0000077C; // type:object size:0xC data:float lbl_1_data_788 = .data:0x00000788; // type:object size:0x4 lbl_1_data_78C = .data:0x0000078C; // type:object size:0xC data:float lbl_1_data_798 = .data:0x00000798; // type:object size:0xC data:float -lbl_1_data_7A4 = .data:0x000007A4; // type:object size:0x24 scope:local data:string +lbl_1_data_7A4 = .data:0x000007A4; // type:object size:0x23 scope:local data:string lbl_1_data_7C8 = .data:0x000007C8; // type:object size:0x4 data:4byte jumptable_1_data_7CC = .data:0x000007CC; // type:object size:0x28 scope:local lbl_1_data_7F4 = .data:0x000007F4; // type:object size:0x1C scope:local data:string @@ -128,7 +128,7 @@ lbl_1_data_8D8 = .data:0x000008D8; // type:object size:0x10 data:float lbl_1_data_8E8 = .data:0x000008E8; // type:object size:0xC lbl_1_data_8F4 = .data:0x000008F4; // type:object size:0x8 data:2byte lbl_1_data_8FC = .data:0x000008FC; // type:object size:0x18 -lbl_1_data_914 = .data:0x00000914; // type:object size:0x1C scope:local data:string +lbl_1_data_914 = .data:0x00000914; // type:object size:0x19 scope:local data:string lbl_1_data_930 = .data:0x00000930; // type:object size:0x20 lbl_1_data_950 = .data:0x00000950; // type:object size:0x20 lbl_1_data_970 = .data:0x00000970; // type:object size:0x7 scope:local data:string diff --git a/config/GMPE01_00/rels/m406Dll/symbols.txt b/config/GMPE01_00/rels/m406Dll/symbols.txt index 5697d866..1287dc3c 100644 --- a/config/GMPE01_00/rels/m406Dll/symbols.txt +++ b/config/GMPE01_00/rels/m406Dll/symbols.txt @@ -340,7 +340,7 @@ lbl_1_rodata_430 = .rodata:0x00000430; // type:object size:0x4 scope:local data: lbl_1_rodata_434 = .rodata:0x00000434; // type:object size:0x4 scope:local data:float lbl_1_rodata_438 = .rodata:0x00000438; // type:object size:0x4 scope:local data:float lbl_1_data_0 = .data:0x00000000; // type:object size:0x8C data:float -lbl_1_data_8C = .data:0x0000008C; // type:object size:0x24 scope:local data:string +lbl_1_data_8C = .data:0x0000008C; // type:object size:0x23 scope:local data:string jumptable_1_data_B0 = .data:0x000000B0; // type:object size:0x40 scope:local lbl_1_data_F0 = .data:0x000000F0; // type:object size:0x348 lbl_1_data_438 = .data:0x00000438; // type:object size:0x348 @@ -378,7 +378,7 @@ lbl_1_data_FF0 = .data:0x00000FF0; // type:object size:0x10 lbl_1_data_1000 = .data:0x00001000; // type:object size:0x19 scope:local data:string lbl_1_data_1019 = .data:0x00001019; // type:object size:0x19 scope:local data:string lbl_1_data_1032 = .data:0x00001032; // type:object size:0x1A scope:local data:string -lbl_1_data_104C = .data:0x0000104C; // type:object size:0x1C scope:local data:string +lbl_1_data_104C = .data:0x0000104C; // type:object size:0x1A scope:local data:string lbl_1_data_1068 = .data:0x00001068; // type:object size:0x10 lbl_1_data_1078 = .data:0x00001078; // type:object size:0x28 lbl_1_data_10A0 = .data:0x000010A0; // type:object size:0x80 data:4byte diff --git a/config/GMPE01_00/rels/m410Dll/symbols.txt b/config/GMPE01_00/rels/m410Dll/symbols.txt index 9403fd83..b0cd6c90 100644 --- a/config/GMPE01_00/rels/m410Dll/symbols.txt +++ b/config/GMPE01_00/rels/m410Dll/symbols.txt @@ -277,13 +277,13 @@ lbl_1_data_88 = .data:0x00000088; // type:object size:0x3C data:float lbl_1_data_C4 = .data:0x000000C4; // type:object size:0x14 lbl_1_data_D8 = .data:0x000000D8; // type:object size:0x2 data:2byte lbl_1_data_DC = .data:0x000000DC; // type:object size:0x20 -lbl_1_data_FC = .data:0x000000FC; // type:object size:0x8 scope:local data:string +lbl_1_data_FC = .data:0x000000FC; // type:object size:0x7 scope:local data:string lbl_1_data_104 = .data:0x00000104; // type:object size:0xC lbl_1_data_110 = .data:0x00000110; // type:object size:0x4 data:4byte lbl_1_data_114 = .data:0x00000114; // type:object size:0x16 scope:local data:string -lbl_1_data_130 = .data:0x00000130; // type:object size:0x10 scope:local data:string +lbl_1_data_130 = .data:0x00000130; // type:object size:0xF scope:local data:string lbl_1_data_140 = .data:0x00000140; // type:object size:0x20 -lbl_1_data_160 = .data:0x00000160; // type:object size:0xC scope:local data:string +lbl_1_data_160 = .data:0x00000160; // type:object size:0xB scope:local data:string lbl_1_data_16C = .data:0x0000016C; // type:object size:0x20 lbl_1_data_18C = .data:0x0000018C; // type:object size:0x20 lbl_1_data_1AC = .data:0x000001AC; // type:object size:0x28 diff --git a/config/GMPE01_00/rels/m412Dll/symbols.txt b/config/GMPE01_00/rels/m412Dll/symbols.txt index f6b625d3..95938828 100644 --- a/config/GMPE01_00/rels/m412Dll/symbols.txt +++ b/config/GMPE01_00/rels/m412Dll/symbols.txt @@ -160,7 +160,7 @@ lbl_1_data_284 = .data:0x00000284; // type:object size:0x14 scope:local data:str lbl_1_data_298 = .data:0x00000298; // type:object size:0x5C lbl_1_data_2F4 = .data:0x000002F4; // type:object size:0xC scope:local data:string lbl_1_data_300 = .data:0x00000300; // type:object size:0x7 scope:local data:string -lbl_1_data_307 = .data:0x00000307; // type:object size:0x6 scope:local data:string +lbl_1_data_307 = .data:0x00000307; // type:object size:0x7 scope:local data:string lbl_1_data_310 = .data:0x00000310; // type:object size:0x30 lbl_1_data_340 = .data:0x00000340; // type:object size:0x8 lbl_1_data_348 = .data:0x00000348; // type:object size:0x18 diff --git a/config/GMPE01_00/rels/m420dll/symbols.txt b/config/GMPE01_00/rels/m420dll/symbols.txt index 365355d3..096cbad2 100644 --- a/config/GMPE01_00/rels/m420dll/symbols.txt +++ b/config/GMPE01_00/rels/m420dll/symbols.txt @@ -205,7 +205,7 @@ lbl_1_rodata_564 = .rodata:0x00000564; // type:object size:0x4 scope:local data: lbl_1_rodata_568 = .rodata:0x00000568; // type:object size:0x8 scope:local data:float lbl_1_data_0 = .data:0x00000000; // type:object size:0x1E scope:local data:string lbl_1_data_1E = .data:0x0000001E; // type:object size:0x1E scope:local data:string -lbl_1_data_3C = .data:0x0000003C; // type:object size:0x11 scope:local data:string +lbl_1_data_3C = .data:0x0000003C; // type:object size:0x10 scope:local data:string lbl_1_data_50 = .data:0x00000050; // type:object size:0x80 lbl_1_data_D0 = .data:0x000000D0; // type:object size:0x1B scope:local data:string lbl_1_data_EC = .data:0x000000EC; // type:object size:0x30 diff --git a/config/GMPE01_00/rels/m432Dll/symbols.txt b/config/GMPE01_00/rels/m432Dll/symbols.txt index 4926357c..c01d6777 100644 --- a/config/GMPE01_00/rels/m432Dll/symbols.txt +++ b/config/GMPE01_00/rels/m432Dll/symbols.txt @@ -264,7 +264,7 @@ lbl_1_data_407 = .data:0x00000407; // type:object size:0xB scope:local data:stri lbl_1_data_412 = .data:0x00000412; // type:object size:0xB scope:local data:string lbl_1_data_41D = .data:0x0000041D; // type:object size:0xB scope:local data:string lbl_1_data_428 = .data:0x00000428; // type:object size:0xB scope:local data:string -lbl_1_data_433 = .data:0x00000433; // type:object size:0xD scope:local data:string +lbl_1_data_433 = .data:0x00000433; // type:object size:0xB scope:local data:string lbl_1_data_440 = .data:0x00000440; // type:object size:0x18 data:4byte lbl_1_data_458 = .data:0x00000458; // type:object size:0xB scope:local data:string lbl_1_data_463 = .data:0x00000463; // type:object size:0xB scope:local data:string @@ -275,7 +275,7 @@ lbl_1_data_48F = .data:0x0000048F; // type:object size:0xB scope:local data:stri lbl_1_data_49A = .data:0x0000049A; // type:object size:0xB scope:local data:string lbl_1_data_4A5 = .data:0x000004A5; // type:object size:0xB scope:local data:string lbl_1_data_4B0 = .data:0x000004B0; // type:object size:0xB scope:local data:string -lbl_1_data_4BB = .data:0x000004BB; // type:object size:0xD scope:local data:string +lbl_1_data_4BB = .data:0x000004BB; // type:object size:0xB scope:local data:string lbl_1_data_4C8 = .data:0x000004C8; // type:object size:0x28 data:4byte lbl_1_data_4F0 = .data:0x000004F0; // type:object size:0x14 data:byte lbl_1_data_504 = .data:0x00000504; // type:object size:0x24 data:byte @@ -302,7 +302,7 @@ lbl_1_data_EA4 = .data:0x00000EA4; // type:object size:0xB scope:local data:stri lbl_1_data_EAF = .data:0x00000EAF; // type:object size:0xB scope:local data:string lbl_1_data_EBA = .data:0x00000EBA; // type:object size:0xB scope:local data:string lbl_1_data_EC5 = .data:0x00000EC5; // type:object size:0xB scope:local data:string -lbl_1_data_ED0 = .data:0x00000ED0; // type:object size:0xC scope:local data:string +lbl_1_data_ED0 = .data:0x00000ED0; // type:object size:0xB scope:local data:string lbl_1_data_EDC = .data:0x00000EDC; // type:object size:0x8B8 lbl_1_data_1794 = .data:0x00001794; // type:object size:0x20 lbl_1_data_17B4 = .data:0x000017B4; // type:object size:0x20 @@ -318,11 +318,11 @@ lbl_1_data_18BA = .data:0x000018BA; // type:object size:0x18 scope:local data:st lbl_1_data_18D2 = .data:0x000018D2; // type:object size:0xC scope:local data:string lbl_1_data_18DE = .data:0x000018DE; // type:object size:0x6 scope:local data:string lbl_1_data_18E4 = .data:0x000018E4; // type:object size:0x21 scope:local data:string -lbl_1_data_1905 = .data:0x00001905; // type:object size:0x1F scope:local data:string +lbl_1_data_1905 = .data:0x00001905; // type:object size:0x1D scope:local data:string jumptable_1_data_1924 = .data:0x00001924; // type:object size:0x1C scope:local jumptable_1_data_1940 = .data:0x00001940; // type:object size:0x44 scope:local lbl_1_data_1984 = .data:0x00001984; // type:object size:0xB scope:local data:string -lbl_1_data_198F = .data:0x0000198F; // type:object size:0x1D scope:local data:string +lbl_1_data_198F = .data:0x0000198F; // type:object size:0x1B scope:local data:string jumptable_1_data_19AC = .data:0x000019AC; // type:object size:0x28 scope:local lbl_1_data_19D4 = .data:0x000019D4; // type:object size:0x24 scope:local data:string lbl_1_bss_0 = .bss:0x00000000; // type:object size:0x3F0 data:float diff --git a/config/GMPE01_00/rels/m438Dll/symbols.txt b/config/GMPE01_00/rels/m438Dll/symbols.txt index 8b3796d8..dfbd3109 100644 --- a/config/GMPE01_00/rels/m438Dll/symbols.txt +++ b/config/GMPE01_00/rels/m438Dll/symbols.txt @@ -381,7 +381,7 @@ lbl_1_data_18 = .data:0x00000018; // type:object size:0x4 lbl_1_data_1C = .data:0x0000001C; // type:object size:0xC lbl_1_data_28 = .data:0x00000028; // type:object size:0xC lbl_1_data_34 = .data:0x00000034; // type:object size:0xC -lbl_1_data_40 = .data:0x00000040; // type:object size:0x24 data:string +lbl_1_data_40 = .data:0x00000040; // type:object size:0x23 data:string lbl_1_data_64 = .data:0x00000064; // type:object size:0x4 data:4byte lbl_1_data_68 = .data:0x00000068; // type:object size:0x420 lbl_1_data_488 = .data:0x00000488; // type:object size:0x2C diff --git a/config/GMPE01_00/rels/m440Dll/symbols.txt b/config/GMPE01_00/rels/m440Dll/symbols.txt index 1457a3b2..8cff0e70 100644 --- a/config/GMPE01_00/rels/m440Dll/symbols.txt +++ b/config/GMPE01_00/rels/m440Dll/symbols.txt @@ -247,7 +247,7 @@ lbl_1_data_104 = .data:0x00000104; // type:object size:0x2 data:2byte lbl_1_data_108 = .data:0x00000108; // type:object size:0x2 data:2byte lbl_1_data_10C = .data:0x0000010C; // type:object size:0x12 lbl_1_data_11E = .data:0x0000011E; // type:object size:0x13 scope:local data:string -lbl_1_data_131 = .data:0x00000131; // type:object size:0x18 scope:local data:string +lbl_1_data_131 = .data:0x00000131; // type:object size:0x17 scope:local data:string lbl_1_data_149 = .data:0x00000149; // type:object size:0x19 scope:local data:string lbl_1_data_162 = .data:0x00000162; // type:object size:0x1C scope:local data:string lbl_1_data_17E = .data:0x0000017E; // type:object size:0x10 scope:local data:string diff --git a/config/GMPE01_00/rels/m442Dll/symbols.txt b/config/GMPE01_00/rels/m442Dll/symbols.txt index c4f962cc..e5e664a3 100644 --- a/config/GMPE01_00/rels/m442Dll/symbols.txt +++ b/config/GMPE01_00/rels/m442Dll/symbols.txt @@ -167,14 +167,14 @@ lbl_1_data_60 = .data:0x00000060; // type:object size:0xC data:float lbl_1_data_6C = .data:0x0000006C; // type:object size:0x4 data:byte lbl_1_data_70 = .data:0x00000070; // type:object size:0xC data:float lbl_1_data_7C = .data:0x0000007C; // type:object size:0xC data:float -lbl_1_data_88 = .data:0x00000088; // type:object size:0x24 scope:local data:string +lbl_1_data_88 = .data:0x00000088; // type:object size:0x23 scope:local data:string lbl_1_data_AC = .data:0x000000AC; // type:object size:0x4 data:4byte jumptable_1_data_B0 = .data:0x000000B0; // type:object size:0x30 scope:local lbl_1_data_E0 = .data:0x000000E0; // type:object size:0x1C scope:local data:string lbl_1_data_FC = .data:0x000000FC; // type:object size:0x1C data:4byte lbl_1_data_118 = .data:0x00000118; // type:object size:0x8 data:4byte lbl_1_data_120 = .data:0x00000120; // type:object size:0x30 data:float -lbl_1_data_150 = .data:0x00000150; // type:object size:0x1A scope:local data:string +lbl_1_data_150 = .data:0x00000150; // type:object size:0x19 scope:local data:string lbl_1_data_16A = .data:0x0000016A; // type:object size:0x20 data:2byte lbl_1_data_18A = .data:0x0000018A; // type:object size:0x14 data:2byte lbl_1_data_1A0 = .data:0x000001A0; // type:object size:0xC data:4byte diff --git a/config/GMPE01_00/rels/m443Dll/symbols.txt b/config/GMPE01_00/rels/m443Dll/symbols.txt index 66c15dad..ed466311 100644 --- a/config/GMPE01_00/rels/m443Dll/symbols.txt +++ b/config/GMPE01_00/rels/m443Dll/symbols.txt @@ -307,7 +307,7 @@ lbl_1_data_3C4 = .data:0x000003C4; // type:object size:0x30 lbl_1_data_3F4 = .data:0x000003F4; // type:object size:0x5 scope:local data:string lbl_1_data_3F9 = .data:0x000003F9; // type:object size:0x7 scope:local data:string lbl_1_data_400 = .data:0x00000400; // type:object size:0x7 scope:local data:string -lbl_1_data_407 = .data:0x00000407; // type:object size:0x9 scope:local data:string +lbl_1_data_407 = .data:0x00000407; // type:object size:0x7 scope:local data:string lbl_1_data_410 = .data:0x00000410; // type:object size:0x58 lbl_1_data_468 = .data:0x00000468; // type:object size:0x20 lbl_1_data_488 = .data:0x00000488; // type:object size:0x58 diff --git a/config/GMPE01_00/rels/m446dll/symbols.txt b/config/GMPE01_00/rels/m446dll/symbols.txt index e9879dc0..b1e4494c 100644 --- a/config/GMPE01_00/rels/m446dll/symbols.txt +++ b/config/GMPE01_00/rels/m446dll/symbols.txt @@ -260,22 +260,22 @@ lbl_1_data_150 = .data:0x00000150; // type:object size:0xC lbl_1_data_15C = .data:0x0000015C; // type:object size:0x20 scope:local jumptable_1_data_17C = .data:0x0000017C; // type:object size:0x2C scope:local lbl_1_data_1A8 = .data:0x000001A8; // type:object size:0x1F scope:local data:string -lbl_1_data_1C7 = .data:0x000001C7; // type:object size:0x1F scope:local data:string +lbl_1_data_1C7 = .data:0x000001C7; // type:object size:0x1E scope:local data:string lbl_1_data_1E8 = .data:0x000001E8; // type:object size:0x1E scope:local data:string -lbl_1_data_206 = .data:0x00000206; // type:object size:0x22 scope:local data:string +lbl_1_data_206 = .data:0x00000206; // type:object size:0x1E scope:local data:string lbl_1_data_228 = .data:0x00000228; // type:object size:0x24 lbl_1_data_24C = .data:0x0000024C; // type:object size:0x90 lbl_1_data_2DC = .data:0x000002DC; // type:object size:0x14 lbl_1_data_2F0 = .data:0x000002F0; // type:object size:0x1F scope:local data:string lbl_1_data_30F = .data:0x0000030F; // type:object size:0x1F scope:local data:string -lbl_1_data_32E = .data:0x0000032E; // type:object size:0x22 scope:local data:string +lbl_1_data_32E = .data:0x0000032E; // type:object size:0x1F scope:local data:string jumptable_1_data_350 = .data:0x00000350; // type:object size:0x1C scope:local lbl_1_data_370 = .data:0x00000370; // type:object size:0xC data:float lbl_1_data_37C = .data:0x0000037C; // type:object size:0x1E scope:local data:string lbl_1_data_39A = .data:0x0000039A; // type:object size:0x1E scope:local data:string -lbl_1_data_3B8 = .data:0x000003B8; // type:object size:0x10 scope:local data:string +lbl_1_data_3B8 = .data:0x000003B8; // type:object size:0xE scope:local data:string lbl_1_data_3C8 = .data:0x000003C8; // type:object size:0x24 -lbl_1_data_3EC = .data:0x000003EC; // type:object size:0x24 scope:local data:string +lbl_1_data_3EC = .data:0x000003EC; // type:object size:0x1F scope:local data:string lbl_1_data_410 = .data:0x00000410; // type:object size:0x14 lbl_1_data_424 = .data:0x00000424; // type:object size:0x3C lbl_1_data_460 = .data:0x00000460; // type:object size:0x54 data:byte diff --git a/config/GMPE01_00/rels/m450Dll/symbols.txt b/config/GMPE01_00/rels/m450Dll/symbols.txt index 6adc8754..37af9137 100644 --- a/config/GMPE01_00/rels/m450Dll/symbols.txt +++ b/config/GMPE01_00/rels/m450Dll/symbols.txt @@ -367,7 +367,7 @@ lbl_1_data_2B6 = .data:0x000002B6; // type:object size:0x13 scope:local data:str lbl_1_data_2C9 = .data:0x000002C9; // type:object size:0x14 scope:local data:string lbl_1_data_2DD = .data:0x000002DD; // type:object size:0x1C scope:local data:string lbl_1_data_2F9 = .data:0x000002F9; // type:object size:0x12 scope:local data:string -lbl_1_data_30B = .data:0x0000030B; // type:object size:0x11 scope:local data:string +lbl_1_data_30B = .data:0x0000030B; // type:object size:0xE scope:local data:string jumptable_1_data_31C = .data:0x0000031C; // type:object size:0x60 scope:local lbl_1_data_37C = .data:0x0000037C; // type:object size:0x12 scope:local data:string lbl_1_data_38E = .data:0x0000038E; // type:object size:0x12 scope:local data:string @@ -375,9 +375,9 @@ lbl_1_data_3A0 = .data:0x000003A0; // type:object size:0x13 scope:local data:str lbl_1_data_3B3 = .data:0x000003B3; // type:object size:0x14 scope:local data:string lbl_1_data_3C7 = .data:0x000003C7; // type:object size:0x14 scope:local data:string lbl_1_data_3DB = .data:0x000003DB; // type:object size:0x13 scope:local data:string -lbl_1_data_3EE = .data:0x000003EE; // type:object size:0x1E scope:local data:string +lbl_1_data_3EE = .data:0x000003EE; // type:object size:0x1C scope:local data:string jumptable_1_data_40C = .data:0x0000040C; // type:object size:0x44 scope:local -lbl_1_data_450 = .data:0x00000450; // type:object size:0x14 scope:local data:string +lbl_1_data_450 = .data:0x00000450; // type:object size:0x12 scope:local data:string lbl_1_data_464 = .data:0x00000464; // type:object size:0xC data:4byte lbl_1_data_470 = .data:0x00000470; // type:object size:0xC lbl_1_data_47C = .data:0x0000047C; // type:object size:0xC data:4byte @@ -411,7 +411,7 @@ lbl_1_data_9EC = .data:0x000009EC; // type:object size:0x20 lbl_1_data_A0C = .data:0x00000A0C; // type:object size:0x38 data:4byte lbl_1_data_A44 = .data:0x00000A44; // type:object size:0x13 scope:local data:string lbl_1_data_A57 = .data:0x00000A57; // type:object size:0x13 scope:local data:string -lbl_1_data_A6A = .data:0x00000A6A; // type:object size:0x16 scope:local data:string +lbl_1_data_A6A = .data:0x00000A6A; // type:object size:0x13 scope:local data:string lbl_1_data_A80 = .data:0x00000A80; // type:object size:0x18C lbl_1_data_C0C = .data:0x00000C0C; // type:object size:0x13 scope:local data:string lbl_1_data_C1F = .data:0x00000C1F; // type:object size:0x13 scope:local data:string @@ -422,7 +422,7 @@ lbl_1_data_E10 = .data:0x00000E10; // type:object size:0x11 scope:local data:str lbl_1_data_E21 = .data:0x00000E21; // type:object size:0x11 scope:local data:string lbl_1_data_E32 = .data:0x00000E32; // type:object size:0x11 scope:local data:string lbl_1_data_E43 = .data:0x00000E43; // type:object size:0x11 scope:local data:string -lbl_1_data_E54 = .data:0x00000E54; // type:object size:0x14 scope:local data:string +lbl_1_data_E54 = .data:0x00000E54; // type:object size:0x11 scope:local data:string lbl_1_data_E68 = .data:0x00000E68; // type:object size:0x14 lbl_1_data_E7C = .data:0x00000E7C; // type:object size:0x84 lbl_1_data_F00 = .data:0x00000F00; // type:object size:0x5C @@ -466,7 +466,7 @@ lbl_1_data_12FC = .data:0x000012FC; // type:object size:0x13 scope:local data:st lbl_1_data_130F = .data:0x0000130F; // type:object size:0x13 scope:local data:string lbl_1_data_1322 = .data:0x00001322; // type:object size:0x13 scope:local data:string lbl_1_data_1335 = .data:0x00001335; // type:object size:0x13 scope:local data:string -lbl_1_data_1348 = .data:0x00001348; // type:object size:0x14 scope:local data:string +lbl_1_data_1348 = .data:0x00001348; // type:object size:0x13 scope:local data:string lbl_1_data_135C = .data:0x0000135C; // type:object size:0x24 lbl_1_data_1380 = .data:0x00001380; // type:object size:0x38 data:4byte lbl_1_data_13B8 = .data:0x000013B8; // type:object size:0x38 data:4byte @@ -474,7 +474,7 @@ lbl_1_data_13F0 = .data:0x000013F0; // type:object size:0x13 scope:local data:st lbl_1_data_1403 = .data:0x00001403; // type:object size:0x13 scope:local data:string lbl_1_data_1416 = .data:0x00001416; // type:object size:0x13 scope:local data:string lbl_1_data_1429 = .data:0x00001429; // type:object size:0x13 scope:local data:string -lbl_1_data_143C = .data:0x0000143C; // type:object size:0x14 scope:local data:string +lbl_1_data_143C = .data:0x0000143C; // type:object size:0x13 scope:local data:string lbl_1_data_1450 = .data:0x00001450; // type:object size:0xB4 lbl_1_data_1504 = .data:0x00001504; // type:object size:0x50 lbl_1_data_1554 = .data:0x00001554; // type:object size:0x13 scope:local data:string @@ -491,7 +491,7 @@ lbl_1_data_161F = .data:0x0000161F; // type:object size:0xE scope:local data:str lbl_1_data_162D = .data:0x0000162D; // type:object size:0x6 scope:local data:string lbl_1_data_1633 = .data:0x00001633; // type:object size:0x1D scope:local data:string jumptable_1_data_1650 = .data:0x00001650; // type:object size:0x70 scope:local -lbl_1_data_16C0 = .data:0x000016C0; // type:object size:0x1C scope:local data:string +lbl_1_data_16C0 = .data:0x000016C0; // type:object size:0x1B scope:local data:string jumptable_1_data_16DC = .data:0x000016DC; // type:object size:0xC4 scope:local lbl_1_data_17A0 = .data:0x000017A0; // type:object size:0x24 scope:local data:string lbl_1_bss_0 = .bss:0x00000000; // type:object size:0x4 data:4byte diff --git a/config/GMPE01_00/rels/m453Dll/symbols.txt b/config/GMPE01_00/rels/m453Dll/symbols.txt index 518e286d..298e2fb6 100644 --- a/config/GMPE01_00/rels/m453Dll/symbols.txt +++ b/config/GMPE01_00/rels/m453Dll/symbols.txt @@ -213,7 +213,7 @@ lbl_1_data_0 = .data:0x00000000; // type:object size:0x2 data:2byte lbl_1_data_4 = .data:0x00000004; // type:object size:0xC lbl_1_data_10 = .data:0x00000010; // type:object size:0xC lbl_1_data_1C = .data:0x0000001C; // type:object size:0x28 -lbl_1_data_44 = .data:0x00000044; // type:object size:0x24 scope:local data:string +lbl_1_data_44 = .data:0x00000044; // type:object size:0x23 scope:local data:string lbl_1_data_68 = .data:0x00000068; // type:object size:0x24 data:4byte jumptable_1_data_8C = .data:0x0000008C; // type:object size:0x1C scope:local jumptable_1_data_A8 = .data:0x000000A8; // type:object size:0x1C scope:local diff --git a/config/GMPE01_00/rels/mentDll/symbols.txt b/config/GMPE01_00/rels/mentDll/symbols.txt index e29109dd..fe98fd1f 100644 --- a/config/GMPE01_00/rels/mentDll/symbols.txt +++ b/config/GMPE01_00/rels/mentDll/symbols.txt @@ -392,7 +392,7 @@ lbl_1_data_245 = .data:0x00000245; // type:object size:0x1D scope:local data:str lbl_1_data_262 = .data:0x00000262; // type:object size:0x14 scope:local data:string lbl_1_data_276 = .data:0x00000276; // type:object size:0x15 scope:local data:string lbl_1_data_28B = .data:0x0000028B; // type:object size:0x14 scope:local data:string -lbl_1_data_29F = .data:0x0000029F; // type:object size:0x15 scope:local data:string +lbl_1_data_29F = .data:0x0000029F; // type:object size:0x14 scope:local data:string lbl_1_data_2B4 = .data:0x000002B4; // type:object size:0x3C lbl_1_data_2F0 = .data:0x000002F0; // type:object size:0x4 data:4byte lbl_1_data_2F4 = .data:0x000002F4; // type:object size:0x20 scope:local data:string @@ -408,7 +408,7 @@ lbl_1_data_413 = .data:0x00000413; // type:object size:0x2B scope:local data:str lbl_1_data_43E = .data:0x0000043E; // type:object size:0x29 scope:local data:string lbl_1_data_467 = .data:0x00000467; // type:object size:0x2B scope:local data:string lbl_1_data_492 = .data:0x00000492; // type:object size:0x20 scope:local data:string -lbl_1_data_4B2 = .data:0x000004B2; // type:object size:0x22 scope:local data:string +lbl_1_data_4B2 = .data:0x000004B2; // type:object size:0x20 scope:local data:string jumptable_1_data_4D4 = .data:0x000004D4; // type:object size:0x54 scope:local lbl_1_data_528 = .data:0x00000528; // type:object size:0x1B scope:local data:string lbl_1_data_543 = .data:0x00000543; // type:object size:0x1A scope:local data:string diff --git a/config/GMPE01_00/rels/mpexDll/symbols.txt b/config/GMPE01_00/rels/mpexDll/symbols.txt index bc7d5ab0..d4725e33 100644 --- a/config/GMPE01_00/rels/mpexDll/symbols.txt +++ b/config/GMPE01_00/rels/mpexDll/symbols.txt @@ -395,14 +395,14 @@ lbl_1_data_232 = .data:0x00000232; // type:object size:0xE scope:local data:stri lbl_1_data_240 = .data:0x00000240; // type:object size:0x54 data:float lbl_1_data_294 = .data:0x00000294; // type:object size:0x4 data:4byte lbl_1_data_298 = .data:0x00000298; // type:object size:0x4 data:4byte -lbl_1_data_29C = .data:0x0000029C; // type:object size:0x18 scope:local data:string +lbl_1_data_29C = .data:0x0000029C; // type:object size:0x15 scope:local data:string lbl_1_data_2B4 = .data:0x000002B4; // type:object size:0x10 data:4byte lbl_1_data_2C4 = .data:0x000002C4; // type:object size:0x4 data:4byte lbl_1_data_2C8 = .data:0x000002C8; // type:object size:0x3 scope:local data:string lbl_1_data_2CB = .data:0x000002CB; // type:object size:0x5 scope:local data:string lbl_1_data_2D0 = .data:0x000002D0; // type:object size:0x19 scope:local data:string lbl_1_data_2E9 = .data:0x000002E9; // type:object size:0x12 scope:local data:string -lbl_1_data_2FB = .data:0x000002FB; // type:object size:0x29 scope:local data:string +lbl_1_data_2FB = .data:0x000002FB; // type:object size:0x28 scope:local data:string lbl_1_data_324 = .data:0x00000324; // type:object size:0x4 data:4byte lbl_1_data_328 = .data:0x00000328; // type:object size:0x4 data:4byte lbl_1_data_32C = .data:0x0000032C; // type:object size:0xC data:4byte @@ -410,7 +410,7 @@ lbl_1_data_338 = .data:0x00000338; // type:object size:0x2B scope:local data:str lbl_1_data_363 = .data:0x00000363; // type:object size:0x28 scope:local data:string lbl_1_data_38B = .data:0x0000038B; // type:object size:0x5 scope:local data:string lbl_1_data_390 = .data:0x00000390; // type:object size:0x4 scope:local data:string -lbl_1_data_394 = .data:0x00000394; // type:object size:0x4 scope:local data:string +lbl_1_data_394 = .data:0x00000394; // type:object size:0x3 scope:local data:string jumptable_1_data_398 = .data:0x00000398; // type:object size:0x2C scope:local lbl_1_data_3C4 = .data:0x000003C4; // type:object size:0x3C scope:local data:string lbl_1_data_400 = .data:0x00000400; // type:object size:0x16 scope:local data:string @@ -422,11 +422,11 @@ lbl_1_data_47B = .data:0x0000047B; // type:object size:0x16 scope:local data:str lbl_1_data_491 = .data:0x00000491; // type:object size:0x16 scope:local data:string lbl_1_data_4A7 = .data:0x000004A7; // type:object size:0x19 scope:local data:string lbl_1_data_4C0 = .data:0x000004C0; // type:object size:0x16 scope:local data:string -lbl_1_data_4D6 = .data:0x000004D6; // type:object size:0x42 scope:local data:string +lbl_1_data_4D6 = .data:0x000004D6; // type:object size:0x3B scope:local data:string lbl_1_data_518 = .data:0x00000518; // type:object size:0x3C scope:local data:string lbl_1_data_554 = .data:0x00000554; // type:object size:0x19 scope:local data:string lbl_1_data_56D = .data:0x0000056D; // type:object size:0x1A scope:local data:string -lbl_1_data_587 = .data:0x00000587; // type:object size:0x3D scope:local data:string +lbl_1_data_587 = .data:0x00000587; // type:object size:0x3A scope:local data:string lbl_1_data_5C4 = .data:0x000005C4; // type:object size:0x20 data:4byte lbl_1_data_5E4 = .data:0x000005E4; // type:object size:0x40 data:4byte lbl_1_data_624 = .data:0x00000624; // type:object size:0x70 diff --git a/config/GMPE01_00/rels/present/symbols.txt b/config/GMPE01_00/rels/present/symbols.txt index a5b07fdb..332b6bce 100644 --- a/config/GMPE01_00/rels/present/symbols.txt +++ b/config/GMPE01_00/rels/present/symbols.txt @@ -171,16 +171,16 @@ lbl_1_rodata_C48 = .rodata:0x00000C48; // type:object size:0x4 scope:local data: lbl_1_rodata_C4C = .rodata:0x00000C4C; // type:object size:0x4 scope:local data:float lbl_1_data_0 = .data:0x00000000; // type:object size:0x1B scope:local data:string lbl_1_data_1B = .data:0x0000001B; // type:object size:0x1B scope:local data:string -lbl_1_data_36 = .data:0x00000036; // type:object size:0x1A scope:local data:string +lbl_1_data_36 = .data:0x00000036; // type:object size:0x16 scope:local data:string lightTbl = .data:0x00000050; // type:object size:0x1C scope:local data:4byte execModeTbl = .data:0x0000006C; // type:object size:0x10 scope:local data:4byte -lbl_1_data_7C = .data:0x0000007C; // type:object size:0x8 scope:local data:string +lbl_1_data_7C = .data:0x0000007C; // type:object size:0x7 scope:local data:string roomIdxTbl2 = .data:0x00000084; // type:object size:0x20 jumptable_1_data_A4 = .data:0x000000A4; // type:object size:0x2C scope:local jumptable_1_data_D0 = .data:0x000000D0; // type:object size:0x1C scope:local shadowPosTbl = .data:0x000000F0; // type:object size:0x24 scope:local data:float lbl_1_data_114 = .data:0x00000114; // type:object size:0x2A scope:local data:string -lbl_1_data_13E = .data:0x0000013E; // type:object size:0x2E scope:local data:string +lbl_1_data_13E = .data:0x0000013E; // type:object size:0x2B scope:local data:string jumptable_1_data_16C = .data:0x0000016C; // type:object size:0x34 scope:local execModeTbl = .data:0x000001A0; // type:object size:0xC scope:local data:4byte scene = .bss:0x00000000; // type:object size:0x4 scope:local data:4byte diff --git a/config/GMPE01_00/rels/w05Dll/symbols.txt b/config/GMPE01_00/rels/w05Dll/symbols.txt index 4f1ddabd..56c26c7c 100644 --- a/config/GMPE01_00/rels/w05Dll/symbols.txt +++ b/config/GMPE01_00/rels/w05Dll/symbols.txt @@ -287,7 +287,7 @@ lbl_1_data_2F4 = .data:0x000002F4; // type:object size:0x18 lbl_1_data_310 = .data:0x00000310; // type:object size:0x8 lbl_1_data_318 = .data:0x00000318; // type:object size:0x7 scope:local data:string lbl_1_data_31F = .data:0x0000031F; // type:object size:0x7 scope:local data:string -lbl_1_data_326 = .data:0x00000326; // type:object size:0xA scope:local data:string +lbl_1_data_326 = .data:0x00000326; // type:object size:0x7 scope:local data:string lbl_1_data_330 = .data:0x00000330; // type:object size:0xC lbl_1_data_33C = .data:0x0000033C; // type:object size:0x7 scope:local data:string lbl_1_data_343 = .data:0x00000343; // type:object size:0xD scope:local data:string @@ -302,7 +302,7 @@ lbl_1_data_470 = .data:0x00000470; // type:object size:0xC lbl_1_data_47C = .data:0x0000047C; // type:object size:0xC lbl_1_data_488 = .data:0x00000488; // type:object size:0x3 scope:local data:string lbl_1_data_48B = .data:0x0000048B; // type:object size:0x4 scope:local data:string -lbl_1_data_48F = .data:0x0000048F; // type:object size:0x5 scope:local data:string +lbl_1_data_48F = .data:0x0000048F; // type:object size:0x4 scope:local data:string lbl_1_data_494 = .data:0x00000494; // type:object size:0xC lbl_1_data_4A0 = .data:0x000004A0; // type:object size:0xD scope:local data:string lbl_1_data_4AD = .data:0x000004AD; // type:object size:0x5 scope:local data:string diff --git a/config/GMPE01_00/rels/w10Dll/symbols.txt b/config/GMPE01_00/rels/w10Dll/symbols.txt index 89f2a634..f10220e4 100644 --- a/config/GMPE01_00/rels/w10Dll/symbols.txt +++ b/config/GMPE01_00/rels/w10Dll/symbols.txt @@ -98,7 +98,7 @@ lotteryHostMot = .data:0x00000064; // type:object size:0x8 scope:local booHouseHostMot = .data:0x0000006C; // type:object size:0x8 scope:local hostMot = .data:0x00000078; // type:object size:0x8 scope:local hostPosTbl = .data:0x00000080; // type:object size:0x18 scope:local data:float -lbl_1_data_98 = .data:0x00000098; // type:object size:0x2E scope:local data:string +lbl_1_data_98 = .data:0x00000098; // type:object size:0x2D scope:local data:string rollDataTbl = .data:0x000000C6; // type:object size:0x42 scope:local sceneTbl = .data:0x00000108; // type:object size:0x150 scope:local lbl_1_data_258 = .data:0x00000258; // type:object size:0x50 scope:local data:string diff --git a/config/GMPE01_00/rels/ztardll/symbols.txt b/config/GMPE01_00/rels/ztardll/symbols.txt index 05abe49e..f92691a8 100644 --- a/config/GMPE01_00/rels/ztardll/symbols.txt +++ b/config/GMPE01_00/rels/ztardll/symbols.txt @@ -219,7 +219,7 @@ lbl_1_data_3E8 = .data:0x000003E8; // type:object size:0x20 lbl_1_data_408 = .data:0x00000408; // type:object size:0x3C scope:local data:string lbl_1_data_444 = .data:0x00000444; // type:object size:0x19 scope:local data:string lbl_1_data_45D = .data:0x0000045D; // type:object size:0x1A scope:local data:string -lbl_1_data_477 = .data:0x00000477; // type:object size:0x3D scope:local data:string +lbl_1_data_477 = .data:0x00000477; // type:object size:0x3A scope:local data:string lbl_1_data_4B4 = .data:0x000004B4; // type:object size:0x20 data:4byte lbl_1_data_4D4 = .data:0x000004D4; // type:object size:0x40 data:4byte lbl_1_data_514 = .data:0x00000514; // type:object size:0x70 diff --git a/config/GMPE01_00/symbols.txt b/config/GMPE01_00/symbols.txt index 8b2b8d1b..3cb7cb54 100644 --- a/config/GMPE01_00/symbols.txt +++ b/config/GMPE01_00/symbols.txt @@ -3665,7 +3665,7 @@ T = .rodata:0x8011E950; // type:object size:0x68 scope:local data:double atanhi = .rodata:0x8011E9B8; // type:object size:0x20 scope:local atanlo = .rodata:0x8011E9D8; // type:object size:0x20 scope:local aT = .rodata:0x8011E9F8; // type:object size:0x58 scope:local -@62 = .rodata:0x8011EA50; // type:object size:0x1B scope:local data:string +@62 = .rodata:0x8011EA50; // type:object size:0x1C scope:local data:string lbl_8011EA70 = .rodata:0x8011EA70; // type:object size:0x20 gTRKMemMap = .rodata:0x8011EA90; // type:object size:0x10 data:4byte lbl_8011EAA0 = .rodata:0x8011EAA0; // type:object size:0x28 data:4byte @@ -3826,7 +3826,8 @@ DataDirStat = .data:0x8011F7C4; // type:object size:0x468 scope:local data:4byte lbl_8011FC2C = .data:0x8011FC2C; // type:object size:0x1D data:string lbl_8011FC49 = .data:0x8011FC49; // type:object size:0x1F data:string lbl_8011FC68 = .data:0x8011FC68; // type:object size:0x1D data:string -lbl_8011FC85 = .data:0x8011FC85; // type:object size:0x1F data:string +lbl_8011FC85 = .data:0x8011FC85; // type:object size:0x12 data:string +lbl_8011FC97 = .data:0x8011FC97; // type:object size:0xD data:string lbl_8011FCA4 = .data:0x8011FCA4; // type:object size:0x1A data:string lbl_8011FCBE = .data:0x8011FCBE; // type:object size:0x122 lbl_8011FDE0 = .data:0x8011FDE0; // type:object size:0x20 @@ -4328,12 +4329,47 @@ jumptable_8013B4D4 = .data:0x8013B4D4; // type:object size:0x20 scope:local jumptable_8013B4F4 = .data:0x8013B4F4; // type:object size:0x20 scope:local lbl_8013B518 = .data:0x8013B518; // type:object size:0x24 data:string lbl_8013B53C = .data:0x8013B53C; // type:object size:0x24 data:string -@84 = .data:0x8013B560; // type:object size:0x1E scope:local data:string -__OSExceptionLocations = .data:0x8013B648; // type:object size:0x3C +@82 = .data:0x8013B560; // type:object size:0x1E scope:local data:string +lbl_8013B580 = .data:0x8013B580; // type:object size:0x16 scope:local data:string +lbl_8013B598 = .data:0x8013B598; // type:object size:0xC scope:local data:string +lbl_8013B5A4 = .data:0x8013B5A4; // type:object size:0x9 scope:local data:string +lbl_8013B5B4 = .data:0x8013B5B0; // type:object size:0x10 scope:local data:string +lbl_8013B5C0 = .data:0x8013B5C0; // type:object size:0xB scope:local data:string +lbl_8013B5CC = .data:0x8013B5CC; // type:object size:0xE scope:local data:string +lbl_8013B5DC = .data:0x8013B5DC; // type:object size:0xD scope:local data:string +lbl_8013B5EC = .data:0x8013B5EC; // type:object size:0xD scope:local data:string +lbl_8013B5FC = .data:0x8013B5FC; // type:object size:0xD scope:local data:string +lbl_8013B60C = .data:0x8013B60C; // type:object size:0x12 scope:local data:string +lbl_8013B620 = .data:0x8013B620; // type:object size:0xE scope:local data:string +lbl_8013B630 = .data:0x8013B630; // type:object size:0x15 scope:local data:string +__OSExceptionLocations = .data:0x8013B648; // type:object size:0x3C scope:local lbl_8013B720 = .data:0x8013B720; // type:object size:0x398 DSPInitCode = .data:0x8013BAB8; // type:object size:0x80 scope:local @69 = .data:0x8013BB38; // type:object size:0x29 scope:local data:string -lbl_8013BD68 = .data:0x8013BD68; // type:object size:0x1B4 +lbl_8013BB64 = .data:0x8013BB64; // type:object size:0x18 scope:local data:string +lbl_8013BB7C = .data:0x8013BB7C; // type:object size:0x1B scope:local data:string +lbl_8013BB98 = .data:0x8013BB98; // type:object size:0x30 scope:local data:string +lbl_8013BBC8 = .data:0x8013BBC8; // type:object size:0x3C scope:local data:string +lbl_8013BC04 = .data:0x8013BC04; // type:object size:0x37 scope:local data:string +lbl_8013BC3D = .data:0x8013BC3D; // type:object size:0x3E scope:local data:string +lbl_8013BC7C = .data:0x8013BC7C; // type:object size:0x29 scope:local data:string +lbl_8013BCA8 = .data:0x8013BCA8; // type:object size:0x1D scope:local data:string +lbl_8013BCC8 = .data:0x8013BCC8; // type:object size:0x19 scope:local data:string +lbl_8013BCE4 = .data:0x8013BCE4; // type:object size:0x19 scope:local data:string +lbl_8013BD00 = .data:0x8013BD00; // type:object size:0x19 scope:local data:string +lbl_8013BD1C = .data:0x8013BD1C; // type:object size:0x16 scope:local data:string +lbl_8013BD34 = .data:0x8013BD34; // type:object size:0x2E scope:local data:string +lbl_8013BD68 = .data:0x8013BD68; // type:object size:0x44 scope:local data:string +lbl_8013BDAC = .data:0x8013BDAC; // type:object size:0x5F scope:local data:string +lbl_8013BE0C = .data:0x8013BE0C; // type:object size:0x2F scope:local data:string +lbl_8013BE3C = .data:0x8013BE3C; // type:object size:0x11 scope:local data:string +lbl_8013BE50 = .data:0x8013BE50; // type:object size:0x21 scope:local data:string +lbl_8013BE74 = .data:0x8013BE74; // type:object size:0x12 scope:local data:string +lbl_8013BE88 = .data:0x8013BE88; // type:object size:0x19 scope:local data:string +lbl_8013BEA4 = .data:0x8013BEA4; // type:object size:0x12 scope:local data:string +lbl_8013BEB8 = .data:0x8013BEB8; // type:object size:0x1D scope:local data:string +lbl_8013BED8 = .data:0x8013BED8; // type:object size:0x26 scope:local data:string +lbl_8013BF00 = .data:0x8013BF00; // type:object size:0x1C scope:local data:string @74 = .data:0x8013BF1C; // type:object size:0x23 scope:local data:string @10 = .data:0x8013BF40; // type:object size:0x16 scope:local data:string @43 = .data:0x8013C21C; // type:object size:0x40 scope:local @@ -4367,23 +4403,23 @@ lbl_8013C984 = .data:0x8013C984; // type:object size:0x29 scope:local data:strin lbl_8013C9B0 = .data:0x8013C9B0; // type:object size:0x29 scope:local data:string DEMOFontBitmap = .data:0x8013C9E0; // type:object size:0xC00 align:32 lbl_8013D5E0 = .data:0x8013D5E0; // type:object size:0xC scope:local data:string -lbl_8013D5EC = .data:0x8013D5EC; // type:object size:0x28 scope:local data:string +lbl_8013D5EC = .data:0x8013D5EC; // type:object size:0x26 scope:local data:string jumptable_8013D614 = .data:0x8013D614; // type:object size:0x28 scope:local jumptable_8013D698 = .data:0x8013D698; // type:object size:0x28 scope:local jumptable_8013D6C0 = .data:0x8013D6C0; // type:object size:0x28 scope:local jumptable_8013D6E8 = .data:0x8013D6E8; // type:object size:0x28 scope:local jumptable_8013D710 = .data:0x8013D710; // type:object size:0x28 scope:local ResetFunctionInfo = .data:0x8013D738; // type:object size:0x10 -lbl_8013D748 = .data:0x8013D748; // type:object size:0x20 scope:local data:string +lbl_8013D748 = .data:0x8013D748; // type:object size:0x1E scope:local data:string lbl_8013D768 = .data:0x8013D768; // type:object size:0xC scope:local data:string -lbl_8013D774 = .data:0x8013D774; // type:object size:0xC scope:local data:string -lbl_8013D780 = .data:0x8013D780; // type:object size:0x20 scope:local data:string -lbl_8013D7A0 = .data:0x8013D7A0; // type:object size:0x30 scope:local data:string -lbl_8013D7D0 = .data:0x8013D7D0; // type:object size:0x30 scope:local data:string -lbl_8013D800 = .data:0x8013D800; // type:object size:0x30 scope:local data:string -lbl_8013D830 = .data:0x8013D830; // type:object size:0x30 scope:local data:string -lbl_8013D860 = .data:0x8013D860; // type:object size:0x30 scope:local data:string -lbl_8013D890 = .data:0x8013D890; // type:object size:0x30 scope:local data:string +lbl_8013D774 = .data:0x8013D774; // type:object size:0x9 scope:local data:string +lbl_8013D780 = .data:0x8013D780; // type:object size:0x1D scope:local data:string +lbl_8013D7A0 = .data:0x8013D7A0; // type:object size:0x2D scope:local data:string +lbl_8013D7D0 = .data:0x8013D7D0; // type:object size:0x2D scope:local data:string +lbl_8013D800 = .data:0x8013D800; // type:object size:0x2D scope:local data:string +lbl_8013D830 = .data:0x8013D830; // type:object size:0x2D scope:local data:string +lbl_8013D860 = .data:0x8013D860; // type:object size:0x2D scope:local data:string +lbl_8013D890 = .data:0x8013D890; // type:object size:0x2B scope:local data:string jumptable_8013D8C0 = .data:0x8013D8C0; // type:object size:0x68 scope:local jumptable_8013D928 = .data:0x8013D928; // type:object size:0x44 scope:local jumptable_8013D96C = .data:0x8013D96C; // type:object size:0x1C scope:local @@ -4408,7 +4444,7 @@ SectorSizeTable = .data:0x8013E060; // type:object size:0x20 scope:local LatencyTable = .data:0x8013E080; // type:object size:0x20 scope:local Si = .data:0x8013E0A0; // type:object size:0x14 scope:local data:4byte Type = .data:0x8013E0B4; // type:object size:0x10 scope:local -@464 = .data:0x8013E0C4; // type:object size:0x9 scope:local data:string +@464 = .data:0x8013E0C4; // type:object size:0xC scope:local data:string lbl_8013E0D0 = .data:0x8013E0D0; // type:object size:0xF scope:local data:string lbl_8013E0E0 = .data:0x8013E0E0; // type:object size:0xF scope:local data:string lbl_8013E0F0 = .data:0x8013E0F0; // type:object size:0xD scope:local data:string diff --git a/src/REL/E3setupDLL/mgselect.c b/src/REL/E3setupDLL/mgselect.c index 5dbd89eb..d87c662f 100644 --- a/src/REL/E3setupDLL/mgselect.c +++ b/src/REL/E3setupDLL/mgselect.c @@ -142,8 +142,6 @@ static float cursorYOfsTbl[] = { -100.0f, -50.0f, 0.0f, 50.0f, 100.0f }; static s32 mgPicTbl[] = { 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52 }; -static char startText[] = "\013\016\r PRESS START"; - static void StartMGSelect(omObjData *object) { HuAudSeqPlay(0x2B); @@ -490,12 +488,12 @@ static void CreateMGInterface(omObjData *object) index = HuSprCreate(temp_r3_2, 0x271A, 0); HuSprGrpMemberSet(group, 0, index); index2++; - HuWinMesMaxSizeGet(1, sp8, &startText); + HuWinMesMaxSizeGet(1, sp8, "\013\016\r PRESS START"); index = HuWinCreate(340.0f, 362.0f, sp8[0], sp8[1], 0); unkStruct->unk_2C = index; HuWinMesColSet(index, 0); HuWinBGTPLvlSet(index, 0.0f); HuWinMesSpeedSet(index, 0); - HuWinMesSet(index, MAKE_MESSID_PTR(startText)); + HuWinMesSet(index, MAKE_MESSID_PTR("\013\016\r PRESS START")); object->func = UpdateMGInterface; } From 970da00ce2ce2696db14e872975f0212e6f42499 Mon Sep 17 00:00:00 2001 From: dbalatoni13 Date: Tue, 12 Nov 2024 19:16:59 +0100 Subject: [PATCH 3/3] Imported most of dolphin/os --- config/GMPE01_00/symbols.txt | 54 ++- configure.py | 44 +-- include/__ppc_eabi_linker.h | 79 ++++ include/dolphin/OSRtcPriv.h | 41 +- include/dolphin/os.h | 116 +++--- include/dolphin/os/OSAlloc.h | 17 +- include/dolphin/os/OSContext.h | 6 + include/dolphin/os/OSFont.h | 43 ++- include/dolphin/os/OSIC.h | 20 + include/dolphin/os/OSModule.h | 4 +- include/dolphin/os/OSPriv.h | 32 ++ src/dolphin/os/OS.c | 645 +++++++++++++++++++++++++++++++ src/dolphin/os/OSAlarm.c | 199 ++++++++++ src/dolphin/os/OSAlloc.c | 531 +++++++++++++++++++++++++ src/dolphin/os/OSArena.c | 53 +++ src/dolphin/os/OSAudioSystem.c | 118 ++++++ src/dolphin/os/OSCache.c | 450 +++++++++++++++++++++ src/dolphin/os/OSContext.c | 555 ++++++++++++++++++++++++++ src/dolphin/os/OSError.c | 115 ++++++ src/dolphin/os/OSFont.c | 323 ++++++++++++++++ src/dolphin/os/OSInterrupt.c | 434 +++++++++++++++++++++ src/dolphin/os/OSLink.c | 504 ++++++++++++++++++++++++ src/dolphin/os/OSMemory.c | 230 +++++++++++ src/dolphin/os/OSMessage.c | 91 +++++ src/dolphin/os/OSMutex.c | 244 ++++++++++++ src/dolphin/os/OSReboot.c | 94 +++++ src/dolphin/os/OSReset.c | 203 ++++++++++ src/dolphin/os/OSResetSW.c | 89 +++++ src/dolphin/os/OSRtc.c | 363 +++++++++++++++++ src/dolphin/os/OSStopwatch.c | 61 +++ src/dolphin/os/OSSync.c | 29 ++ src/dolphin/os/OSThread.c | 552 ++++++++++++++++++++++++++ src/dolphin/os/OSTime.c | 146 +++++++ src/dolphin/os/__ppc_eabi_init.c | 76 ++++ src/dolphin/os/__start.c | 161 ++++++++ 35 files changed, 6591 insertions(+), 131 deletions(-) create mode 100644 include/__ppc_eabi_linker.h create mode 100644 include/dolphin/os/OSIC.h create mode 100644 src/dolphin/os/OS.c create mode 100644 src/dolphin/os/OSAlarm.c create mode 100644 src/dolphin/os/OSAlloc.c create mode 100644 src/dolphin/os/OSArena.c create mode 100644 src/dolphin/os/OSAudioSystem.c create mode 100644 src/dolphin/os/OSCache.c create mode 100644 src/dolphin/os/OSContext.c create mode 100644 src/dolphin/os/OSError.c create mode 100644 src/dolphin/os/OSFont.c create mode 100644 src/dolphin/os/OSInterrupt.c create mode 100644 src/dolphin/os/OSLink.c create mode 100644 src/dolphin/os/OSMemory.c create mode 100644 src/dolphin/os/OSMessage.c create mode 100644 src/dolphin/os/OSMutex.c create mode 100644 src/dolphin/os/OSReboot.c create mode 100644 src/dolphin/os/OSReset.c create mode 100644 src/dolphin/os/OSResetSW.c create mode 100644 src/dolphin/os/OSRtc.c create mode 100644 src/dolphin/os/OSStopwatch.c create mode 100644 src/dolphin/os/OSSync.c create mode 100644 src/dolphin/os/OSThread.c create mode 100644 src/dolphin/os/OSTime.c create mode 100644 src/dolphin/os/__ppc_eabi_init.c create mode 100644 src/dolphin/os/__start.c diff --git a/config/GMPE01_00/symbols.txt b/config/GMPE01_00/symbols.txt index 3cb7cb54..144dc6c3 100644 --- a/config/GMPE01_00/symbols.txt +++ b/config/GMPE01_00/symbols.txt @@ -2102,6 +2102,8 @@ OSSetErrorHandler = .text:0x800B6FC8; // type:function size:0x1C scope:global __OSUnhandledException = .text:0x800B6FE4; // type:function size:0x200 scope:global OSGetFontEncode = .text:0x800B71E4; // type:function size:0x58 OSDisableInterrupts = .text:0x800B723C; // type:function size:0x14 scope:global +__RAS_OSDisableInterrupts_begin = .text:0x800B723C; // type:label scope:global +__RAS_OSDisableInterrupts_end = .text:0x800B724C; // type:label scope:global OSEnableInterrupts = .text:0x800B7250; // type:function size:0x14 scope:global OSRestoreInterrupts = .text:0x800B7264; // type:function size:0x24 scope:global __OSSetInterruptHandler = .text:0x800B7288; // type:function size:0x1C scope:global @@ -4343,7 +4345,25 @@ lbl_8013B60C = .data:0x8013B60C; // type:object size:0x12 scope:local data:strin lbl_8013B620 = .data:0x8013B620; // type:object size:0xE scope:local data:string lbl_8013B630 = .data:0x8013B630; // type:object size:0x15 scope:local data:string __OSExceptionLocations = .data:0x8013B648; // type:object size:0x3C scope:local -lbl_8013B720 = .data:0x8013B720; // type:object size:0x398 +lbl_8013B720 = .data:0x8013B720; // type:object size:0x24 scope:local data:string +lbl_8013B744 = .data:0x8013B744; // type:object size:0x37 scope:local data:string +lbl_8013B77C = .data:0x8013B77C; // type:object size:0x28 scope:local data:string +lbl_8013B7A4 = .data:0x8013B7A4; // type:object size:0x4F scope:local data:string +lbl_8013B7F4 = .data:0x8013B7F4; // type:object size:0x3E scope:local data:string +lbl_8013B834 = .data:0x8013B834; // type:object size:0x37 scope:local data:string +lbl_8013B86C = .data:0x8013B86C; // type:object size:0x49 scope:local data:string +lbl_8013B8B8 = .data:0x8013B8B8; // type:object size:0x33 scope:local data:string +lbl_8013B8EC = .data:0x8013B8EC; // type:object size:0x3D scope:local data:string +lbl_8013B92C = .data:0x8013B92C; // type:object size:0x39 scope:local data:string +lbl_8013B968 = .data:0x8013B968; // type:object size:0x45 scope:local data:string +lbl_8013B9B0 = .data:0x8013B9B0; // type:object size:0x5F scope:local data:string +lbl_8013BA10 = .data:0x8013BA10; // type:object size:0x2C scope:local data:string +lbl_8013BA3C = .data:0x8013BA3C; // type:object size:0x12 scope:local data:string +lbl_8013BA50 = .data:0x8013BA50; // type:object size:0x12 scope:local data:string +lbl_8013BA64 = .data:0x8013BA64; // type:object size:0x1A scope:local data:string +lbl_8013BA80 = .data:0x8013BA80; // type:object size:0x13 scope:local data:string +lbl_8013BA94 = .data:0x8013BA94; // type:object size:0x10 scope:local data:string +lbl_8013BAA4 = .data:0x8013BAA4; // type:object size:0xE scope:local data:string DSPInitCode = .data:0x8013BAB8; // type:object size:0x80 scope:local @69 = .data:0x8013BB38; // type:object size:0x29 scope:local data:string lbl_8013BB64 = .data:0x8013BB64; // type:object size:0x18 scope:local data:string @@ -4360,7 +4380,8 @@ lbl_8013BD00 = .data:0x8013BD00; // type:object size:0x19 scope:local data:strin lbl_8013BD1C = .data:0x8013BD1C; // type:object size:0x16 scope:local data:string lbl_8013BD34 = .data:0x8013BD34; // type:object size:0x2E scope:local data:string lbl_8013BD68 = .data:0x8013BD68; // type:object size:0x44 scope:local data:string -lbl_8013BDAC = .data:0x8013BDAC; // type:object size:0x5F scope:local data:string +lbl_8013BDAC = .data:0x8013BDAC; // type:object size:0x30 scope:local data:string +lbl_8013BDDC = .data:0x8013BDDC; // type:object size:0x2F scope:local data:string lbl_8013BE0C = .data:0x8013BE0C; // type:object size:0x2F scope:local data:string lbl_8013BE3C = .data:0x8013BE3C; // type:object size:0x11 scope:local data:string lbl_8013BE50 = .data:0x8013BE50; // type:object size:0x21 scope:local data:string @@ -4370,14 +4391,33 @@ lbl_8013BEA4 = .data:0x8013BEA4; // type:object size:0x12 scope:local data:strin lbl_8013BEB8 = .data:0x8013BEB8; // type:object size:0x1D scope:local data:string lbl_8013BED8 = .data:0x8013BED8; // type:object size:0x26 scope:local data:string lbl_8013BF00 = .data:0x8013BF00; // type:object size:0x1C scope:local data:string -@74 = .data:0x8013BF1C; // type:object size:0x23 scope:local data:string +@76 = .data:0x8013BF1C; // type:object size:0x23 scope:local data:string @10 = .data:0x8013BF40; // type:object size:0x16 scope:local data:string -@43 = .data:0x8013C21C; // type:object size:0x40 scope:local +lbl_8013BF58 = .data:0x8013BF58; // type:object size:0x26 scope:local data:string +lbl_8013BF80 = .data:0x8013BF80; // type:object size:0x1C scope:local data:string +lbl_8013BF9C = .data:0x8013BF9C; // type:object size:0x1D scope:local data:string +lbl_8013BFBC = .data:0x8013BFBC; // type:object size:0x17 scope:local data:string +lbl_8013BFD4 = .data:0x8013BFD4; // type:object size:0x31 scope:local data:string +lbl_8013C008 = .data:0x8013C008; // type:object size:0x10 scope:local data:string +lbl_8013C018 = .data:0x8013C018; // type:object size:0x60 scope:local data:string +lbl_8013C078 = .data:0x8013C078; // type:object size:0x4C scope:local data:string +lbl_8013C0C4 = .data:0x8013C0C4; // type:object size:0x62 scope:local data:string +lbl_8013C128 = .data:0x8013C128; // type:object size:0x60 scope:local data:string +lbl_8013C188 = .data:0x8013C188; // type:object size:0x1F scope:local data:string +lbl_8013C1A8 = .data:0x8013C1A8; // type:object size:0x1F scope:local data:string +lbl_8013C1C8 = .data:0x8013C1C8; // type:object size:0x1B scope:local data:string +lbl_8013C1E4 = .data:0x8013C1E4; // type:object size:0x35 scope:local data:string +@87 = .data:0x8013C21C; // type:object size:0x40 scope:local InterruptPrioTable = .data:0x8013C260; // type:object size:0x2C scope:local data:4byte -lbl_8013C290 = .data:0x8013C290; // type:object size:0x28 -lbl_8013C2B8 = .data:0x8013C2B8; // type:object size:0x28 +lbl_8013C290 = .data:0x8013C290; // type:object size:0x25 scope:local data:string +lbl_8013C2B8 = .data:0x8013C2B8; // type:object size:0x27 scope:local data:string ResetFunctionInfo = .data:0x8013C2E0; // type:object size:0x10 scope:local -lbl_8013C2F0 = .data:0x8013C2F0; // type:object size:0x78 +lbl_8013C2F0 = .data:0x8013C2F0; // type:object size:0x12 scope:local data:string +lbl_8013C304 = .data:0x8013C304; // type:object size:0x11 scope:local data:string +lbl_8013C318 = .data:0x8013C318; // type:object size:0xD scope:local data:string +lbl_8013C328 = .data:0x8013C328; // type:object size:0x11 scope:local data:string +lbl_8013C33C = .data:0x8013C33C; // type:object size:0x11 scope:local data:string +lbl_8013C350 = .data:0x8013C350; // type:object size:0x11 scope:local data:string YearDays = .data:0x8013C368; // type:object size:0x30 scope:local LeapYearDays = .data:0x8013C398; // type:object size:0x30 scope:local lbl_8013C3C8 = .data:0x8013C3C8; // type:object size:0x18 scope:local data:string diff --git a/configure.py b/configure.py index 5e8750df..52215c30 100644 --- a/configure.py +++ b/configure.py @@ -458,30 +458,30 @@ config.libs = [ DolphinLib( "os", [ - Object(NonMatching, "dolphin/os/OS.c"), - Object(NonMatching, "dolphin/os/OSAlarm.c"), + Object(Matching, "dolphin/os/OS.c"), + Object(Matching, "dolphin/os/OSAlarm.c"), Object(NonMatching, "dolphin/os/OSAlloc.c"), - Object(NonMatching, "dolphin/os/OSArena.c"), - Object(NonMatching, "dolphin/os/OSAudioSystem.c"), - Object(NonMatching, "dolphin/os/OSCache.c"), - Object(NonMatching, "dolphin/os/OSContext.c"), - Object(NonMatching, "dolphin/os/OSError.c"), - Object(NonMatching, "dolphin/os/OSFont.c"), - Object(NonMatching, "dolphin/os/OSInterrupt.c"), - Object(NonMatching, "dolphin/os/OSLink.c"), - Object(NonMatching, "dolphin/os/OSMessage.c"), - Object(NonMatching, "dolphin/os/OSMemory.c"), - Object(NonMatching, "dolphin/os/OSMutex.c"), + Object(Matching, "dolphin/os/OSArena.c"), + Object(Matching, "dolphin/os/OSAudioSystem.c"), + Object(Matching, "dolphin/os/OSCache.c"), + Object(Matching, "dolphin/os/OSContext.c"), + Object(Matching, "dolphin/os/OSError.c"), + Object(Matching, "dolphin/os/OSFont.c"), + Object(Matching, "dolphin/os/OSInterrupt.c"), + Object(Matching, "dolphin/os/OSLink.c"), + Object(Matching, "dolphin/os/OSMessage.c"), + Object(Matching, "dolphin/os/OSMemory.c"), + Object(Matching, "dolphin/os/OSMutex.c"), Object(NonMatching, "dolphin/os/OSReboot.c"), - Object(NonMatching, "dolphin/os/OSReset.c"), - Object(NonMatching, "dolphin/os/OSResetSW.c"), - Object(NonMatching, "dolphin/os/OSRtc.c"), - Object(NonMatching, "dolphin/os/OSStopwatch.c"), - Object(NonMatching, "dolphin/os/OSSync.c"), - Object(NonMatching, "dolphin/os/OSThread.c"), - Object(NonMatching, "dolphin/os/OSTime.c"), - Object(NonMatching, "dolphin/os/__start.c"), - Object(NonMatching, "dolphin/os/__ppc_eabi_init.c"), + Object(Matching, "dolphin/os/OSReset.c"), + Object(Matching, "dolphin/os/OSResetSW.c"), + Object(Matching, "dolphin/os/OSRtc.c"), + Object(Matching, "dolphin/os/OSStopwatch.c"), + Object(Matching, "dolphin/os/OSSync.c"), + Object(Matching, "dolphin/os/OSThread.c"), + Object(Matching, "dolphin/os/OSTime.c"), + Object(Matching, "dolphin/os/__start.c"), + Object(Matching, "dolphin/os/__ppc_eabi_init.c"), ], ), DolphinLib( diff --git a/include/__ppc_eabi_linker.h b/include/__ppc_eabi_linker.h new file mode 100644 index 00000000..2fddd9c9 --- /dev/null +++ b/include/__ppc_eabi_linker.h @@ -0,0 +1,79 @@ +#ifndef __PPC_EABI_LINKER +#define __PPC_EABI_LINKER + +#ifdef __MWERKS__ +#define DECL_SECTION(name) __declspec(section name) +#else +#define DECL_SECTION(name) +#endif + +DECL_SECTION(".init") extern char _stack_addr[]; +DECL_SECTION(".init") extern char _stack_end[]; +DECL_SECTION(".init") extern char _heap_addr[]; +DECL_SECTION(".init") extern char _heap_end[]; +DECL_SECTION(".init") extern const char _fextabindex_rom[]; +DECL_SECTION(".init") extern char _fextabindex[]; +DECL_SECTION(".init") extern char _eextabindex[]; + +DECL_SECTION(".init") extern char _SDA_BASE_[]; + +DECL_SECTION(".init") extern char _SDA2_BASE_[]; + +typedef struct __rom_copy_info { + char* rom; + char* addr; + unsigned int size; +} __rom_copy_info; + +DECL_SECTION(".init") extern __rom_copy_info _rom_copy_info[]; + +typedef struct __bss_init_info { + char* addr; + unsigned int size; +} __bss_init_info; + +DECL_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; + +DECL_SECTION(".init") extern __eti_init_info _eti_init_info[]; +DECL_SECTION(".init") extern const char _f_init_rom[]; +DECL_SECTION(".init") extern char _f_init[]; +DECL_SECTION(".init") extern char _e_init[]; +DECL_SECTION(".init") extern const char _f_text_rom[]; +DECL_SECTION(".init") extern char _f_text[]; +DECL_SECTION(".init") extern char _e_text[]; +DECL_SECTION(".init") extern const char _f_rodata_rom[]; +DECL_SECTION(".init") extern char _f_rodata[]; +DECL_SECTION(".init") extern char _e_rodata[]; +DECL_SECTION(".init") extern const char _fextab_rom[]; +DECL_SECTION(".init") extern char _fextab[]; +DECL_SECTION(".init") extern char _eextab[]; +DECL_SECTION(".init") extern const char _f_data_rom[]; +DECL_SECTION(".init") extern char _f_data[]; +DECL_SECTION(".init") extern char _e_data[]; +DECL_SECTION(".init") extern char _f_bss[]; +DECL_SECTION(".init") extern char _e_bss[]; +DECL_SECTION(".init") extern const char _f_sdata_rom[]; +DECL_SECTION(".init") extern char _f_sdata[]; +DECL_SECTION(".init") extern char _e_sdata[]; +DECL_SECTION(".init") extern char _f_sbss[]; +DECL_SECTION(".init") extern char _e_sbss[]; +DECL_SECTION(".init") extern const char _f_sdata2_rom[]; +DECL_SECTION(".init") extern char _f_sdata2[]; +DECL_SECTION(".init") extern char _e_sdata2[]; +DECL_SECTION(".init") extern char _f_sbss2[]; +DECL_SECTION(".init") extern char _e_sbss2[]; +DECL_SECTION(".init") extern const char _f_PPC_EMB_sdata0_rom[]; +DECL_SECTION(".init") extern char _f_PPC_EMB_sdata0[]; +DECL_SECTION(".init") extern char _e_PPC_EMB_sdata0[]; +DECL_SECTION(".init") extern char _f_PPC_EMB_sbss0[]; +DECL_SECTION(".init") extern char _e_PPC_EMB_sbss0[]; + + +#endif // __PPC_EABI_LINKER diff --git a/include/dolphin/OSRtcPriv.h b/include/dolphin/OSRtcPriv.h index 949c71e7..fe1df144 100644 --- a/include/dolphin/OSRtcPriv.h +++ b/include/dolphin/OSRtcPriv.h @@ -4,30 +4,33 @@ #include typedef struct OSSram { - u16 checkSum; - u16 checkSumInv; - u32 ead0; - u32 ead1; - u32 counterBias; - s8 displayOffsetH; - u8 ntd; - u8 language; - u8 flags; + u16 checkSum; + u16 checkSumInv; + u32 ead0; + u32 ead1; + u32 counterBias; + s8 displayOffsetH; + u8 ntd; + u8 language; + u8 flags; } OSSram; typedef struct OSSramEx { - u8 flashID[2][12]; - u32 wirelessKeyboardID; - u16 wirelessPadID[4]; - u8 dvdErrorCode; - u8 _padding0; - u8 flashIDCheckSum[2]; - u16 gbs; - u8 _padding1[2]; + u8 flashID[2][12]; + u32 wirelessKeyboardID; + u16 wirelessPadID[4]; + u8 dvdErrorCode; + u8 _padding0; + u8 flashIDCheckSum[2]; + u16 gbs; + u8 _padding1[2]; } OSSramEx; -OSSram* __OSLockSram(); -OSSramEx* __OSLockSramEx(); +void __OSInitSram(); +OSSram *__OSLockSram(); +BOOL __OSSyncSram(); +BOOL __OSUnlockSram(BOOL commit); +OSSramEx *__OSLockSramEx(); void OSSetWirelessID(s32 chan, u16 id); u16 OSGetWirelessID(s32 chan); diff --git a/include/dolphin/os.h b/include/dolphin/os.h index 83f15519..6394de8b 100644 --- a/include/dolphin/os.h +++ b/include/dolphin/os.h @@ -23,26 +23,26 @@ extern "C" { #endif typedef s64 OSTime; typedef u32 OSTick; -u32 __OSBusClock AT_ADDRESS(OS_BASE_CACHED | 0x00F8); // sync with OSLoMem.h +u32 __OSBusClock AT_ADDRESS(OS_BASE_CACHED | 0x00F8); // sync with OSLoMem.h u32 __OSCoreClock AT_ADDRESS(OS_BASE_CACHED | 0x00FC); // sync with OSLoMem.h -#define OS_BUS_CLOCK (u32)__OSBusClock +#define OS_BUS_CLOCK (u32) __OSBusClock #define OS_CORE_CLOCK __OSCoreClock #define OS_TIMER_CLOCK (OS_BUS_CLOCK / 4) #ifndef _DEBUG -#define OSPhysicalToCached(paddr) ((void*)((u32)(paddr) + OS_BASE_CACHED)) -#define OSPhysicalToUncached(paddr) ((void*)((u32)(paddr) + OS_BASE_UNCACHED)) -#define OSCachedToPhysical(caddr) ((u32)((u8*)(caddr)-OS_BASE_CACHED)) -#define OSUncachedToPhysical(ucaddr) ((u32)((u8*)(ucaddr)-OS_BASE_UNCACHED)) -#define OSCachedToUncached(caddr) ((void*)((u8*)(caddr) + (OS_BASE_UNCACHED - OS_BASE_CACHED))) -#define OSUncachedToCached(ucaddr) ((void*)((u8*)(ucaddr) - (OS_BASE_UNCACHED - OS_BASE_CACHED))) +#define OSPhysicalToCached(paddr) ((void *)((u32)(paddr) + OS_BASE_CACHED)) +#define OSPhysicalToUncached(paddr) ((void *)((u32)(paddr) + OS_BASE_UNCACHED)) +#define OSCachedToPhysical(caddr) ((u32)((u8 *)(caddr)-OS_BASE_CACHED)) +#define OSUncachedToPhysical(ucaddr) ((u32)((u8 *)(ucaddr)-OS_BASE_UNCACHED)) +#define OSCachedToUncached(caddr) ((void *)((u8 *)(caddr) + (OS_BASE_UNCACHED - OS_BASE_CACHED))) +#define OSUncachedToCached(ucaddr) ((void *)((u8 *)(ucaddr) - (OS_BASE_UNCACHED - OS_BASE_CACHED))) #else -u32 OSPhysicalToCached(void* paddr); -u32 OSPhysicalToUncached(void* paddr); -u32 OSCachedToPhysical(void* caddr); -u32 OSUncachedToPhysical(void* ucaddr); -u32 OSCachedToUncached(void* caddr); -u32 OSUncachedToCached(void* ucaddr); +u32 OSPhysicalToCached(void *paddr); +u32 OSPhysicalToUncached(void *paddr); +u32 OSCachedToPhysical(void *caddr); +u32 OSUncachedToPhysical(void *ucaddr); +u32 OSCachedToUncached(void *caddr); +u32 OSUncachedToCached(void *ucaddr); #endif #define OSTicksToCycles(ticks) (((ticks) * ((OS_CORE_CLOCK * 2) / OS_TIMER_CLOCK)) / 2) @@ -50,7 +50,7 @@ u32 OSUncachedToCached(void* ucaddr); #define OSTicksToMilliseconds(ticks) ((ticks) / (OS_TIMER_CLOCK / 1000)) #define OSTicksToMicroseconds(ticks) (((ticks)*8) / (OS_TIMER_CLOCK / 125000)) #define OSTicksToNanoseconds(ticks) (((ticks)*8000) / (OS_TIMER_CLOCK / 125000)) -#define OSSecondsToTicks(sec) ((sec)*OS_TIMER_CLOCK) +#define OSSecondsToTicks(sec) ((sec)*OS_TIMER_CLOCK) #define OSMillisecondsToTicks(msec) ((msec) * (OS_TIMER_CLOCK / 1000)) #define OSMicrosecondsToTicks(usec) (((usec) * (OS_TIMER_CLOCK / 125000)) / 8) #define OSNanosecondsToTicks(nsec) (((nsec) * (OS_TIMER_CLOCK / 125000)) / 8000) @@ -60,52 +60,44 @@ u32 OSUncachedToCached(void* ucaddr); #define OSRoundUp32B(v) (((u32)(v + 31) & ~31)) #define OSRoundDown32B(x) (((u32)(x)) & ~31) -void* OSGetArenaHi(void); -void* OSGetArenaLo(void); -void OSSetArenaHi(void* newHi); -void OSSetArenaLo(void* newLo); - -void* OSAllocFromArenaLo(u32 size, u32 align); -void* OSAllocFromArenaHi(u32 size, u32 align); - void OSInit(); OSTime OSGetTime(); OSTick OSGetTick(); typedef struct OSCalendarTime { - int sec; // seconds after the minute [0, 61] - int min; // minutes after the hour [0, 59] - int hour; // hours since midnight [0, 23] - int mday; // day of the month [1, 31] - int mon; // month since January [0, 11] - int year; // years in AD [1, ...] - int wday; // days since Sunday [0, 6] - int yday; // days since January 1 [0, 365] + int sec; // seconds after the minute [0, 61] + int min; // minutes after the hour [0, 59] + int hour; // hours since midnight [0, 23] + int mday; // day of the month [1, 31] + int mon; // month since January [0, 11] + int year; // years in AD [1, ...] + int wday; // days since Sunday [0, 6] + int yday; // days since January 1 [0, 365] - int msec; // milliseconds after the second [0,999] - int usec; // microseconds after the millisecond [0,999] + int msec; // milliseconds after the second [0,999] + int usec; // microseconds after the millisecond [0,999] } OSCalendarTime; -OSTime OSCalendarTimeToTicks(OSCalendarTime* td); -void OSTicksToCalendarTime(OSTime ticks, OSCalendarTime* td); +OSTime OSCalendarTimeToTicks(OSCalendarTime *td); +void OSTicksToCalendarTime(OSTime ticks, OSCalendarTime *td); typedef struct OSStopwatch { - char* name; - OSTime total; - u32 hits; - OSTime min; - OSTime max; - OSTime last; - BOOL running; + char *name; + OSTime total; + u32 hits; + OSTime min; + OSTime max; + OSTime last; + BOOL running; } OSStopwatch; -void OSInitStopwatch(OSStopwatch* sw, char* name); -void OSStartStopwatch(OSStopwatch* sw); -void OSStopStopwatch(OSStopwatch* sw); -OSTime OSCheckStopwatch(OSStopwatch* sw); -void OSResetStopwatch(OSStopwatch* sw); -void OSDumpStopwatch(OSStopwatch* sw); +void OSInitStopwatch(OSStopwatch *sw, char *name); +void OSStartStopwatch(OSStopwatch *sw); +void OSStopStopwatch(OSStopwatch *sw); +OSTime OSCheckStopwatch(OSStopwatch *sw); +void OSResetStopwatch(OSStopwatch *sw); +void OSDumpStopwatch(OSStopwatch *sw); #define OS_CONSOLE_MASK 0xf0000000 #define OS_CONSOLE_RETAIL 0x00000000 @@ -159,7 +151,7 @@ void OSSetLanguage(u8 language); u32 OSGetEuRgb60Mode(void); void OSSetEuRgb60Mode(u32 on); -void OSRegisterVersion(const char* id); +void OSRegisterVersion(const char *id); BOOL OSDisableInterrupts(void); BOOL OSEnableInterrupts(void); @@ -174,8 +166,7 @@ BOOL OSRestoreInterrupts(BOOL level); #endif #ifndef ASSERTMSG -#if defined(__STDC_VERSION__) && (199901L <= __STDC_VERSION__) || defined(__MWERKS__) || \ - defined(__SN__) +#if defined(__STDC_VERSION__) && (199901L <= __STDC_VERSION__) || defined(__MWERKS__) || defined(__SN__) #define ASSERTMSG(exp, ...) (void)((exp) || (OSPanic(__FILE__, __LINE__, __VA_ARGS__), 0)) #else #define ASSERTMSG(exp, msg) (void)((exp) || (OSPanic(__FILE__, __LINE__, (msg)), 0)) @@ -183,23 +174,20 @@ BOOL OSRestoreInterrupts(BOOL level); #endif #ifndef ASSERTMSG1 -#define ASSERTMSG1(exp, msg, param1) \ - (void)((exp) || (OSPanic(__FILE__, __LINE__, (msg), (param1)), 0)) +#define ASSERTMSG1(exp, msg, param1) (void)((exp) || (OSPanic(__FILE__, __LINE__, (msg), (param1)), 0)) #endif #ifndef ASSERTMSG2 -#define ASSERTMSG2(exp, msg, param1, param2) \ - (void)((exp) || (OSPanic(__FILE__, __LINE__, (msg), (param1), (param2)), 0)) +#define ASSERTMSG2(exp, msg, param1, param2) (void)((exp) || (OSPanic(__FILE__, __LINE__, (msg), (param1), (param2)), 0)) #endif #ifndef ASSERTMSG3 -#define ASSERTMSG3(exp, msg, param1, param2, param3) \ - (void)((exp) || (OSPanic(__FILE__, __LINE__, (msg), (param1), (param2), (param3)), 0)) +#define ASSERTMSG3(exp, msg, param1, param2, param3) (void)((exp) || (OSPanic(__FILE__, __LINE__, (msg), (param1), (param2), (param3)), 0)) #endif #ifndef ASSERTMSG4 -#define ASSERTMSG4(exp, msg, param1, param2, param3, param4) \ - (void)((exp) || (OSPanic(__FILE__, __LINE__, (msg), (param1), (param2), (param3), (param4)), 0)) +#define ASSERTMSG4(exp, msg, param1, param2, param3, param4) \ + (void)((exp) || (OSPanic(__FILE__, __LINE__, (msg), (param1), (param2), (param3), (param4)), 0)) #endif #else // _DEBUG @@ -209,8 +197,7 @@ BOOL OSRestoreInterrupts(BOOL level); #endif #ifndef ASSERTMSG -#if defined(__STDC_VERSION__) && (199901L <= __STDC_VERSION__) || defined(__MWERKS__) || \ - defined(__SN__) +#if defined(__STDC_VERSION__) && (199901L <= __STDC_VERSION__) || defined(__MWERKS__) || defined(__SN__) #define ASSERTMSG(exp, ...) ((void)0) #else #define ASSERTMSG(exp, msg) ((void)0) @@ -232,9 +219,9 @@ BOOL OSRestoreInterrupts(BOOL level); #endif // _DEBUG -void OSReport(const char* msg, ...); -void OSPanic(const char* file, int line, const char* msg, ...); -void OSFatal(GXColor fg, GXColor bg, const char* msg); +void OSReport(const char *msg, ...); +void OSPanic(const char *file, int line, const char *msg, ...); +void OSFatal(GXColor fg, GXColor bg, const char *msg); u32 OSGetPhysicalMemSize(void); u32 OSGetConsoleSimulatedMemSize(void); @@ -253,6 +240,7 @@ u32 OSGetConsoleSimulatedMemSize(void); #include #include #include +#include #include #include #include diff --git a/include/dolphin/os/OSAlloc.h b/include/dolphin/os/OSAlloc.h index bbd90491..686dae2b 100644 --- a/include/dolphin/os/OSAlloc.h +++ b/include/dolphin/os/OSAlloc.h @@ -7,19 +7,18 @@ extern "C" { #endif typedef int OSHeapHandle; -typedef void (*OSAllocVisitor)(void* obj, u32 size); -void* OSInitAlloc(void* arenaStart, void* arenaEnd, int maxHeaps); -OSHeapHandle OSCreateHeap(void* start, void* end); +typedef void (*OSAllocVisitor)(void *obj, u32 size); +void *OSInitAlloc(void *arenaStart, void *arenaEnd, int maxHeaps); +OSHeapHandle OSCreateHeap(void *start, void *end); void OSDestroyHeap(OSHeapHandle heap); -void OSAddToHeap(OSHeapHandle heap, void* start, void* end); +void OSAddToHeap(OSHeapHandle heap, void *start, void *end); OSHeapHandle OSSetCurrentHeap(OSHeapHandle heap); -void* OSAllocFromHeap(OSHeapHandle heap, u32 size); -void* OSAllocFixed(void** rstart, void** rend); -void OSFreeToHeap(OSHeapHandle heap, void* ptr); +void *OSAllocFromHeap(OSHeapHandle heap, u32 size); +void *OSAllocFixed(void **rstart, void **rend); +void OSFreeToHeap(OSHeapHandle heap, void *ptr); long OSCheckHeap(OSHeapHandle heap); void OSDumpHeap(OSHeapHandle heap); -void *OSAllocFixed(void **rstart, void **rend); -u32 OSReferentSize(void* ptr); +u32 OSReferentSize(void *ptr); void OSVisitAllocated(OSAllocVisitor visitor); extern volatile OSHeapHandle __OSCurrHeap; #define OSAlloc(size) OSAllocFromHeap(__OSCurrHeap, (size)) diff --git a/include/dolphin/os/OSContext.h b/include/dolphin/os/OSContext.h index bbd0aaa1..b363a214 100644 --- a/include/dolphin/os/OSContext.h +++ b/include/dolphin/os/OSContext.h @@ -158,10 +158,16 @@ typedef struct OSContext { } OSContext; +u32 OSGetStackPointer(void); +void OSDumpContext(OSContext *context); u32 OSSaveContext(OSContext* context); +void OSLoadContext(OSContext* context); void OSClearContext(OSContext* context); OSContext* OSGetCurrentContext(); void OSSetCurrentContext(OSContext* context); +void OSSaveFPUContext(OSContext *fpuContext); +void OSInitContext(OSContext *context, u32 pc, u32 newsp); + #ifdef __cplusplus } diff --git a/include/dolphin/os/OSFont.h b/include/dolphin/os/OSFont.h index 99238bad..54cfec1b 100644 --- a/include/dolphin/os/OSFont.h +++ b/include/dolphin/os/OSFont.h @@ -9,17 +9,44 @@ extern "C" { #define OS_FONT_ENCODE_ANSI 0u #define OS_FONT_ENCODE_SJIS 1u -#define OS_FONT_ENCODE_UTF8 3u // UTF-8 [RFC 3629] -#define OS_FONT_ENCODE_UTF16 4u // UTF-16BE [RFC 2781] -#define OS_FONT_ENCODE_UTF32 5u // UTF-32 -#define OS_FONT_ENCODE_MAX 5u -#define OS_FONT_ENCODE_VOID 0xffffu +#define OS_FONT_SIZE_ANSI (288 + 131072) // 9 sheets +#define OS_FONT_SIZE_SJIS (3840 + 1179648) // 1 sheet +#define OS_FONT_ROM_SIZE_ANSI 0x03000 +#define OS_FONT_ROM_SIZE_SJIS 0x4D000 -#define OS_FONT_PROPORTIONAL FALSE -#define OS_FONT_FIXED TRUE +typedef struct OSFontHeader +{ + /*0x00*/ u16 fontType; + u16 firstChar; + u16 lastChar; + u16 invalChar; + /*0x08*/ u16 ascent; + u16 descent; + u16 width; + u16 leading; + /*0x10*/ u16 cellWidth; + u16 cellHeight; + /*0x14*/ u32 sheetSize; + /*0x18*/ u16 sheetFormat; + u16 sheetColumn; + u16 sheetRow; + u16 sheetWidth; + /*0x20*/ u16 sheetHeight; + u16 widthTable; + u32 sheetImage; + u32 sheetFullSize; + u8 c0; + u8 c1; + u8 c2; + u8 c3; +} OSFontHeader; u16 OSGetFontEncode(void); -u16 OSSetFontEncode(u16 encode); +BOOL OSInitFont(OSFontHeader *fontData); +u32 OSLoadFont(OSFontHeader *fontData, void *temp); +char *OSGetFontTexture(char *string, void **image, s32 *x, s32 *y, s32 *width); +char *OSGetFontWidth(char *string, s32 *width); +char *OSGetFontTexel(char *string, void *image, s32 pos, s32 stride, s32 *width); #ifdef __cplusplus } diff --git a/include/dolphin/os/OSIC.h b/include/dolphin/os/OSIC.h new file mode 100644 index 00000000..017d5a58 --- /dev/null +++ b/include/dolphin/os/OSIC.h @@ -0,0 +1,20 @@ +#ifndef _DOLPHIN_OSIC +#define _DOLPHIN_OSIC + +#ifdef __cplusplus +extern "C" { +#endif + +void ICFlashInvalidate(void); +void ICEnable(void); +void ICDisable(void); +void ICFreeze(void); +void ICUnfreeze(void); +void ICBlockInvalidate(void *addr); +void ICSync(void); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/dolphin/os/OSModule.h b/include/dolphin/os/OSModule.h index 7baf2a9f..e8cbe25b 100644 --- a/include/dolphin/os/OSModule.h +++ b/include/dolphin/os/OSModule.h @@ -105,8 +105,8 @@ BOOL OSUnlink(OSModuleInfo* oldModule); OSModuleInfo* OSSearchModule(void* ptr, u32* section, u32* offset); // debugger notification -void OSNotifyLink(OSModuleInfo* module); -void OSNotifyUnlink(OSModuleInfo* module); +void OSNotifyLink(void); +void OSNotifyUnlink(void); #ifdef __cplusplus } diff --git a/include/dolphin/os/OSPriv.h b/include/dolphin/os/OSPriv.h index 8b914f25..11eeec59 100644 --- a/include/dolphin/os/OSPriv.h +++ b/include/dolphin/os/OSPriv.h @@ -7,10 +7,42 @@ extern "C" { #endif +#define OFFSET(addr, align) (((u32)(addr) & ((align)-1))) + +// OSAudioSystem.c +void __OSInitAudioSystem(void); +void __OSStopAudioSystem(void); + +// OSCache.c +void __OSCacheInit(void); + +// OSContext.c +void __OSContextInit(void); + +// OSMutex.c +void __OSUnlockAllMutex(struct OSThread *thread); + +// OSInterrupt.c +extern void __RAS_OSDisableInterrupts_begin(void); +extern void __RAS_OSDisableInterrupts_end(void); +void __OSInterruptInit(void); +void __OSModuleInit(void); + +void __OSInitSystemCall(void); + +// OSThread.c +void __OSThreadInit(void); +void __OSReschedule(void); + +typedef void (*OSExceptionHandler)(__OSException, OSContext*); +OSExceptionHandler __OSSetExceptionHandler(__OSException exception, OSExceptionHandler handler); __OSExceptionHandler __OSGetExceptionHandler(__OSException exception); OSTime __OSGetSystemTime(); OSTime __OSTimeToSystemTime(OSTime); +// OSReboot +void __OSReboot(u32 resetCode, u32 bootDol); + #ifdef __cplusplus } #endif diff --git a/src/dolphin/os/OS.c b/src/dolphin/os/OS.c new file mode 100644 index 00000000..69843d73 --- /dev/null +++ b/src/dolphin/os/OS.c @@ -0,0 +1,645 @@ +#include <__ppc_eabi_linker.h> +#include +#include +#include +#include +#include +#include +#include +#include +#include + +extern OSTime __OSGetSystemTime(); +extern char _db_stack_end[]; + +#define OS_BI2_DEBUG_ADDRESS 0x800000F4 +#define DEBUGFLAG_ADDR 0x800030E8 +#define OS_DEBUG_ADDRESS_2 0x800030E9 +#define OS_CURRENTCONTEXT_PADDR 0x00C0 + +extern char *__OSResetSWInterruptHandler[]; + +vu16 __OSDeviceCode : (OS_BASE_CACHED | 0x30E6); +static DVDDriveInfo DriveInfo ATTRIBUTE_ALIGN(32); +static DVDCommandBlock DriveBlock; + +static OSBootInfo *BootInfo; +static u32 *BI2DebugFlag; +static u32 *BI2DebugFlagHolder; +__declspec(weak) BOOL __OSIsGcam = FALSE; +static f64 ZeroF; +static f32 ZeroPS[2]; +static BOOL AreWeInitialized = FALSE; +static __OSExceptionHandler *OSExceptionTable; +OSTime __OSStartTime; +BOOL __OSInIPL; + +extern u8 __ArenaHi[]; +extern u8 __ArenaLo[]; +extern u32 __DVDLongFileNameFlag; +extern u32 __PADSpec; + +#define OS_EXCEPTIONTABLE_ADDR 0x3000 +#define OS_DBJUMPPOINT_ADDR 0x60 +// memory locations for important stuff +#define OS_CACHED_REGION_PREFIX 0x8000 +#define OS_BI2_DEBUG_ADDRESS 0x800000F4 +#define OS_BI2_DEBUGFLAG_OFFSET 0xC +#define PAD3_BUTTON_ADDR 0x800030E4 +#define OS_DVD_DEVICECODE 0x800030E6 +#define DEBUGFLAG_ADDR 0x800030E8 +#define OS_DEBUG_ADDRESS_2 0x800030E9 +#define DB_EXCEPTIONRET_OFFSET 0xC +#define DB_EXCEPTIONDEST_OFFSET 0x8 + +void OSDefaultExceptionHandler(__OSException exception, OSContext *context); +extern BOOL __DBIsExceptionMarked(__OSException); +static void OSExceptionInit(void); + +/* clang-format off */ +asm void __OSFPRInit(void) +{ + nofralloc + + mfmsr r3 + ori r3, r3, 0x2000 + mtmsr r3 + + mfspr r3, 0x398 + rlwinm. r3, r3, 3, 31, 31 + beq SkipPairedSingles + + lis r3, ZeroPS@ha + addi r3, r3, ZeroPS@l + psq_l fp0, 0(r3), 0, 0 + ps_mr fp1, fp0 + ps_mr fp2, fp0 + ps_mr fp3, fp0 + ps_mr fp4, fp0 + ps_mr fp5, fp0 + ps_mr fp6, fp0 + ps_mr fp7, fp0 + ps_mr fp8, fp0 + ps_mr fp9, fp0 + ps_mr fp10, fp0 + ps_mr fp11, fp0 + ps_mr fp12, fp0 + ps_mr fp13, fp0 + ps_mr fp14, fp0 + ps_mr fp15, fp0 + ps_mr fp16, fp0 + ps_mr fp17, fp0 + ps_mr fp18, fp0 + ps_mr fp19, fp0 + ps_mr fp20, fp0 + ps_mr fp21, fp0 + ps_mr fp22, fp0 + ps_mr fp23, fp0 + ps_mr fp24, fp0 + ps_mr fp25, fp0 + ps_mr fp26, fp0 + ps_mr fp27, fp0 + ps_mr fp28, fp0 + ps_mr fp29, fp0 + ps_mr fp30, fp0 + ps_mr fp31, fp0 + +SkipPairedSingles: + lfd fp0, ZeroF + fmr fp1, fp0 + fmr fp2, fp0 + fmr fp3, fp0 + fmr fp4, fp0 + fmr fp5, fp0 + fmr fp6, fp0 + fmr fp7, fp0 + fmr fp8, fp0 + fmr fp9, fp0 + fmr fp10, fp0 + fmr fp11, fp0 + fmr fp12, fp0 + fmr fp13, fp0 + fmr fp14, fp0 + fmr fp15, fp0 + fmr fp16, fp0 + fmr fp17, fp0 + fmr fp18, fp0 + fmr fp19, fp0 + fmr fp20, fp0 + fmr fp21, fp0 + fmr fp22, fp0 + fmr fp23, fp0 + fmr fp24, fp0 + fmr fp25, fp0 + fmr fp26, fp0 + fmr fp27, fp0 + fmr fp28, fp0 + fmr fp29, fp0 + fmr fp30, fp0 + fmr fp31, fp0 + + mtfsf 0xFF, fp0 + + blr +} +/* clang-format on */ + +u32 OSGetConsoleType() +{ + if (BootInfo == NULL || BootInfo->consoleType == 0) { + return OS_CONSOLE_ARTHUR; + } + return BootInfo->consoleType; +} + +void *__OSSavedRegionStart; +void *__OSSavedRegionEnd; + +extern u32 BOOT_REGION_START : 0x812FDFF0; //(*(u32 *)0x812fdff0) +extern u32 BOOT_REGION_END : 0x812FDFEC; //(*(u32 *)0x812fdfec) + +void ClearArena(void) +{ + if ((u32)(OSGetResetCode() + 0x80000000) != 0U) { + __OSSavedRegionStart = 0U; + __OSSavedRegionEnd = 0U; + memset(OSGetArenaLo(), 0U, (u32)OSGetArenaHi() - (u32)OSGetArenaLo()); + return; + } + __OSSavedRegionStart = (void *)BOOT_REGION_START; + __OSSavedRegionEnd = (void *)BOOT_REGION_END; + if (BOOT_REGION_START == 0U) { + memset(OSGetArenaLo(), 0U, (u32)OSGetArenaHi() - (u32)OSGetArenaLo()); + return; + } + + if ((u32)OSGetArenaLo() < (u32)__OSSavedRegionStart) { + if ((u32)OSGetArenaHi() <= (u32)__OSSavedRegionStart) { + memset((u32)OSGetArenaLo(), 0U, (u32)OSGetArenaHi() - (u32)OSGetArenaLo()); + return; + } + memset(OSGetArenaLo(), 0U, (u32)__OSSavedRegionStart - (u32)OSGetArenaLo()); + if ((u32)OSGetArenaHi() > (u32)__OSSavedRegionEnd) { + memset((u32)__OSSavedRegionEnd, 0, (u32)OSGetArenaHi() - (u32)__OSSavedRegionEnd); + } + } +} + +static void InquiryCallback(s32 result, DVDCommandBlock *block) +{ + switch (block->state) { + case 0: + __OSDeviceCode = (u16)(0x8000 | DriveInfo.deviceCode); + break; + default: + __OSDeviceCode = 1; + break; + } +} + +void OSInit(void) +{ + /* + Initializes the Dolphin operating system. + - most of the main operations get farmed out to other functions + - loading debug info and setting up heap bounds largely happen here + - a lot of OS reporting also gets controlled here + */ + // pretty sure this is the min(/max) amount of pointers etc for the stack to match + BI2Debug *DebugInfo; + void *debugArenaLo; + u32 inputConsoleType; + + // check if we've already done all this or not + if ((BOOL)AreWeInitialized == FALSE) { // fantastic name + AreWeInitialized = TRUE; // flag to make sure we don't have to do this again + + // SYSTEM // + __OSStartTime = __OSGetSystemTime(); + OSDisableInterrupts(); + + // set some PPC things + PPCDisableSpeculation(); + PPCSetFpNonIEEEMode(); + + // DEBUG // + // load some DVD stuff + BI2DebugFlag = 0; // debug flag from the DVD BI2 header + BootInfo = (OSBootInfo *)OS_BASE_CACHED; // set pointer to BootInfo + + __DVDLongFileNameFlag = (u32)0; // flag to tell us whether we make it through the debug loading + + // time to grab a bunch of debug info from the DVD + // the address for where the BI2 debug info is, is stored at OS_BI2_DEBUG_ADDRESS + DebugInfo = (BI2Debug *)*((u32 *)OS_BI2_DEBUG_ADDRESS); + + // if the debug info address exists, grab some debug info + if (DebugInfo != NULL) { + BI2DebugFlag = &DebugInfo->debugFlag; // debug flag from DVD BI2 + __PADSpec = (u32)DebugInfo->padSpec; // some other info from DVD BI2 + *((u8 *)DEBUGFLAG_ADDR) = (u8)*BI2DebugFlag; // store flag in mem + *((u8 *)OS_DEBUG_ADDRESS_2) = (u8)__PADSpec; // store other info in mem + } + else if (BootInfo->arenaHi) { // if the top of the heap is already set + BI2DebugFlagHolder = (u32 *)*((u8 *)DEBUGFLAG_ADDR); // grab whatever's stored at 0x800030E8 + BI2DebugFlag = (u32 *)&BI2DebugFlagHolder; // flag is then address of flag holder + __PADSpec = (u32) * ((u8 *)OS_DEBUG_ADDRESS_2); // pad spec is whatever's at 0x800030E9 + } + + __DVDLongFileNameFlag = 1; // we made it through debug! + + // HEAP // + // set up bottom of heap (ArenaLo) + // grab address from BootInfo if it exists, otherwise use default __ArenaLo + OSSetArenaLo((BootInfo->arenaLo == NULL) ? __ArenaLo : BootInfo->arenaLo); + + // if the input arenaLo is null, and debug flag location exists (and flag is < 2), + // set arenaLo to just past the end of the db stack + if ((BootInfo->arenaLo == NULL) && (BI2DebugFlag != 0) && (*BI2DebugFlag < 2)) { + debugArenaLo = (char *)(((u32)_stack_addr + 0x1f) & ~0x1f); + OSSetArenaLo(debugArenaLo); + } + + // set up top of heap (ArenaHi) + // grab address from BootInfo if it exists, otherwise use default __ArenaHi + OSSetArenaHi((BootInfo->arenaHi == NULL) ? __ArenaHi : BootInfo->arenaHi); + + // OS INIT AND REPORT // + // initialise a whole bunch of OS stuff + OSExceptionInit(); + __OSInitSystemCall(); + OSInitAlarm(); + __OSModuleInit(); + __OSInterruptInit(); + __OSSetInterruptHandler(__OS_INTERRUPT_PI_RSW, (void *)__OSResetSWInterruptHandler); + __OSContextInit(); + __OSCacheInit(); + EXIInit(); + SIInit(); + __OSInitSram(); + __OSThreadInit(); + __OSInitAudioSystem(); + PPCMthid2(PPCMfhid2() & 0xBFFFFFFF); + if ((BootInfo->consoleType & OS_CONSOLE_DEVELOPMENT) != 0) { + BootInfo->consoleType = OS_CONSOLE_DEVHW1; + } + else { + BootInfo->consoleType = OS_CONSOLE_RETAIL1; + } + BootInfo->consoleType += (__PIRegs[11] & 0xF0000000) >> 28; + if ((BOOL)__OSInIPL == FALSE) { + __OSInitMemoryProtection(); + } + + // begin OS reporting + OSReport("\nDolphin OS $Revision: 54 $.\n"); + OSReport("Kernel built : %s %s\n", "Jun 5 2002", "02:09:12"); + OSReport("Console Type : "); + + // this is a function in the same file, but it doesn't seem to match + // inputConsoleType = OSGetConsoleType(); + + // inputConsoleType = (BootInfo == NULL || (inputConsoleType = BootInfo->consoleType) == 0) ? + // 0x10000002 : BootInfo->consoleType; + if (BootInfo == NULL || (inputConsoleType = BootInfo->consoleType) == 0) { + inputConsoleType = OS_CONSOLE_ARTHUR; // default console type + } + else { + inputConsoleType = BootInfo->consoleType; + } + + // work out what console type this corresponds to and report it + // consoleTypeSwitchHi = inputConsoleType & 0xF0000000; + inputConsoleType = OSGetConsoleType(); + if ((inputConsoleType & 0x10000000) == OS_CONSOLE_RETAIL) { // check "first" byte + OSReport("Retail %d\n", inputConsoleType); + } + else { + switch (inputConsoleType) { // if "first" byte is 2, check "the rest" + case OS_CONSOLE_EMULATOR: + OSReport("Mac Emulator\n"); + break; + case OS_CONSOLE_PC_EMULATOR: + OSReport("PC Emulator\n"); + break; + case OS_CONSOLE_ARTHUR: + OSReport("EPPC Arthur\n"); + break; + case OS_CONSOLE_MINNOW: + OSReport("EPPC Minnow\n"); + break; + default: + OSReport("Development HW%d\n", ((u32)inputConsoleType - 0x10000000) - 3); + break; + } + } + + // report memory size + OSReport("Memory %d MB\n", (u32)BootInfo->memorySize >> 0x14U); + // report heap bounds + OSReport("Arena : 0x%x - 0x%x\n", OSGetArenaLo(), OSGetArenaHi()); + // report OS version + + // if location of debug flag exists, and flag is >= 2, enable MetroTRKInterrupts + if (BI2DebugFlag && ((*BI2DebugFlag) >= 2)) { + EnableMetroTRKInterrupts(); + } + + // free up memory and re-enable things + ClearArena(); + OSEnableInterrupts(); + + // check if we can load OS from IPL; if not, grab it from DVD (?) + if ((BOOL)__OSInIPL == FALSE) { + DVDInit(); + if ((BOOL)__OSIsGcam) { + __OSDeviceCode = 0x9000; + return; + } + DCInvalidateRange(&DriveInfo, sizeof(DriveInfo)); + DVDInquiryAsync((char *)&DriveBlock, &DriveInfo, InquiryCallback); + } + } +} + +static u32 __OSExceptionLocations[] = { + 0x00000100, + 0x00000200, + 0x00000300, + 0x00000400, + 0x00000500, + 0x00000600, + 0x00000700, + 0x00000800, + 0x00000900, + 0x00000C00, + 0x00000D00, + 0x00000F00, + 0x00001300, + 0x00001400, + 0x00001700, +}; + +// dummy entry points to the OS Exception vector +void __OSEVStart(void); +void __OSEVEnd(void); +void __OSEVSetNumber(void); +void __OSExceptionVector(void); + +void __DBVECTOR(void); +void __OSDBINTSTART(void); +void __OSDBINTEND(void); +void __OSDBJUMPSTART(void); +void __OSDBJUMPEND(void); + +#define NOP 0x60000000 + +__OSExceptionHandler __OSSetExceptionHandler(__OSException exception, __OSExceptionHandler handler); + +static void OSExceptionInit(void) +{ + __OSException exception; + void *destAddr; + + // These two vars help us change the exception number embedded + // in the exception handler code. + u32 *opCodeAddr; + u32 oldOpCode; + + // Address range of the actual code to be copied. + u8 *handlerStart; + u32 handlerSize; + + // Install the first level exception vector. + opCodeAddr = (u32 *)__OSEVSetNumber; + oldOpCode = *opCodeAddr; + handlerStart = (u8 *)__OSEVStart; + handlerSize = (u32)((u8 *)__OSEVEnd - (u8 *)__OSEVStart); + + // Install the DB integrator, only if we are the first OSInit to be run + destAddr = (void *)OSPhysicalToCached(OS_DBJUMPPOINT_ADDR); + if (*(u32 *)destAddr == 0) // Lomem should be zero cleared only once by BS2 + { + DBPrintf("Installing OSDBIntegrator\n"); + memcpy(destAddr, (void *)__OSDBINTSTART, (u32)__OSDBINTEND - (u32)__OSDBINTSTART); + DCFlushRangeNoSync(destAddr, (u32)__OSDBINTEND - (u32)__OSDBINTSTART); + __sync(); + ICInvalidateRange(destAddr, (u32)__OSDBINTEND - (u32)__OSDBINTSTART); + } + + // Copy the right vector into the table + for (exception = 0; exception < 15; exception++) { + if (BI2DebugFlag && (*BI2DebugFlag >= 2) && __DBIsExceptionMarked(exception)) { + // this DBPrintf is suspicious. + DBPrintf(">>> OSINIT: exception %d commandeered by TRK\n", exception); + continue; + } + + // Modify the copy of code in text before transferring + // to the exception table. + *opCodeAddr = oldOpCode | exception; + + // Modify opcodes at __DBVECTOR if necessary + if (__DBIsExceptionMarked(exception)) { + DBPrintf(">>> OSINIT: exception %d vectored to debugger\n", exception); + memcpy((void *)__DBVECTOR, (void *)__OSDBINTEND, (u32)__OSDBJUMPEND - (u32)__OSDBINTEND); + } + else { + // make sure the opcodes are still nop + u32 *ops = (u32 *)__DBVECTOR; + int cb; + + for (cb = 0; cb < (u32)__OSDBJUMPEND - (u32)__OSDBINTEND; cb += sizeof(u32)) { + *ops++ = NOP; + } + } + + // Install the modified handler. + destAddr = (void *)OSPhysicalToCached(__OSExceptionLocations[(u32)exception]); + memcpy(destAddr, handlerStart, handlerSize); + DCFlushRangeNoSync(destAddr, handlerSize); + __sync(); + ICInvalidateRange(destAddr, handlerSize); + } + + // initialize pointer to exception table + OSExceptionTable = OSPhysicalToCached(OS_EXCEPTIONTABLE_ADDR); + + // install default exception handlers + for (exception = 0; exception < 15; exception++) { + __OSSetExceptionHandler(exception, OSDefaultExceptionHandler); + } + + // restore the old opcode, so that we can re-start an application without + // downloading the text segments + *opCodeAddr = oldOpCode; + + DBPrintf("Exceptions initialized...\n"); +} + +static asm void __OSDBIntegrator(void) +{ + /* clang-format off */ + nofralloc +entry __OSDBINTSTART + li r5, OS_DBINTERFACE_ADDR + mflr r3 + stw r3, DB_EXCEPTIONRET_OFFSET(r5) + lwz r3, DB_EXCEPTIONDEST_OFFSET(r5) + oris r3, r3, OS_CACHED_REGION_PREFIX + mtlr r3 + li r3, 0x30 // MSR_IR | MSR_DR // turn on memory addressing + mtmsr r3 + blr +entry __OSDBINTEND + /* clang-format on */ +} + +static asm void __OSDBJump(void) { + /* clang-format off */ + + nofralloc +entry __OSDBJUMPSTART + bla OS_DBJUMPPOINT_ADDR +entry __OSDBJUMPEND + /* clang-format on */ + +} + +__OSExceptionHandler __OSSetExceptionHandler(__OSException exception, __OSExceptionHandler handler) +{ + __OSExceptionHandler oldHandler; + oldHandler = OSExceptionTable[exception]; + OSExceptionTable[exception] = handler; + return oldHandler; +} + +__OSExceptionHandler __OSGetExceptionHandler(__OSException exception) +{ + return OSExceptionTable[exception]; +} + +static asm void OSExceptionVector(void) +{ + /* clang-format off */ + nofralloc + +entry __OSEVStart + // Save r4 into SPRG0 + mtsprg 0, r4 + + // Load current context physical address into r4 + lwz r4, OS_CURRENTCONTEXT_PADDR + + // Save r3 - r5 into the current context + stw r3, OS_CONTEXT_R3(r4) + mfsprg r3, 0 + stw r3, OS_CONTEXT_R4(r4) + stw r5, OS_CONTEXT_R5(r4) + + lhz r3, OS_CONTEXT_STATE(r4) + ori r3, r3, OS_CONTEXT_STATE_EXC + sth r3, OS_CONTEXT_STATE(r4) + + // Save misc registers + mfcr r3 + stw r3, OS_CONTEXT_CR(r4) + mflr r3 + stw r3, OS_CONTEXT_LR(r4) + mfctr r3 + stw r3, OS_CONTEXT_CTR(r4) + mfxer r3 + stw r3, OS_CONTEXT_XER(r4) + mfsrr0 r3 + stw r3, OS_CONTEXT_SRR0(r4) + mfsrr1 r3 + stw r3, OS_CONTEXT_SRR1(r4) + mr r5, r3 + +entry __DBVECTOR + nop + + // Set SRR1[IR|DR] to turn on address + // translation at the next RFI + mfmsr r3 + ori r3, r3, 0x30 + mtsrr1 r3 + + // This lets us change the exception number based on the + // exception we're installing. +entry __OSEVSetNumber + addi r3, 0, 0x0000 + + // Load current context virtual address into r4 + lwz r4, 0xD4 + + // Check non-recoverable interrupt + rlwinm. r5, r5, 0, MSR_RI_BIT, MSR_RI_BIT + bne recoverable + addis r5, 0, OSDefaultExceptionHandler@ha + addi r5, r5, OSDefaultExceptionHandler@l + mtsrr0 r5 + rfi + // NOT REACHED HERE + +recoverable: + // Locate exception handler. + rlwinm r5, r3, 2, 22, 29 // r5 contains exception*4 + lwz r5, OS_EXCEPTIONTABLE_ADDR(r5) + mtsrr0 r5 + + // Final state + // r3 - exception number + // r4 - pointer to context + // r5 - garbage + // srr0 - exception handler + // srr1 - address translation enalbed, not yet recoverable + + rfi + // NOT REACHED HERE + // The handler will restore state + +entry __OSEVEnd + nop + /* clang-format on */ +} + +void __OSUnhandledException(__OSException exception, OSContext *context, u32 dsisr, u32 dar); +asm void OSDefaultExceptionHandler(register __OSException exception, register OSContext *context) +{ + /* clang-format off */ + nofralloc + OS_EXCEPTION_SAVE_GPRS(context) + mfdsisr r5 + mfdar r6 + + stwu r1,-8(r1) + b __OSUnhandledException + /* clang-foramt on */ +} + +void __OSPSInit(void) +{ + PPCMthid2(PPCMfhid2() | 0xA0000000); + ICFlashInvalidate(); + __sync(); + // clang-format off + asm + { + li r3, 0 + mtspr GQR0, r3 + } + // clang-format on +} + +#define DI_CONFIG_IDX 0x9 +#define DI_CONFIG_CONFIG_MASK 0xFF +u32 __OSGetDIConfig(void) +{ + return (__DIRegs[DI_CONFIG_IDX] & DI_CONFIG_CONFIG_MASK); +} + +void OSRegisterVersion(const char *id) +{ + OSReport("%s\n", id); +} diff --git a/src/dolphin/os/OSAlarm.c b/src/dolphin/os/OSAlarm.c new file mode 100644 index 00000000..7c3f0e97 --- /dev/null +++ b/src/dolphin/os/OSAlarm.c @@ -0,0 +1,199 @@ +#include +#include + +#include + +static struct OSAlarmQueue { + OSAlarm *head; + OSAlarm *tail; +} AlarmQueue; + +static void DecrementerExceptionHandler(__OSException exception, OSContext *context); +static BOOL OnReset(BOOL final); + +void OSInitAlarm(void) +{ + if (__OSGetExceptionHandler(8) != DecrementerExceptionHandler) { + AlarmQueue.head = AlarmQueue.tail = NULL; + __OSSetExceptionHandler(8, DecrementerExceptionHandler); + } +} + +void OSCreateAlarm(OSAlarm *alarm) +{ + alarm->handler = 0; +} + +static void SetTimer(OSAlarm *alarm) +{ + OSTime delta; + + delta = alarm->fire - __OSGetSystemTime(); + if (delta < 0) { + PPCMtdec(0); + } + else if (delta < 0x80000000) { + PPCMtdec((u32)delta); + } + else { + PPCMtdec(0x7fffffff); + } +} + +static void InsertAlarm(OSAlarm *alarm, OSTime fire, OSAlarmHandler handler) +{ + OSAlarm *next; + OSAlarm *prev; + + if (0 < alarm->period) { + OSTime time = __OSGetSystemTime(); + + fire = alarm->start; + if (alarm->start < time) { + fire += alarm->period * ((time - alarm->start) / alarm->period + 1); + } + } + + alarm->handler = handler; + alarm->fire = fire; + + for (next = AlarmQueue.head; next; next = next->next) { + if (next->fire <= fire) { + continue; + } + + alarm->prev = next->prev; + next->prev = alarm; + alarm->next = next; + prev = alarm->prev; + if (prev) { + prev->next = alarm; + } + else { + AlarmQueue.head = alarm; + SetTimer(alarm); + } + return; + } + alarm->next = 0; + prev = AlarmQueue.tail; + AlarmQueue.tail = alarm; + alarm->prev = prev; + if (prev) { + prev->next = alarm; + } + else { + AlarmQueue.head = AlarmQueue.tail = alarm; + SetTimer(alarm); + } +} + +void OSSetAlarm(OSAlarm *alarm, OSTime tick, OSAlarmHandler handler) +{ + BOOL enabled; + enabled = OSDisableInterrupts(); + alarm->period = 0; + InsertAlarm(alarm, __OSGetSystemTime() + tick, handler); + OSRestoreInterrupts(enabled); +} + +void OSSetPeriodicAlarm(OSAlarm *alarm, OSTime start, OSTime period, OSAlarmHandler handler) +{ + BOOL enabled; + enabled = OSDisableInterrupts(); + alarm->period = period; + alarm->start = __OSTimeToSystemTime(start); + InsertAlarm(alarm, 0, handler); + OSRestoreInterrupts(enabled); +} + +void OSCancelAlarm(OSAlarm *alarm) +{ + OSAlarm *next; + BOOL enabled; + + enabled = OSDisableInterrupts(); + + if (alarm->handler == 0) { + OSRestoreInterrupts(enabled); + return; + } + + next = alarm->next; + if (next == 0) { + AlarmQueue.tail = alarm->prev; + } + else { + next->prev = alarm->prev; + } + if (alarm->prev) { + alarm->prev->next = next; + } + else { + AlarmQueue.head = next; + if (next) { + SetTimer(next); + } + } + alarm->handler = 0; + + OSRestoreInterrupts(enabled); +} + +static void DecrementerExceptionCallback(register __OSException exception, register OSContext *context) +{ + OSAlarm *alarm; + OSAlarm *next; + OSAlarmHandler handler; + OSTime time; + OSContext exceptionContext; + time = __OSGetSystemTime(); + alarm = AlarmQueue.head; + if (alarm == 0) { + OSLoadContext(context); + } + + if (time < alarm->fire) { + SetTimer(alarm); + OSLoadContext(context); + } + + next = alarm->next; + AlarmQueue.head = next; + if (next == 0) { + AlarmQueue.tail = 0; + } + else { + next->prev = 0; + } + + handler = alarm->handler; + alarm->handler = 0; + if (0 < alarm->period) { + InsertAlarm(alarm, 0, handler); + } + + if (AlarmQueue.head) { + SetTimer(AlarmQueue.head); + } + + OSDisableScheduler(); + OSClearContext(&exceptionContext); + OSSetCurrentContext(&exceptionContext); + handler(alarm, context); + OSClearContext(&exceptionContext); + OSSetCurrentContext(context); + OSEnableScheduler(); + __OSReschedule(); + OSLoadContext(context); +} + +static asm void DecrementerExceptionHandler(register __OSException exception, register OSContext *context) +{ + /* clang-format off */ + nofralloc + OS_EXCEPTION_SAVE_GPRS(context) + stwu r1, -8(r1) + b DecrementerExceptionCallback + /* clang-format on */ +} diff --git a/src/dolphin/os/OSAlloc.c b/src/dolphin/os/OSAlloc.c new file mode 100644 index 00000000..fe0c34ae --- /dev/null +++ b/src/dolphin/os/OSAlloc.c @@ -0,0 +1,531 @@ +#include +#include +#include + +#define ALIGNMENT 32 + +#define InRange(cell, arenaStart, arenaEnd) ((u32)arenaStart <= (u32)cell) && ((u32)cell < (u32)arenaEnd) + +#define HEADERSIZE 32u +#define MINOBJSIZE 64u + +struct Cell { + struct Cell *prev; + struct Cell *next; + long size; +}; + +struct HeapDesc { + long size; + struct Cell *free; + struct Cell *allocated; +}; + +volatile int __OSCurrHeap = -1; + +static struct HeapDesc *HeapArray; +static int NumHeaps; +static void *ArenaStart; +static void *ArenaEnd; + +// functions +static struct Cell *DLAddFront(struct Cell *list, struct Cell *cell); +static struct Cell *DLLookup(struct Cell *list, struct Cell *cell); +static struct Cell *DLExtract(struct Cell *list, struct Cell *cell); +static struct Cell *DLInsert(struct Cell *list, struct Cell *cell); +static int DLOverlap(struct Cell *list, void *start, void *end); +static long DLSize(struct Cell *list); + +static struct Cell *DLAddFront(struct Cell *list, struct Cell *cell) +{ + cell->next = list; + cell->prev = 0; + if (list) { + list->prev = cell; + } + return cell; +} + +static struct Cell *DLLookup(struct Cell *list, struct Cell *cell) +{ + for (; list; list = list->next) { + if (list == cell) { + return list; + } + } + return NULL; +} + +static struct Cell *DLExtract(struct Cell *list, struct Cell *cell) +{ + if (cell->next) { + cell->next->prev = cell->prev; + } + if (cell->prev == NULL) { + return cell->next; + } + cell->prev->next = cell->next; + return list; +} + +static struct Cell *DLInsert(struct Cell *list, struct Cell *cell) +{ + struct Cell *prev; + struct Cell *next; + + for (next = list, prev = NULL; next != 0; prev = next, next = next->next) { + if (cell <= next) { + break; + } + } + + cell->next = next; + cell->prev = prev; + if (next) { + next->prev = cell; + if ((u8 *)cell + cell->size == (u8 *)next) { + cell->size += next->size; + next = next->next; + cell->next = next; + if (next) { + next->prev = cell; + } + } + } + if (prev) { + prev->next = cell; + if ((u8 *)prev + prev->size == (u8 *)cell) { + prev->size += cell->size; + prev->next = next; + if (next) { + next->prev = prev; + } + } + return list; + } + return cell; +} + +static int DLOverlap(struct Cell *list, void *start, void *end) +{ + struct Cell *cell = list; + + while (cell) { + if (((start <= cell) && (cell < end)) || ((start < (void *)((u8 *)cell + cell->size)) && ((void *)((u8 *)cell + cell->size) <= end))) { + return 1; + } + cell = cell->next; + } + return 0; +} + +static long DLSize(struct Cell *list) +{ + struct Cell *cell; + long size; + + size = 0; + cell = list; + + while (cell) { + size += cell->size; + cell = cell->next; + } + + return size; +} + +void *OSAllocFromHeap(int heap, unsigned long size) +{ + struct HeapDesc *hd; + struct Cell *cell; + struct Cell *newCell; + long leftoverSize; + long requested; + + requested = size; + ASSERTMSG1(0x14D, HeapArray, "OSAllocFromHeap(): heap is not initialized."); + ASSERTMSG1(0x14E, (signed long)size > 0, "OSAllocFromHeap(): invalid size."); + ASSERTMSG1(0x14F, heap >= 0 && heap < NumHeaps, "OSAllocFromHeap(): invalid heap handle."); + ASSERTMSG1(0x150, HeapArray[heap].size >= 0, "OSAllocFromHeap(): invalid heap handle."); + + hd = &HeapArray[heap]; + size += 0x20; + size = (size + 0x1F) & 0xFFFFFFE0; + + for (cell = hd->free; cell != NULL; cell = cell->next) { + if ((signed)size <= (signed)cell->size) { + break; + } + } + + if (cell == NULL) { + return NULL; + } + ASSERTMSG1(0x168, !((s32)cell & 0x1F), "OSAllocFromHeap(): heap is broken."); + ASSERTMSG1(0x169, cell->hd == NULL, "OSAllocFromHeap(): heap is broken."); + + leftoverSize = cell->size - size; + if (leftoverSize < 0x40U) { + hd->free = DLExtract(hd->free, cell); + } + else { + cell->size = size; + newCell = (void *)((u8 *)cell + size); + newCell->size = leftoverSize; + newCell->prev = cell->prev; + newCell->next = cell->next; + if (newCell->next != NULL) { + newCell->next->prev = newCell; + } + if (newCell->prev != NULL) { + newCell->prev->next = newCell; + } + else { + ASSERTMSG1(0x186, hd->free == cell, "OSAllocFromHeap(): heap is broken."); + hd->free = newCell; + } + } + + hd->allocated = DLAddFront(hd->allocated, cell); + return (u8 *)cell + 0x20; +} + +void *OSAllocFixed(void **rstart, void **rend) +{ + int i; + struct Cell *cell; + struct Cell *newCell; + struct HeapDesc *hd; + void *start; + void *end; + void *cellEnd; + + start = (void *)((*(u32 *)rstart) & ~((32) - 1)); + end = (void *)((*(u32 *)rend + 0x1FU) & ~((32) - 1)); + + ASSERTMSG1(0x1B0, HeapArray, "OSAllocFixed(): heap is not initialized."); + ASSERTMSG1(0x1B1, (u32)start < (u32)end, "OSAllocFixed(): invalid range."); + ASSERTMSG1(0x1B3, ((u32)ArenaStart <= (u32)start) && ((u32)end <= (u32)ArenaEnd), "OSAllocFixed(): invalid range."); + + for (i = 0; i < NumHeaps; i++) { + hd = &HeapArray[i]; + if (hd->size >= 0) { + if (DLOverlap(hd->allocated, start, end)) { + return NULL; + } + } + } + + for (i = 0; i < NumHeaps; i++) { + hd = &HeapArray[i]; + if (hd->size >= 0) { + for (cell = hd->free; cell; cell = cell->next) { + cellEnd = ((u8 *)cell + cell->size); + if (cellEnd > start) { + if (end <= cell) { + break; + } + if ((char *)start - 0x20 <= (char *)cell && cell < end && (start <= cellEnd) && (cellEnd < ((char *)end + 0x40))) { + if (cell < start) { + start = cell; + } + if (end < cellEnd) { + end = cellEnd; + } + hd->free = DLExtract(hd->free, cell); + hd->size -= cell->size; + } + else if ((char *)start - 0x20 <= (char *)cell && cell < end) { + if (cell < start) { + start = cell; + } + ASSERTMSG(0x1F3, MINOBJSIZE <= (char *)cellEnd - (char *)end); + newCell = (struct Cell *)end; + + newCell->size = (s32)((char *)cellEnd - (char *)end); + newCell->next = cell->next; + if (newCell->next) { + newCell->next->prev = newCell; + } + newCell->prev = cell->prev; + if (newCell->prev) { + newCell->prev->next = newCell; + } + else { + hd->free = newCell; + } + hd->size -= ((char *)end - (char *)cell); + break; + } + else { + if ((start <= cellEnd) && (cellEnd < ((char *)end + 0x40U))) { + if (end < cellEnd) { + end = cellEnd; + } + ASSERTMSG(0x20C, MINOBJSIZE <= (char *)start - (char *)cell); + hd->size -= ((char *)cellEnd - (char *)start); + cell->size = ((char *)start - (char *)cell); + } + else { + ASSERTMSG(0x213, MINOBJSIZE <= (char *)cellEnd - (char *)end); + newCell = (struct Cell *)end; + newCell->size = ((char *)cellEnd - (char *)end); + newCell->next = cell->next; + if (newCell->next) { + newCell->next->prev = newCell; + } + newCell->prev = cell; + cell->next = newCell; + cell->size = ((char *)start - (char *)cell); + hd->size -= ((char *)end - (char *)start); + break; + } + } + } + } + ASSERTMSG(0x222, 0 <= hd->size); + } + } + ASSERTMSG(0x225, OFFSET(start, ALIGNMENT) == 0); + ASSERTMSG(0x226, OFFSET(end, ALIGNMENT) == 0); + ASSERTMSG(0x227, start < end); + *(u32 *)rstart = (u32)start; + *(u32 *)rend = (u32)end; + return (void *)*(u32 *)rstart; +} + +void OSFreeToHeap(int heap, void *ptr) +{ + struct HeapDesc *hd; + struct Cell *cell; + + ASSERTMSG1(0x23D, HeapArray, "OSFreeToHeap(): heap is not initialized."); + ASSERTMSG1(0x23F, ((u32)ArenaStart + 0x20) <= (u32)ptr && (u32)ptr < (u32)ArenaEnd, "OSFreeToHeap(): invalid pointer."); + ASSERTMSG1(0x240, OFFSET(ptr, ALIGNMENT) == 0, "OSFreeToHeap(): invalid pointer."); + ASSERTMSG1(0x241, HeapArray[heap].size >= 0, "OSFreeToHeap(): invalid heap handle."); + cell = (void *)((u32)ptr - 0x20); + hd = &HeapArray[heap]; + ASSERTMSG1(0x246, cell->hd == hd, "OSFreeToHeap(): invalid pointer."); + ASSERTMSG1(0x247, DLLookup(hd->allocated, cell), "OSFreeToHeap(): invalid pointer."); + hd->allocated = DLExtract(hd->allocated, cell); + hd->free = DLInsert(hd->free, cell); +} + +int OSSetCurrentHeap(int heap) +{ + int prev; + + ASSERTMSG1(0x267, HeapArray, "OSSetCurrentHeap(): heap is not initialized."); + ASSERTMSG1(0x268, (heap >= 0) && (heap < NumHeaps), "OSSetCurrentHeap(): invalid heap handle."); + ASSERTMSG1(0x269, HeapArray[heap].size >= 0, "OSSetCurrentHeap(): invalid heap handle."); + prev = __OSCurrHeap; + __OSCurrHeap = heap; + return prev; +} + +void *OSInitAlloc(void *arenaStart, void *arenaEnd, int maxHeaps) +{ + unsigned long arraySize; + int i; + struct HeapDesc *hd; + + ASSERTMSG1(0x283, maxHeaps > 0, "OSInitAlloc(): invalid number of heaps."); + ASSERTMSG1(0x285, (u32)arenaStart < (u32)arenaEnd, "OSInitAlloc(): invalid range."); + ASSERTMSG1(0x288, maxHeaps <= (((u32)arenaEnd - (u32)arenaStart) / 24U), "OSInitAlloc(): too small range."); + arraySize = maxHeaps * sizeof(struct HeapDesc); + HeapArray = arenaStart; + NumHeaps = maxHeaps; + + for (i = 0; i < NumHeaps; i++) { + hd = &HeapArray[i]; + hd->size = -1; + hd->free = hd->allocated = 0; + } + __OSCurrHeap = -1; + arenaStart = (void *)((u32)((char *)HeapArray + arraySize)); + arenaStart = (void *)(((u32)arenaStart + 0x1F) & 0xFFFFFFE0); + ArenaStart = arenaStart; + ArenaEnd = (void *)((u32)arenaEnd & 0xFFFFFFE0); + ASSERTMSG1(0x2A4, ((u32)ArenaEnd - (u32)ArenaStart) >= 0x40U, "OSInitAlloc(): too small range."); + return arenaStart; +} + +int OSCreateHeap(void *start, void *end) +{ + int heap; + struct HeapDesc *hd; + struct Cell *cell; + + ASSERTMSG1(0x2BD, HeapArray, "OSCreateHeap(): heap is not initialized."); + ASSERTMSG1(0x2BE, (u32)start < (u32)end, "OSCreateHeap(): invalid range."); + + start = (void *)(((u32)start + 0x1FU) & ~((32) - 1)); + end = (void *)(((u32)end) & ~((32) - 1)); + + ASSERTMSG1(0x2C1, (u32)start < (u32)end, "OSCreateHeap(): invalid range."); + ASSERTMSG1(0x2C3, (u32)ArenaStart <= (u32)start && (u32)end <= (u32)ArenaEnd, "OSCreateHeap(): invalid range."); + ASSERTMSG1(0x2C5, ((u32)end - (u32)start) >= 0x40U, "OSCreateHeap(): too small range."); + + for (heap = 0; heap < NumHeaps; heap++) { + hd = &HeapArray[heap]; + if (hd->size < 0) { + hd->size = (u32)end - (u32)start; + cell = start; + cell->prev = 0; + cell->next = 0; + cell->size = hd->size; + hd->free = cell; + hd->allocated = 0; + return heap; + } + } + return -1; +} + +void OSDestroyHeap(int heap) +{ + struct HeapDesc *hd; + long size; + + ASSERTMSG1(0x30A, HeapArray, "OSDestroyHeap(): heap is not initialized."); + ASSERTMSG1(0x30B, (heap >= 0) && (heap < NumHeaps), "OSDestroyHeap(): invalid heap handle."); + ASSERTMSG1(0x30C, HeapArray[heap].size >= 0, "OSDestroyHeap(): invalid heap handle."); + + hd = &HeapArray[heap]; + hd->size = -1; +} + +void OSAddToHeap(int heap, void *start, void *end) +{ + struct HeapDesc *hd; + struct Cell *cell; + int i; + + ASSERTMSG1(0x339, HeapArray, "OSAddToHeap(): heap is not initialized."); + ASSERTMSG1(0x33A, (heap >= 0) && (heap < NumHeaps), "OSAddToHeap(): invalid heap handle."); + ASSERTMSG1(0x33B, HeapArray[heap].size >= 0, "OSAddToHeap(): invalid heap handle."); + + hd = &HeapArray[heap]; + + ASSERTMSG1(0x33F, (u32)start < (u32)end, "OSAddToHeap(): invalid range."); + + start = (void *)(((u32)start + 0x1F) & ~((32) - 1)); + end = (void *)(((u32)end) & ~((32) - 1)); + + ASSERTMSG1(0x343, ((u32)end - (u32)start) >= 0x40U, "OSAddToHeap(): too small range."); + ASSERTMSG1(0x345, (u32)ArenaStart <= (u32)start && (u32)end <= (u32)ArenaEnd, "OSAddToHeap(): invalid range."); + + cell = (struct Cell *)start; + cell->size = ((char *)end - (char *)start); + hd->size += cell->size; + hd->free = DLInsert(hd->free, cell); +} + +// custom macro for OSCheckHeap +#define ASSERTREPORT(line, cond) \ + if (!(cond)) { \ + OSReport("OSCheckHeap: Failed " #cond " in %d", line); \ + return -1; \ + } + +long OSCheckHeap(int heap) +{ + struct HeapDesc *hd; + struct Cell *cell; + long total = 0; + long free = 0; + + ASSERTREPORT(0x37D, HeapArray); + ASSERTREPORT(0x37E, 0 <= heap && heap < NumHeaps); + hd = &HeapArray[heap]; + ASSERTREPORT(0x381, 0 <= hd->size); + + ASSERTREPORT(0x383, hd->allocated == NULL || hd->allocated->prev == NULL); + + for (cell = hd->allocated; cell; cell = cell->next) { + ASSERTREPORT(0x386, InRange(cell, ArenaStart, ArenaEnd)); + ASSERTREPORT(0x387, OFFSET(cell, ALIGNMENT) == 0); + ASSERTREPORT(0x388, cell->next == NULL || cell->next->prev == cell); + ASSERTREPORT(0x389, MINOBJSIZE <= cell->size); + ASSERTREPORT(0x38A, OFFSET(cell->size, ALIGNMENT) == 0); + total += cell->size; + ASSERTREPORT(0x38D, 0 < total && total <= hd->size); + } + + ASSERTREPORT(0x395, hd->free == NULL || hd->free->prev == NULL); + + for (cell = hd->free; cell; cell = cell->next) { + ASSERTREPORT(0x398, InRange(cell, ArenaStart, ArenaEnd)); + ASSERTREPORT(0x399, OFFSET(cell, ALIGNMENT) == 0); + ASSERTREPORT(0x39A, cell->next == NULL || cell->next->prev == cell); + ASSERTREPORT(0x39B, MINOBJSIZE <= cell->size); + ASSERTREPORT(0x39C, OFFSET(cell->size, ALIGNMENT) == 0); + ASSERTREPORT(0x39D, cell->next == NULL || (char *)cell + cell->size < (char *)cell->next); + total += cell->size; + free = (cell->size + free); + free -= HEADERSIZE; + ASSERTREPORT(0x3A1, 0 < total && total <= hd->size); + } + ASSERTREPORT(0x3A8, total == hd->size); + return free; +} + +unsigned long OSReferentSize(void *ptr) +{ + struct Cell *cell; + + ASSERTMSG1(0x3BB, HeapArray, "OSReferentSize(): heap is not initialized."); + ASSERTMSG1(0x3BD, InRange(ptr, ArenaStart + HEADERSIZE, ArenaEnd), "OSReferentSize(): invalid pointer."); + ASSERTMSG1(0x3BE, !OFFSET(ptr, 32), "OSReferentSize(): invalid pointer."); + cell = (void *)((u32)ptr - HEADERSIZE); + ASSERTMSG1(0x3C2, cell->hd, "OSReferentSize(): invalid pointer."); + ASSERTMSG1(0x3C4, !(((u32)cell->hd - (u32)HeapArray) % 24), "OSReferentSize(): invalid pointer."); + ASSERTMSG1(0x3C6, ((u32)HeapArray <= (u32)cell->hd) && ((u32)cell->hd < (u32)((u32)HeapArray + (NumHeaps * 0x18))), + "OSReferentSize(): invalid pointer."); + ASSERTMSG1(0x3C7, cell->hd->size >= 0, "OSReferentSize(): invalid pointer."); + ASSERTMSG1(0x3C9, DLLookup(cell->hd->allocated, cell), "OSReferentSize(): invalid pointer."); + return (long)((u32)cell->size - HEADERSIZE); +} + +void OSDumpHeap(int heap) +{ + struct HeapDesc *hd; + struct Cell *cell; + + OSReport("\nOSDumpHeap(%d):\n", heap); + ASSERTMSG1(0x3DE, HeapArray, "OSDumpHeap(): heap is not initialized."); + ASSERTMSG1(0x3DF, (heap >= 0) && (heap < NumHeaps), "OSDumpHeap(): invalid heap handle."); + hd = &HeapArray[heap]; + if (hd->size < 0) { + OSReport("--------Inactive\n"); + return; + } + ASSERTMSG1(0x3E8, OSCheckHeap(heap) >= 0, "OSDumpHeap(): heap is broken."); + OSReport("addr size end prev next\n"); + OSReport("--------Allocated\n"); + + ASSERTMSG1(0x3F5, hd->allocated == NULL || hd->allocated->prev == NULL, "OSDumpHeap(): heap is broken."); + + for (cell = hd->allocated; cell; cell = cell->next) { + OSReport("%x %d %x %x %x\n", cell, cell->size, (char *)cell + cell->size, cell->prev, cell->next); + } + OSReport("--------Free\n"); + for (cell = hd->free; cell; cell = cell->next) { + OSReport("%x %d %x %x %x\n", cell, cell->size, (char *)cell + cell->size, cell->prev, cell->next); + } +} + +void OSVisitAllocated(void (*visitor)(void *, unsigned long)) +{ + unsigned long heap; + struct Cell *cell; + + for (heap = 0; heap < NumHeaps; heap++) { + if (HeapArray[heap].size >= 0) { + for (cell = HeapArray[heap].allocated; cell; cell = cell->next) { + visitor((char *)cell + HEADERSIZE, cell->size); + } + } + } +} diff --git a/src/dolphin/os/OSArena.c b/src/dolphin/os/OSArena.c new file mode 100644 index 00000000..563b01a8 --- /dev/null +++ b/src/dolphin/os/OSArena.c @@ -0,0 +1,53 @@ +#include + +#define ROUND(n, a) (((u32)(n) + (a)-1) & ~((a)-1)) +#define TRUNC(n, a) (((u32)(n)) & ~((a)-1)) + +void *__OSArenaHi; +void *__OSArenaLo = (void *)-1; + +void *OSGetArenaHi(void) +{ + return __OSArenaHi; +} + +void *OSGetArenaLo(void) +{ + return __OSArenaLo; +} + +void OSSetArenaHi(void *addr) +{ + __OSArenaHi = addr; +} + +void OSSetArenaLo(void *addr) +{ + __OSArenaLo = addr; +} + +void *OSAllocFromArenaLo(u32 size, u32 align) +{ + void *ptr; + u8 *arenaLo; + + ptr = OSGetArenaLo(); + arenaLo = ptr = (void *)ROUND(ptr, align); + arenaLo += size; + arenaLo = (u8 *)ROUND(arenaLo, align); + OSSetArenaLo(arenaLo); + return ptr; +} + +void *OSAllocFromArenaHi(u32 size, u32 align) +{ + void *ptr; + u8 *arenaHi; + + arenaHi = OSGetArenaHi(); + arenaHi = (u8 *)TRUNC(arenaHi, align); + arenaHi -= size; + arenaHi = ptr = (void *)TRUNC(arenaHi, align); + OSSetArenaHi(arenaHi); + return ptr; +} diff --git a/src/dolphin/os/OSAudioSystem.c b/src/dolphin/os/OSAudioSystem.c new file mode 100644 index 00000000..f622deaf --- /dev/null +++ b/src/dolphin/os/OSAudioSystem.c @@ -0,0 +1,118 @@ +#include "types.h" +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +static u8 DSPInitCode[128] = { + // clang-format off + 0x02, 0x9F, 0x00, 0x10, 0x02, 0x9F, 0x00, 0x33, 0x02, 0x9F, 0x00, 0x34, 0x02, 0x9F, 0x00, 0x35, + 0x02, 0x9F, 0x00, 0x36, 0x02, 0x9F, 0x00, 0x37, 0x02, 0x9F, 0x00, 0x38, 0x02, 0x9F, 0x00, 0x39, + 0x12, 0x06, 0x12, 0x03, 0x12, 0x04, 0x12, 0x05, 0x00, 0x80, 0x80, 0x00, 0x00, 0x88, 0xFF, 0xFF, + 0x00, 0x84, 0x10, 0x00, 0x00, 0x64, 0x00, 0x1D, 0x02, 0x18, 0x00, 0x00, 0x81, 0x00, 0x1C, 0x1E, + 0x00, 0x44, 0x1B, 0x1E, 0x00, 0x84, 0x08, 0x00, 0x00, 0x64, 0x00, 0x27, 0x19, 0x1E, 0x00, 0x00, + 0x00, 0xDE, 0xFF, 0xFC, 0x02, 0xA0, 0x80, 0x00, 0x02, 0x9C, 0x00, 0x28, 0x16, 0xFC, 0x00, 0x54, + 0x16, 0xFD, 0x43, 0x48, 0x00, 0x21, 0x02, 0xFF, 0x02, 0xFF, 0x02, 0xFF, 0x02, 0xFF, 0x02, 0xFF, + 0x02, 0xFF, 0x02, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + // clang-format on +}; + +#define __DSPWorkBuffer (void *)0x81000000 + +void __OSInitAudioSystem(void) +{ + u32 r28; + u16 r3; + + u32 padding; + + memcpy((void *)((u8 *)OSGetArenaHi() - 128), __DSPWorkBuffer, 128); + memcpy(__DSPWorkBuffer, (void *)DSPInitCode, 128); + + DCFlushRange(__DSPWorkBuffer, 128); + + __DSPRegs[9] = 0x43; + __DSPRegs[5] = 0x8AC; + __DSPRegs[5] |= 1; + while (__DSPRegs[5] & 1) + ; + __DSPRegs[0] = 0; + while (((__DSPRegs[2] << 16) | __DSPRegs[3]) & 0x80000000) + ; + *(u32 *)&__DSPRegs[16] = 0x1000000; + *(u32 *)&__DSPRegs[18] = 0; + *(u32 *)&__DSPRegs[20] = 0x20; + + r3 = __DSPRegs[5]; + while (!(r3 & 0x20)) + r3 = __DSPRegs[5]; + __DSPRegs[5] = r3; + + r28 = OSGetTick(); + while ((s32)(OSGetTick() - r28) < 0x892) + ; + + *(u32 *)&__DSPRegs[16] = 0x1000000; + *(u32 *)&__DSPRegs[18] = 0; + *(u32 *)&__DSPRegs[20] = 0x20; + + r3 = __DSPRegs[5]; + while (!(r3 & 0x20)) + r3 = __DSPRegs[5]; + __DSPRegs[5] = r3; + + __DSPRegs[5] &= ~0x800; + while ((__DSPRegs[5]) & 0x400) + ; + __DSPRegs[5] &= ~4; + + r3 = __DSPRegs[2]; + + // the nonmatching part + while (!(r3 & 0x8000)) + r3 = __DSPRegs[2]; + + (void)__DSPRegs[3]; + r3 != 42069; + __DSPRegs[5] |= 4; + __DSPRegs[5] = 0x8AC; + __DSPRegs[5] |= 1; + while (__DSPRegs[5] & 1) + ; + memcpy(__DSPWorkBuffer, (void *)((u8 *)OSGetArenaHi() - 128), 128); +} + +void __OSStopAudioSystem(void) +{ + u32 r28; + +#define waitUntil(load, mask) \ + r28 = (load); \ + while (r28 & (mask)) { \ + r28 = (load); \ + } + + __DSPRegs[5] = 0x804; + r28 = __DSPRegs[27]; + __DSPRegs[27] = r28 & ~0x8000; + waitUntil(__DSPRegs[5], 0x400); + waitUntil(__DSPRegs[5], 0x200); + __DSPRegs[5] = 0x8ac; + __DSPRegs[0] = 0; + + while (((__DSPRegs[2] << 16) | __DSPRegs[3]) & 0x80000000) + ; + r28 = OSGetTick(); + while ((s32)(OSGetTick() - r28) < 0x2c) + ; + __DSPRegs[5] |= 1; + waitUntil(__DSPRegs[5], 0x001); + +#undef waitUntil +} + +#ifdef __cplusplus +} +#endif diff --git a/src/dolphin/os/OSCache.c b/src/dolphin/os/OSCache.c new file mode 100644 index 00000000..d1b69735 --- /dev/null +++ b/src/dolphin/os/OSCache.c @@ -0,0 +1,450 @@ +#include "dolphin/PPCArch.h" +#include "dolphin/os.h" + +// Can't use this due to weird condition register issues +// #include "asm_types.h" +#define HID2 920 + +#include "dolphin/db.h" + +/* clang-format off */ +asm void DCEnable() { + nofralloc + sync + mfspr r3, HID0 + ori r3, r3, 0x4000 + mtspr HID0, r3 + blr +} + +asm void DCInvalidateRange(register void* addr, register u32 nBytes) { + nofralloc + cmplwi nBytes, 0 + blelr + clrlwi. r5, addr, 27 + beq @2 + addi nBytes, nBytes, 32 +@2 + addi nBytes, nBytes, 31 + srwi nBytes, nBytes, 5 + mtctr nBytes + +@1 + dcbi r0, addr + addi addr, addr, 32 + bdnz @1 + blr +} + + +asm void DCFlushRange(register void* addr, register u32 nBytes) { + nofralloc + cmplwi nBytes, 0 + blelr + clrlwi. r5, addr, 27 + beq @2 + addi nBytes, nBytes, 32 +@2 + addi nBytes, nBytes, 31 + srwi nBytes, nBytes, 5 + mtctr nBytes + +@1 + dcbf r0, addr + addi addr, addr, 32 + bdnz @1 + sc + blr +} + +asm void DCStoreRange(register void* addr, register u32 nBytes) { + nofralloc + cmplwi nBytes, 0 + blelr + clrlwi. r5, addr, 27 + beq @2 + addi nBytes, nBytes, 32 +@2 + addi nBytes, nBytes, 31 + srwi nBytes, nBytes, 5 + mtctr nBytes + +@1 + dcbst r0, addr + addi addr, addr, 32 + bdnz @1 + sc + + blr +} + +asm void DCFlushRangeNoSync(register void* addr, register u32 nBytes) { + nofralloc + cmplwi nBytes, 0 + blelr + clrlwi. r5, addr, 27 + beq @2 + addi nBytes, nBytes, 32 +@2 + addi nBytes, nBytes, 31 + srwi nBytes, nBytes, 5 + mtctr nBytes + +@1 + dcbf r0, addr + addi addr, addr, 32 + bdnz @1 + blr +} + +asm void DCStoreRangeNoSync(register void* addr, register u32 nBytes) { + nofralloc + cmplwi nBytes, 0 + blelr + clrlwi. r5, addr, 27 + beq @2 + addi nBytes, nBytes, 32 +@2 + addi nBytes, nBytes, 31 + srwi nBytes, nBytes, 5 + mtctr nBytes + +@1 + dcbst r0, addr + addi addr, addr, 32 + bdnz @1 + + blr +} + +asm void DCZeroRange(register void* addr, register u32 nBytes) { + nofralloc + cmplwi nBytes, 0 + blelr + clrlwi. r5, addr, 27 + beq @2 + addi nBytes, nBytes, 32 +@2 + addi nBytes, nBytes, 31 + srwi nBytes, nBytes, 5 + mtctr nBytes + +@1 + dcbz r0, addr + addi addr, addr, 32 + bdnz @1 + + blr +} + + +asm void ICInvalidateRange(register void* addr, register u32 nBytes) { + nofralloc + cmplwi nBytes, 0 + blelr + clrlwi. r5, addr, 27 + beq @2 + addi nBytes, nBytes, 32 +@2 + addi nBytes, nBytes, 31 + srwi nBytes, nBytes, 5 + mtctr nBytes + +@1 + icbi r0, addr + addi addr, addr, 32 + bdnz @1 + sync + isync + + blr +} + + +asm void ICFlashInvalidate() { + nofralloc + mfspr r3, HID0 + ori r3, r3, 0x800 + mtspr HID0, r3 + blr +} + +asm void ICEnable() { + nofralloc + isync + mfspr r3, HID0 + ori r3, r3, 0x8000 + mtspr HID0, r3 + blr +} + +#define LC_LINES 512 +#define CACHE_LINES 1024 + +asm void __LCEnable() { + nofralloc + mfmsr r5 + ori r5, r5, 0x1000 + mtmsr r5 + + lis r3, OS_CACHED_REGION_PREFIX + li r4, CACHE_LINES + mtctr r4 +_touchloop: + dcbt 0,r3 + dcbst 0,r3 + addi r3,r3,32 + bdnz _touchloop + mfspr r4, HID2 + oris r4, r4, 0x100F + mtspr HID2, r4 + + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + lis r3, LC_BASE_PREFIX + ori r3, r3, 0x0002 + mtspr DBAT3L, r3 + ori r3, r3, 0x01fe + mtspr DBAT3U, r3 + isync + lis r3, LC_BASE_PREFIX + li r6, LC_LINES + mtctr r6 + li r6, 0 + +_lockloop: + dcbz_l r6, r3 + addi r3, r3, 32 + bdnz+ _lockloop + + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + + blr +} + +void LCEnable() { + BOOL enabled; + + enabled = OSDisableInterrupts(); + __LCEnable(); + OSRestoreInterrupts(enabled); +} + + +asm void LCDisable() { + nofralloc + lis r3, LC_BASE_PREFIX + li r4, LC_LINES + mtctr r4 +@1 + dcbi r0, r3 + addi r3, r3, 32 + bdnz @1 + mfspr r4, HID2 + rlwinm r4, r4, 0, 4, 2 + mtspr HID2, r4 + blr +} + + +asm void LCLoadBlocks(register void* destTag, register void* srcAddr, register u32 numBlocks) { + nofralloc + rlwinm r6, numBlocks, 30, 27, 31 + rlwinm srcAddr, srcAddr, 0, 4, 31 + or r6, r6, srcAddr + mtspr DMA_U, r6 + rlwinm r6, numBlocks, 2, 28, 29 + or r6, r6, destTag + ori r6, r6, 0x12 + mtspr DMA_L, r6 + blr +} + +asm void LCStoreBlocks(register void* destAddr, register void* srcTag, register u32 numBlocks) { + nofralloc + rlwinm r6, numBlocks, 30, 27, 31 + rlwinm destAddr, destAddr, 0, 4, 31 + or r6, r6, destAddr + mtspr DMA_U, r6 + rlwinm r6, numBlocks, 2, 28, 29 + or r6, r6, srcTag + ori r6, r6, 0x2 + mtspr DMA_L, r6 + blr +} + +/* clang-format on */ + +u32 LCLoadData(register void *destAddr, register void *srcAddr, register u32 nBytes) +{ + u32 numBlocks = (nBytes + 31) / 32; + u32 numTransactions = (numBlocks + 128 - 1) / 128; + + while (numBlocks > 0) { + if (numBlocks < 128) { + LCLoadBlocks(destAddr, srcAddr, numBlocks); + numBlocks = 0; + } + else { + LCLoadBlocks(destAddr, srcAddr, 0); + numBlocks -= 128; + destAddr = (void *)((u32)destAddr + 4096); + srcAddr = (void *)((u32)srcAddr + 4096); + } + } + + return numTransactions; +} +u32 LCStoreData(void *destAddr, void *srcAddr, u32 nBytes) +{ + u32 numBlocks = (nBytes + 31) / 32; + u32 numTransactions = (numBlocks + 128 - 1) / 128; + + while (numBlocks > 0) { + if (numBlocks < 128) { + LCStoreBlocks(destAddr, srcAddr, numBlocks); + numBlocks = 0; + } + else { + LCStoreBlocks(destAddr, srcAddr, 0); + numBlocks -= 128; + destAddr = (void *)((u32)destAddr + 4096); + srcAddr = (void *)((u32)srcAddr + 4096); + } + } + + return numTransactions; +} + +/* clang-format off */ +asm u32 LCQueueLength() { + nofralloc + mfspr r4, HID2 + rlwinm r3, r4, 8, 28, 31 + blr +} + +asm void LCQueueWait(register u32 len) { + nofralloc + addi len, len, 1 +@1 + mfspr r4, HID2 + rlwinm r4, r4, 8, 28, 31 + cmpw cr2, r4, r3 + bge cr2, @1 + blr +} + +/* clang-format on */ +static void L2Disable(void) +{ + __sync(); + PPCMtl2cr(PPCMfl2cr() & ~0x80000000); + __sync(); +} + +void L2GlobalInvalidate(void) +{ + L2Disable(); + PPCMtl2cr(PPCMfl2cr() | 0x00200000); + while (PPCMfl2cr() & 0x00000001u) + ; + PPCMtl2cr(PPCMfl2cr() & ~0x00200000); + while (PPCMfl2cr() & 0x00000001u) { + DBPrintf(">>> L2 INVALIDATE : SHOULD NEVER HAPPEN\n"); + } +} + +static void L2Init(void) +{ + u32 oldMSR; + oldMSR = PPCMfmsr(); + __sync(); + PPCMtmsr(MSR_IR | MSR_DR); + __sync(); + L2Disable(); + L2GlobalInvalidate(); + PPCMtmsr(oldMSR); +} + +void L2Enable(void) +{ + PPCMtl2cr((PPCMfl2cr() | L2CR_L2E) & ~L2CR_L2I); +} + +void DMAErrorHandler(OSError error, OSContext *context, ...) +{ + u32 hid2 = PPCMfhid2(); + + OSReport("Machine check received\n"); + OSReport("HID2 = 0x%x SRR1 = 0x%x\n", hid2, context->srr1); + if (!(hid2 & (HID2_DCHERR | HID2_DNCERR | HID2_DCMERR | HID2_DQOERR)) || !(context->srr1 & SRR1_DMA_BIT)) { + OSReport("Machine check was not DMA/locked cache related\n"); + OSDumpContext(context); + PPCHalt(); + } + + OSReport("DMAErrorHandler(): An error occurred while processing DMA.\n"); + OSReport("The following errors have been detected and cleared :\n"); + + if (hid2 & HID2_DCHERR) { + OSReport("\t- Requested a locked cache tag that was already in the cache\n"); + } + + if (hid2 & HID2_DNCERR) { + OSReport("\t- DMA attempted to access normal cache\n"); + } + + if (hid2 & HID2_DCMERR) { + OSReport("\t- DMA missed in data cache\n"); + } + + if (hid2 & HID2_DQOERR) { + OSReport("\t- DMA queue overflowed\n"); + } + + // write hid2 back to clear the error bits + PPCMthid2(hid2); +} + +void __OSCacheInit() +{ + if (!(PPCMfhid0() & HID0_ICE)) { + ICEnable(); + DBPrintf("L1 i-caches initialized\n"); + } + if (!(PPCMfhid0() & HID0_DCE)) { + DCEnable(); + DBPrintf("L1 d-caches initialized\n"); + } + + if (!(PPCMfl2cr() & L2CR_L2E)) { + L2Init(); + L2Enable(); + DBPrintf("L2 cache initialized\n"); + } + + OSSetErrorHandler(OS_ERROR_MACHINE_CHECK, DMAErrorHandler); + DBPrintf("Locked cache machine check handler installed\n"); +} diff --git a/src/dolphin/os/OSContext.c b/src/dolphin/os/OSContext.c new file mode 100644 index 00000000..81b28648 --- /dev/null +++ b/src/dolphin/os/OSContext.c @@ -0,0 +1,555 @@ +#include +#include +#include + +#define HID2 920 + +volatile OSContext *__OSCurrentContext : (OS_BASE_CACHED | 0x00D4); +volatile OSContext *__OSFPUContext : (OS_BASE_CACHED | 0x00D8); + +static asm void __OSLoadFPUContext(register u32, register OSContext *fpuContext) +{ + // clang-format off + nofralloc + lhz r5, fpuContext->state; + clrlwi. r5, r5, 31 + beq _return + + lfd fp0, OS_CONTEXT_FPSCR(fpuContext) + mtfsf 0xFF, fp0 + mfspr r5, HID2 + rlwinm. r5, r5, 3, 31, 31 + beq _regular_FPRs + + psq_l fp0, OS_CONTEXT_PSF0(fpuContext), 0, 0 + psq_l fp1, OS_CONTEXT_PSF1(fpuContext), 0, 0 + psq_l fp2, OS_CONTEXT_PSF2(fpuContext), 0, 0 + psq_l fp3, OS_CONTEXT_PSF3(fpuContext), 0, 0 + psq_l fp4, OS_CONTEXT_PSF4(fpuContext), 0, 0 + psq_l fp5, OS_CONTEXT_PSF5(fpuContext), 0, 0 + psq_l fp6, OS_CONTEXT_PSF6(fpuContext), 0, 0 + psq_l fp7, OS_CONTEXT_PSF7(fpuContext), 0, 0 + psq_l fp8, OS_CONTEXT_PSF8(fpuContext), 0, 0 + psq_l fp9, OS_CONTEXT_PSF9(fpuContext), 0, 0 + psq_l fp10, OS_CONTEXT_PSF10(fpuContext), 0, 0 + psq_l fp11, OS_CONTEXT_PSF11(fpuContext), 0, 0 + psq_l fp12, OS_CONTEXT_PSF12(fpuContext), 0, 0 + psq_l fp13, OS_CONTEXT_PSF13(fpuContext), 0, 0 + psq_l fp14, OS_CONTEXT_PSF14(fpuContext), 0, 0 + psq_l fp15, OS_CONTEXT_PSF15(fpuContext), 0, 0 + psq_l fp16, OS_CONTEXT_PSF16(fpuContext), 0, 0 + psq_l fp17, OS_CONTEXT_PSF17(fpuContext), 0, 0 + psq_l fp18, OS_CONTEXT_PSF18(fpuContext), 0, 0 + psq_l fp19, OS_CONTEXT_PSF19(fpuContext), 0, 0 + psq_l fp20, OS_CONTEXT_PSF20(fpuContext), 0, 0 + psq_l fp21, OS_CONTEXT_PSF21(fpuContext), 0, 0 + psq_l fp22, OS_CONTEXT_PSF22(fpuContext), 0, 0 + psq_l fp23, OS_CONTEXT_PSF23(fpuContext), 0, 0 + psq_l fp24, OS_CONTEXT_PSF24(fpuContext), 0, 0 + psq_l fp25, OS_CONTEXT_PSF25(fpuContext), 0, 0 + psq_l fp26, OS_CONTEXT_PSF26(fpuContext), 0, 0 + psq_l fp27, OS_CONTEXT_PSF27(fpuContext), 0, 0 + psq_l fp28, OS_CONTEXT_PSF28(fpuContext), 0, 0 + psq_l fp29, OS_CONTEXT_PSF29(fpuContext), 0, 0 + psq_l fp30, OS_CONTEXT_PSF30(fpuContext), 0, 0 + psq_l fp31, OS_CONTEXT_PSF31(fpuContext), 0, 0 + +_regular_FPRs: + lfd fp0, fpuContext->fpr[0] + lfd fp1, fpuContext->fpr[1] + lfd fp2, fpuContext->fpr[2] + lfd fp3, fpuContext->fpr[3] + lfd fp4, fpuContext->fpr[4] + lfd fp5, fpuContext->fpr[5] + lfd fp6, fpuContext->fpr[6] + lfd fp7, fpuContext->fpr[7] + lfd fp8, fpuContext->fpr[8] + lfd fp9, fpuContext->fpr[9] + lfd fp10, fpuContext->fpr[10] + lfd fp11, fpuContext->fpr[11] + lfd fp12, fpuContext->fpr[12] + lfd fp13, fpuContext->fpr[13] + lfd fp14, fpuContext->fpr[14] + lfd fp15, fpuContext->fpr[15] + lfd fp16, fpuContext->fpr[16] + lfd fp17, fpuContext->fpr[17] + lfd fp18, fpuContext->fpr[18] + lfd fp19, fpuContext->fpr[19] + lfd fp20, fpuContext->fpr[20] + lfd fp21, fpuContext->fpr[21] + lfd fp22, fpuContext->fpr[22] + lfd fp23, fpuContext->fpr[23] + lfd fp24, fpuContext->fpr[24] + lfd fp25, fpuContext->fpr[25] + lfd fp26, fpuContext->fpr[26] + lfd fp27, fpuContext->fpr[27] + lfd fp28, fpuContext->fpr[28] + lfd fp29, fpuContext->fpr[29] + lfd fp30, fpuContext->fpr[30] + lfd fp31, fpuContext->fpr[31] +_return: + blr + // clang-format on +} + +static asm void __OSSaveFPUContext(register u32, register u32, register OSContext *fpuContext) +{ + // clang-format off + nofralloc + + lhz r3, fpuContext->state + ori r3, r3, 1 + sth r3, fpuContext->state + + stfd fp0, fpuContext->fpr[0] + stfd fp1, fpuContext->fpr[1] + stfd fp2, fpuContext->fpr[2] + stfd fp3, fpuContext->fpr[3] + stfd fp4, fpuContext->fpr[4] + stfd fp5, fpuContext->fpr[5] + stfd fp6, fpuContext->fpr[6] + stfd fp7, fpuContext->fpr[7] + stfd fp8, fpuContext->fpr[8] + stfd fp9, fpuContext->fpr[9] + stfd fp10, fpuContext->fpr[10] + stfd fp11, fpuContext->fpr[11] + stfd fp12, fpuContext->fpr[12] + stfd fp13, fpuContext->fpr[13] + stfd fp14, fpuContext->fpr[14] + stfd fp15, fpuContext->fpr[15] + stfd fp16, fpuContext->fpr[16] + stfd fp17, fpuContext->fpr[17] + stfd fp18, fpuContext->fpr[18] + stfd fp19, fpuContext->fpr[19] + stfd fp20, fpuContext->fpr[20] + stfd fp21, fpuContext->fpr[21] + stfd fp22, fpuContext->fpr[22] + stfd fp23, fpuContext->fpr[23] + stfd fp24, fpuContext->fpr[24] + stfd fp25, fpuContext->fpr[25] + stfd fp26, fpuContext->fpr[26] + stfd fp27, fpuContext->fpr[27] + stfd fp28, fpuContext->fpr[28] + stfd fp29, fpuContext->fpr[29] + stfd fp30, fpuContext->fpr[30] + stfd fp31, fpuContext->fpr[31] + + mffs fp0 + stfd fp0, OS_CONTEXT_FPSCR(fpuContext) + + lfd fp0, fpuContext->fpr[0] + + mfspr r3, HID2 + rlwinm. r3, r3, 3, 31, 31 + bc 12, 2, _return + + psq_st fp0, OS_CONTEXT_PSF0(fpuContext), 0, 0 + psq_st fp1, OS_CONTEXT_PSF1(fpuContext), 0, 0 + psq_st fp2, OS_CONTEXT_PSF2(fpuContext), 0, 0 + psq_st fp3, OS_CONTEXT_PSF3(fpuContext), 0, 0 + psq_st fp4, OS_CONTEXT_PSF4(fpuContext), 0, 0 + psq_st fp5, OS_CONTEXT_PSF5(fpuContext), 0, 0 + psq_st fp6, OS_CONTEXT_PSF6(fpuContext), 0, 0 + psq_st fp7, OS_CONTEXT_PSF7(fpuContext), 0, 0 + psq_st fp8, OS_CONTEXT_PSF8(fpuContext), 0, 0 + psq_st fp9, OS_CONTEXT_PSF9(fpuContext), 0, 0 + psq_st fp10, OS_CONTEXT_PSF10(fpuContext), 0, 0 + psq_st fp11, OS_CONTEXT_PSF11(fpuContext), 0, 0 + psq_st fp12, OS_CONTEXT_PSF12(fpuContext), 0, 0 + psq_st fp13, OS_CONTEXT_PSF13(fpuContext), 0, 0 + psq_st fp14, OS_CONTEXT_PSF14(fpuContext), 0, 0 + psq_st fp15, OS_CONTEXT_PSF15(fpuContext), 0, 0 + psq_st fp16, OS_CONTEXT_PSF16(fpuContext), 0, 0 + psq_st fp17, OS_CONTEXT_PSF17(fpuContext), 0, 0 + psq_st fp18, OS_CONTEXT_PSF18(fpuContext), 0, 0 + psq_st fp19, OS_CONTEXT_PSF19(fpuContext), 0, 0 + psq_st fp20, OS_CONTEXT_PSF20(fpuContext), 0, 0 + psq_st fp21, OS_CONTEXT_PSF21(fpuContext), 0, 0 + psq_st fp22, OS_CONTEXT_PSF22(fpuContext), 0, 0 + psq_st fp23, OS_CONTEXT_PSF23(fpuContext), 0, 0 + psq_st fp24, OS_CONTEXT_PSF24(fpuContext), 0, 0 + psq_st fp25, OS_CONTEXT_PSF25(fpuContext), 0, 0 + psq_st fp26, OS_CONTEXT_PSF26(fpuContext), 0, 0 + psq_st fp27, OS_CONTEXT_PSF27(fpuContext), 0, 0 + psq_st fp28, OS_CONTEXT_PSF28(fpuContext), 0, 0 + psq_st fp29, OS_CONTEXT_PSF29(fpuContext), 0, 0 + psq_st fp30, OS_CONTEXT_PSF30(fpuContext), 0, 0 + psq_st fp31, OS_CONTEXT_PSF31(fpuContext), 0, 0 + +_return: + blr + // clang-format on +} + +asm void OSLoadFPUContext(register OSContext *fpuContext) +{ + // clang-format off + nofralloc + addi r4, fpuContext, 0 + b __OSLoadFPUContext + // clang-format on +} + +asm void OSSaveFPUContext(register OSContext *fpuContext) +{ + // clang-format off + nofralloc + addi r5, fpuContext, 0 + b __OSSaveFPUContext + // clang-format on +} + +asm void OSSetCurrentContext(register OSContext *context) { + // clang-format off + nofralloc + + addis r4, r0, OS_CACHED_REGION_PREFIX + + stw context, 0x00D4(r4) + + clrlwi r5, context, 2 + stw r5, 0x00C0(r4) + + lwz r5, 0x00D8(r4) + cmpw r5, context + bne _disableFPU + + lwz r6, context->srr1 + ori r6, r6, 0x2000 + stw r6, context->srr1 + mfmsr r6 + ori r6, r6, 2 + mtmsr r6 + blr + +_disableFPU: + lwz r6, context->srr1 + rlwinm r6, r6, 0, 19, 17 + stw r6, context->srr1 + mfmsr r6 + rlwinm r6, r6, 0, 19, 17 + ori r6, r6, 2 + mtmsr r6 + isync + blr + // clang-format on +} + +OSContext *OSGetCurrentContext(void) +{ + return (OSContext *)__OSCurrentContext; +} + +asm u32 OSSaveContext(register OSContext *context) +{ + // clang-format off + nofralloc + stmw r13, context->gpr[13] + mfspr r0, GQR1 + stw r0, context->gqr[1] + mfspr r0, GQR2 + stw r0, context->gqr[2] + mfspr r0, GQR3 + stw r0, context->gqr[3] + mfspr r0, GQR4 + stw r0, context->gqr[4] + mfspr r0, GQR5 + stw r0, context->gqr[5] + mfspr r0, GQR6 + stw r0, context->gqr[6] + mfspr r0, GQR7 + stw r0, context->gqr[7] + mfcr r0 + stw r0, context->cr + mflr r0 + stw r0, context->lr + stw r0, context->srr0 + mfmsr r0 + stw r0, context->srr1 + mfctr r0 + stw r0, context->ctr + mfxer r0 + stw r0, context->xer + stw r1, context->gpr[1] + stw r2, context->gpr[2] + li r0, 0x1 + stw r0, context->gpr[3] + li r3, 0 + blr + // clang-format on +} + +asm void OSLoadContext(register OSContext *context) +{ + // clang-format off + nofralloc + + lis r4, __RAS_OSDisableInterrupts_begin@ha + lwz r6, 0x198(context) + addi r5, r4, __RAS_OSDisableInterrupts_begin@l + cmplw r6, r5 + blt srr0_not_in_disableintr + lis r4, __RAS_OSDisableInterrupts_end@ha + addi r0, r4, __RAS_OSDisableInterrupts_end@l + cmplw r6, r0 + bgt srr0_not_in_disableintr + stw r5, 0x198(context) + +srr0_not_in_disableintr: + lwz r0, 0(context) + lwz r1, 4(context) + lwz r2, 8(context) + lhz r4, 0x1a2(context) + rlwinm. r5, r4, 0, 0x1e, 0x1e + beq load_saved_gprs + rlwinm r4, r4, 0, 0x1f, 0x1d + sth r4, 0x1a2(context) + lmw r5, 0x14(context) + b load_special_regs + +load_saved_gprs: + lmw r13, 0x34(context) + +load_special_regs: + lwz r4, 0x1a8(context) + mtspr 0x391, r4 + lwz r4, 0x1ac(context) + mtspr 0x392, r4 + lwz r4, 0x1b0(context) + mtspr 0x393, r4 + lwz r4, 0x1b4(context) + mtspr 0x394, r4 + lwz r4, 0x1b8(context) + mtspr 0x395, r4 + lwz r4, 0x1bc(context) + mtspr 0x396, r4 + lwz r4, 0x1c0(context) + mtspr 0x397, r4 + lwz r4, 0x80(context) + mtcrf 0xff, r4 + lwz r4, 0x84(context) + mtlr r4 + lwz r4, 0x88(context) + mtctr r4 + lwz r4, 0x8c(context) + mtxer r4 + mfmsr r4 + rlwinm r4, r4, 0, 0x11, 0xf + rlwinm r4, r4, 0, 0x1f, 0x1d + mtmsr r4 + lwz r4, 0x198(context) + mtspr 0x1a, r4 + lwz r4, 0x19c(context) + mtspr 0x1b, r4 + lwz r4, 0x10(context) + lwz context, 0xc(context) + rfi + // clang-format on +} + +asm u32 OSGetStackPointer() +{ + // clang-format off + nofralloc + mr r3, r1 + blr + // clang-format on +} + +asm u32 OSSwitchStack(register u32 newsp) +{ + // clang-format off + nofralloc + mr r5, r1 + mr r1, newsp + mr r3, r5 + blr + // clang-format on +} + +asm int OSSwitchFiber(register u32 pc, register u32 newsp) +{ + // clang-format off + nofralloc + mflr r0 + mr r5, r1 + stwu r5, -8(newsp) + mr r1, newsp + stw r0, 4(r5) + mtlr pc + blrl + lwz r5, 0(r1) + lwz r0, 4(r5) + mtlr r0 + mr r1, r5 + blr + // clang-format on +} + +void OSClearContext(register OSContext *context) +{ + context->mode = 0; + context->state = 0; + if (context == __OSFPUContext) + __OSFPUContext = NULL; +} + +asm void OSInitContext(register OSContext *context, register u32 pc, register u32 newsp) +{ + // clang-format off + nofralloc + + stw pc, OS_CONTEXT_SRR0(context) + stw newsp, OS_CONTEXT_R1(context) + li r11, 0 + ori r11, r11, 0x00008000 | 0x00000020 | 0x00000010 | 0x00000002 | 0x00001000 + stw r11, OS_CONTEXT_SRR1(context) + li r0, 0x0 + stw r0, OS_CONTEXT_CR(context) + stw r0, OS_CONTEXT_XER(context) + + + stw r2, OS_CONTEXT_R2(context) + stw r13, OS_CONTEXT_R13(context) + + stw r0, OS_CONTEXT_R3(context) + stw r0, OS_CONTEXT_R4(context) + stw r0, OS_CONTEXT_R5(context) + stw r0, OS_CONTEXT_R6(context) + stw r0, OS_CONTEXT_R7(context) + stw r0, OS_CONTEXT_R8(context) + stw r0, OS_CONTEXT_R9(context) + stw r0, OS_CONTEXT_R10(context) + stw r0, OS_CONTEXT_R11(context) + stw r0, OS_CONTEXT_R12(context) + + stw r0, OS_CONTEXT_R14(context) + stw r0, OS_CONTEXT_R15(context) + stw r0, OS_CONTEXT_R16(context) + stw r0, OS_CONTEXT_R17(context) + stw r0, OS_CONTEXT_R18(context) + stw r0, OS_CONTEXT_R19(context) + stw r0, OS_CONTEXT_R20(context) + stw r0, OS_CONTEXT_R21(context) + stw r0, OS_CONTEXT_R22(context) + stw r0, OS_CONTEXT_R23(context) + stw r0, OS_CONTEXT_R24(context) + stw r0, OS_CONTEXT_R25(context) + stw r0, OS_CONTEXT_R26(context) + stw r0, OS_CONTEXT_R27(context) + stw r0, OS_CONTEXT_R28(context) + stw r0, OS_CONTEXT_R29(context) + stw r0, OS_CONTEXT_R30(context) + stw r0, OS_CONTEXT_R31(context) + + stw r0, OS_CONTEXT_GQR0(context) + stw r0, OS_CONTEXT_GQR1(context) + stw r0, OS_CONTEXT_GQR2(context) + stw r0, OS_CONTEXT_GQR3(context) + stw r0, OS_CONTEXT_GQR4(context) + stw r0, OS_CONTEXT_GQR5(context) + stw r0, OS_CONTEXT_GQR6(context) + stw r0, OS_CONTEXT_GQR7(context) + + b OSClearContext + // clang-format on +} + +void OSDumpContext(OSContext *context) +{ + u32 i; + u32 *p; + + OSReport("------------------------- Context 0x%08x -------------------------\n", context); + + for (i = 0; i < 16; ++i) { + OSReport("r%-2d = 0x%08x (%14d) r%-2d = 0x%08x (%14d)\n", i, context->gpr[i], context->gpr[i], i + 16, context->gpr[i + 16], + context->gpr[i + 16]); + } + + OSReport("LR = 0x%08x CR = 0x%08x\n", context->lr, context->cr); + OSReport("SRR0 = 0x%08x SRR1 = 0x%08x\n", context->srr0, context->srr1); + + OSReport("\nGQRs----------\n"); + for (i = 0; i < 4; ++i) { + OSReport("gqr%d = 0x%08x \t gqr%d = 0x%08x\n", i, context->gqr[i], i + 4, context->gqr[i + 4]); + } + + if (context->state & OS_CONTEXT_STATE_FPSAVED) { + OSContext *currentContext; + OSContext fpuContext; + BOOL enabled; + + enabled = OSDisableInterrupts(); + currentContext = OSGetCurrentContext(); + OSClearContext(&fpuContext); + OSSetCurrentContext(&fpuContext); + + OSReport("\n\nFPRs----------\n"); + for (i = 0; i < 32; i += 2) { + OSReport("fr%d \t= %d \t fr%d \t= %d\n", i, (u32)context->fpr[i], i + 1, (u32)context->fpr[i + 1]); + } + OSReport("\n\nPSFs----------\n"); + for (i = 0; i < 32; i += 2) { + OSReport("ps%d \t= 0x%x \t ps%d \t= 0x%x\n", i, (u32)context->psf[i], i + 1, (u32)context->psf[i + 1]); + } + + OSClearContext(&fpuContext); + OSSetCurrentContext(currentContext); + OSRestoreInterrupts(enabled); + } + + OSReport("\nAddress: Back Chain LR Save\n"); + for (i = 0, p = (u32 *)context->gpr[1]; p && (u32)p != 0xffffffff && i++ < 16; p = (u32 *)*p) { + OSReport("0x%08x: 0x%08x 0x%08x\n", p, p[0], p[1]); + } +} + +static asm void OSSwitchFPUContext(register __OSException exception, register OSContext *context) +{ + // clang-format off + nofralloc + mfmsr r5 + ori r5, r5, 0x2000 + mtmsr r5 + isync + lwz r5, OS_CONTEXT_SRR1(context) + ori r5, r5, 0x2000 + mtsrr1 r5 + addis r3, r0, OS_CACHED_REGION_PREFIX + lwz r5, 0x00D8(r3) + stw context, 0x00D8(r3) + cmpw r5, r4 + beq _restoreAndExit + cmpwi r5, 0x0 + beq _loadNewFPUContext + bl __OSSaveFPUContext +_loadNewFPUContext: + bl __OSLoadFPUContext +_restoreAndExit: + lwz r3, OS_CONTEXT_CR(context) + mtcr r3 + lwz r3, OS_CONTEXT_LR(context) + mtlr r3 + lwz r3, OS_CONTEXT_SRR0(context) + mtsrr0 r3 + lwz r3, OS_CONTEXT_CTR(context) + mtctr r3 + lwz r3, OS_CONTEXT_XER(context) + mtxer r3 + lhz r3, context->state + rlwinm r3, r3, 0, 31, 29 + sth r3, context->state + lwz r5, OS_CONTEXT_R5(context) + lwz r3, OS_CONTEXT_R3(context) + lwz r4, OS_CONTEXT_R4(context) + rfi + // clang-format on +} + +void __OSContextInit(void) +{ + __OSSetExceptionHandler(__OS_EXCEPTION_FLOATING_POINT, OSSwitchFPUContext); + __OSFPUContext = NULL; + DBPrintf("FPU-unavailable handler installed\n"); +} diff --git a/src/dolphin/os/OSError.c b/src/dolphin/os/OSError.c new file mode 100644 index 00000000..2965756f --- /dev/null +++ b/src/dolphin/os/OSError.c @@ -0,0 +1,115 @@ +#include +#include +#include +#include + +#include + +OSThread *__OSCurrentThread : (OS_BASE_CACHED | 0x00E4); +OSThreadQueue __OSActiveThreadQueue : (OS_BASE_CACHED | 0x00DC); +volatile OSContext *__OSFPUContext : (OS_BASE_CACHED | 0x00D8); + +OSErrorHandler __OSErrorTable[OS_ERROR_MAX]; +#define FPSCR_ENABLE (FPSCR_VE | FPSCR_OE | FPSCR_UE | FPSCR_ZE | FPSCR_XE) + +__declspec(weak) void OSReport(const char *msg, ...) +{ + va_list args; + va_start(args, msg); + vprintf(msg, args); + va_end(args); +} + +__declspec(weak) void OSVReport(const char *msg, va_list list) +{ + vprintf(msg, list); +} + +__declspec(weak) void OSPanic(const char *file, int line, const char *msg, ...) +{ + va_list marker; + u32 i; + u32 *p; + + OSDisableInterrupts(); + va_start(marker, msg); + vprintf(msg, marker); + va_end(marker); + OSReport(" in \"%s\" on line %d.\n", file, line); + + OSReport("\nAddress: Back Chain LR Save\n"); + for (i = 0, p = (u32 *)OSGetStackPointer(); p && (u32)p != 0xffffffff && i++ < 16; p = (u32 *)*p) { + OSReport("0x%08x: 0x%08x 0x%08x\n", p, p[0], p[1]); + } + + PPCHalt(); +} + +OSErrorHandler OSSetErrorHandler(OSError error, OSErrorHandler handler) +{ + OSErrorHandler oldHandler; + + oldHandler = __OSErrorTable[error]; + __OSErrorTable[error] = handler; + return oldHandler; +} + +void __OSUnhandledException(__OSException exception, OSContext *context, u32 dsisr, u32 dar) +{ + if (!(context->srr1 & MSR_RI)) { + OSReport("Non-recoverable Exception %d", exception); + } + else { + if (__OSErrorTable[exception]) { + OSDisableScheduler(); + __OSErrorTable[exception](exception, context, dsisr, dar); + OSEnableScheduler(); + __OSReschedule(); + OSLoadContext(context); + } + + if (exception == OS_ERROR_DECREMENTER) { + OSLoadContext(context); + } + + OSReport("Unhandled Exception %d", exception); + } + + OSReport("\n"); + OSDumpContext(context); + OSReport("\nDSISR = 0x%08x DAR = 0x%08x\n", dsisr, dar); + OSReport("TB = 0x%016llx\n", OSGetTime()); + + switch (exception) { + case __OS_EXCEPTION_DSI: + OSReport("\nInstruction at 0x%x (read from SRR0) attempted to access " + "invalid address 0x%x (read from DAR)\n", + context->srr0, dar); + break; + case __OS_EXCEPTION_ISI: + OSReport("\nAttempted to fetch instruction from invalid address 0x%x " + "(read from SRR0)\n", + context->srr0); + break; + case __OS_EXCEPTION_ALIGNMENT: + OSReport("\nInstruction at 0x%x (read from SRR0) attempted to access " + "unaligned address 0x%x (read from DAR)\n", + context->srr0, dar); + break; + case __OS_EXCEPTION_PROGRAM: + OSReport("\nProgram exception : Possible illegal instruction/operation " + "at or around 0x%x (read from SRR0)\n", + context->srr0, dar); + break; + case OS_ERROR_PROTECTION: + OSReport("\n"); + OSReport("AI DMA Address = 0x%04x%04x\n", __DSPRegs[0x00000018], __DSPRegs[0x00000018 + 1]); + OSReport("ARAM DMA Address = 0x%04x%04x\n", __DSPRegs[0x00000010], __DSPRegs[0x00000010 + 1]); + OSReport("DI DMA Address = 0x%08x\n", __DIRegs[0x00000005]); + break; + } + + OSReport("\nLast interrupt (%d): SRR0 = 0x%08x TB = 0x%016llx\n", __OSLastInterrupt, __OSLastInterruptSrr0, __OSLastInterruptTime); + + PPCHalt(); +} diff --git a/src/dolphin/os/OSFont.c b/src/dolphin/os/OSFont.c new file mode 100644 index 00000000..a87ba76e --- /dev/null +++ b/src/dolphin/os/OSFont.c @@ -0,0 +1,323 @@ +#include +#include +#include + +static OSFontHeader *FontData; +static u8 *SheetImage; +static u8 *WidthTable; +static int CharsInSheet; + +static u16 HankakuToCode[] = { 0x20C, 0x20D, 0x20E, 0x20F, 0x210, 0x211, 0x212, 0x213, 0x214, 0x215, 0x216, 0x217, 0x218, 0x219, 0x21A, 0x21B, 0x21C, + 0x21D, 0x21E, 0x21F, 0x220, 0x221, 0x222, 0x223, 0x224, 0x225, 0x226, 0x227, 0x228, 0x229, 0x22A, 0x22B, 0x22C, 0x22D, 0x22E, 0x22F, 0x230, 0x231, + 0x232, 0x233, 0x234, 0x235, 0x236, 0x237, 0x238, 0x239, 0x23A, 0x23B, 0x23C, 0x23D, 0x23E, 0x23F, 0x240, 0x241, 0x242, 0x243, 0x244, 0x245, 0x246, + 0x247, 0x248, 0x249, 0x24A, 0x24B, 0x24C, 0x24D, 0x24E, 0x24F, 0x250, 0x251, 0x252, 0x253, 0x254, 0x255, 0x256, 0x257, 0x258, 0x259, 0x25A, 0x25B, + 0x25C, 0x25D, 0x25E, 0x25F, 0x260, 0x261, 0x262, 0x263, 0x264, 0x265, 0x266, 0x267, 0x268, 0x269, 0x26A, 0x20C, 0x20C, 0x20C, 0x20C, 0x20C, 0x20C, + 0x20C, 0x20C, 0x20C, 0x20C, 0x20C, 0x20C, 0x20C, 0x20C, 0x20C, 0x20C, 0x20C, 0x20C, 0x20C, 0x20C, 0x20C, 0x20C, 0x20C, 0x20C, 0x20C, 0x20C, 0x20C, + 0x20C, 0x20C, 0x20C, 0x20C, 0x20C, 0x20C, 0x20C, 0x26B, 0x26C, 0x26D, 0x26E, 0x26F, 0x270, 0x271, 0x272, 0x273, 0x274, 0x275, 0x276, 0x277, 0x278, + 0x279, 0x27A, 0x27B, 0x27C, 0x27D, 0x27E, 0x27F, 0x280, 0x281, 0x282, 0x283, 0x284, 0x285, 0x286, 0x287, 0x288, 0x289, 0x28A, 0x28B, 0x28C, 0x28D, + 0x28E, 0x28F, 0x290, 0x291, 0x292, 0x293, 0x294, 0x295, 0x296, 0x297, 0x298, 0x299, 0x29A, 0x29B, 0x29C, 0x29D, 0x29E, 0x29F, 0x2A0, 0x2A1, 0x2A2, + 0x2A3, 0x2A4, 0x2A5, 0x2A6, 0x2A7, 0x2A8, 0x2A9 }; + +static u16 Zenkaku2Code[] = { 0x000, 0x001, 0x002, 0x003, 0x004, 0x005, 0x006, 0x007, 0x008, 0x009, 0x00A, 0x00B, 0x00C, 0x00D, 0x00E, 0x00F, 0x010, + 0x011, 0x012, 0x013, 0x014, 0x015, 0x016, 0x017, 0x018, 0x019, 0x01A, 0x01B, 0x01C, 0x01D, 0x01E, 0x01F, 0x020, 0x021, 0x022, 0x023, 0x024, 0x025, + 0x026, 0x027, 0x028, 0x029, 0x02A, 0x02B, 0x02C, 0x02D, 0x02E, 0x02F, 0x030, 0x031, 0x032, 0x033, 0x034, 0x035, 0x036, 0x037, 0x038, 0x039, 0x03A, + 0x03B, 0x03C, 0x03D, 0x03E, 0x03F, 0x040, 0x041, 0x042, 0x043, 0x044, 0x045, 0x046, 0x047, 0x048, 0x049, 0x04A, 0x04B, 0x04C, 0x04D, 0x04E, 0x04F, + 0x050, 0x051, 0x052, 0x053, 0x054, 0x055, 0x056, 0x057, 0x058, 0x059, 0x05A, 0x05B, 0x05C, 0x05D, 0x05E, 0x05F, 0x060, 0x061, 0x062, 0x063, 0x064, + 0x065, 0x066, 0x067, 0x068, 0x069, 0x06A, 0x06B, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x06C, 0x06D, 0x06E, + 0x06F, 0x070, 0x071, 0x072, 0x073, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x074, 0x075, 0x076, 0x077, 0x078, 0x079, 0x07A, 0x000, + 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x07B, 0x07C, 0x07D, 0x07E, 0x07F, 0x080, 0x081, 0x082, 0x083, 0x084, 0x085, + 0x086, 0x087, 0x088, 0x089, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x08A, 0x08B, 0x08C, 0x08D, 0x08E, 0x08F, 0x090, 0x091, 0x000, 0x000, + 0x000, 0x000, 0x092, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x093, 0x094, 0x095, + 0x096, 0x097, 0x098, 0x099, 0x09A, 0x09B, 0x09C, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x09D, 0x09E, 0x09F, 0x0A0, 0x0A1, 0x0A2, 0x0A3, + 0x0A4, 0x0A5, 0x0A6, 0x0A7, 0x0A8, 0x0A9, 0x0AA, 0x0AB, 0x0AC, 0x0AD, 0x0AE, 0x0AF, 0x0B0, 0x0B1, 0x0B2, 0x0B3, 0x0B4, 0x0B5, 0x0B6, 0x000, 0x000, + 0x000, 0x000, 0x000, 0x000, 0x0B7, 0x0B8, 0x0B9, 0x0BA, 0x0BB, 0x0BC, 0x0BD, 0x0BE, 0x0BF, 0x0C0, 0x0C1, 0x0C2, 0x0C3, 0x0C4, 0x0C5, 0x0C6, 0x0C7, + 0x0C8, 0x0C9, 0x0CA, 0x0CB, 0x0CC, 0x0CD, 0x0CE, 0x0CF, 0x0D0, 0x000, 0x000, 0x000, 0x000, 0x0D1, 0x0D2, 0x0D3, 0x0D4, 0x0D5, 0x0D6, 0x0D7, 0x0D8, + 0x0D9, 0x0DA, 0x0DB, 0x0DC, 0x0DD, 0x0DE, 0x0DF, 0x0E0, 0x0E1, 0x0E2, 0x0E3, 0x0E4, 0x0E5, 0x0E6, 0x0E7, 0x0E8, 0x0E9, 0x0EA, 0x0EB, 0x0EC, 0x0ED, + 0x0EE, 0x0EF, 0x0F0, 0x0F1, 0x0F2, 0x0F3, 0x0F4, 0x0F5, 0x0F6, 0x0F7, 0x0F8, 0x0F9, 0x0FA, 0x0FB, 0x0FC, 0x0FD, 0x0FE, 0x0FF, 0x100, 0x101, 0x102, + 0x103, 0x104, 0x105, 0x106, 0x107, 0x108, 0x109, 0x10A, 0x10B, 0x10C, 0x10D, 0x10E, 0x10F, 0x110, 0x111, 0x112, 0x113, 0x114, 0x115, 0x116, 0x117, + 0x118, 0x119, 0x11A, 0x11B, 0x11C, 0x11D, 0x11E, 0x11F, 0x120, 0x121, 0x122, 0x123, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, + 0x000, 0x000, 0x124, 0x125, 0x126, 0x127, 0x128, 0x129, 0x12A, 0x12B, 0x12C, 0x12D, 0x12E, 0x12F, 0x130, 0x131, 0x132, 0x133, 0x134, 0x135, 0x136, + 0x137, 0x138, 0x139, 0x13A, 0x13B, 0x13C, 0x13D, 0x13E, 0x13F, 0x140, 0x141, 0x142, 0x143, 0x144, 0x145, 0x146, 0x147, 0x148, 0x149, 0x14A, 0x14B, + 0x14C, 0x14D, 0x14E, 0x14F, 0x150, 0x151, 0x152, 0x153, 0x154, 0x155, 0x156, 0x157, 0x158, 0x159, 0x15A, 0x15B, 0x15C, 0x15D, 0x15E, 0x15F, 0x160, + 0x161, 0x162, 0x163, 0x164, 0x165, 0x166, 0x167, 0x168, 0x169, 0x16A, 0x16B, 0x16C, 0x16D, 0x16E, 0x16F, 0x170, 0x171, 0x172, 0x173, 0x174, 0x175, + 0x176, 0x177, 0x178, 0x179, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x17A, 0x17B, 0x17C, 0x17D, 0x17E, 0x17F, 0x180, 0x181, 0x182, + 0x183, 0x184, 0x185, 0x186, 0x187, 0x188, 0x189, 0x18A, 0x18B, 0x18C, 0x18D, 0x18E, 0x18F, 0x190, 0x191, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, + 0x000, 0x000, 0x192, 0x193, 0x194, 0x195, 0x196, 0x197, 0x198, 0x199, 0x19A, 0x19B, 0x19C, 0x19D, 0x19E, 0x19F, 0x1A0, 0x1A1, 0x1A2, 0x1A3, 0x1A4, + 0x1A5, 0x1A6, 0x1A7, 0x1A8, 0x1A9, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, + 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, + 0x000, 0x1AA, 0x1AB, 0x1AC, 0x1AD, 0x1AE, 0x1AF, 0x1B0, 0x1B1, 0x1B2, 0x1B3, 0x1B4, 0x1B5, 0x1B6, 0x1B7, 0x1B8, 0x1B9, 0x1BA, 0x1BB, 0x1BC, 0x1BD, + 0x1BE, 0x1BF, 0x1C0, 0x1C1, 0x1C2, 0x1C3, 0x1C4, 0x1C5, 0x1C6, 0x1C7, 0x1C8, 0x1C9, 0x1CA, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, + 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x1CB, 0x1CC, 0x1CD, 0x1CE, 0x1CF, 0x1D0, 0x1D1, 0x1D2, 0x1D3, 0x1D4, 0x1D5, 0x1D6, 0x1D7, 0x1D8, + 0x1D9, 0x1DA, 0x1DB, 0x1DC, 0x1DD, 0x1DE, 0x1DF, 0x1E0, 0x1E1, 0x1E2, 0x1E3, 0x1E4, 0x1E5, 0x1E6, 0x1E7, 0x1E8, 0x1E9, 0x1EA, 0x1EB, 0x000, 0x000, + 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x1EC, 0x1ED, 0x1EE, 0x1EF, 0x1F0, 0x1F1, 0x1F2, 0x1F3, 0x1F4, 0x1F5, + 0x1F6, 0x1F7, 0x1F8, 0x1F9, 0x1FA, 0x1FB, 0x1FC, 0x1FD, 0x1FE, 0x1FF, 0x200, 0x201, 0x202, 0x203, 0x204, 0x205, 0x206, 0x207, 0x208, 0x209, 0x20A, + 0x20B, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, + 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, + 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x20C, + 0x20D, 0x20E, 0x20F, 0x210, 0x211, 0x212, 0x213, 0x214, 0x215, 0x216, 0x217, 0x218, 0x219, 0x21A, 0x21B, 0x21C, 0x21D, 0x21E, 0x21F, 0x220, 0x221, + 0x222, 0x223, 0x224, 0x225, 0x226, 0x227, 0x228, 0x229, 0x22A, 0x22B, 0x22C, 0x22D, 0x22E, 0x22F, 0x230, 0x231, 0x232, 0x233, 0x234, 0x235, 0x236, + 0x237, 0x238, 0x239, 0x23A, 0x23B, 0x23C, 0x23D, 0x23E, 0x23F, 0x240, 0x241, 0x242, 0x243, 0x244, 0x245, 0x246, 0x247, 0x248, 0x249, 0x24A, 0x24B, + 0x24C, 0x24D, 0x24E, 0x24F, 0x250, 0x251, 0x252, 0x253, 0x254, 0x255, 0x256, 0x257, 0x258, 0x259, 0x25A, 0x25B, 0x25C, 0x25D, 0x25E, 0x25F, 0x260, + 0x261, 0x262, 0x263, 0x264, 0x265, 0x266, 0x267, 0x268, 0x269, 0x26A, 0x26B, 0x26C, 0x26D, 0x26E, 0x26F, 0x270, 0x271, 0x272, 0x273, 0x274, 0x275, + 0x276, 0x277, 0x278, 0x279, 0x27A, 0x27B, 0x27C, 0x27D, 0x27E, 0x27F, 0x280, 0x281, 0x282, 0x283, 0x284, 0x285, 0x286, 0x287, 0x288, 0x289, 0x28A, + 0x28B, 0x28C, 0x28D, 0x28E, 0x28F, 0x290, 0x291, 0x292, 0x293, 0x294, 0x295, 0x296, 0x297, 0x298, 0x299, 0x29A, 0x29B, 0x29C, 0x29D, 0x29E, 0x29F, + 0x2A0, 0x2A1, 0x2A2, 0x2A3, 0x2A4, 0x2A5, 0x2A6, 0x2A7, 0x2A8, 0x2A9, 0x2AA, 0x2AB, 0x2AC, 0x2AD, 0x2AE, 0x2AF, 0x2B0, 0x2B1, 0x2B2, 0x2B3, 0x2B4, + 0x2B5, 0x2B6, 0x2B7, 0x2B8, 0x2B9, 0x2BA, 0x2BB, 0x2BC, 0x2BD, 0x2BE, 0x2BF, 0x2C0, 0x2C1, 0x2C2, 0x2C3, 0x2C4, 0x2C5, 0x2C6, 0x2C7, 0x2C8, 0x000, + 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, + 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, + 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, + 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, + 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, + 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, + 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, + 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, + 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x2C9, 0x2CA, + 0x2CB, 0x2CC, 0x2CD, 0x2CE, 0x2CF, 0x2D0, 0x2D1, 0x2D2, 0x2D3, 0x2D4, 0x2D5, 0x2D6, 0x2D7, 0x2D8, 0x2D9, 0x2DA, 0x2DB, 0x2DC, 0x2DD, 0x2DE, 0x2DF, + 0x2E0, 0x2E1, 0x2E2, 0x2E3, 0x2E4, 0x2E5, 0x2E6, 0x000, 0x2E7, 0x2E8, 0x2E9, 0x2EA, 0x2EB, 0x2EC, 0x2ED, 0x2EE, 0x2EF, 0x2F0, 0x2F1, 0x2F2, 0x2F3, + 0x2F4, 0x2F5, 0x2F6, 0x2F7, 0x2F8, 0x2F9, 0x2FA, 0x2FB, 0x2FC, 0x2FD, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x2FE, 0x2FF, 0x300, + 0x301, 0x302, 0x303, 0x304, 0x305, 0x306, 0x307, 0x308, 0x309, 0x30A, 0x30B, 0x30C, 0x30D, 0x30E, 0x30F, 0x310, 0x311, 0x312, 0x313, 0x314, 0x315, + 0x316, 0x317, 0x318, 0x319, 0x31A, 0x31B, 0x000 }; + +static int GetFontCode(unsigned short code) +{ + if (OSGetFontEncode() == OS_FONT_ENCODE_SJIS) { + if (code >= 0x20 && code <= 0xDF) { + return HankakuToCode[code - 0x20]; + } + + if (code > 0x889E) { + int i = ((code >> 8) - 0x88) * 188; + int j = (code & 0xFF) - 0x40; + + if (j >= 0x40) { + j--; + } + + return (i + j + 0x2BE); + } + + if (code < 0x879E) { + int i = ((code >> 8) - 0x81) * 188; + int j = (code & 0xFF) - 0x40; + + if (j >= 0x40) { + j--; + } + + return Zenkaku2Code[i + j]; + } + } + else if (code > 0x20 && code <= 0xFF) { + return code - 0x20; + } + else { + return 0; + } +} + +static void Decode(unsigned char *s, unsigned char *d) +{ + int i; + int j; + int k; + int p; + int q; + int r7; // huh? DWARF info says these 2 variables might be register names and not actual names. + int r25; + int cnt; + int os; + unsigned int flag; + unsigned int code; + + os = *(int *)(s + 0x4); + r7 = *(int *)(s + 0x8); + r25 = *(int *)(s + 0xC); + + q = 0; + flag = 0; + p = 16; + + do { + // Get next mask + if (flag == 0) { + code = *(u32 *)(s + p); + p += sizeof(u32); + flag = sizeof(u32) * 8; + } + + // Non-linked chunk + if (code & 0x80000000) { + d[q++] = s[r25++]; + } + // Linked chunk + else { + // Read offset from link table + j = s[r7] << 8 | s[r7 + 1]; + r7 += sizeof(u16); + + // Apply offset + k = q - (j & 0x0FFF); + cnt = j >> 12; + if (cnt == 0) { + cnt = s[r25++] + 0x12; + } + else { + cnt += 2; + } + + // Copy chunk + for (i = 0; i < cnt; i++, q++, k++) { + d[q] = d[k - 1]; + } + } + + // Prepare next mask bit + code <<= 1; + flag--; + } while (q < os); +} + +static u32 GetFontSize(u8 *buf) +{ + if (buf[0] == 'Y' && buf[1] == 'a' && buf[2] == 'y') { + return *(u32 *)(buf + 0x4); + } + + return 0; +} + +u16 OSGetFontEncode(void) +{ + static u16 fontEncode = 0xFFFF; + if (fontEncode <= 1) { + return fontEncode; + } + switch (*(int *)OSPhysicalToCached(0xCC)) { + case VI_NTSC: + fontEncode = (__VIRegs[VI_DTV_STAT] & 2) ? OS_FONT_ENCODE_SJIS : OS_FONT_ENCODE_ANSI; + break; + + case VI_PAL: + case VI_MPAL: + case VI_DEBUG: + case VI_DEBUG_PAL: + case VI_EURGB60: + default: + fontEncode = OS_FONT_ENCODE_ANSI; + } + + return fontEncode; +} + +static void ReadROM(void *buf, int length, int offset) +{ + int len; + while (length > 0) { + len = (length <= 0x100) ? length : 0x100; + length -= len; + + while (!__OSReadROM(buf, len, offset)) { + ; + } + + offset += len; + (u8 *)buf += len; + } +} + +static u32 ReadFont(void *img) +{ + if (OSGetFontEncode() == OS_FONT_ENCODE_SJIS) { + ReadROM(img, OS_FONT_ROM_SIZE_SJIS, 0x1AFF00); + } + else { + ReadROM(img, OS_FONT_ROM_SIZE_ANSI, 0x1FCF00); + } + + return GetFontSize(img); +} + +u32 OSLoadFont(OSFontHeader *fontData, void *temp) +{ + u32 size; + + SheetImage = NULL; + size = ReadFont(temp); + if (size) { + Decode(temp, (void *)fontData); + FontData = fontData; + WidthTable = (u8 *)FontData + FontData->widthTable; + CharsInSheet = FontData->sheetColumn * FontData->sheetRow; + } + + return size; +} + +char *OSGetFontTexel(char *string, void *image, long pos, long stride, long *width) +{ + unsigned short code; + unsigned char *src; + unsigned char *dst; + int fontCode; + int sheet; + int numChars; + int row; + int column; + int x; + int y; + int offsetSrc; + int offsetDst; + unsigned char *colorIndex; + unsigned char *imageSrc; + + // ASSERTLINE(0x1F6, FontData && !SheetImage); + + code = *string; + if (code == '\0') { + return string; + } + + string++; + if (OSGetFontEncode() == OS_FONT_ENCODE_SJIS) { + if ((((code >= 0x80) && (code <= 0x9F)) || ((code >= 0xE0) && (code <= 0xFF))) && ((s8)*string != 0U)) { + code = (code << 8) | (*string++); // Shift-JIS encoded byte + } + } + colorIndex = &FontData->c0; + + // ASSERTLINE(0x209, FontData->sheetFormat == GX_TF_I4); + + fontCode = GetFontCode(code); + + sheet = fontCode / CharsInSheet; + numChars = fontCode - (sheet * CharsInSheet); + row = numChars / FontData->sheetColumn; + column = (numChars - (row * FontData->sheetColumn)); + row *= FontData->cellHeight; + column *= FontData->cellWidth; + imageSrc = (u8 *)FontData + FontData->sheetImage; + imageSrc += (sheet * FontData->sheetSize) / 2; + + for (y = 0; y < FontData->cellHeight; y++) { + for (x = 0; x < FontData->cellWidth; x++) { + src = imageSrc + (((FontData->sheetWidth / 8) * 32) / 2) * ((row + y) / 8); + src += ((column + x) / 8) * 16; + src += ((row + y) % 8) * 2; + src += ((column + x) % 8) / 4; + + offsetSrc = (column + x) % 4; + + dst = (u8 *)image + ((y / 8) * (((stride * 4) / 8) * 32)); + dst += (((pos + x) / 8) * 32); + dst += ((y % 8) * 4); + dst += ((pos + x) % 8) / 2; + + offsetDst = (pos + x) % 2; + + *dst |= colorIndex[*src >> (6 - (offsetSrc * 2)) & 3] & ((offsetDst != 0) ? 0x0F : 0xF0); + } + } + *width = WidthTable[fontCode]; + + return string; +} diff --git a/src/dolphin/os/OSInterrupt.c b/src/dolphin/os/OSInterrupt.c new file mode 100644 index 00000000..061e7daf --- /dev/null +++ b/src/dolphin/os/OSInterrupt.c @@ -0,0 +1,434 @@ +#include +#include +#include + +static asm void ExternalInterruptHandler(register __OSException exception, register OSContext *context); + +static __OSInterruptHandler *InterruptHandlerTable; + +static OSInterruptMask InterruptPrioTable[] = { + OS_INTERRUPTMASK_PI_ERROR, + OS_INTERRUPTMASK_PI_DEBUG, + OS_INTERRUPTMASK_MEM, + OS_INTERRUPTMASK_PI_RSW, + OS_INTERRUPTMASK_PI_VI, + OS_INTERRUPTMASK_PI_PE, + OS_INTERRUPTMASK_PI_HSP, + OS_INTERRUPTMASK_DSP_ARAM | OS_INTERRUPTMASK_DSP_DSP | OS_INTERRUPTMASK_AI | OS_INTERRUPTMASK_EXI | OS_INTERRUPTMASK_PI_SI + | OS_INTERRUPTMASK_PI_DI, + OS_INTERRUPTMASK_DSP_AI, + OS_INTERRUPTMASK_PI_CP, + 0xFFFFFFFF, +}; + +asm BOOL OSDisableInterrupts(void) +{ + // clang-format off + nofralloc +entry __RAS_OSDisableInterrupts_begin + mfmsr r3 + rlwinm r4, r3, 0, 17, 15 + mtmsr r4 + rlwinm r3, r3, 17, 31, 31 +entry __RAS_OSDisableInterrupts_end + blr + // clang-format on +} +asm BOOL OSEnableInterrupts(void) +{ + // clang-format off + nofralloc + + mfmsr r3 + ori r4, r3, 0x8000 + mtmsr r4 + rlwinm r3, r3, 17, 31, 31 + blr + // clang-format on +} + +asm BOOL OSRestoreInterrupts(register BOOL level) { + // clang-format off + + nofralloc + + cmpwi level, 0 + mfmsr r4 + beq _disable + ori r5, r4, 0x8000 + b _restore +_disable: + rlwinm r5, r4, 0, 17, 15 +_restore: + mtmsr r5 + rlwinm r3, r4, 17, 31, 31 + blr + // clang-format on +} + +__OSInterruptHandler __OSSetInterruptHandler(__OSInterrupt interrupt, __OSInterruptHandler handler) +{ + __OSInterruptHandler oldHandler; + + oldHandler = InterruptHandlerTable[interrupt]; + InterruptHandlerTable[interrupt] = handler; + return oldHandler; +} + +__OSInterruptHandler __OSGetInterruptHandler(__OSInterrupt interrupt) +{ + return InterruptHandlerTable[interrupt]; +} + +void __OSInterruptInit(void) +{ + InterruptHandlerTable = OSPhysicalToCached(0x3040); + memset(InterruptHandlerTable, 0, __OS_INTERRUPT_MAX * sizeof(__OSInterruptHandler)); + + *(OSInterruptMask *)OSPhysicalToCached(0x00C4) = 0; + + *(OSInterruptMask *)OSPhysicalToCached(0x00C8) = 0; + + __PIRegs[1] = 0xf0; + + __OSMaskInterrupts(OS_INTERRUPTMASK_MEM | OS_INTERRUPTMASK_DSP | OS_INTERRUPTMASK_AI | OS_INTERRUPTMASK_EXI | OS_INTERRUPTMASK_PI); + + __OSSetExceptionHandler(4, ExternalInterruptHandler); +} + +u32 SetInterruptMask(OSInterruptMask mask, OSInterruptMask current) +{ + u32 reg; + + switch (__cntlzw(mask)) { + case __OS_INTERRUPT_MEM_0: + case __OS_INTERRUPT_MEM_1: + case __OS_INTERRUPT_MEM_2: + case __OS_INTERRUPT_MEM_3: + case __OS_INTERRUPT_MEM_ADDRESS: + reg = 0; + if (!(current & OS_INTERRUPTMASK_MEM_0)) + reg |= 0x1; + if (!(current & OS_INTERRUPTMASK_MEM_1)) + reg |= 0x2; + if (!(current & OS_INTERRUPTMASK_MEM_2)) + reg |= 0x4; + if (!(current & OS_INTERRUPTMASK_MEM_3)) + reg |= 0x8; + if (!(current & OS_INTERRUPTMASK_MEM_ADDRESS)) + reg |= 0x10; + __MEMRegs[0x0000000e] = (u16)reg; + mask &= ~OS_INTERRUPTMASK_MEM; + break; + case __OS_INTERRUPT_DSP_AI: + case __OS_INTERRUPT_DSP_ARAM: + case __OS_INTERRUPT_DSP_DSP: + reg = __DSPRegs[0x00000005]; + reg &= ~0x1F8; + if (!(current & OS_INTERRUPTMASK_DSP_AI)) + reg |= 0x10; + if (!(current & OS_INTERRUPTMASK_DSP_ARAM)) + reg |= 0x40; + if (!(current & OS_INTERRUPTMASK_DSP_DSP)) + reg |= 0x100; + __DSPRegs[0x00000005] = (u16)reg; + mask &= ~OS_INTERRUPTMASK_DSP; + break; + case __OS_INTERRUPT_AI_AI: + reg = __AIRegs[0]; + reg &= ~0x2C; + if (!(current & OS_INTERRUPTMASK_AI_AI)) + reg |= 0x4; + __AIRegs[0] = reg; + mask &= ~OS_INTERRUPTMASK_AI; + break; + case __OS_INTERRUPT_EXI_0_EXI: + case __OS_INTERRUPT_EXI_0_TC: + case __OS_INTERRUPT_EXI_0_EXT: + reg = __EXIRegs[0]; + reg &= ~0x2C0F; + if (!(current & OS_INTERRUPTMASK_EXI_0_EXI)) + reg |= 0x1; + if (!(current & OS_INTERRUPTMASK_EXI_0_TC)) + reg |= 0x4; + if (!(current & OS_INTERRUPTMASK_EXI_0_EXT)) + reg |= 0x400; + __EXIRegs[0] = reg; + mask &= ~OS_INTERRUPTMASK_EXI_0; + break; + case __OS_INTERRUPT_EXI_1_EXI: + case __OS_INTERRUPT_EXI_1_TC: + case __OS_INTERRUPT_EXI_1_EXT: + reg = __EXIRegs[5]; + reg &= ~0xC0F; + + if (!(current & OS_INTERRUPTMASK_EXI_1_EXI)) + reg |= 0x1; + if (!(current & OS_INTERRUPTMASK_EXI_1_TC)) + reg |= 0x4; + if (!(current & OS_INTERRUPTMASK_EXI_1_EXT)) + reg |= 0x400; + __EXIRegs[5] = reg; + mask &= ~OS_INTERRUPTMASK_EXI_1; + break; + case __OS_INTERRUPT_EXI_2_EXI: + case __OS_INTERRUPT_EXI_2_TC: + reg = __EXIRegs[10]; + reg &= ~0xF; + if (!(current & OS_INTERRUPTMASK_EXI_2_EXI)) + reg |= 0x1; + if (!(current & OS_INTERRUPTMASK_EXI_2_TC)) + reg |= 0x4; + + __EXIRegs[10] = reg; + mask &= ~OS_INTERRUPTMASK_EXI_2; + break; + case __OS_INTERRUPT_PI_CP: + case __OS_INTERRUPT_PI_SI: + case __OS_INTERRUPT_PI_DI: + case __OS_INTERRUPT_PI_RSW: + case __OS_INTERRUPT_PI_ERROR: + case __OS_INTERRUPT_PI_VI: + case __OS_INTERRUPT_PI_DEBUG: + case __OS_INTERRUPT_PI_PE_TOKEN: + case __OS_INTERRUPT_PI_PE_FINISH: + case __OS_INTERRUPT_PI_HSP: + reg = 0xF0; + + if (!(current & OS_INTERRUPTMASK_PI_CP)) { + reg |= 0x800; + } + if (!(current & OS_INTERRUPTMASK_PI_SI)) { + reg |= 0x8; + } + if (!(current & OS_INTERRUPTMASK_PI_DI)) { + reg |= 0x4; + } + if (!(current & OS_INTERRUPTMASK_PI_RSW)) { + reg |= 0x2; + } + if (!(current & OS_INTERRUPTMASK_PI_ERROR)) { + reg |= 0x1; + } + if (!(current & OS_INTERRUPTMASK_PI_VI)) { + reg |= 0x100; + } + if (!(current & OS_INTERRUPTMASK_PI_DEBUG)) { + reg |= 0x1000; + } + if (!(current & OS_INTERRUPTMASK_PI_PE_TOKEN)) { + reg |= 0x200; + } + if (!(current & OS_INTERRUPTMASK_PI_PE_FINISH)) { + reg |= 0x400; + } + if (!(current & OS_INTERRUPTMASK_PI_HSP)) { + reg |= 0x2000; + } + __PIRegs[1] = reg; + mask &= ~OS_INTERRUPTMASK_PI; + break; + default: + break; + } + return mask; +} + +OSInterruptMask OSGetInterruptMask(void) +{ + return *(OSInterruptMask *)OSPhysicalToCached(0x00C8); +} + +OSInterruptMask OSSetInterruptMask(OSInterruptMask local) +{ + BOOL enabled; + OSInterruptMask global; + OSInterruptMask prev; + OSInterruptMask mask; + + enabled = OSDisableInterrupts(); + global = *(OSInterruptMask *)OSPhysicalToCached(0x00C4); + prev = *(OSInterruptMask *)OSPhysicalToCached(0x00C8); + mask = (global | prev) ^ local; + *(OSInterruptMask *)OSPhysicalToCached(0x00C8) = local; + while (mask) { + mask = SetInterruptMask(mask, global | local); + } + OSRestoreInterrupts(enabled); + return prev; +} + +OSInterruptMask __OSMaskInterrupts(OSInterruptMask global) +{ + BOOL enabled; + OSInterruptMask prev; + OSInterruptMask local; + OSInterruptMask mask; + + enabled = OSDisableInterrupts(); + prev = *(OSInterruptMask *)OSPhysicalToCached(0x00C4); + local = *(OSInterruptMask *)OSPhysicalToCached(0x00C8); + mask = ~(prev | local) & global; + global |= prev; + *(OSInterruptMask *)OSPhysicalToCached(0x00C4) = global; + while (mask) { + mask = SetInterruptMask(mask, global | local); + } + OSRestoreInterrupts(enabled); + return prev; +} + +OSInterruptMask __OSUnmaskInterrupts(OSInterruptMask global) +{ + BOOL enabled; + OSInterruptMask prev; + OSInterruptMask local; + OSInterruptMask mask; + + enabled = OSDisableInterrupts(); + prev = *(OSInterruptMask *)OSPhysicalToCached(0x00C4); + local = *(OSInterruptMask *)OSPhysicalToCached(0x00C8); + mask = (prev | local) & global; + global = prev & ~global; + *(OSInterruptMask *)OSPhysicalToCached(0x00C4) = global; + while (mask) { + mask = SetInterruptMask(mask, global | local); + } + OSRestoreInterrupts(enabled); + return prev; +} + +volatile OSTime __OSLastInterruptTime; +volatile __OSInterrupt __OSLastInterrupt; +volatile u32 __OSLastInterruptSrr0; + +void __OSDispatchInterrupt(__OSException exception, OSContext *context) +{ + u32 intsr; + u32 reg; + OSInterruptMask cause; + OSInterruptMask unmasked; + OSInterruptMask *prio; + __OSInterrupt interrupt; + __OSInterruptHandler handler; + intsr = __PIRegs[0]; + intsr &= ~0x00010000; + + if (intsr == 0 || (intsr & __PIRegs[1]) == 0) { + OSLoadContext(context); + } + + cause = 0; + + if (intsr & 0x00000080) { + reg = __MEMRegs[15]; + if (reg & 0x1) + cause |= OS_INTERRUPTMASK_MEM_0; + if (reg & 0x2) + cause |= OS_INTERRUPTMASK_MEM_1; + if (reg & 0x4) + cause |= OS_INTERRUPTMASK_MEM_2; + if (reg & 0x8) + cause |= OS_INTERRUPTMASK_MEM_3; + if (reg & 0x10) + cause |= OS_INTERRUPTMASK_MEM_ADDRESS; + } + + if (intsr & 0x00000040) { + reg = __DSPRegs[5]; + if (reg & 0x8) + cause |= OS_INTERRUPTMASK_DSP_AI; + if (reg & 0x20) + cause |= OS_INTERRUPTMASK_DSP_ARAM; + if (reg & 0x80) + cause |= OS_INTERRUPTMASK_DSP_DSP; + } + + if (intsr & 0x00000020) { + reg = __AIRegs[0]; + if (reg & 0x8) + cause |= OS_INTERRUPTMASK_AI_AI; + } + + if (intsr & 0x00000010) { + reg = __EXIRegs[0]; + if (reg & 0x2) + cause |= OS_INTERRUPTMASK_EXI_0_EXI; + if (reg & 0x8) + cause |= OS_INTERRUPTMASK_EXI_0_TC; + if (reg & 0x800) + cause |= OS_INTERRUPTMASK_EXI_0_EXT; + reg = __EXIRegs[5]; + if (reg & 0x2) + cause |= OS_INTERRUPTMASK_EXI_1_EXI; + if (reg & 0x8) + cause |= OS_INTERRUPTMASK_EXI_1_TC; + if (reg & 0x800) + cause |= OS_INTERRUPTMASK_EXI_1_EXT; + reg = __EXIRegs[10]; + if (reg & 0x2) + cause |= OS_INTERRUPTMASK_EXI_2_EXI; + if (reg & 0x8) + cause |= OS_INTERRUPTMASK_EXI_2_TC; + } + + if (intsr & 0x00002000) + cause |= OS_INTERRUPTMASK_PI_HSP; + if (intsr & 0x00001000) + cause |= OS_INTERRUPTMASK_PI_DEBUG; + if (intsr & 0x00000400) + cause |= OS_INTERRUPTMASK_PI_PE_FINISH; + if (intsr & 0x00000200) + cause |= OS_INTERRUPTMASK_PI_PE_TOKEN; + if (intsr & 0x00000100) + cause |= OS_INTERRUPTMASK_PI_VI; + if (intsr & 0x00000008) + cause |= OS_INTERRUPTMASK_PI_SI; + if (intsr & 0x00000004) + cause |= OS_INTERRUPTMASK_PI_DI; + if (intsr & 0x00000002) + cause |= OS_INTERRUPTMASK_PI_RSW; + if (intsr & 0x00000800) + cause |= OS_INTERRUPTMASK_PI_CP; + if (intsr & 0x00000001) + cause |= OS_INTERRUPTMASK_PI_ERROR; + + unmasked = cause & ~(*(OSInterruptMask *)OSPhysicalToCached(0x00C4) | *(OSInterruptMask *)OSPhysicalToCached(0x00C8)); + if (unmasked) { + for (prio = InterruptPrioTable;; ++prio) { + if (unmasked & *prio) { + interrupt = (__OSInterrupt)__cntlzw(unmasked & *prio); + break; + } + } + + handler = __OSGetInterruptHandler(interrupt); + if (handler) { + if (__OS_INTERRUPT_MEM_ADDRESS < interrupt) { + __OSLastInterrupt = interrupt; + __OSLastInterruptTime = OSGetTime(); + __OSLastInterruptSrr0 = context->srr0; + } + + OSDisableScheduler(); + handler(interrupt, context); + OSEnableScheduler(); + __OSReschedule(); + OSLoadContext(context); + } + } + + OSLoadContext(context); +} + +static asm void ExternalInterruptHandler(register __OSException exception, register OSContext *context) +{ +#pragma unused(exception) + // clang-format off + nofralloc + OS_EXCEPTION_SAVE_GPRS(context) + + stwu r1, -8(r1) + b __OSDispatchInterrupt + // clang-format on +} diff --git a/src/dolphin/os/OSLink.c b/src/dolphin/os/OSLink.c new file mode 100644 index 00000000..c3f3e03c --- /dev/null +++ b/src/dolphin/os/OSLink.c @@ -0,0 +1,504 @@ +#include "dolphin/os.h" + +#define SHN_UNDEF 0 +#define SHN_LORESERVE 0xff00 +#define SHN_LOPROC 0xff00 +#define SHN_HIPROC 0xff1f +#define SHN_ABS 0xfff1 +#define SHN_COMMON 0xfff2 +#define SHN_HIRESERVE 0xffff + +#define ELF32_R_SYM(i) ((i) >> 8) +#define ELF32_R_TYPE(i) ((unsigned char)(i)) +#define ELF32_R_INFO(s, t) (((s) << 8) + (unsigned char)(t)) + +// Name Value Field Calculation +#define R_PPC_NONE 0 // none none +#define R_PPC_ADDR32 1 // word32 S + A +#define R_PPC_ADDR24 2 // low24* (S + A) >> 2 +#define R_PPC_ADDR16 3 // half16* S + A +#define R_PPC_ADDR16_LO 4 // half16 #lo(S + A) +#define R_PPC_ADDR16_HI 5 // half16 #hi(S + A) +#define R_PPC_ADDR16_HA 6 // half16 #ha(S + A) +#define R_PPC_ADDR14 7 // low14* (S + A) >> 2 +#define R_PPC_ADDR14_BRTAKEN 8 // low14* (S + A) >> 2 +#define R_PPC_ADDR14_BRNTAKEN 9 // low14* (S + A) >> 2 +#define R_PPC_REL24 10 // low24* (S + A - P) >> 2 +#define R_PPC_REL14 11 // low14* (S + A - P) >> 2 +#define R_PPC_REL14_BRTAKEN 12 // low14* (S + A - P) >> 2 +#define R_PPC_REL14_BRNTAKEN 13 // low14* (S + A - P) >> 2 + +#define R_PPC_GOT16 14 // half16* G + A +#define R_PPC_GOT16_LO 15 // half16 #lo(G + A) +#define R_PPC_GOT16_HI 16 // half16 #hi(G + A) +#define R_PPC_GOT16_HA 17 // half16 #ha(G + A) +#define R_PPC_PLTREL24 18 // low24* (L + A - P) >> 2 +#define R_PPC_COPY 19 // none none +#define R_PPC_GLOB_DAT 20 // word32 S + A +#define R_PPC_JMP_SLOT 21 // none +#define R_PPC_RELATIVE 22 // word32 B + A + +#define R_PPC_LOCAL24PC 23 // low24* + +#define R_PPC_UADDR32 24 // word32 S + A +#define R_PPC_UADDR16 25 // half16* S + A +#define R_PPC_REL32 26 // word32 S + A - P + +#define R_PPC_PLT32 27 // word32 L + A +#define R_PPC_PLTREL32 28 // word32 L + A - P +#define R_PPC_PLT16_LO 29 // half16 #lo(L + A) +#define R_PPL_PLT16_HI 30 // half16 #hi(L + A) +#define R_PPC_PLT16_HA 31 // half16 #ha(L + A) + +#define R_PPC_SDAREL16 32 // half16* S + A - _SDA_BASE_ +#define R_PPC_SECTOFF 33 // half16* R + A +#define R_PPC_SECTOFF_LO 34 // half16 #lo(R + A) +#define R_PPC_SECTOFF_HI 35 // half16 #hi(R + A) +#define R_PPC_SECTOFF_HA 36 // half16 #ha(R + A) +#define R_PPC_ADDR30 37 // word30 (S + A - P) >> 2 + +#define R_PPC_EMB_NADDR32 101 // uword32 N (A - S) +#define R_PPC_EMB_NADDR16 102 // uhalf16 Y (A - S) +#define R_PPC_EMB_NADDR16_LO 103 // uhalf16 N #lo(A - S) +#define R_PPC_EMB_NADDR16_HI 104 // uhalf16 N #hi(A - S) +#define R_PPC_EMB_NADDR16_HA 105 // uhalf16 N #ha(A - S) +#define R_PPC_EMB_SDAI16 106 // uhalf16 Y T +#define R_PPC_EMB_SDA2I16 107 // uhalf16 Y U +#define R_PPC_EMB_SDA2REL 108 // uhalf16 Y S + A - _SDA2_BASE_ +#define R_PPC_EMB_SDA21 109 // ulow21 N +#define R_PPC_EMB_MRKREF 110 // none N +#define R_PPC_EMB_RELSEC16 111 // uhalf16 Y V + A +#define R_PPC_EMB_RELST_LO 112 // uhalf16 N #lo(W + A) +#define R_PPC_EMB_RELST_HI 113 // uhalf16 N #hi(W + A) +#define R_PPC_EMB_RELST_HA 114 // uhalf16 N #ha(W + A) +#define R_PPC_EMB_BIT_FLD 115 // uword32 Y +#define R_PPC_EMB_RELSDA 116 // uhalf16 Y + +OSModuleQueue __OSModuleInfoList : (OS_BASE_CACHED | 0x30C8); +const void *__OSStringTable : (OS_BASE_CACHED | 0x30D0); + +#pragma dont_inline on +__declspec(weak) void OSNotifyLink(void) { } + +__declspec(weak) void OSNotifyUnlink(void) { } + +#pragma dont_inline reset + +#define EnqueueTail(queue, moduleInfo, link) \ + do { \ + OSModuleInfo *__prev; \ + \ + __prev = (queue)->tail; \ + if (__prev == NULL) \ + (queue)->head = (moduleInfo); \ + else \ + __prev->link.next = (moduleInfo); \ + (moduleInfo)->link.prev = __prev; \ + (moduleInfo)->link.next = NULL; \ + (queue)->tail = (moduleInfo); \ + } while (0) + +#define DequeueItem(queue, moduleInfo, link) \ + do { \ + OSModuleInfo *__next; \ + OSModuleInfo *__prev; \ + \ + __next = (moduleInfo)->link.next; \ + __prev = (moduleInfo)->link.prev; \ + \ + if (__next == NULL) \ + (queue)->tail = __prev; \ + else \ + __next->link.prev = __prev; \ + \ + if (__prev == NULL) \ + (queue)->head = __next; \ + else \ + __prev->link.next = __next; \ + } while (0) + +void OSSetStringTable(const void *stringTable) +{ + __OSStringTable = stringTable; +} + +static BOOL Relocate(OSModuleHeader *newModule, OSModuleHeader *module) +{ + OSModuleID idNew; + OSImportInfo *imp; + OSRel *rel; + OSSectionInfo *si; + OSSectionInfo *siFlush; + u32 *p; + u32 offset; + u32 x; + + idNew = newModule ? newModule->info.id : 0; + for (imp = (OSImportInfo *)module->impOffset; imp < (OSImportInfo *)(module->impOffset + module->impSize); imp++) { + if (imp->id == idNew) { + goto Found; + } + } + return FALSE; + +Found: + siFlush = 0; + for (rel = (OSRel *)imp->offset; rel->type != R_DOLPHIN_END; rel++) { + (u8 *)p += rel->offset; + if (idNew) { + si = &OSGetSectionInfo(newModule)[rel->section]; + offset = OS_SECTIONINFO_OFFSET(si->offset); + } + else { + offset = 0; + } + switch (rel->type) { + case R_PPC_NONE: + break; + case R_PPC_ADDR32: + x = offset + rel->addend; + *p = x; + break; + case R_PPC_ADDR24: + x = offset + rel->addend; + *p = (*p & ~0x03fffffc) | (x & 0x03fffffc); + break; + case R_PPC_ADDR16: + x = offset + rel->addend; + *(u16 *)p = (u16)(x & 0xffff); + break; + case R_PPC_ADDR16_LO: + x = offset + rel->addend; + *(u16 *)p = (u16)(x & 0xffff); + break; + case R_PPC_ADDR16_HI: + x = offset + rel->addend; + *(u16 *)p = (u16)(((x >> 16) & 0xffff)); + break; + case R_PPC_ADDR16_HA: + x = offset + rel->addend; + *(u16 *)p = (u16)(((x >> 16) + ((x & 0x8000) ? 1 : 0)) & 0xffff); + break; + case R_PPC_REL24: + x = offset + rel->addend - (u32)p; + *p = (*p & ~0x03fffffc) | (x & 0x03fffffc); + break; + case R_DOLPHIN_NOP: + break; + case R_DOLPHIN_SECTION: + si = &OSGetSectionInfo(module)[rel->section]; + p = (u32 *)OS_SECTIONINFO_OFFSET(si->offset); + if (siFlush) { + offset = OS_SECTIONINFO_OFFSET(siFlush->offset); + DCFlushRange((void *)offset, siFlush->size); + ICInvalidateRange((void *)offset, siFlush->size); + } + siFlush = (si->offset & OS_SECTIONINFO_EXEC) ? si : 0; + break; + default: + OSReport("OSLink: unknown relocation type %3d\n", rel->type); + break; + } + } + + if (siFlush) { + offset = OS_SECTIONINFO_OFFSET(siFlush->offset); + DCFlushRange((void *)offset, siFlush->size); + ICInvalidateRange((void *)offset, siFlush->size); + } + + return TRUE; +} + +#if OS_MODULE_VERSION >= 3 +static BOOL Link(OSModuleInfo *newModule, void *bss, BOOL fixed) +{ + u32 i; + OSSectionInfo *si; + OSModuleHeader *moduleHeader; + OSModuleInfo *moduleInfo; + OSImportInfo *imp; + + moduleHeader = (OSModuleHeader *)newModule; + moduleHeader->bssSection = 0; + + if (OS_MODULE_VERSION < newModule->version + || 2 <= newModule->version + && (moduleHeader->align && (u32)newModule % moduleHeader->align != 0 + || moduleHeader->bssAlign && (u32)bss % moduleHeader->bssAlign != 0)) { + return FALSE; + } + + EnqueueTail(&__OSModuleInfoList, newModule, link); + newModule->sectionInfoOffset += (u32)moduleHeader; + moduleHeader->relOffset += (u32)moduleHeader; + moduleHeader->impOffset += (u32)moduleHeader; + if (3 <= newModule->version) { + moduleHeader->fixSize += (u32)moduleHeader; + } + for (i = 1; i < newModule->numSections; i++) { + si = &OSGetSectionInfo(newModule)[i]; + if (si->offset != 0) { + si->offset += (u32)moduleHeader; + } + else if (si->size != 0) { + moduleHeader->bssSection = (u8)i; + si->offset = (u32)bss; + bss = (void *)((u32)bss + si->size); + } + } + for (imp = (OSImportInfo *)moduleHeader->impOffset; imp < (OSImportInfo *)(moduleHeader->impOffset + moduleHeader->impSize); imp++) { + imp->offset += (u32)moduleHeader; + } + if (moduleHeader->prologSection != SHN_UNDEF) { + moduleHeader->prolog += OS_SECTIONINFO_OFFSET(OSGetSectionInfo(newModule)[moduleHeader->prologSection].offset); + } + if (moduleHeader->epilogSection != SHN_UNDEF) { + moduleHeader->epilog += OS_SECTIONINFO_OFFSET(OSGetSectionInfo(newModule)[moduleHeader->epilogSection].offset); + } + if (moduleHeader->unresolvedSection != SHN_UNDEF) { + moduleHeader->unresolved += OS_SECTIONINFO_OFFSET(OSGetSectionInfo(newModule)[moduleHeader->unresolvedSection].offset); + } + if (__OSStringTable) { + newModule->nameOffset += (u32)__OSStringTable; + } + + Relocate(0, moduleHeader); + + for (moduleInfo = __OSModuleInfoList.head; moduleInfo; moduleInfo = moduleInfo->link.next) { + Relocate(moduleHeader, (OSModuleHeader *)moduleInfo); + if (moduleInfo != newModule) { + Relocate((OSModuleHeader *)moduleInfo, moduleHeader); + } + } + + if (fixed) { + for (imp = (OSImportInfo *)moduleHeader->impOffset; imp < (OSImportInfo *)(moduleHeader->impOffset + moduleHeader->impSize); imp++) { + if (imp->id == 0 || imp->id == newModule->id) { + moduleHeader->impSize = (u32)((u8 *)imp - (u8 *)moduleHeader->impOffset); + break; + } + } + } + + memset(bss, 0, moduleHeader->bssSize); + + OSNotifyLink(newModule); + + return TRUE; +} + +BOOL OSLink(OSModuleInfo *newModule, void *bss) +{ + return Link(newModule, bss, FALSE); +} + +BOOL OSLinkFixed(OSModuleInfo *newModule, void *bss) +{ + if (OS_MODULE_VERSION < newModule->version || newModule->version < 3) { + return FALSE; + } + return Link(newModule, bss, TRUE); +} +#else +BOOL OSLink(OSModuleInfo *newModule, void *bss) +{ + u32 i; + OSSectionInfo *si; + OSModuleHeader *moduleHeader; + OSModuleInfo *moduleInfo; + OSImportInfo *imp; + + moduleHeader = (OSModuleHeader *)newModule; + + if (OS_MODULE_VERSION < newModule->version + || 2 <= newModule->version + && (moduleHeader->align && (u32)newModule % moduleHeader->align != 0 + || moduleHeader->bssAlign && (u32)bss % moduleHeader->bssAlign != 0)) { + return FALSE; + } + + EnqueueTail(&__OSModuleInfoList, newModule, link); + memset(bss, 0, moduleHeader->bssSize); + newModule->sectionInfoOffset += (u32)moduleHeader; + moduleHeader->relOffset += (u32)moduleHeader; + moduleHeader->impOffset += (u32)moduleHeader; + + for (i = 0; i < newModule->numSections; i++) { + si = &OSGetSectionInfo(newModule)[i]; + if (si->offset != 0) { + si->offset += (u32)moduleHeader; + } + else if (si->size != 0) { + si->offset = (u32)bss; + bss = (void *)((u32)bss + si->size); + } + } + for (imp = (OSImportInfo *)moduleHeader->impOffset; imp < (OSImportInfo *)(moduleHeader->impOffset + moduleHeader->impSize); imp++) { + imp->offset += (u32)moduleHeader; + } + if (moduleHeader->prologSection != SHN_UNDEF) { + moduleHeader->prolog += OS_SECTIONINFO_OFFSET(OSGetSectionInfo(newModule)[moduleHeader->prologSection].offset); + } + if (moduleHeader->epilogSection != SHN_UNDEF) { + moduleHeader->epilog += OS_SECTIONINFO_OFFSET(OSGetSectionInfo(newModule)[moduleHeader->epilogSection].offset); + } + if (moduleHeader->unresolvedSection != SHN_UNDEF) { + moduleHeader->unresolved += OS_SECTIONINFO_OFFSET(OSGetSectionInfo(newModule)[moduleHeader->unresolvedSection].offset); + } + if (__OSStringTable) { + newModule->nameOffset += (u32)__OSStringTable; + } + + Relocate(0, moduleHeader); + + for (moduleInfo = __OSModuleInfoList.head; moduleInfo; moduleInfo = moduleInfo->link.next) { + Relocate(moduleHeader, (OSModuleHeader *)moduleInfo); + if (moduleInfo != newModule) { + Relocate((OSModuleHeader *)moduleInfo, moduleHeader); + } + } + + OSNotifyLink(); + + return TRUE; +} +#endif + +static BOOL Undo(OSModuleHeader *newModule, OSModuleHeader *module) +{ + OSModuleID idNew; + OSImportInfo *imp; + OSRel *rel; + OSSectionInfo *si; + OSSectionInfo *siFlush; + u32 *p; + u32 offset; + u32 x; + + idNew = newModule->info.id; + + for (imp = (OSImportInfo *)module->impOffset; imp < (OSImportInfo *)(module->impOffset + module->impSize); imp++) { + if (imp->id == idNew) { + goto Found; + } + } + return FALSE; + +Found: + siFlush = 0; + for (rel = (OSRel *)imp->offset; rel->type != R_DOLPHIN_END; rel++) { + (u8 *)p += rel->offset; + si = &OSGetSectionInfo(newModule)[rel->section]; + offset = OS_SECTIONINFO_OFFSET(si->offset); + x = 0; + switch (rel->type) { + case R_PPC_NONE: + break; + case R_PPC_ADDR32: + *p = x; + break; + case R_PPC_ADDR24: + *p = (*p & ~0x03fffffc) | (x & 0x03fffffc); + break; + case R_PPC_ADDR16: + *(u16 *)p = (u16)(x & 0xffff); + break; + case R_PPC_ADDR16_LO: + *(u16 *)p = (u16)(x & 0xffff); + break; + case R_PPC_ADDR16_HI: + *(u16 *)p = (u16)(((x >> 16) & 0xffff)); + break; + case R_PPC_ADDR16_HA: + *(u16 *)p = (u16)(((x >> 16) + ((x & 0x8000) ? 1 : 0)) & 0xffff); + break; + case R_PPC_REL24: + if (module->unresolvedSection != SHN_UNDEF) { + x = (u32)module->unresolved - (u32)p; + } + *p = (*p & ~0x03fffffc) | (x & 0x03fffffc); + break; + case R_DOLPHIN_NOP: + break; + case R_DOLPHIN_SECTION: + si = &OSGetSectionInfo(module)[rel->section]; + p = (u32 *)OS_SECTIONINFO_OFFSET(si->offset); + if (siFlush) { + offset = OS_SECTIONINFO_OFFSET(siFlush->offset); + DCFlushRange((void *)offset, siFlush->size); + ICInvalidateRange((void *)offset, siFlush->size); + } + siFlush = (si->offset & OS_SECTIONINFO_EXEC) ? si : 0; + break; + default: + OSReport("OSUnlink: unknown relocation type %3d\n", rel->type); + break; + } + } + + if (siFlush) { + offset = OS_SECTIONINFO_OFFSET(siFlush->offset); + DCFlushRange((void *)offset, siFlush->size); + ICInvalidateRange((void *)offset, siFlush->size); + } + + return TRUE; +} + +BOOL OSUnlink(OSModuleInfo *oldModule) +{ + OSModuleHeader *moduleHeader; + OSModuleInfo *moduleInfo; + + moduleHeader = (OSModuleHeader *)oldModule; + + DequeueItem(&__OSModuleInfoList, oldModule, link); + + for (moduleInfo = __OSModuleInfoList.head; moduleInfo; moduleInfo = moduleInfo->link.next) { + Undo(moduleHeader, (OSModuleHeader *)moduleInfo); + } + + OSNotifyUnlink(); + + return TRUE; +} + +void __OSModuleInit(void) +{ + __OSModuleInfoList.head = __OSModuleInfoList.tail = 0; + __OSStringTable = 0; +} + +OSModuleInfo *OSSearchModule(void *ptr, u32 *section, u32 *offset) +{ + OSModuleInfo *moduleInfo; + OSSectionInfo *sectionInfo; + u32 i; + u32 baseSection; + + if (ptr == NULL) { + return NULL; + } + + for (moduleInfo = __OSModuleInfoList.head; moduleInfo; moduleInfo = moduleInfo->link.next) { + sectionInfo = OSGetSectionInfo(moduleInfo); + for (i = 0; i < moduleInfo->numSections; ++i) { + if (sectionInfo->size) { + baseSection = OS_SECTIONINFO_OFFSET(sectionInfo->offset); + if (baseSection <= (u32)ptr && (u32)ptr < baseSection + sectionInfo->size) { + if (section) { + *section = i; + } + if (offset) { + *offset = (u32)ptr - baseSection; + } + return moduleInfo; + } + } + sectionInfo++; + } + } + + return NULL; +} diff --git a/src/dolphin/os/OSMemory.c b/src/dolphin/os/OSMemory.c new file mode 100644 index 00000000..7cfda15a --- /dev/null +++ b/src/dolphin/os/OSMemory.c @@ -0,0 +1,230 @@ +#include +#include + +#define TRUNC(n, a) (((u32)(n)) & ~((a)-1)) +#define ROUND(n, a) (((u32)(n) + (a)-1) & ~((a)-1)) + +extern OSErrorHandler __OSErrorTable[16]; + +static BOOL OnReset(BOOL final); + +static OSResetFunctionInfo ResetFunctionInfo = { + OnReset, + 127, +}; +u32 OSGetPhysicalMemSize() +{ + return *(u32 *)(OSPhysicalToCached(0x0028)); +} + +u32 OSGetConsoleSimulatedMemSize() +{ + return *(u32 *)(OSPhysicalToCached(0x00F0)); +} + +static BOOL OnReset(BOOL final) +{ + if (final != FALSE) { + __MEMRegs[8] = 0xFF; + __OSMaskInterrupts(0xf0000000); + } + return TRUE; +} + +static void MEMIntrruptHandler(__OSInterrupt interrupt, OSContext *context) +{ + u32 addr; + u32 cause; + + cause = __MEMRegs[0xf]; + addr = (((u32)__MEMRegs[0x12] & 0x3ff) << 16) | __MEMRegs[0x11]; + __MEMRegs[0x10] = 0; + + if (__OSErrorTable[OS_ERROR_PROTECTION]) { + __OSErrorTable[OS_ERROR_PROTECTION](OS_ERROR_PROTECTION, context, cause, addr); + return; + } + + __OSUnhandledException(OS_ERROR_PROTECTION, context, cause, addr); +} + +void OSProtectRange(u32 chan, void *addr, u32 nBytes, u32 control) +{ + BOOL enabled; + u32 start; + u32 end; + u16 reg; + if (4 <= chan) { + return; + } + + control &= OS_PROTECT_CONTROL_RDWR; + + end = (u32)addr + nBytes; + start = TRUNC(addr, 1u << 10); + end = ROUND(end, 1u << 10); + + DCFlushRange((void *)start, end - start); + + enabled = OSDisableInterrupts(); + + __OSMaskInterrupts(OS_INTERRUPTMASK(__OS_INTERRUPT_MEM_0 + chan)); + + __MEMRegs[0 + 2 * chan] = (u16)(start >> 10); + __MEMRegs[1 + 2 * chan] = (u16)(end >> 10); + + reg = __MEMRegs[8]; + reg &= ~(OS_PROTECT_CONTROL_RDWR << 2 * chan); + reg |= control << 2 * chan; + __MEMRegs[8] = reg; + + if (control != OS_PROTECT_CONTROL_RDWR) { + __OSUnmaskInterrupts(OS_INTERRUPTMASK(__OS_INTERRUPT_MEM_0 + chan)); + } + + OSRestoreInterrupts(enabled); +} + +asm void Config24MB() +{ + // clang-format off + nofralloc + + addi r7,r0,0 + + addis r4,r0,0x00000002@ha + addi r4,r4,0x00000002@l + addis r3,r0,0x800001ff@ha + addi r3,r3,0x800001ff@l + + addis r6,r0,0x01000002@ha + addi r6,r6,0x01000002@l + addis r5,r0,0x810000ff@ha + addi r5,r5,0x810000ff@l + + isync + + mtspr dbat0u,r7 + mtspr dbat0l,r4 + mtspr dbat0u,r3 + isync + + mtspr ibat0u,r7 + mtspr ibat0l,r4 + mtspr ibat0u,r3 + isync + + mtspr dbat2u,r7 + mtspr dbat2l,r6 + mtspr dbat2u,r5 + isync + + mtspr ibat2u,r7 + mtspr ibat2l,r6 + mtspr ibat2u,r5 + isync + + mfmsr r3 + ori r3, r3, 0x30 + mtsrr1 r3 + + mflr r3 + mtsrr0 r3 + rfi + // clang-format on +} + +asm void Config48MB() +{ + // clang-format off + nofralloc + + addi r7,r0,0x0000 + + addis r4,r0,0x00000002@ha + addi r4,r4,0x00000002@l + addis r3,r0,0x800003ff@ha + addi r3,r3,0x800003ff@l + + addis r6,r0,0x02000002@ha + addi r6,r6,0x02000002@l + addis r5,r0,0x820001ff@ha + addi r5,r5,0x820001ff@l + + isync + + mtspr dbat0u,r7 + mtspr dbat0l,r4 + mtspr dbat0u,r3 + isync + + mtspr ibat0u,r7 + mtspr ibat0l,r4 + mtspr ibat0u,r3 + isync + + mtspr dbat2u,r7 + mtspr dbat2l,r6 + mtspr dbat2u,r5 + isync + + mtspr ibat2u,r7 + mtspr ibat2l,r6 + mtspr ibat2u,r5 + isync + + mfmsr r3 + ori r3, r3, 0x30 + mtsrr1 r3 + + mflr r3 + mtsrr0 r3 + rfi + // clang-format on +} + +asm void RealMode(register u32 addr) +{ + // clang-format off + nofralloc + clrlwi r3, r3, 2 + mtsrr0 r3 + mfmsr r3 + rlwinm r3, r3, 0, 28, 25 + mtsrr1 r3 + rfi + // clang-format on +} + +void __OSInitMemoryProtection() +{ + u32 padding[8]; + u32 simulatedSize; + BOOL enabled; + simulatedSize = OSGetConsoleSimulatedMemSize(); + enabled = OSDisableInterrupts(); + if (simulatedSize <= 0x1800000) { + RealMode((u32)&Config24MB); + } + else if (simulatedSize <= 0x3000000) { + RealMode((u32)&Config48MB); + } + + __MEMRegs[16] = 0; + __MEMRegs[8] = 0xFF; + + __OSMaskInterrupts(OS_INTERRUPTMASK_MEM_0 | OS_INTERRUPTMASK_MEM_1 | OS_INTERRUPTMASK_MEM_2 | OS_INTERRUPTMASK_MEM_3); + __OSSetInterruptHandler(__OS_INTERRUPT_MEM_0, MEMIntrruptHandler); + __OSSetInterruptHandler(__OS_INTERRUPT_MEM_1, MEMIntrruptHandler); + __OSSetInterruptHandler(__OS_INTERRUPT_MEM_2, MEMIntrruptHandler); + __OSSetInterruptHandler(__OS_INTERRUPT_MEM_3, MEMIntrruptHandler); + __OSSetInterruptHandler(__OS_INTERRUPT_MEM_ADDRESS, MEMIntrruptHandler); + OSRegisterResetFunction(&ResetFunctionInfo); + + if (OSGetConsoleSimulatedMemSize() < OSGetPhysicalMemSize() && OSGetConsoleSimulatedMemSize() == 0x1800000) { + __MEMRegs[20] = 2; + } + + __OSUnmaskInterrupts(OS_INTERRUPTMASK_MEM_ADDRESS); + OSRestoreInterrupts(enabled); +} diff --git a/src/dolphin/os/OSMessage.c b/src/dolphin/os/OSMessage.c new file mode 100644 index 00000000..0d364af2 --- /dev/null +++ b/src/dolphin/os/OSMessage.c @@ -0,0 +1,91 @@ +#include + +void OSInitMessageQueue(OSMessageQueue *mq, OSMessage *msgArray, s32 msgCount) +{ + OSInitThreadQueue(&mq->queueSend); + OSInitThreadQueue(&mq->queueReceive); + mq->msgArray = msgArray; + mq->msgCount = msgCount; + mq->firstIndex = 0; + mq->usedCount = 0; +} +BOOL OSSendMessage(OSMessageQueue *mq, OSMessage msg, s32 flags) +{ + BOOL enabled; + s32 lastIndex; + + enabled = OSDisableInterrupts(); + + while (mq->msgCount <= mq->usedCount) { + if (!(flags & OS_MESSAGE_BLOCK)) { + OSRestoreInterrupts(enabled); + return FALSE; + } + else { + OSSleepThread(&mq->queueSend); + } + } + + lastIndex = (mq->firstIndex + mq->usedCount) % mq->msgCount; + mq->msgArray[lastIndex] = msg; + mq->usedCount++; + + OSWakeupThread(&mq->queueReceive); + + OSRestoreInterrupts(enabled); + return TRUE; +} + +BOOL OSReceiveMessage(OSMessageQueue *mq, OSMessage *msg, s32 flags) +{ + BOOL enabled; + + enabled = OSDisableInterrupts(); + + while (mq->usedCount == 0) { + if (!(flags & OS_MESSAGE_BLOCK)) { + OSRestoreInterrupts(enabled); + return FALSE; + } + else { + OSSleepThread(&mq->queueReceive); + } + } + + if (msg != NULL) { + *msg = mq->msgArray[mq->firstIndex]; + } + mq->firstIndex = (mq->firstIndex + 1) % mq->msgCount; + mq->usedCount--; + + OSWakeupThread(&mq->queueSend); + + OSRestoreInterrupts(enabled); + return TRUE; +} + +BOOL OSJamMessage(OSMessageQueue *mq, OSMessage msg, s32 flags) +{ + BOOL enabled; + + enabled = OSDisableInterrupts(); + + while (mq->msgCount <= mq->usedCount) { + if (!(flags & OS_MESSAGE_BLOCK)) { + OSRestoreInterrupts(enabled); + return FALSE; + } + else { + OSSleepThread(&mq->queueSend); + } + } + + mq->firstIndex = (mq->firstIndex + mq->msgCount - 1) % mq->msgCount; + mq->msgArray[mq->firstIndex] = msg; + mq->usedCount++; + + OSWakeupThread(&mq->queueReceive); + + OSRestoreInterrupts(enabled); + return TRUE; +} diff --git a/src/dolphin/os/OSMutex.c b/src/dolphin/os/OSMutex.c new file mode 100644 index 00000000..986b81e0 --- /dev/null +++ b/src/dolphin/os/OSMutex.c @@ -0,0 +1,244 @@ +#include "dolphin/os.h" + +#define PushTail(queue, mutex, link) \ + do { \ + OSMutex *__prev; \ + \ + __prev = (queue)->tail; \ + if (__prev == NULL) \ + (queue)->head = (mutex); \ + else \ + __prev->link.next = (mutex); \ + (mutex)->link.prev = __prev; \ + (mutex)->link.next = NULL; \ + (queue)->tail = (mutex); \ + } while (0) + +#define PopHead(queue, mutex, link) \ + do { \ + OSMutex *__next; \ + \ + (mutex) = (queue)->head; \ + __next = (mutex)->link.next; \ + if (__next == NULL) \ + (queue)->tail = NULL; \ + else \ + __next->link.prev = NULL; \ + (queue)->head = __next; \ + } while (0) + +#define PopItem(queue, mutex, link) \ + do { \ + OSMutex *__next; \ + OSMutex *__prev; \ + \ + __next = (mutex)->link.next; \ + __prev = (mutex)->link.prev; \ + \ + if (__next == NULL) \ + (queue)->tail = __prev; \ + else \ + __next->link.prev = __prev; \ + \ + if (__prev == NULL) \ + (queue)->head = __next; \ + else \ + __prev->link.next = __next; \ + } while (0) + +void OSInitMutex(OSMutex *mutex) +{ + OSInitThreadQueue(&mutex->queue); + mutex->thread = 0; + mutex->count = 0; +} + +void OSLockMutex(OSMutex *mutex) +{ + BOOL enabled = OSDisableInterrupts(); + OSThread *currentThread = OSGetCurrentThread(); + OSThread *ownerThread; + + while (TRUE) { + ownerThread = ((OSMutex *)mutex)->thread; + if (ownerThread == 0) { + mutex->thread = currentThread; + mutex->count++; + PushTail(¤tThread->queueMutex, mutex, link); + break; + } + else if (ownerThread == currentThread) { + mutex->count++; + break; + } + else { + currentThread->mutex = mutex; + __OSPromoteThread(mutex->thread, currentThread->priority); + OSSleepThread(&mutex->queue); + currentThread->mutex = 0; + } + } + OSRestoreInterrupts(enabled); +} + +void OSUnlockMutex(OSMutex *mutex) +{ + BOOL enabled = OSDisableInterrupts(); + OSThread *currentThread = OSGetCurrentThread(); + + if (mutex->thread == currentThread && --mutex->count == 0) { + PopItem(¤tThread->queueMutex, mutex, link); + mutex->thread = NULL; + if (currentThread->priority < currentThread->base) { + currentThread->priority = __OSGetEffectivePriority(currentThread); + } + + OSWakeupThread(&mutex->queue); + } + OSRestoreInterrupts(enabled); +} + +void __OSUnlockAllMutex(OSThread *thread) +{ + OSMutex *mutex; + + while (thread->queueMutex.head) { + PopHead(&thread->queueMutex, mutex, link); + mutex->count = 0; + mutex->thread = NULL; + OSWakeupThread(&mutex->queue); + } +} + +BOOL OSTryLockMutex(OSMutex *mutex) +{ + BOOL enabled = OSDisableInterrupts(); + OSThread *currentThread = OSGetCurrentThread(); + BOOL locked; + if (mutex->thread == 0) { + mutex->thread = currentThread; + mutex->count++; + PushTail(¤tThread->queueMutex, mutex, link); + locked = TRUE; + } + else if (mutex->thread == currentThread) { + mutex->count++; + locked = TRUE; + } + else { + locked = FALSE; + } + OSRestoreInterrupts(enabled); + return locked; +} + +void OSInitCond(OSCond *cond) +{ + OSInitThreadQueue(&cond->queue); +} + +void OSWaitCond(OSCond *cond, OSMutex *mutex) +{ + BOOL enabled = OSDisableInterrupts(); + OSThread *currentThread = OSGetCurrentThread(); + s32 count; + + if (mutex->thread == currentThread) { + count = mutex->count; + mutex->count = 0; + PopItem(¤tThread->queueMutex, mutex, link); + mutex->thread = NULL; + + if (currentThread->priority < currentThread->base) { + currentThread->priority = __OSGetEffectivePriority(currentThread); + } + + OSDisableScheduler(); + OSWakeupThread(&mutex->queue); + OSEnableScheduler(); + OSSleepThread(&cond->queue); + OSLockMutex(mutex); + mutex->count = count; + } + + OSRestoreInterrupts(enabled); +} + +void OSSignalCond(OSCond *cond) +{ + OSWakeupThread(&cond->queue); +} + +static BOOL IsMember(OSMutexQueue *queue, OSMutex *mutex) +{ + OSMutex *member; + + for (member = queue->head; member; member = member->link.next) { + if (mutex == member) + return TRUE; + } + return FALSE; +} + +BOOL __OSCheckMutex(OSMutex *mutex) +{ + OSThread *thread; + OSThreadQueue *queue; + OSPriority priority = 0; + + queue = &mutex->queue; + if (!(queue->head == NULL || queue->head->link.prev == NULL)) + return FALSE; + if (!(queue->tail == NULL || queue->tail->link.next == NULL)) + return FALSE; + for (thread = queue->head; thread; thread = thread->link.next) { + if (!(thread->link.next == NULL || thread == thread->link.next->link.prev)) + return FALSE; + if (!(thread->link.prev == NULL || thread == thread->link.prev->link.next)) + return FALSE; + + if (thread->state != OS_THREAD_STATE_WAITING) + return FALSE; + + if (thread->priority < priority) + return FALSE; + priority = thread->priority; + } + + if (mutex->thread) { + if (mutex->count <= 0) + return FALSE; + } + else { + if (0 != mutex->count) + return FALSE; + } + + return TRUE; +} + +BOOL __OSCheckDeadLock(OSThread *thread) +{ + OSMutex *mutex; + + mutex = thread->mutex; + while (mutex && mutex->thread) { + if (mutex->thread == thread) + return TRUE; + mutex = mutex->thread->mutex; + } + return FALSE; +} + +BOOL __OSCheckMutexes(OSThread *thread) +{ + OSMutex *mutex; + + for (mutex = thread->queueMutex.head; mutex; mutex = mutex->link.next) { + if (mutex->thread != thread) + return FALSE; + if (!__OSCheckMutex(mutex)) + return FALSE; + } + return TRUE; +} diff --git a/src/dolphin/os/OSReboot.c b/src/dolphin/os/OSReboot.c new file mode 100644 index 00000000..381d39c4 --- /dev/null +++ b/src/dolphin/os/OSReboot.c @@ -0,0 +1,94 @@ +#include +#include +#include +#include +#include + +typedef struct ApploaderHeader { + // total size: 0x20 + char date[16]; // offset 0x0, size 0x10 + u32 entry; // offset 0x10, size 0x4 + u32 size; // offset 0x14, size 0x4 + u32 rebootSize; // offset 0x18, size 0x4 + u32 reserved2; // offset 0x1C, size 0x4 +} ApploaderHeader; + +struct { + // total size: 0x1C + int valid; // offset 0x0, size 0x4 + unsigned long restartCode; // offset 0x4, size 0x4 + unsigned long bootDol; // offset 0x8, size 0x4 + void *regionStart; // offset 0xC, size 0x4 + void *regionEnd; // offset 0x10, size 0x4 + int argsUseDefault; // offset 0x14, size 0x4 + void *argsAddr; // offset 0x18, size 0x4 +} __OSRebootParams; // size: 0x1C, address: 0x0 + +static ApploaderHeader Header; + +extern void *__OSSavedRegionStart; +extern void *__OSSavedRegionEnd; + +static void *SaveStart = NULL; +static void *SaveEnd = NULL; + +volatile u8 DAT_800030e2 : 0x800030e2; + +extern u32 BOOT_REGION_START AT_ADDRESS(0x812FDFF0); //(*(u32 *)0x812fdff0) +extern u32 BOOT_REGION_END AT_ADDRESS(0x812FDFEC); //(*(u32 *)0x812fdfec) +extern u32 UNK_HOT_RESET1 AT_ADDRESS(0x817ffff8); +extern u32 UNK_HOT_RESET2 AT_ADDRESS(0x817ffffc); +// extern u32 OS_RESET_CODE AT_ADDRESS(0x800030F0); +// extern u8 OS_REBOOT_BOOL AT_ADDRESS(0x800030E2); // unknown function, set to true by __OSReboot + +extern u32 __OSIsGcam; + +static BOOL Prepared = FALSE; + +extern void __DVDPrepareResetAsync(DVDCBCallback callback); +extern BOOL DVDCheckDisk(void); +extern BOOL DVDReadAbsAsyncForBS(DVDCommandBlock *block, void *addr, s32 length, s32 offset, DVDCBCallback callback); + +void Run(register u32 addr) +{ + OSDisableInterrupts(); + ICFlashInvalidate(); + // clang-format off + asm { + sync + isync + mtlr addr + blr + } + // clang-format on +} + +static void Callback() +{ + Prepared = TRUE; +} + +void ReadApploader(OSTime time1) { } + +void __OSReboot(u32 resetCode, u32 bootDol) +{ + // TODO +} + +void OSSetSaveRegion(void *start, void *end) +{ + SaveStart = start; + SaveEnd = end; +} + +void OSGetSaveRegion(void **start, void **end) +{ + *start = SaveStart; + *end = SaveEnd; +} + +void OSGetSavedRegion(void **start, void **end) +{ + *start = __OSSavedRegionStart; + *end = __OSSavedRegionEnd; +} diff --git a/src/dolphin/os/OSReset.c b/src/dolphin/os/OSReset.c new file mode 100644 index 00000000..c4ee2c9b --- /dev/null +++ b/src/dolphin/os/OSReset.c @@ -0,0 +1,203 @@ +#include +#include +#include +#include +#include + +#include "string.h" + +volatile u8 DAT_800030e2 : 0x800030e2; +typedef struct Unk { + u8 pad[0x24]; + u32 resetCode; +} Unk; +volatile Unk DAT_cc003000 : 0xcc003000; + +typedef struct Unk2 { + u16 _0; + u16 _2; +} Unk2; + +volatile Unk2 DAT_cc002000 : 0xcc002000; + +typedef struct OSResetQueue { + OSResetFunctionInfo *first; + OSResetFunctionInfo *last; +} OSResetQueue; + +OSResetQueue ResetFunctionQueue; + +void OSRegisterResetFunction(OSResetFunctionInfo *func) +{ + OSResetFunctionInfo *tmp; + OSResetFunctionInfo *iter; + + for (iter = ResetFunctionQueue.first; iter && iter->priority <= func->priority; iter = iter->next) + ; + + if (iter == NULL) { + tmp = ResetFunctionQueue.last; + if (tmp == NULL) { + ResetFunctionQueue.first = func; + } + else { + tmp->next = func; + } + func->prev = tmp; + func->next = NULL; + ResetFunctionQueue.last = func; + return; + } + + func->next = iter; + tmp = iter->prev; + iter->prev = func; + func->prev = tmp; + if (tmp == NULL) { + ResetFunctionQueue.first = func; + return; + } + tmp->next = func; +} + +BOOL __OSCallResetFunctions(u32 arg0) +{ + OSResetFunctionInfo *iter; + s32 retCode = 0; + + for (iter = ResetFunctionQueue.first; iter != NULL; iter = iter->next) { + retCode |= !iter->func(arg0); + } + retCode |= !__OSSyncSram(); + if (retCode) { + return 0; + } + return 1; +} + +asm void Reset(register s32 resetCode) +{ + // clang-format off + nofralloc + b lbl_8038315C +lbl_80383140: + mfspr r8, HID0 + ori r8, r8, 8 + mtspr HID0, r8 + isync + sync + nop + b lbl_80383160 +lbl_8038315C: + b lbl_8038317C +lbl_80383160: + mftb r5, 268 +lbl_80383164: + mftb r6, 268 + subf r7, r5, r6 + cmplwi r7, 0x1124 + blt lbl_80383164 + nop + b lbl_80383180 +lbl_8038317C: + b lbl_8038319C +lbl_80383180: + lis r8, 0xCC003000@h + ori r8, r8, 0xCC003000@l + li r4, 3 + stw r4, 0x24(r8) + stw r3, 0x24(r8) + nop + b lbl_803831A0 +lbl_8038319C: + b lbl_803831A8 +lbl_803831A0: + nop + b lbl_803831A0 +lbl_803831A8: + b lbl_80383140 + // clang-format on +} + +OSThreadQueue __OSActiveThreadQueue : (OS_BASE_CACHED | 0x00DC); + +static void KillThreads(void) +{ + OSThread *thread; + OSThread *next; + + for (thread = __OSActiveThreadQueue.head; thread; thread = next) { + next = thread->linkActive.next; + switch (thread->state) { + case 1: + case 4: + OSCancelThread(thread); + break; + default: + break; + } + } +} + +void __OSDoHotReset(s32 arg0) +{ + OSDisableInterrupts(); + __VIRegs[1] = 0; + ICFlashInvalidate(); + Reset(arg0 * 8); +} + +void OSResetSystem(int reset, u32 resetCode, BOOL forceMenu) +{ + BOOL rc; + BOOL disableRecalibration; + u32 unk[3]; + OSDisableScheduler(); + __OSStopAudioSystem(); + + if (reset == OS_RESET_SHUTDOWN) { + disableRecalibration = __PADDisableRecalibration(TRUE); + } + + while (!__OSCallResetFunctions(FALSE)) + ; + + if (reset == OS_RESET_HOTRESET && forceMenu) { + OSSram *sram; + + sram = __OSLockSram(); + sram->flags |= 0x40; + __OSUnlockSram(TRUE); + + while (!__OSSyncSram()) + ; + } + OSDisableInterrupts(); + __OSCallResetFunctions(TRUE); + LCDisable(); + if (reset == OS_RESET_HOTRESET) { + __OSDoHotReset(resetCode); + } + else if (reset == OS_RESET_RESTART) { + KillThreads(); + OSEnableScheduler(); + __OSReboot(resetCode, forceMenu); + } + KillThreads(); + memset(OSPhysicalToCached(0x40), 0, 0xcc - 0x40); + memset(OSPhysicalToCached(0xd4), 0, 0xe8 - 0xd4); + memset(OSPhysicalToCached(0xf4), 0, 0xf8 - 0xf4); + memset(OSPhysicalToCached(0x3000), 0, 0xc0); + memset(OSPhysicalToCached(0x30c8), 0, 0xd4 - 0xc8); + memset(OSPhysicalToCached(0x30e2), 0, 1); + + __PADDisableRecalibration(disableRecalibration); +} + +u32 OSGetResetCode(void) +{ + if (DAT_800030e2 != 0) { + return 0x80000000; + } + return ((DAT_cc003000.resetCode & ~7) >> 3); +} diff --git a/src/dolphin/os/OSResetSW.c b/src/dolphin/os/OSResetSW.c new file mode 100644 index 00000000..59e70494 --- /dev/null +++ b/src/dolphin/os/OSResetSW.c @@ -0,0 +1,89 @@ +#include + +extern OSTime __OSGetSystemTime(); + +u8 GameChoice : (OS_BASE_CACHED | 0x30E3); + +vu32 __PIRegs[12] : 0xCC003000; + +extern OSTime __OSStartTime; + +static OSResetCallback ResetCallback; +static BOOL Down; +static BOOL LastState; +static OSTime HoldUp; +static OSTime HoldDown; + +void __OSResetSWInterruptHandler(__OSInterrupt interrupt, OSContext* context) { + OSResetCallback callback; + + HoldDown = __OSGetSystemTime(); + while (__OSGetSystemTime() - HoldDown < OSMicrosecondsToTicks(100) && + !(__PIRegs[0] & 0x00010000)) { + ; + } + if (!(__PIRegs[0] & 0x00010000)) { + LastState = Down = TRUE; + __OSMaskInterrupts(OS_INTERRUPTMASK_PI_RSW); + if (ResetCallback) { + callback = ResetCallback; + ResetCallback = NULL; + callback(); + } + } + __PIRegs[0] = 2; +} + +BOOL OSGetResetButtonState(void) { + BOOL enabled; + BOOL state; + u32 reg; + OSTime now; + + enabled = OSDisableInterrupts(); + + now = __OSGetSystemTime(); + + reg = __PIRegs[0]; + if (!(reg & 0x00010000)) { + if (!Down) { + Down = TRUE; + state = HoldUp ? TRUE : FALSE; + HoldDown = now; + } else { + state = (HoldUp || (OSMicrosecondsToTicks(100) < now - HoldDown)) ? TRUE : FALSE; + } + } else if (Down) { + Down = FALSE; + state = LastState; + if (state) { + HoldUp = now; + } else { + HoldUp = 0; + } + } else if (HoldUp && (now - HoldUp < OSMillisecondsToTicks(40))) { + state = TRUE; + } else { + state = FALSE; + HoldUp = 0; + } + + LastState = state; + + if (GameChoice & 0x3f) { + OSTime fire = (GameChoice & 0x3f) * 60; + fire = __OSStartTime + OSSecondsToTicks(fire); + if (fire < now) { + now -= fire; + now = OSTicksToSeconds(now) / 2; + if ((now & 1) == 0) { + state = TRUE; + } else { + state = FALSE; + } + } + } + + OSRestoreInterrupts(enabled); + return state; +} diff --git a/src/dolphin/os/OSRtc.c b/src/dolphin/os/OSRtc.c new file mode 100644 index 00000000..e3d2da41 --- /dev/null +++ b/src/dolphin/os/OSRtc.c @@ -0,0 +1,363 @@ +#include +#include +#include + +#define RTC_CMD_READ 0x20000000 +#define RTC_CMD_WRITE 0xa0000000 + +#define RTC_SRAM_ADDR 0x00000100 +#define RTC_SRAM_SIZE 64 + +#define RTC_CHAN 0 +#define RTC_DEV 1 +#define RTC_FREQ 3 // EXI_FREQ_8M + +typedef struct SramControlBlock { + u8 sram[RTC_SRAM_SIZE]; + u32 offset; + BOOL enabled; + BOOL locked; + BOOL sync; + void (*callback)(void); +} SramControlBlock; + +static SramControlBlock Scb ATTRIBUTE_ALIGN(32); + +static BOOL GetRTC(u32 *rtc) +{ + BOOL err; + u32 cmd; + + if (!EXILock(RTC_CHAN, RTC_DEV, 0)) { + return FALSE; + } + if (!EXISelect(RTC_CHAN, RTC_DEV, RTC_FREQ)) { + EXIUnlock(RTC_CHAN); + return FALSE; + } + + cmd = RTC_CMD_READ; + err = FALSE; + err |= !EXIImm(RTC_CHAN, &cmd, 4, 1, NULL); + err |= !EXISync(RTC_CHAN); + err |= !EXIImm(RTC_CHAN, &cmd, 4, 0, NULL); + err |= !EXISync(RTC_CHAN); + err |= !EXIDeselect(RTC_CHAN); + EXIUnlock(RTC_CHAN); + + *rtc = cmd; + + return !err; +} + +BOOL __OSGetRTC(u32 *rtc) +{ + BOOL err; + u32 t0; + u32 t1; + int i; + + for (i = 0; i < 16; i++) { + err = FALSE; + err |= !GetRTC(&t0); + err |= !GetRTC(&t1); + if (err) { + break; + } + if (t0 == t1) { + *rtc = t0; + return TRUE; + } + } + return FALSE; +} + +BOOL __OSSetRTC(u32 rtc) +{ + BOOL err; + u32 cmd; + + if (!EXILock(RTC_CHAN, RTC_DEV, 0)) { + return FALSE; + } + if (!EXISelect(RTC_CHAN, RTC_DEV, RTC_FREQ)) { + EXIUnlock(RTC_CHAN); + return FALSE; + } + + cmd = RTC_CMD_WRITE; + err = FALSE; + err |= !EXIImm(RTC_CHAN, &cmd, 4, 1, NULL); + err |= !EXISync(RTC_CHAN); + err |= !EXIImm(RTC_CHAN, &rtc, 4, 1, NULL); + err |= !EXISync(RTC_CHAN); + err |= !EXIDeselect(RTC_CHAN); + EXIUnlock(RTC_CHAN); + + return !err; +} + +static BOOL ReadSram(void *buffer) +{ + BOOL err; + u32 cmd; + + DCInvalidateRange(buffer, RTC_SRAM_SIZE); + + if (!EXILock(RTC_CHAN, RTC_DEV, 0)) { + return FALSE; + } + if (!EXISelect(RTC_CHAN, RTC_DEV, RTC_FREQ)) { + EXIUnlock(RTC_CHAN); + return FALSE; + } + + cmd = RTC_CMD_READ | RTC_SRAM_ADDR; + err = FALSE; + err |= !EXIImm(RTC_CHAN, &cmd, 4, 1, NULL); + err |= !EXISync(RTC_CHAN); + err |= !EXIDma(RTC_CHAN, buffer, RTC_SRAM_SIZE, 0, NULL); + err |= !EXISync(RTC_CHAN); + err |= !EXIDeselect(RTC_CHAN); + EXIUnlock(RTC_CHAN); + + return !err; +} + +BOOL WriteSram(void *buffer, u32 offset, u32 size); +static void WriteSramCallback(s32 chan, OSContext *context) +{ + Scb.sync = WriteSram(Scb.sram + Scb.offset, Scb.offset, RTC_SRAM_SIZE - Scb.offset); + if (Scb.sync) { + Scb.offset = RTC_SRAM_SIZE; + } +} + +BOOL WriteSram(void *buffer, u32 offset, u32 size) +{ + BOOL err; + u32 cmd; + + if (!EXILock(RTC_CHAN, RTC_DEV, WriteSramCallback)) { + return FALSE; + } + if (!EXISelect(RTC_CHAN, RTC_DEV, RTC_FREQ)) { + EXIUnlock(RTC_CHAN); + return FALSE; + } + + offset <<= 6; + cmd = RTC_CMD_WRITE | RTC_SRAM_ADDR + offset; + err = FALSE; + err |= !EXIImm(RTC_CHAN, &cmd, 4, 1, NULL); + err |= !EXISync(RTC_CHAN); + err |= !EXIImmEx(RTC_CHAN, buffer, (s32)size, 1); + err |= !EXIDeselect(RTC_CHAN); + EXIUnlock(RTC_CHAN); + + return !err; +} + +void __OSInitSram() +{ + Scb.locked = Scb.enabled = FALSE; + Scb.sync = ReadSram(Scb.sram); + Scb.offset = RTC_SRAM_SIZE; +} + +static void *LockSram(u32 offset) +{ + BOOL enabled; + enabled = OSDisableInterrupts(); + + if (Scb.locked != FALSE) { + OSRestoreInterrupts(enabled); + return NULL; + } + + Scb.enabled = enabled; + Scb.locked = TRUE; + + return Scb.sram + offset; +} + +OSSram *__OSLockSram() +{ + return LockSram(0); +} + +OSSramEx *__OSLockSramEx() +{ + return LockSram(sizeof(OSSram)); +} + +static BOOL UnlockSram(BOOL commit, u32 offset) +{ + u16 *p; + + if (commit) { + if (offset == 0) { + OSSram *sram = (OSSram *)Scb.sram; + + if (2u < (sram->flags & 3)) { + sram->flags &= ~3; + } + + sram->checkSum = sram->checkSumInv = 0; + for (p = (u16 *)&sram->counterBias; p < (u16 *)(Scb.sram + sizeof(OSSram)); p++) { + sram->checkSum += *p; + sram->checkSumInv += ~*p; + } + } + + if (offset < Scb.offset) { + Scb.offset = offset; + } + + Scb.sync = WriteSram(Scb.sram + Scb.offset, Scb.offset, RTC_SRAM_SIZE - Scb.offset); + if (Scb.sync) { + Scb.offset = RTC_SRAM_SIZE; + } + } + Scb.locked = FALSE; + OSRestoreInterrupts(Scb.enabled); + return Scb.sync; +} + +BOOL __OSUnlockSram(BOOL commit) +{ + return UnlockSram(commit, 0); +} + +BOOL __OSUnlockSramEx(BOOL commit) +{ + return UnlockSram(commit, sizeof(OSSram)); +} + +BOOL __OSSyncSram() +{ + return Scb.sync; +} + +BOOL __OSReadROM(void *buffer, s32 length, s32 offset) +{ + BOOL err; + u32 cmd; + + DCInvalidateRange(buffer, (u32)length); + + if (!EXILock(RTC_CHAN, RTC_DEV, 0)) { + return FALSE; + } + if (!EXISelect(RTC_CHAN, RTC_DEV, RTC_FREQ)) { + EXIUnlock(RTC_CHAN); + return FALSE; + } + + cmd = (u32)(offset << 6); + err = FALSE; + err |= !EXIImm(RTC_CHAN, &cmd, 4, 1, NULL); + err |= !EXISync(RTC_CHAN); + err |= !EXIDma(RTC_CHAN, buffer, length, 0, NULL); + err |= !EXISync(RTC_CHAN); + err |= !EXIDeselect(RTC_CHAN); + EXIUnlock(RTC_CHAN); + + return !err; +} + +inline OSSram *__OSLockSramHACK() +{ + return LockSram(0); +} +u32 OSGetSoundMode() +{ + OSSram *sram; + u32 mode; + + sram = __OSLockSramHACK(); + mode = (sram->flags & 0x4) ? OS_SOUND_MODE_STEREO : OS_SOUND_MODE_MONO; + __OSUnlockSram(FALSE); + return mode; +} + +void OSSetSoundMode(u32 mode) +{ + OSSram *sram; + mode <<= 2; + mode &= 4; + + sram = __OSLockSramHACK(); + if (mode == (sram->flags & 4)) { + __OSUnlockSram(FALSE); + return; + } + + sram->flags &= ~4; + sram->flags |= mode; + __OSUnlockSram(TRUE); +} + +u32 OSGetProgressiveMode() +{ + OSSram *sram; + u32 mode; + + sram = __OSLockSramHACK(); + mode = (sram->flags & 0x80) >> 7; + __OSUnlockSram(FALSE); + return mode; +} + +void OSSetProgressiveMode(u32 mode) +{ + OSSram *sram; + mode <<= 7; + mode &= 0x80; + + sram = __OSLockSramHACK(); + if (mode == (sram->flags & 0x80)) { + __OSUnlockSram(FALSE); + return; + } + + sram->flags &= ~0x80; + sram->flags |= mode; + __OSUnlockSram(TRUE); +} + +u8 OSGetLanguage() +{ + OSSram *sram; + u8 language; + + sram = __OSLockSramHACK(); + language = sram->language; + __OSUnlockSram(FALSE); + return language; +} + +u16 OSGetWirelessID(s32 channel) +{ + OSSramEx *sram; + u16 id; + + sram = __OSLockSramEx(); + id = sram->wirelessPadID[channel]; + __OSUnlockSramEx(FALSE); + return id; +} + +void OSSetWirelessID(s32 channel, u16 id) +{ + OSSramEx *sram; + + sram = __OSLockSramEx(); + if (sram->wirelessPadID[channel] != id) { + sram->wirelessPadID[channel] = id; + __OSUnlockSramEx(TRUE); + return; + } + + __OSUnlockSramEx(FALSE); +} diff --git a/src/dolphin/os/OSStopwatch.c b/src/dolphin/os/OSStopwatch.c new file mode 100644 index 00000000..80e7dbdd --- /dev/null +++ b/src/dolphin/os/OSStopwatch.c @@ -0,0 +1,61 @@ +#include +#include + +void OSInitStopwatch(struct OSStopwatch *sw, char *name) +{ + sw->name = name; + sw->total = 0; + sw->hits = 0; + sw->min = 0x00000000FFFFFFFF; + sw->max = 0; +} + +void OSStartStopwatch(struct OSStopwatch *sw) +{ + sw->running = 1; + sw->last = OSGetTime(); +} + +void OSStopStopwatch(struct OSStopwatch *sw) +{ + long long interval; + + if (sw->running != 0) { + interval = OSGetTime() - sw->last; + sw->total += interval; + sw->running = 0; + sw->hits++; + if (sw->max < interval) { + sw->max = interval; + } + if (interval < sw->min) { + sw->min = interval; + } + } +} + +long long OSCheckStopwatch(struct OSStopwatch *sw) +{ + long long currTotal; + + currTotal = sw->total; + if (sw->running != 0) { + currTotal += OSGetTime() - sw->last; + } + return currTotal; +} + +void OSResetStopwatch(struct OSStopwatch *sw) +{ + OSInitStopwatch(sw, sw->name); +} + +void OSDumpStopwatch(struct OSStopwatch *sw) +{ + OSReport("Stopwatch [%s] :\n", sw->name); + OSReport("\tTotal= %lld us\n", OSTicksToMicroseconds(sw->total)); + OSReport("\tHits = %d \n", sw->hits); + OSReport("\tMin = %lld us\n", OSTicksToMicroseconds(sw->min)); + OSReport("\tMax = %lld us\n", OSTicksToMicroseconds(sw->max)); + OSReport("\tMean = %lld us\n", OSTicksToMicroseconds(sw->total / sw->hits)); +} diff --git a/src/dolphin/os/OSSync.c b/src/dolphin/os/OSSync.c new file mode 100644 index 00000000..b5aeccf7 --- /dev/null +++ b/src/dolphin/os/OSSync.c @@ -0,0 +1,29 @@ +#include "string.h" +#include "dolphin/PPCArch.h" +#include "dolphin/os.h" + +void __OSSystemCallVectorStart(); +void __OSSystemCallVectorEnd(); +static asm void SystemCallVector() { + nofralloc +entry __OSSystemCallVectorStart + mfspr r9, HID0 + ori r10, r9, 8 + mtspr HID0, r10 + isync + sync + mtspr HID0, r9 + + rfi + +entry __OSSystemCallVectorEnd + nop +} + +void __OSInitSystemCall() { + void* addr = OSPhysicalToCached(0x00C00); + memcpy(addr, __OSSystemCallVectorStart, (size_t)__OSSystemCallVectorEnd - (size_t)__OSSystemCallVectorStart); + DCFlushRangeNoSync(addr, 0x100); + __sync(); + ICInvalidateRange(addr, 0x100); +} diff --git a/src/dolphin/os/OSThread.c b/src/dolphin/os/OSThread.c new file mode 100644 index 00000000..c9f4348d --- /dev/null +++ b/src/dolphin/os/OSThread.c @@ -0,0 +1,552 @@ +#include + +static vu32 RunQueueBits; +static volatile BOOL RunQueueHint; +static vs32 Reschedule; + +static OSThreadQueue RunQueue[32]; +static OSThread IdleThread; +static OSThread DefaultThread; +static OSContext IdleContext; +static void DefaultSwitchThreadCallback(OSThread *from, OSThread *to); +static OSSwitchThreadCallback SwitchThreadCallback = DefaultSwitchThreadCallback; + +OSThread *__OSCurrentThread : OS_BASE_CACHED + 0x00E4; +OSThreadQueue __OSActiveThreadQueue : OS_BASE_CACHED + 0x00DC; +volatile OSContext __OSCurrentContext : OS_BASE_CACHED + 0x00D4; +volatile OSContext *__OSFPUContext : OS_BASE_CACHED + 0x00D8; + +static void DefaultSwitchThreadCallback(OSThread *from, OSThread *to) { } + +extern u8 _stack_addr[]; +extern u8 _stack_end[]; + +#define AddTail(queue, thread, link) \ + do { \ + OSThread *prev; \ + \ + prev = (queue)->tail; \ + if (prev == NULL) \ + (queue)->head = (thread); \ + else \ + prev->link.next = (thread); \ + (thread)->link.prev = prev; \ + (thread)->link.next = NULL; \ + (queue)->tail = (thread); \ + } while (0) + +#define AddPrio(queue, thread, link) \ + do { \ + OSThread *prev, *next; \ + \ + for (next = (queue)->head; next && next->priority <= thread->priority; next = next->link.next) \ + ; \ + if (next == NULL) \ + AddTail(queue, thread, link); \ + else { \ + (thread)->link.next = next; \ + prev = next->link.prev; \ + next->link.prev = (thread); \ + (thread)->link.prev = prev; \ + if (prev == NULL) \ + (queue)->head = (thread); \ + else \ + prev->link.next = (thread); \ + } \ + } while (0) + +#define RemoveItem(queue, thread, link) \ + do { \ + OSThread *next, *prev; \ + next = (thread)->link.next; \ + prev = (thread)->link.prev; \ + if (next == NULL) \ + (queue)->tail = prev; \ + else \ + next->link.prev = prev; \ + if (prev == NULL) \ + (queue)->head = next; \ + else \ + prev->link.next = next; \ + } while (0) + +#define RemoveHead(queue, thread, link) \ + do { \ + OSThread *__next; \ + (thread) = (queue)->head; \ + __next = (thread)->link.next; \ + if (__next == NULL) \ + (queue)->tail = NULL; \ + else \ + __next->link.prev = NULL; \ + (queue)->head = __next; \ + } while (0) + +static inline void OSInitMutexQueue(OSMutexQueue *queue) +{ + queue->head = queue->tail = NULL; +} + +static inline void OSSetCurrentThread(OSThread *thread) +{ + __OSCurrentThread = thread; +} + +void __OSThreadInit() +{ + OSThread *thread = &DefaultThread; + int prio; + + thread->state = OS_THREAD_STATE_RUNNING; + thread->attr = OS_THREAD_ATTR_DETACH; + thread->priority = thread->base = 16; + thread->suspend = 0; + thread->val = (void *)-1; + thread->mutex = NULL; + OSInitThreadQueue(&thread->queueJoin); + OSInitMutexQueue(&thread->queueMutex); + + __OSFPUContext = &thread->context; + + OSClearContext(&thread->context); + OSSetCurrentContext(&thread->context); + thread->stackBase = (void *)_stack_addr; + thread->stackEnd = (void *)_stack_end; + *(thread->stackEnd) = OS_THREAD_STACK_MAGIC; + + OSSetCurrentThread(thread); + RunQueueBits = 0; + RunQueueHint = FALSE; + for (prio = OS_PRIORITY_MIN; prio <= OS_PRIORITY_MAX; ++prio) { + OSInitThreadQueue(&RunQueue[prio]); + } + + OSInitThreadQueue(&__OSActiveThreadQueue); + AddTail(&__OSActiveThreadQueue, thread, linkActive); + OSClearContext(&IdleContext); + Reschedule = 0; +} + +void OSInitThreadQueue(OSThreadQueue *queue) +{ + queue->head = queue->tail = NULL; +} + +OSThread *OSGetCurrentThread() +{ + return __OSCurrentThread; +} + +s32 OSDisableScheduler() +{ + BOOL enabled; + s32 count; + + enabled = OSDisableInterrupts(); + count = Reschedule++; + OSRestoreInterrupts(enabled); + return count; +} + +s32 OSEnableScheduler() +{ + BOOL enabled; + s32 count; + + enabled = OSDisableInterrupts(); + count = Reschedule--; + OSRestoreInterrupts(enabled); + return count; +} + +static void SetRun(OSThread *thread) +{ + thread->queue = &RunQueue[thread->priority]; + AddTail(thread->queue, thread, link); + RunQueueBits |= 1u << (OS_PRIORITY_MAX - thread->priority); + RunQueueHint = TRUE; +} +#pragma dont_inline on +static void UnsetRun(OSThread *thread) +{ + OSThreadQueue *queue; + queue = thread->queue; + RemoveItem(queue, thread, link); + if (queue->head == 0) + RunQueueBits &= ~(1u << (OS_PRIORITY_MAX - thread->priority)); + thread->queue = NULL; +} +#pragma dont_inline reset + +OSPriority __OSGetEffectivePriority(OSThread *thread) +{ + OSPriority priority; + OSMutex *mutex; + OSThread *blocked; + + priority = thread->base; + for (mutex = thread->queueMutex.head; mutex; mutex = mutex->link.next) { + blocked = mutex->queue.head; + if (blocked && blocked->priority < priority) { + priority = blocked->priority; + } + } + return priority; +} + +static OSThread *SetEffectivePriority(OSThread *thread, OSPriority priority) +{ + switch (thread->state) { + case OS_THREAD_STATE_READY: + UnsetRun(thread); + thread->priority = priority; + SetRun(thread); + break; + case OS_THREAD_STATE_WAITING: + RemoveItem(thread->queue, thread, link); + thread->priority = priority; + AddPrio(thread->queue, thread, link); + if (thread->mutex) { + return thread->mutex->thread; + } + break; + case OS_THREAD_STATE_RUNNING: + RunQueueHint = TRUE; + thread->priority = priority; + break; + } + return NULL; +} + +static void UpdatePriority(OSThread *thread) +{ + OSPriority priority; + + do { + if (0 < thread->suspend) { + break; + } + priority = __OSGetEffectivePriority(thread); + if (thread->priority == priority) { + break; + } + thread = SetEffectivePriority(thread, priority); + } while (thread); +} + +static void __OSSwitchThread(OSThread *nextThread) +{ + OSSetCurrentThread(nextThread); + OSSetCurrentContext(&nextThread->context); + OSLoadContext(&nextThread->context); +} + +static OSThread *SelectThread(BOOL yield) +{ + OSContext *currentContext; + OSThread *currentThread; + OSThread *nextThread; + OSPriority priority; + OSThreadQueue *queue; + + if (0 < Reschedule) { + return 0; + } + + currentContext = OSGetCurrentContext(); + currentThread = OSGetCurrentThread(); + if (currentContext != ¤tThread->context) { + return 0; + } + + if (currentThread) { + if (currentThread->state == OS_THREAD_STATE_RUNNING) { + if (!yield) { + priority = __cntlzw(RunQueueBits); + if (currentThread->priority <= priority) { + return 0; + } + } + currentThread->state = OS_THREAD_STATE_READY; + SetRun(currentThread); + } + + if (!(currentThread->context.state & OS_CONTEXT_STATE_EXC) && OSSaveContext(¤tThread->context)) { + return 0; + } + } + + OSSetCurrentThread(NULL); + if (RunQueueBits == 0) { + OSSetCurrentContext(&IdleContext); + do { + OSEnableInterrupts(); + while (RunQueueBits == 0) + ; + OSDisableInterrupts(); + } while (RunQueueBits == 0); + + OSClearContext(&IdleContext); + } + + RunQueueHint = FALSE; + + priority = __cntlzw(RunQueueBits); + queue = &RunQueue[priority]; + RemoveHead(queue, nextThread, link); + if (queue->head == 0) { + RunQueueBits &= ~(1u << (OS_PRIORITY_MAX - priority)); + } + nextThread->queue = NULL; + nextThread->state = OS_THREAD_STATE_RUNNING; + __OSSwitchThread(nextThread); + return nextThread; +} + +void __OSReschedule() +{ + if (!RunQueueHint) { + return; + } + + SelectThread(FALSE); +} + +void OSYieldThread(void) +{ + BOOL enabled; + + enabled = OSDisableInterrupts(); + SelectThread(TRUE); + OSRestoreInterrupts(enabled); +} + +int OSCreateThread(struct OSThread * thread, void * (* func)(void *), void * param, void * stack, unsigned long stackSize, long priority, unsigned short attr) { + int enabled; + unsigned long sp; + + // why check this for an assert just to check it again right after? + if ((priority < 0) || (priority > 0x1F)) { + return 0; + } + + thread->state = 1; + thread->attr = attr & 1U; + thread->base = priority; + thread->priority = priority; + thread->suspend = 1; + thread->val = (void*)-1; + thread->mutex = 0; + OSInitThreadQueue(&thread->queueJoin); + OSInitThreadQueue((void*)&thread->queueMutex); // why + sp = (u32)stack; + sp &= ~7; + sp -= 8; + ((u32*)sp)[0] = 0; + ((u32*)sp)[1] = 0; + OSInitContext(&thread->context, (u32)func, sp); + thread->context.lr = (unsigned long)&OSExitThread; + thread->context.gpr[3] = (unsigned long)param; + thread->stackBase = stack; + thread->stackEnd = (void*)((unsigned int)stack - stackSize); + *thread->stackEnd = 0xDEADBABE; + enabled = OSDisableInterrupts(); + + AddTail(&__OSActiveThreadQueue, thread, linkActive); + + OSRestoreInterrupts(enabled); + return 1; +} + +void OSExitThread(void *val) +{ + int enabled = OSDisableInterrupts(); + struct OSThread *currentThread = OSGetCurrentThread(); + + OSClearContext(¤tThread->context); + if (currentThread->attr & 1) { + RemoveItem(&__OSActiveThreadQueue, currentThread, linkActive); + currentThread->state = 0; + } + else { + currentThread->state = 8; + currentThread->val = val; + } + __OSUnlockAllMutex(currentThread); + OSWakeupThread(¤tThread->queueJoin); + RunQueueHint = 1; + if (RunQueueHint != 0) { + SelectThread(0); + } + OSRestoreInterrupts(enabled); +} + +void OSCancelThread(OSThread *thread) +{ + BOOL enabled; + + enabled = OSDisableInterrupts(); + + switch (thread->state) { + case OS_THREAD_STATE_READY: + if (!(0 < thread->suspend)) { + UnsetRun(thread); + } + break; + case OS_THREAD_STATE_RUNNING: + RunQueueHint = TRUE; + break; + case OS_THREAD_STATE_WAITING: + RemoveItem(thread->queue, thread, link); + thread->queue = NULL; + if (!(0 < thread->suspend) && thread->mutex) { + UpdatePriority(thread->mutex->thread); + } + break; + default: + OSRestoreInterrupts(enabled); + return; + } + + OSClearContext(&thread->context); + if (thread->attr & OS_THREAD_ATTR_DETACH) { + RemoveItem(&__OSActiveThreadQueue, thread, linkActive); + thread->state = 0; + } + else { + thread->state = OS_THREAD_STATE_MORIBUND; + } + + __OSUnlockAllMutex(thread); + + OSWakeupThread(&thread->queueJoin); + + __OSReschedule(); + OSRestoreInterrupts(enabled); + + return; +} + +s32 OSResumeThread(OSThread *thread) +{ + BOOL enabled; + s32 suspendCount; + + enabled = OSDisableInterrupts(); + suspendCount = thread->suspend--; + if (thread->suspend < 0) { + thread->suspend = 0; + } + else if (thread->suspend == 0) { + switch (thread->state) { + case OS_THREAD_STATE_READY: + thread->priority = __OSGetEffectivePriority(thread); + SetRun(thread); + break; + case OS_THREAD_STATE_WAITING: + RemoveItem(thread->queue, thread, link); + thread->priority = __OSGetEffectivePriority(thread); + AddPrio(thread->queue, thread, link); + if (thread->mutex) { + UpdatePriority(thread->mutex->thread); + } + break; + } + __OSReschedule(); + } + OSRestoreInterrupts(enabled); + return suspendCount; +} + +s32 OSSuspendThread(OSThread *thread) +{ + BOOL enabled; + s32 suspendCount; + + enabled = OSDisableInterrupts(); + suspendCount = thread->suspend++; + if (suspendCount == 0) { + switch (thread->state) { + case OS_THREAD_STATE_RUNNING: + RunQueueHint = TRUE; + thread->state = OS_THREAD_STATE_READY; + break; + case OS_THREAD_STATE_READY: + UnsetRun(thread); + break; + case OS_THREAD_STATE_WAITING: + RemoveItem(thread->queue, thread, link); + thread->priority = 32; + AddTail(thread->queue, thread, link); + if (thread->mutex) { + UpdatePriority(thread->mutex->thread); + } + break; + } + + __OSReschedule(); + } + OSRestoreInterrupts(enabled); + return suspendCount; +} + +void OSSleepThread(OSThreadQueue *queue) +{ + BOOL enabled; + OSThread *currentThread; + + enabled = OSDisableInterrupts(); + currentThread = OSGetCurrentThread(); + + currentThread->state = OS_THREAD_STATE_WAITING; + currentThread->queue = queue; + AddPrio(queue, currentThread, link); + RunQueueHint = TRUE; + __OSReschedule(); + OSRestoreInterrupts(enabled); +} + +void OSWakeupThread(OSThreadQueue *queue) +{ + BOOL enabled; + OSThread *thread; + + enabled = OSDisableInterrupts(); + while (queue->head) { + RemoveHead(queue, thread, link); + thread->state = OS_THREAD_STATE_READY; + if (!(0 < thread->suspend)) { + SetRun(thread); + } + } + __OSReschedule(); + OSRestoreInterrupts(enabled); +} + +void OSClearStack(u8 val) +{ + register u32 sp; + register u32 *p; + register u32 pattern; + + pattern = ((u32)val << 24) | ((u32)val << 16) | ((u32)val << 8) | (u32)val; + sp = OSGetStackPointer(); + for (p = __OSCurrentThread->stackEnd + 1; p < (u32 *)sp; ++p) { + *p = pattern; + } +} + +struct OSThread *OSSetIdleFunction(void (*idleFunction)(void *), void *param, void *stack, unsigned long stackSize) +{ + if (idleFunction) { + if (IdleThread.state == 0) { + OSCreateThread(&IdleThread, (void *)idleFunction, param, stack, stackSize, 0x1F, 1); + OSResumeThread(&IdleThread); + return &IdleThread; + } + } + else if (IdleThread.state != 0) { + OSCancelThread(&IdleThread); + } + return NULL; +} diff --git a/src/dolphin/os/OSTime.c b/src/dolphin/os/OSTime.c new file mode 100644 index 00000000..604e45c6 --- /dev/null +++ b/src/dolphin/os/OSTime.c @@ -0,0 +1,146 @@ +#include + +#define OS_TIME_MONTH_MAX 12 +#define OS_TIME_WEEK_DAY_MAX 7 +#define OS_TIME_YEAR_DAY_MAX 365 + +// End of each month in standard year +static s32 YearDays[OS_TIME_MONTH_MAX] = { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 }; +// End of each month in leap year +static s32 LeapYearDays[OS_TIME_MONTH_MAX] = { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335 }; + +asm OSTime OSGetTime(void) +{ + // clang-format off + nofralloc +@0 + mftbu r3 + mftb r4 + + // Check for possible carry from TBL to TBU + mftbu r5 + cmpw r3, r5 + bne @0 + + blr + // clang-format on +} + +asm OSTick OSGetTick(void) { + // clang-format off + nofralloc + + mftb r3 + blr + // clang-format on +} + +#define OS_SYSTEMTIME_BASE 0x30D8 + +OSTime __OSGetSystemTime(void) +{ + BOOL enabled; + OSTime *timeAdjustAddr = (OSTime *)(OS_BASE_CACHED + OS_SYSTEMTIME_BASE); + OSTime result; + + enabled = OSDisableInterrupts(); + result = *timeAdjustAddr + OSGetTime(); + OSRestoreInterrupts(enabled); + + return result; +} + +OSTime __OSTimeToSystemTime(OSTime time) +{ + BOOL enabled; + OSTime *timeAdjustAddr = (OSTime *)(OS_BASE_CACHED + OS_SYSTEMTIME_BASE); + OSTime result; + + enabled = OSDisableInterrupts(); + result = *timeAdjustAddr + time; + OSRestoreInterrupts(enabled); + + return result; +} + +static BOOL IsLeapYear(s32 year) +{ + return (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0); +} + +static s32 GetYearDays(s32 year, s32 mon) +{ + return (IsLeapYear(year) ? LeapYearDays : YearDays)[mon]; +} + +static s32 GetLeapDays(s32 year) +{ + if (year < 1) { + return 0; + } + return (year + 3) / 4 - (year - 1) / 100 + (year - 1) / 400; +} + +static void GetDates(s32 days, OSCalendarTime *cal) +{ + s32 year; + s32 totalDays; + s32 *p_days; + s32 month; + cal->wday = (days + 6) % OS_TIME_WEEK_DAY_MAX; + + for (year = days / OS_TIME_YEAR_DAY_MAX; days < (totalDays = year * OS_TIME_YEAR_DAY_MAX + GetLeapDays(year));) { + year--; + } + + days -= totalDays; + cal->year = year; + cal->yday = days; + + p_days = IsLeapYear(year) ? LeapYearDays : YearDays; + month = OS_TIME_MONTH_MAX; + while (days < p_days[--month]) { + ; + } + cal->mon = month; + cal->mday = days - p_days[month] + 1; +} + +#define BIAS (2000 * 365 + (2000 + 3) / 4 - (2000 - 1) / 100 + (2000 - 1) / 400) + +#pragma push +#pragma dont_inline on +void OSTicksToCalendarTime(OSTime ticks, OSCalendarTime *td) +{ + int days; + int secs; + OSTime d; + + d = ticks % OSSecondsToTicks(1); + if (d < 0) { + d += OSSecondsToTicks(1); + } + td->usec = (int)(OSTicksToMicroseconds(d) % 1000); + td->msec = (int)(OSTicksToMilliseconds(d) % 1000); + + ticks -= d; + days = (int)(OSTicksToSeconds(ticks) / 86400 + BIAS); + secs = (int)(OSTicksToSeconds(ticks) % 86400); + if (secs < 0) { + days -= 1; + secs += 24 * 60 * 60; + } + + GetDates(days, td); + + td->hour = secs / 60 / 60; + td->min = (secs / 60) % 60; + td->sec = secs % 60; +} +#pragma dont_inline reset + +OSTime OSCalendarTimeToTicks(OSCalendarTime *time) +{ + ; + ; +} diff --git a/src/dolphin/os/__ppc_eabi_init.c b/src/dolphin/os/__ppc_eabi_init.c new file mode 100644 index 00000000..4b7c8c6e --- /dev/null +++ b/src/dolphin/os/__ppc_eabi_init.c @@ -0,0 +1,76 @@ +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif +void __OSPSInit(); +void __OSCacheInit(); + +asm void __init_hardware(void) +{ + // clang-format off + nofralloc + mfmsr r0 + ori r0, r0, 0x2000 + mtmsr r0 + + mflr r31 + bl __OSPSInit + bl __OSCacheInit + mtlr r31 + blr + // clang-format on +} + +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 00000000..475b3b4c --- /dev/null +++ b/src/dolphin/os/__start.c @@ -0,0 +1,161 @@ +#include +#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++; + } +}