crash screen: support for libultra asserts

This commit is contained in:
a
2025-07-14 22:53:11 -04:00
parent b632aa8c3d
commit a6761e664f
8 changed files with 53 additions and 11 deletions

View File

@@ -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*);

View File

@@ -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();

View File

@@ -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);

View File

@@ -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);
}

View File

@@ -2,6 +2,12 @@
#include <stdarg.h>
#include <string.h>
#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);
}

View File

@@ -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);
}

View File

@@ -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;

3
src/init/reboot.h Normal file
View File

@@ -0,0 +1,3 @@
#pragma once
void reboot(s32 rom, s32 tv, s32 reset, s32 cic);