diff --git a/gc_bba_test/README.md b/gc_bba_test/README.md index 97c51a3..e5a5ba6 100644 --- a/gc_bba_test/README.md +++ b/gc_bba_test/README.md @@ -73,6 +73,19 @@ Builds clean (no warnings) with devkitPPC 16.1.0 / GCC 16 in the devcontainer: `.gitignore` excludes the build products — run `make` to produce the `.dol`. +## Boot Swiss (R button) + +**R** on the main menu boots `/boot.dol` from the SD card and leaves the test +app, so you can get back to Swiss without power-cycling the console. + +It asks for confirmation (A to go, B to cancel). R is an easy trigger to catch +by accident, test results are not saved anywhere, and losing a full run to a +stray press is worse than one extra button. It is also main-menu only — inside +a suite, R would be easy to hit while navigating. + +It uses the same `netboot_boot_file()` path as the post-update boot, so there +is one DOL launcher and one set of safety checks rather than two. + ## Self-update over the BBA (Z button) Press **Z**, then on the host: diff --git a/gc_bba_test/source/main.c b/gc_bba_test/source/main.c index 89720ae..ba1c725 100644 --- a/gc_bba_test/source/main.c +++ b/gc_bba_test/source/main.c @@ -9,6 +9,7 @@ * Y clear all results * B back * Z self-update over the BBA, then relaunch (see netboot.c) + * R boot Swiss (/boot.dol) and leave the test app */ #include #include @@ -92,7 +93,8 @@ static void draw_main(int sel, const char *status) } printf("\n"); } - printf("\n" C_DIM " A open X run suite START run all Y clear Z net-update\n" C_RESET); + printf("\n" C_DIM " A open X run suite START all Y clear " + "Z net-update R Swiss\n" C_RESET); if (status && *status) printf("\n %s\n", status); } @@ -198,6 +200,50 @@ static void do_netboot(char *status, size_t nstatus) "update saved, but /boot.dol would not boot (%d)", rc); } +/* Boot Swiss from the SD card and leave the test app. + * + * Confirmed rather than one-touch: R is an easy trigger to catch by accident, + * test results are not saved anywhere, and losing a full run to a stray press + * is worse than one extra button. */ +static void do_boot_swiss(char *status, size_t nstatus) +{ + int rc; + + printf("\n" C_HEAD " Boot Swiss (/boot.dol)" C_RESET "\n\n"); + printf(" A = confirm, B = cancel\n"); + printf(C_DIM " Test results are not saved and will be lost.\n" C_RESET); + + for (;;) { + u16 d; + VIDEO_WaitVSync(); + PAD_ScanPads(); + d = PAD_ButtonsDown(0); + if (d & PAD_BUTTON_B) { + snprintf(status, nstatus, "boot cancelled"); + return; + } + if (d & PAD_BUTTON_A) + break; + } + + if (!s_stage) { + snprintf(status, nstatus, "staging region unavailable"); + return; + } + + printf("\n booting /boot.dol ...\n"); + VIDEO_WaitVSync(); + VIDEO_WaitVSync(); + + /* Same path netboot uses after an update, so there is one DOL launcher + * and one set of safety checks rather than two. */ + rc = netboot_boot_file("/boot.dol", s_stage, s_stage_max, nb_status); + + /* Only reached on refusal -- the launcher does not return on success. */ + nb_pause("boot refused"); + snprintf(status, nstatus, "/boot.dol would not boot (%d)", rc); +} + int main(void) { int screen = 0; /* 0 = main, 1 = suite detail */ @@ -233,6 +279,14 @@ int main(void) down = PAD_ButtonsDown(0); if (!down) continue; + if (!screen && (down & PAD_TRIGGER_R)) { + /* Main menu only: inside a suite R would be easy to hit + * while navigating. */ + do_boot_swiss(status, sizeof(status)); + draw_main(sel, status); + continue; + } + if (down & PAD_TRIGGER_Z) { /* Self-update: pull a new .dol over the BBA and launch it. * Staged in a malloc'd buffer rather than written in place --