From 67cc8b5cc7677b182d6055fc3dd0eeec0872692a Mon Sep 17 00:00:00 2001 From: Phillip Stephens Date: Thu, 5 Oct 2023 12:54:11 -0700 Subject: [PATCH] RAssertDolphin fixes --- .gitignore | 1 + config/G2ME01/splits.txt | 3 +- config/G2ME01/symbols.txt | 50 +-- include/Kyoto/Basics/RAssertDolphin.hpp | 8 + include/dolphin/ai.h | 7 + include/dolphin/dvd.h | 2 +- include/dolphin/os/OSReset.h | 2 + libc/stdbool.h | 13 + src/Dolphin/os/OSContext.c | 550 ++++++++++++++++++++++++ src/Dolphin/os/OSError.c | 205 +++++++++ src/Dolphin/os/OSInterrupt.c | 427 ++++++++++++++++++ src/Kyoto/Basics/RAssertDolphin.cpp | 253 +++++------ tools/decompctx.py | 18 +- 13 files changed, 1384 insertions(+), 155 deletions(-) create mode 100644 libc/stdbool.h create mode 100644 src/Dolphin/os/OSContext.c create mode 100644 src/Dolphin/os/OSError.c create mode 100644 src/Dolphin/os/OSInterrupt.c diff --git a/.gitignore b/.gitignore index 6313665..f1e5934 100644 --- a/.gitignore +++ b/.gitignore @@ -11,3 +11,4 @@ orig/*/* tools/mwcc_compiler/* !tools/mwcc_compiler/.gitkeep /*.txt +ctx.c diff --git a/config/G2ME01/splits.txt b/config/G2ME01/splits.txt index 3b410aa..6112c55 100644 --- a/config/G2ME01/splits.txt +++ b/config/G2ME01/splits.txt @@ -84,7 +84,8 @@ Kyoto/Basics/CStopwatch.cpp: Kyoto/Basics/RAssertDolphin.cpp: .text start:0x8028C28C end:0x8028C9C8 .rodata start:0x803AEAC8 end:0x803AED58 - .sbss start:0x8041981C end:0x80419828 + .sbss start:0x80419818 end:0x80419828 + .sdata2 start:0x8041E268 end:0x8041E278 Kyoto/Graphics/CGX.cpp: .text start:0x802BCBEC end:0x802BE31C diff --git a/config/G2ME01/symbols.txt b/config/G2ME01/symbols.txt index 78b80dc..b2a733e 100644 --- a/config/G2ME01/symbols.txt +++ b/config/G2ME01/symbols.txt @@ -15327,7 +15327,7 @@ fn_8033EC4C = .text:0x8033EC4C; // type:function size:0x38 fn_8033EC84 = .text:0x8033EC84; // type:function size:0x20 fn_8033ECA4 = .text:0x8033ECA4; // type:function size:0x28 fn_8033ECCC = .text:0x8033ECCC; // type:function size:0x58 -fn_8033ED24 = .text:0x8033ED24; // type:function size:0x64 +fn_8033ED24__Fi = .text:0x8033ED24; // type:function size:0x64 fn_8033ED88 = .text:0x8033ED88; // type:function size:0x20 fn_8033EDA8 = .text:0x8033EDA8; // type:function size:0x4C fn_8033EDF4 = .text:0x8033EDF4; // type:function size:0x38 @@ -15934,10 +15934,10 @@ DVDGetDriveStatus = .text:0x80362A6C; // type:function size:0xAC scope:global fn_80362B18 = .text:0x80362B18; // type:function size:0x10 fn_80362B28 = .text:0x80362B28; // type:function size:0x50 fn_80362B78 = .text:0x80362B78; // type:function size:0x27C -fn_80362DF4 = .text:0x80362DF4; // type:function size:0xAC -fn_80362EA0 = .text:0x80362EA0; // type:function size:0x24 align:4 -fn_80362EC4 = .text:0x80362EC4; // type:function size:0xEC -fn_80362FB0 = .text:0x80362FB0; // type:function size:0x8 +DVDCancel = .text:0x80362DF4; // type:function size:0xAC +cbForCancelSync = .text:0x80362EA0; // type:function size:0x24 scope:local align:4 +DVDCancelAll = .text:0x80362EC4; // type:function size:0xEC +DVDGetCurrentDiskID = .text:0x80362FB0; // type:function size:0x8 fn_80362FB8 = .text:0x80362FB8; // type:function size:0xF8 fn_803630B0 = .text:0x803630B0; // type:function size:0x11C fn_803631CC = .text:0x803631CC; // type:function size:0x38 align:4 @@ -16422,19 +16422,19 @@ THPInit = .text:0x803810E4; // type:function size:0xA0 align:4 THPAudioDecode = .text:0x80381184; // type:function size:0x464 __THPAudioGetNewSample = .text:0x803815E8; // type:function size:0x90 __THPAudioInitialize = .text:0x80381678; // type:function size:0x3C -fn_803816B4 = .text:0x803816B4; // type:function size:0x44 -AIInitDMA__FUlUl = .text:0x803816F8; // type:function size:0x88 scope:global -AIStartDMA__Fv = .text:0x80381780; // type:function size:0x18 scope:global -fn_80381798 = .text:0x80381798; // type:function size:0x18 -fn_803817B0 = .text:0x803817B0; // type:function size:0x1C align:4 -fn_803817CC = .text:0x803817CC; // type:function size:0x44 -fn_80381810 = .text:0x80381810; // type:function size:0x18 -fn_80381828 = .text:0x80381828; // type:function size:0xC -fn_80381834 = .text:0x80381834; // type:function size:0xD8 -fn_8038190C = .text:0x8038190C; // type:function size:0x10 -fn_8038191C = .text:0x8038191C; // type:function size:0xE0 -fn_803819FC = .text:0x803819FC; // type:function size:0x14 -fn_80381A10 = .text:0x80381A10; // type:function size:0xD4 +AIRegisterDMACallback = .text:0x803816B4; // type:function size:0x44 +AIInitDMA = .text:0x803816F8; // type:function size:0x88 scope:global +AIStartDMA = .text:0x80381780; // type:function size:0x18 scope:global +AIStopDMA = .text:0x80381798; // type:function size:0x18 +AIGetDMAStartAddr = .text:0x803817B0; // type:function size:0x1C align:4 +AIRegisterStreamCallback = .text:0x803817CC; // type:function size:0x44 +AIResetStreamSampleCount = .text:0x80381810; // type:function size:0x18 +AISetStreamTrigger = .text:0x80381828; // type:function size:0xC +AISetStreamPlayState = .text:0x80381834; // type:function size:0xD8 +AIGetStreamPlayState = .text:0x8038190C; // type:function size:0x10 +AISetDSPSampleRate = .text:0x8038191C; // type:function size:0xE0 +AIGetDSPSampleRate = .text:0x803819FC; // type:function size:0x14 +__AI_set_stream_sample_rate = .text:0x80381A10; // type:function size:0xD4 fn_80381AE4 = .text:0x80381AE4; // type:function size:0x10 fn_80381AF4 = .text:0x80381AF4; // type:function size:0x1C fn_80381B10 = .text:0x80381B10; // type:function size:0x10 @@ -17705,7 +17705,7 @@ lbl_803AEA80 = .rodata:0x803AEA80; // type:object size:0x18 data:double lbl_803AEA98 = .rodata:0x803AEA98; // type:object size:0x18 lbl_803AEAB0 = .rodata:0x803AEAB0; // type:object size:0x8 lbl_803AEAB8 = .rodata:0x803AEAB8; // type:object size:0x10 -lbl_803AEAC8 = .rodata:0x803AEAC8; // type:object size:0x290 +@stringBase0 = .rodata:0x803AEAC8; // type:object size:0x290 scope:local data:string_table lbl_803AED58 = .rodata:0x803AED58; // type:object size:0x8 lbl_803AED60 = .rodata:0x803AED60; // type:object size:0x8 lbl_803AED68 = .rodata:0x803AED68; // type:object size:0x8 @@ -20639,9 +20639,9 @@ lbl_80419800 = .sbss:0x80419800; // type:object size:0x4 data:4byte lbl_80419804 = .sbss:0x80419804; // type:object size:0x4 data:4byte mGlobalTimer__10CStopwatch = .sbss:0x80419808; // type:object size:0x8 scope:global align:8 data:8byte lbl_80419810 = .sbss:0x80419810; // type:object size:0x8 data:byte -lbl_80419818 = .sbss:0x80419818; // type:object size:0x1 data:byte +SkipFatal = .sbss:0x80419818; // type:object size:0x1 data:byte rs_debugger_buffer = .sbss:0x8041981C; // type:object size:0x4 scope:local data:4byte -lbl_80419820 = .sbss:0x80419820; // type:object size:0x4 data:4byte +rs_debugger_size = .sbss:0x80419820; // type:object size:0x4 data:4byte lbl_80419828 = .sbss:0x80419828; // type:object size:0x1 data:byte lbl_8041982C = .sbss:0x8041982C; // type:object size:0x1 data:byte lbl_80419830 = .sbss:0x80419830; // type:object size:0x1 data:byte @@ -23929,7 +23929,7 @@ lbl_8041D53C = .sdata2:0x8041D53C; // type:object size:0x4 data:float lbl_8041D540 = .sdata2:0x8041D540; // type:object size:0x4 data:float lbl_8041D544 = .sdata2:0x8041D544; // type:object size:0x4 data:float lbl_8041D548 = .sdata2:0x8041D548; // type:object size:0x8 data:float -lbl_8041D550 = .sdata2:0x8041D550; // type:object size:0x8 data:4byte +BuildTime = .sdata2:0x8041D550; // type:object size:0x8 data:4byte lbl_8041D558 = .sdata2:0x8041D558; // type:object size:0x4 lbl_8041D55C = .sdata2:0x8041D55C; // type:object size:0x4 data:float lbl_8041D560 = .sdata2:0x8041D560; // type:object size:0x4 data:float @@ -24635,9 +24635,9 @@ lbl_8041E248 = .sdata2:0x8041E248; // type:object size:0x4 data:float @148 = .sdata2:0x8041E254; // type:object size:0x4 scope:local data:float lbl_8041E258 = .sdata2:0x8041E258; // type:object size:0x4 data:float lbl_8041E260 = .sdata2:0x8041E260; // type:object size:0x8 data:double -lbl_8041E268 = .sdata2:0x8041E268; // type:object size:0x4 data:4byte -lbl_8041E26C = .sdata2:0x8041E26C; // type:object size:0x4 data:4byte -lbl_8041E270 = .sdata2:0x8041E270; // type:object size:0x8 data:4byte +bg = .sdata2:0x8041E268; // type:object size:0x4 scope:local data:4byte +fg = .sdata2:0x8041E26C; // type:object size:0x4 scope:local data:4byte +ExitButtons = .sdata2:0x8041E270; // type:object size:0x4 scope:local data:4byte lbl_8041E278 = .sdata2:0x8041E278; // type:object size:0x8 data:float lbl_8041E280 = .sdata2:0x8041E280; // type:object size:0x4 data:float lbl_8041E284 = .sdata2:0x8041E284; // type:object size:0x4 data:float diff --git a/include/Kyoto/Basics/RAssertDolphin.hpp b/include/Kyoto/Basics/RAssertDolphin.hpp index b7f86d4..8d1e5a7 100644 --- a/include/Kyoto/Basics/RAssertDolphin.hpp +++ b/include/Kyoto/Basics/RAssertDolphin.hpp @@ -5,6 +5,14 @@ #include "dolphin/os.h" +#define BUILD_INFO_TAG "!#$MetroidBuildInfo!#$" +// TODO: Add handling for build info +#define BUILD_TIME_DUMMY "Build v1.028 10/18/2004 10:44:32\0AD" +extern const char* BuildTime; + +#define BUILD_INFO BUILD_INFO_TAG BUILD_TIME_DUMMY +#define BUILD_INFO_TAG_SIZE sizeof(BUILD_INFO_TAG) - 1 + void ErrorHandler(OSError code, OSContext* context, int, uint); void SetErrorHandlers(); void rs_debugger_printf(const char* format, ...); diff --git a/include/dolphin/ai.h b/include/dolphin/ai.h index f226c70..e998e83 100644 --- a/include/dolphin/ai.h +++ b/include/dolphin/ai.h @@ -3,6 +3,9 @@ #include "types.h" +#ifdef __cplusplus +extern "C" { +#endif typedef void (*AISCallback)(u32 count); typedef void (*AIDCallback)(); @@ -33,4 +36,8 @@ void AIInit(u8* stack); BOOL AICheckInit(); void AIReset(); +#ifdef __cplusplus +} +#endif + #endif // _DOLPHIN_AI diff --git a/include/dolphin/dvd.h b/include/dolphin/dvd.h index ad4a8a7..b4f9f01 100644 --- a/include/dolphin/dvd.h +++ b/include/dolphin/dvd.h @@ -96,7 +96,7 @@ s32 DVDGetCommandBlockStatus(const DVDCommandBlock* block); BOOL DVDCancelAsync(DVDCommandBlock* block, DVDCBCallback callback); s32 DVDCancel(DVDCommandBlock* block); BOOL DVDCancelAllAsync(DVDCBCallback callback); -s32 DVDCancelAll(void); +s32 DVDCancelAll(DVDCBCallback callback); BOOL DVDPrepareStreamAsync(DVDFileInfo* fInfo, u32 length, u32 offset, DVDCallback callback); s32 DVDPrepareStream(DVDFileInfo* fInfo, u32 length, u32 offset); diff --git a/include/dolphin/os/OSReset.h b/include/dolphin/os/OSReset.h index a4cb641..032939a 100644 --- a/include/dolphin/os/OSReset.h +++ b/include/dolphin/os/OSReset.h @@ -39,6 +39,8 @@ struct OSResetFunctionInfo { OSResetFunctionInfo* prev; }; +void OSResetSystem(int reset, u32 resetCode, BOOL forceMenu); + #ifdef __cplusplus } #endif diff --git a/libc/stdbool.h b/libc/stdbool.h new file mode 100644 index 0000000..2170ae9 --- /dev/null +++ b/libc/stdbool.h @@ -0,0 +1,13 @@ +#ifndef STDBOOL_H +#define STDBOOL_h + +#define bool _Bool +#ifndef true + #define true 1 +#endif + +#ifndef false + #define false 0 +#endif + +#endif diff --git a/src/Dolphin/os/OSContext.c b/src/Dolphin/os/OSContext.c new file mode 100644 index 0000000..6acefe4 --- /dev/null +++ b/src/Dolphin/os/OSContext.c @@ -0,0 +1,550 @@ +#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 +} + +extern void __RAS_OSDisableInterrupts_begin(); +extern void __RAS_OSDisableInterrupts_end(); + +asm void OSLoadContext(register OSContext* context) { + // clang-format off + nofralloc + + lis r4,__RAS_OSDisableInterrupts_begin@ha + lwz r6,context->srr0 + addi r5,r4,__RAS_OSDisableInterrupts_begin@l + cmplw r6,r5 + ble _notInRAS + lis r4,__RAS_OSDisableInterrupts_end@ha + addi r0,r4,__RAS_OSDisableInterrupts_end@l + cmplw r6,r0 + bge _notInRAS + stw r5,context->srr0 + +_notInRAS: + + lwz r0, context->gpr[0] + lwz r1, context->gpr[1] + lwz r2, context->gpr[2] + + lhz r4, context->state + rlwinm. r5, r4, 0, 30, 30 + beq notexc + rlwinm r4, r4, 0, 31, 29 + sth r4, context->state + lmw r5, context->gpr[5] + b misc +notexc: + lmw r13, context->gpr[13] +misc: + + lwz r4, context->gqr[1] + mtspr GQR1, r4 + lwz r4, context->gqr[2] + mtspr GQR2, r4 + lwz r4, context->gqr[3] + mtspr GQR3, r4 + lwz r4, context->gqr[4] + mtspr GQR4, r4 + lwz r4, context->gqr[5] + mtspr GQR5, r4 + lwz r4, context->gqr[6] + mtspr GQR6, r4 + lwz r4, context->gqr[7] + mtspr GQR7, r4 + + lwz r4, context->cr + mtcr r4 + lwz r4, context->lr + mtlr r4 + lwz r4, context->ctr + mtctr r4 + lwz r4, context->xer + mtxer r4 + + mfmsr r4 + rlwinm r4, r4, 0, 17, 15 + rlwinm r4, r4, 0, 31, 29 + mtmsr r4 + + lwz r4, context->srr0 + mtsrr0 r4 + lwz r4, context->srr1 + mtsrr1 r4 + + lwz r4, context->gpr[4] + lwz r3, context->gpr[3] + + 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 0000000..e9bcfce --- /dev/null +++ b/src/Dolphin/os/OSError.c @@ -0,0 +1,205 @@ +#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) +u32 __OSFpscrEnableBits = FPSCR_ENABLE; + +__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; + BOOL enabled; + + enabled = OSDisableInterrupts(); + oldHandler = __OSErrorTable[error]; + __OSErrorTable[error] = handler; + + if (error == OS_ERROR_FPE) { + u32 msr; + u32 fpscr; + OSThread* thread; + + msr = PPCMfmsr(); + PPCMtmsr(msr | MSR_FP); + fpscr = PPCMffpscr(); + if (handler) { + for (thread = __OSActiveThreadQueue.head; thread; thread = thread->linkActive.next) { + thread->context.srr1 |= MSR_FE0 | MSR_FE1; + if ((thread->context.state & OS_CONTEXT_STATE_FPSAVED) == 0) { + int i; + thread->context.state |= OS_CONTEXT_STATE_FPSAVED; + for (i = 0; i < 32; ++i) { + *(u64*)&thread->context.fpr[i] = (u64)0xffffffffffffffffLL; + *(u64*)&thread->context.psf[i] = (u64)0xffffffffffffffffLL; + } + thread->context.fpscr = FPSCR_NI; + } + thread->context.fpscr |= __OSFpscrEnableBits & FPSCR_ENABLE; + thread->context.fpscr &= + ~(FPSCR_VXVC | FPSCR_VXIMZ | FPSCR_VXZDZ | FPSCR_VXIDI | FPSCR_VXISI | FPSCR_VXSNAN | + FPSCR_VXSOFT | FPSCR_VXSQRT | FPSCR_VXCVI | FPSCR_XX | FPSCR_ZX | FPSCR_UX | + FPSCR_OX | FPSCR_FX | FPSCR_FI); + } + fpscr |= __OSFpscrEnableBits & FPSCR_ENABLE; + msr |= MSR_FE0 | MSR_FE1; + } else { + for (thread = __OSActiveThreadQueue.head; thread; thread = thread->linkActive.next) { + thread->context.srr1 &= ~(MSR_FE0 | MSR_FE1); + thread->context.fpscr &= ~FPSCR_ENABLE; + thread->context.fpscr &= + ~(FPSCR_VXVC | FPSCR_VXIMZ | FPSCR_VXZDZ | FPSCR_VXIDI | FPSCR_VXISI | FPSCR_VXSNAN | + FPSCR_VXSOFT | FPSCR_VXSQRT | FPSCR_VXCVI | FPSCR_XX | FPSCR_ZX | FPSCR_UX | + FPSCR_OX | FPSCR_FX | FPSCR_FI); + } + fpscr &= ~FPSCR_ENABLE; + msr &= ~(MSR_FE0 | MSR_FE1); + } + + fpscr &= ~(FPSCR_VXVC | FPSCR_VXIMZ | FPSCR_VXZDZ | FPSCR_VXIDI | FPSCR_VXISI | FPSCR_VXSNAN | + FPSCR_VXSOFT | FPSCR_VXSQRT | FPSCR_VXCVI | FPSCR_XX | FPSCR_ZX | FPSCR_UX | + FPSCR_OX | FPSCR_FX | FPSCR_FI); + + PPCMtfpscr(fpscr); + PPCMtmsr(msr); + } + + OSRestoreInterrupts(enabled); + return oldHandler; +} + +void __OSUnhandledException(__OSException exception, OSContext* context, u32 dsisr, u32 dar) { + OSTime now; + + now = OSGetTime(); + + if (!(context->srr1 & MSR_RI)) { + OSReport("Non-recoverable Exception %d", exception); + } else { + if (exception == __OS_EXCEPTION_PROGRAM && (context->srr1 & (0x80000000 >> 11)) && + __OSErrorTable[OS_ERROR_FPE] != 0) { + u32 fpscr; + u32 msr; + + exception = OS_ERROR_FPE; + + msr = PPCMfmsr(); + PPCMtmsr(msr | MSR_FP); + + if (__OSFPUContext) { + OSSaveFPUContext((OSContext*)__OSFPUContext); + } + + fpscr = PPCMffpscr(); + fpscr &= ~(FPSCR_VXVC | FPSCR_VXIMZ | FPSCR_VXZDZ | FPSCR_VXIDI | FPSCR_VXISI | FPSCR_VXSNAN | + FPSCR_VXSOFT | FPSCR_VXSQRT | FPSCR_VXCVI | FPSCR_XX | FPSCR_ZX | FPSCR_UX | + FPSCR_OX | FPSCR_FX | FPSCR_FI); + PPCMtfpscr(fpscr); + + PPCMtmsr(msr); + + if (__OSFPUContext == context) { + OSDisableScheduler(); + __OSErrorTable[exception](exception, context, dsisr, dar); + context->srr1 &= ~MSR_FP; + __OSFPUContext = NULL; + + context->fpscr &= ~(FPSCR_VXVC | FPSCR_VXIMZ | FPSCR_VXZDZ | FPSCR_VXIDI | FPSCR_VXISI | + FPSCR_VXSNAN | FPSCR_VXSOFT | FPSCR_VXSQRT | FPSCR_VXCVI | FPSCR_XX | + FPSCR_ZX | FPSCR_UX | FPSCR_OX | FPSCR_FX | FPSCR_FI); + OSEnableScheduler(); + __OSReschedule(); + } else { + context->srr1 &= ~MSR_FP; + __OSFPUContext = NULL; + } + + OSLoadContext(context); + } + + 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", now); + + 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/OSInterrupt.c b/src/Dolphin/os/OSInterrupt.c new file mode 100644 index 0000000..a7bed16 --- /dev/null +++ b/src/Dolphin/os/OSInterrupt.c @@ -0,0 +1,427 @@ +#include +#include + +static asm void ExternalInterruptHandler(register __OSException exception, + register OSContext* context); + +extern void __RAS_OSDisableInterrupts_begin(void); +extern void __RAS_OSDisableInterrupts_end(void); + +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 +entry __RAS_OSDisableInterrupts_end + rlwinm r3, r3, 17, 31, 31 + 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/Kyoto/Basics/RAssertDolphin.cpp b/src/Kyoto/Basics/RAssertDolphin.cpp index 07edb5e..40fbcf3 100644 --- a/src/Kyoto/Basics/RAssertDolphin.cpp +++ b/src/Kyoto/Basics/RAssertDolphin.cpp @@ -2,11 +2,12 @@ #include "dolphin/__start.h" #include "dolphin/ai.h" +#include "dolphin/dvd.h" #include "dolphin/os/OSMemory.h" +#include "dolphin/os/OSReset.h" #include "dolphin/pad.h" #include "dolphin/vi.h" - #include #include #include @@ -14,145 +15,155 @@ extern "C" void fn_803816B4(int); extern "C" void fn_80362EC4(void*); extern "C" void fn_80377118(int); +extern u32* fn_8033ED24(int); -static const char* buildTime = "Build v1.088 10/29/2002 2:21:25"; static char* rs_debugger_buffer; -static int lbl_80419820; -static bool lbl_80419818; +static int rs_debugger_size; +static bool SkipFatal = false; +static const GXColor bg = {128, 0, 0, 0}; +static const GXColor fg = {255, 255, 255, 0}; +static const uchar ExitButtons[4] = {PAD_BUTTON_RIGHT, PAD_BUTTON_LEFT, PAD_BUTTON_DOWN, + PAD_BUTTON_UP}; -#define COMPARE_TIME(current, last) (current / last) > 1.0 +static void hack() { + static const char* tmp1 = "%s\0\n"; + static const char* tmp2 = "0x%08x: 0x%08x 0x%08x"; + static const char* tmp3 = " 0x%08x: %s"; +} void ErrorHandler(OSError code, OSContext* context, int dsisr, uint dar) { - - uint loopExitCriteria; + char buffer[1024]; OSContext newContext; + uint loopExitCriteria; PADStatus pads[4]; - uint local_60; + uchar local_60[4]; + u32 iVar2; + u32* tmp; + u32* gpr; + uint i; + uint len; - if (code != OS_ERROR_PROTECTION || ((dsisr & 0x10) == 0 && (dar < 0x1800001))) { - OSProtectRange(3, 0, 0, 3); - memset((void*)0x81200000, 0, 0x280); - DCFlushRange((void*)0x81200000, 0x280); - fn_803816B4(0); - AIInitDMA(0x81200000, 0x280); - AIStartDMA(); - fn_80362EC4(nullptr); - loopExitCriteria = 0; - PADControlMotor(0, 0); - VISetBlack(1); - VIFlush(); - OSClearContext(&newContext); - OSSetCurrentContext(&newContext); - OSEnableInterrupts(); - OSTime lastTime = OSGetTime(); - OSTime currentTime; + if (code == 15 && ((dsisr & 0x10) != 0 || ((uint)dar > 0x1800000))) { + return; + } - while (loopExitCriteria < 4) { + OSProtectRange(3, 0, 0, 3); + memset((void*)0x81200000, 0, 0x280); + DCFlushRange((void*)0x81200000, 0x280); + AIRegisterDMACallback(NULL); + AIInitDMA(0x81200000, 0x280); + AIStartDMA(); + DVDCancelAll(nullptr); + loopExitCriteria = 0; + PADControlMotor(0, 0); + VISetBlack(1); + VIFlush(); + OSClearContext(&newContext); + OSSetCurrentContext(&newContext); + OSEnableInterrupts(); - currentTime = OSGetTime(); - if (COMPARE_TIME(currentTime, lastTime)) { - OSResetSystem(1, 0, 0); - } + OSTime lastTime = OSGetTime(); + OSTime currentTime; + while (loopExitCriteria < 4) { + + currentTime = OSGetTime(); + if (OSTicksToSeconds(currentTime - lastTime) >= 10) { + OSResetSystem(1, 0, 0); + } + + PADRead(pads); + while (pads[1].err == PAD_ERR_NO_CONTROLLER && OSTicksToSeconds(OSGetTime() - lastTime) < 10) { + PADReset(PAD_CHAN1_BIT); PADRead(pads); - while (pads[1].err == -1) { - currentTime = OSGetTime(); - if (COMPARE_TIME(currentTime, lastTime)) { - break; - } - fn_80377118(0x40000000); - PADRead(pads); - } + } - if (pads[1].err == 0) { - local_60 = 0x2010408; - if ((pads[1].button & 0xc10) == 0xc10) { - lastTime = OSGetTime(); - if ((pads[1].button & 0xf) != 0) { - if ((pads[1].button & loopExitCriteria) == - 0) { // TODO: wrong logic with loopExitCriteria - if ((loopExitCriteria != 0) && - pads[1].button == 0) { // TODO: wrong logic with pads[1].button - loopExitCriteria = 0; - } - } else { - loopExitCriteria += 1; - } + if (pads[1].err == PAD_ERR_NONE) { + *(uint*)local_60 = *(uint*)ExitButtons; + if ((pads[1].button & 0xc10) == 0xc10) { + lastTime = OSGetTime(); + + if ((pads[1].button & 0xf) != 0) { + if ((pads[1].button & local_60[loopExitCriteria]) != 0) { + loopExitCriteria += 1; + + } else if ((loopExitCriteria != 0) && + ((pads[1].button & local_60[loopExitCriteria - 1]) == 0)) { + loopExitCriteria = 0; } - } else { - loopExitCriteria = 0; + } + } else { + loopExitCriteria = 0; + } + } + } + + VISetBlack(0); + VIFlush(); + OSReport("Unhandled exception %d - Production\n", code); + OSReport("%s\n", BuildTime); + 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 + 0x10, context->gpr[i + 0x10], context->gpr[i + 0x10]); + } + + 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("DSISR= 0x%08x DAR = 0x%08x\n", dsisr, dar); + + if (rs_debugger_buffer != nullptr) { + strcpy(buffer, rs_debugger_buffer); + } else { + buffer[0] = 0; + } + len = strlen(buffer); + if (len != 0) { + len += sprintf(buffer + len, " - Production\n"); + } else { + len += sprintf(buffer, "Exception %d - Production\n", code); + } + len += sprintf(buffer + len, "%s\n", BuildTime); + len += sprintf(buffer + len, "IP: 0x%8.8x Mem: 0x%8.8x", context->srr0, dar); + if (code == 0xf) { + len += sprintf(buffer + len, " - %d", dsisr); + } + len += sprintf(buffer + len, "\n\n"); + + OSReport("\nAddress: Back Chain LR Save\n"); + + gpr = (u32*)context->gpr[1]; + for (i = 0; gpr != NULL && gpr != (void*)0xFFFFFFFF && i++ < rs_debugger_size + 16;) { + if (gpr > (void*)0x80000400 && gpr < (void*)0x81800000) { + if (i >= rs_debugger_size) { + OSReport("0x%08x: 0x%08x 0x%08x\n", gpr, *gpr, gpr[1]); + iVar2 = gpr[1]; + tmp = fn_8033ED24(iVar2); + if (tmp == NULL) { + len += sprintf(buffer + len, "0x%08x: 0x%08x 0x%08x\n", gpr, *gpr, gpr[1]); + } + + if (tmp != NULL) { + OSReport("RFO:0x%08x: %s\n", iVar2 - tmp[1], *tmp); + len += sprintf(buffer + len, "RFO:0x%08x: %s\n", iVar2 - tmp[1], *tmp); } } - } - VISetBlack(0); - VIFlush(); - OSReport("Unhandled exception %d - Production\n", code); - OSReport("%s\n", buildTime); - OSReport("------------------------- Context 0x%08x -------------------------\n", context); - - int i = 0; - do { - OSReport("r%-2d = 0x%08x (%14d) r%-2d = 0x%08x (%14d)\n", i, context->gpr[i], - context->gpr[i], i + 0x10, context->gpr[i + 0x10], context->gpr[i + 0x10]); - i += 1; - } while (i < 0x10); - - 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("DSISR= 0x%08x DAR = 0x%08x\n", dsisr, dar); - - char buffer[1024]; - - if (rs_debugger_buffer == nullptr) { - buffer[0] = 0; } else { - strcpy(buffer, rs_debugger_buffer); + OSReport("0x%08x: BAD PTR\n", gpr); + sprintf(buffer + len, "0x%08x: BAD PTR\n", gpr); + break; } + gpr = (u32*)*gpr; + } - int bufferSize = strlen(buffer); - if (bufferSize == 0) { - i = sprintf(buffer, "Exception %d - Production\n", code); - } else { - i = sprintf(buffer + bufferSize, " - Production\n"); - } - int j = sprintf(buffer + bufferSize + i, "%s\n", buildTime); - int bufferIndex = bufferSize + i + j; - bufferIndex += sprintf(buffer + bufferIndex, "IP: 0x%8.8x Mem: 0x%8.8x", context->srr0, dar); - if (code == 0xf) { - bufferIndex += sprintf(buffer + bufferIndex, " - %d", dsisr); - } - bufferIndex += sprintf(buffer + bufferIndex, "\n\n"); + OSReport("\nInstruction at 0x%x (read from SRR0) attempted to access invalid address 0x%x " + "(read from DAR)\n", + context->srr0, dar); - OSReport("\nAddress: Back Chain LR Save\n"); - - uint stackPtr = context->gpr[1]; - bool check; - i = 0; - while (true) { - if (((stackPtr == NULL) || (stackPtr == 0xffffffff)) || (check = 0xf < i, i += 1, check)) { - break; - } - if ((stackPtr < 0x80000401) || (0x817fffff < stackPtr)) { - OSReport("0x%08x: BAD PTR\n", stackPtr); - sprintf(buffer + j, "0x%08x: BAD PTR\n", stackPtr); - break; - } - uint* asPtr = (uint*)stackPtr; - - OSReport("0x%08x: 0x%08x 0x%08x\n", stackPtr, *asPtr, asPtr[1]); - bufferIndex += sprintf(buffer + j, "0x%08x: 0x%08x 0x%08x\n", stackPtr, *asPtr, asPtr[1]); - stackPtr = *asPtr; - } - OSReport("\nInstruction at 0x%x (read from SRR0) attempted to access invalid address 0x%x " - "(read from DAR)\n", - context->srr0, dar); - - if (!lbl_80419818) { - GXColor fg; // = &DAT_80000000; - GXColor bg; // = 0xffffff00; - OSFatal(fg, bg, buffer); - } + if (!SkipFatal) { + OSFatal(fg, bg, buffer); } } @@ -167,11 +178,11 @@ void rs_debugger_printf(const char* format, ...) { va_list arg; OSProtectRange(3, 0, 0, 3); - lbl_80419820 = 0; + rs_debugger_size = 0; if (strncmp(format, "SKIP", 4) == 0) { const char* s = format + 4; format += 5; - lbl_80419820 = *s - 0x30; + rs_debugger_size = *s - 0x30; } char buffer[0x400]; diff --git a/tools/decompctx.py b/tools/decompctx.py index 3b27d6c..28d3cba 100644 --- a/tools/decompctx.py +++ b/tools/decompctx.py @@ -17,7 +17,10 @@ import re script_dir = os.path.dirname(os.path.realpath(__file__)) root_dir = os.path.abspath(os.path.join(script_dir, "..")) src_dir = os.path.join(root_dir, "src") -include_dir = os.path.join(root_dir, "include") +include_dirs = [ + os.path.join(root_dir, "include"), + os.path.join(root_dir, "libc"), +] include_pattern = re.compile(r'^#include\s*[<"](.+?)[>"]$') guard_pattern = re.compile(r'^#ifndef\s+(.*)$') @@ -26,14 +29,15 @@ defines = set() def import_h_file(in_file: str, r_path: str) -> str: rel_path = os.path.join(root_dir, r_path, in_file) - inc_path = os.path.join(include_dir, in_file) if os.path.exists(rel_path): - return import_c_file(rel_path) - elif os.path.exists(inc_path): - return import_c_file(inc_path) + return import_c_file(rel_path) + for include_dir in include_dirs: + inc_path = os.path.join(include_dir, in_file) + if os.path.exists(inc_path): + return import_c_file(inc_path) else: - print("Failed to locate", in_file) - exit(1) + print("Failed to locate", in_file) + return "" def import_c_file(in_file) -> str: in_file = os.path.relpath(in_file, root_dir)