From a6761e664f856610ce23160193cf2f09af5f6682 Mon Sep 17 00:00:00 2001 From: a Date: Mon, 14 Jul 2025 22:53:11 -0400 Subject: [PATCH] crash screen: support for libultra asserts --- sm64.ld | 3 +++ src/game/game_init.c | 9 ++++++--- src/game/game_init.h | 1 + src/game/rumble_init.c | 2 +- src/init/crash_screen.c | 28 +++++++++++++++++++++++++--- src/init/main.c | 8 ++++---- src/init/main.h | 10 ++++++++++ src/init/reboot.h | 3 +++ 8 files changed, 53 insertions(+), 11 deletions(-) create mode 100644 src/init/reboot.h diff --git a/sm64.ld b/sm64.ld index 584f7af1..06f77485 100755 --- a/sm64.ld +++ b/sm64.ld @@ -47,6 +47,7 @@ SECTIONS { BUILD_DIR/asm/entry.o(.text); BUILD_DIR/asm/decompress.o(.text*); + BUILD_DIR/asm/reboot.o(.text); BUILD_DIR/src/init/dma_async.o(.text); BUILD_DIR/src/init*.o(.text); AUDIO_DIR*.o(.text); @@ -58,6 +59,7 @@ SECTIONS BUILD_DIR/asm/entry.o(.data*); BUILD_DIR/asm/decompress.o(.data*); + BUILD_DIR/asm/reboot.o(.data*); BUILD_DIR/src/init/dma_async.o(.data); BUILD_DIR/src/init*.o(.data*); AUDIO_DIR*.o(.data*); @@ -69,6 +71,7 @@ SECTIONS BUILD_DIR/asm/entry.o(.rodata*); BUILD_DIR/asm/decompress.o(.rodata*); + BUILD_DIR/asm/reboot.o(.rodata*); BUILD_DIR/src/init/dma_async.o(.rodata); BUILD_DIR/src/init*.o(.rodata*); AUDIO_DIR*.o(.rodata*); diff --git a/src/game/game_init.c b/src/game/game_init.c index aee1a59a..7e35aa07 100644 --- a/src/game/game_init.c +++ b/src/game/game_init.c @@ -527,12 +527,15 @@ void run_demo_inputs(void) { /** * Update the controller struct with available inputs if present. */ -void read_controller_inputs(void) { +void read_controller_inputs(s32 thread) { s32 i; #ifndef CFG_BENCHMARK // If any controllers are plugged in, update the controller information. if (gControllerBits) { - osRecvMesg(&gSIEventMesgQueue, &gMainReceivedMesg, OS_MESG_BLOCK); + if (thread == THREAD5_GAME) { + osRecvMesg(&gSIEventMesgQueue, &gMainReceivedMesg, OS_MESG_BLOCK); + } + osContGetReadData(&gControllerPads[0]); #if ENABLE_RUMBLE release_rumble_pak_control(); @@ -708,7 +711,7 @@ void thread5_game_loop(UNUSED void *arg) { } audio_game_loop_tick(); select_gfx_pool(); - read_controller_inputs(); + read_controller_inputs(THREAD5_GAME); addr = level_script_execute(addr); display_and_vsync(); diff --git a/src/game/game_init.h b/src/game/game_init.h index 2e1d2fcd..d21715b1 100644 --- a/src/game/game_init.h +++ b/src/game/game_init.h @@ -65,6 +65,7 @@ extern u8 gDemoInputs[]; extern u16 sRenderingFramebuffer; extern u32 gGlobalTimer; +void read_controller_inputs(s32 thread); void setup_game_memory(void); void thread5_game_loop(UNUSED void *arg); void clear_framebuffer(s32 color); diff --git a/src/game/rumble_init.c b/src/game/rumble_init.c index 9b71e201..7efe1f4f 100644 --- a/src/game/rumble_init.c +++ b/src/game/rumble_init.c @@ -296,7 +296,7 @@ void cancel_rumble(void) { void create_thread_6(void) { osCreateMesgQueue(&gRumbleThreadVIMesgQueue, &gRumbleThreadVIMesgBuf, 1); - osCreateThread(&gRumblePakThread, 6, thread6_rumble_loop, NULL, gThread6Stack + 0x2000, 30); + osCreateThread(&gRumblePakThread, THREAD6_RUMBLE, thread6_rumble_loop, NULL, gThread6Stack + 0x2000, 30); osStartThread(&gRumblePakThread); } diff --git a/src/init/crash_screen.c b/src/init/crash_screen.c index 971071bb..3a41f062 100644 --- a/src/init/crash_screen.c +++ b/src/init/crash_screen.c @@ -2,6 +2,12 @@ #include #include +#include "cfg/crash.h" + +#include "main.h" +#include "game/game_init.h" +#include "reboot.h" + #include "sm64.h" #include "PR/os_internal.h" @@ -296,11 +302,12 @@ void draw_crash_screen(OSThread *thread) { n64_printf("\n"); crash_screen_print_float_reg(30, 220, 30, &tc->fp30.f.f_even); n64_printf("\n"); - n64_printf("==============================================\n"); + n64_printf("=============================================\n"); osViBlack(FALSE); crash_screen_sleep(2500); if (assertMsg != NULL) { crash_screen_draw_rect(25, 45, 270, 185); + n64_printf(assertMsg); crash_screen_print(30, 50, assertMsg); } play_music(SEQ_PLAYER_LEVEL, SEQ_LEVEL_BOSS_KOOPA, 0); @@ -331,6 +338,11 @@ void thread2_crash_screen(UNUSED void *arg) { thread = get_crashed_thread(); } while (thread == NULL); +#ifdef CFG_CRASH_REBOOT + reboot(osRomType, osTvType, osResetType, 0x3F); + __builtin_unreachable(); +#endif + if (thread->id == 5 || thread->id == 6) { // only care about this if game or rumble crashes gCrashScreen.thread.priority = 15; sound_reset(0); @@ -344,7 +356,17 @@ void thread2_crash_screen(UNUSED void *arg) { osWritebackDCacheAll(); draw_crash_screen(thread); - for (;;) { + while (TRUE) { + if (gControllerBits) { +#if ENABLE_RUMBLE + block_until_rumble_pak_free(); +#endif + osContStartReadData(&gSIEventMesgQueue); + } + read_controller_inputs(2); + if (gPlayer1Controller->buttonPressed) { + reboot(osRomType, osTvType, osResetType, 0x3F); + } } } @@ -358,7 +380,7 @@ void crash_screen_init(void) { gCrashScreen.width = SCREEN_WIDTH; gCrashScreen.height = 0x10; osCreateMesgQueue(&gCrashScreen.mesgQueue, &gCrashScreen.mesg, 1); - osCreateThread(&gCrashScreen.thread, 2, thread2_crash_screen, NULL, + osCreateThread(&gCrashScreen.thread, THREAD2_FAULT, thread2_crash_screen, NULL, (u8 *) gCrashScreen.stack + sizeof(gCrashScreen.stack), OS_PRIORITY_RMON); osStartThread(&gCrashScreen.thread); } diff --git a/src/init/main.c b/src/init/main.c index d495f963..123504b5 100644 --- a/src/init/main.c +++ b/src/init/main.c @@ -340,10 +340,10 @@ void thread3_main(UNUSED void *arg) { crash_screen_init(); - create_thread(&gSoundThread, 4, thread4_sound, NULL, gThread4Stack + 0x2000, 20); + create_thread(&gSoundThread, THREAD4_SFX, thread4_sound, NULL, gThread4Stack + 0x2000, 20); osStartThread(&gSoundThread); - create_thread(&gGameLoopThread, 5, thread5_game_loop, NULL, gThread5Stack + 0x2000, 10); + create_thread(&gGameLoopThread, THREAD5_GAME, thread5_game_loop, NULL, gThread5Stack + 0x2000, 10); osStartThread(&gGameLoopThread); while (TRUE) { @@ -446,7 +446,7 @@ void thread1_idle(UNUSED void *arg) { osViSetSpecialFeatures(OS_VI_DITHER_FILTER_ON); osViSetSpecialFeatures(OS_VI_GAMMA_OFF); osCreatePiManager(OS_PRIORITY_PIMGR, &gPIMesgQueue, gPIMesgBuf, ARRAY_COUNT(gPIMesgBuf)); - create_thread(&gMainThread, 3, thread3_main, NULL, gThread3Stack + 0x2000, 100); + create_thread(&gMainThread, THREAD3_MAIN, thread3_main, NULL, gThread3Stack + 0x2000, 100); if (D_8032C650 == 0) { osStartThread(&gMainThread); } @@ -463,6 +463,6 @@ void main_func(void) { osInitialize(); stub_main_1(); - create_thread(&gIdleThread, 1, thread1_idle, NULL, gIdleThreadStack + 0x800, 100); + create_thread(&gIdleThread, THREAD1_IDLE, thread1_idle, NULL, gIdleThreadStack + 0x800, 100); osStartThread(&gIdleThread); } diff --git a/src/init/main.h b/src/init/main.h index e0a670ae..b0100623 100644 --- a/src/init/main.h +++ b/src/init/main.h @@ -3,6 +3,16 @@ #include "config.h" +enum { + THREAD0_NONE, + THREAD1_IDLE, + THREAD2_FAULT, + THREAD3_MAIN, + THREAD4_SFX, + THREAD5_GAME, + THREAD6_RUMBLE +}; + extern OSThread D_80339210; extern OSThread gIdleThread; extern OSThread gMainThread; diff --git a/src/init/reboot.h b/src/init/reboot.h new file mode 100644 index 00000000..83d343a6 --- /dev/null +++ b/src/init/reboot.h @@ -0,0 +1,3 @@ +#pragma once + +void reboot(s32 rom, s32 tv, s32 reset, s32 cic);