Add R on the main menu to boot Swiss and leave the test app

Getting back to Swiss previously meant power-cycling the console.  R boots
/boot.dol from the SD card directly.

It reuses netboot_boot_file(), so there is ONE DOL launcher and one set of
safety checks (MEM1 entry point, section overlap against the reserved staging
region, libfat unmounted before the jump) rather than a second copy to keep in
step.

Confirmed rather than one-touch, and main-menu only: 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 press.  Inside a suite R would
be easy to hit while navigating, so it is ignored there.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-10-09 19:17:34 +02:00
parent 1e370deb49
commit 1a1557ff54
2 changed files with 68 additions and 1 deletions
+13
View File
@@ -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:
+55 -1
View File
@@ -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 <gccore.h>
#include <stdio.h>
@@ -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 --