From 9f2abdf4241d2033a1b606bf08514cdd074d434c Mon Sep 17 00:00:00 2001 From: Callan Barrett Date: Sat, 5 Sep 2026 20:31:11 +0800 Subject: [PATCH] fix(zaparoo): leave ACTIVEGAME alone when started from Zaparoo's temp MGL zaparoo_active_game_set_core() runs on every user_io_init(), including the app_restart() re-exec after a load_core, and wrote the MGL path for any .mgl start. Zaparoo Core and mrext send load_core with /media/fat/.LASTLAUNCH.mgl after writing the real game path themselves, so /tmp/ACTIVEGAME flipped from the game to the MGL about a second after every launch. Nothing wrote the game back: menu.cpp skips recent_update() while an MGL is processing. Skip the write for that one path. It is rewritten on every launch, so it never identifies a game. Bare-core starts still clear, menu-selected MRA and MGL starts still write, and set_file is unchanged. --- ZAPAROO_FORK.md | 2 +- support/zaparoo/active_game.cpp | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/ZAPAROO_FORK.md b/ZAPAROO_FORK.md index e47b4c876..8dc06c367 100644 --- a/ZAPAROO_FORK.md +++ b/ZAPAROO_FORK.md @@ -47,7 +47,7 @@ non-blocking spawn) are intentionally omitted. | 23 | **Startup trace** | `zlog()` lines (`alt_launcher t=: …`, flushed) at init queued, first poll, EDID retry, spawn, finalize, child exit, watchdog, stale sweep — capture with Main's stdout redirected to a file | `support/zaparoo/alt_launcher.cpp` | | 24 | **Input loop no longer spins on SD activity** | `input_test` drains events until `poll()` idles for 25 ms; the HPS LED's `brightness_hw_changed` attribute (mmc trigger) wakes it at kHz rates during sustained SD-card activity (a media scrape, for example), so the loop never idled and the UI cothread stalled 200–500 ms per pass — dropped OSD keys, laggy menus, delayed launcher polls. An LED-only wakeup now ends the drain | `input.cpp` (`input_test`, 1-line fork edit) | | 19 | **CI / build infrastructure** | Docker container build; binary named `MiSTer_Zaparoo`; "Z"-suffixed version; release / unstable CI; sync-upstream workflow; deploy script | `docker-build.sh`, `stable-build.sh`, `unstable-build.sh`, `deploy-zaparoo.sh`, `.github/build_*.sh`, `.github/workflows/*.yml` | -| 20 | **Direct active-game tracking** | Main writes the selected game's absolute path directly to `/tmp/ACTIVEGAME`, the MiSTer convention consumed by Zaparoo Core and other integrations. MRA/MGL startup writes it and bare-core startup clears it from `user_io_init()`; in-core file launches update it through the existing `recent_update()` call sites even when recents are disabled. This removes the need to force `RECENTS` or `LOG_FILE_ENTRY`; all upstream behavior behind those user-controlled options, including `/tmp/STARTPATH`, remains unchanged | `support/zaparoo/active_game.cpp/.h`; hooks in `user_io.cpp`, `recent.cpp` | +| 20 | **Direct active-game tracking** | Main writes the selected game's absolute path directly to `/tmp/ACTIVEGAME`, the MiSTer convention consumed by Zaparoo Core and other integrations. MRA/MGL startup writes it and bare-core startup clears it from `user_io_init()`, except a start from `/media/fat/.LASTLAUNCH.mgl`, the temp MGL Zaparoo Core and mrext generate for `load_core` after writing the game path themselves, which leaves the file untouched; in-core file launches update it through the existing `recent_update()` call sites even when recents are disabled. This removes the need to force `RECENTS` or `LOG_FILE_ENTRY`; all upstream behavior behind those user-controlled options, including `/tmp/STARTPATH`, remains unchanged | `support/zaparoo/active_game.cpp/.h`; hooks in `user_io.cpp`, `recent.cpp` | | 25 | **Fork settings store** | `config/zaparoo_settings.bin`, 16-byte blob read into a zeroed buffer so an absent or short file means today's behavior. Byte 0 = frontend **disabled**, byte 1 = kiosk **enabled**, byte 2 = save on core exit, byte 3 = physical-disc autorun, rest reserved and preserved by the read-modify-write setters. Cached (the predicates run per scheduler tick, per gamepad event and inside the OSD render loop) and keyed on the storage root. Deliberately not `MiSTer.ini`: an unknown key breaks non-fork Mains, upstream appends to `ini_vars[]` most releases, and the stable build excludes `MiSTer.ini` | `support/zaparoo/settings.cpp/.h` | | 26 | **Kiosk mode** | Total OSD lockout for card-only setups. Gates: `menu.cpp` key decode (covers F1/F7/F9/F10/F11/F12/ESC/Backspace, the front-panel tap and the keyrah Fn combo), the front-panel button block (its 3s hold sets `menustate` directly), the menu-core auto-open, and `SelectINI()` at boot. **The MGL clause in the auto-open condition is deliberately not gated**: it is how a card launches core + ROM, and gating it would load the core but never mount the game. Deliberately does **not** touch the menu background: whatever the user chose via `status[3:1]` (default 0 = the core's own snow, or a wallpaper / test pattern) is what shows. The idle screensaver keeps working to whatever `OSD_TIMEOUT` / `VIDEO_OFF` say: its countdown only runs while `menustate` is the file browser, which kiosk never reaches, so kiosk substitutes `MENU_NONE2` as the idle state, and skips the `OsdMenuCtl(1)` on wake because that would turn the overlay on over stale OSD buffer contents. Recovery is deleting the settings file | `support/zaparoo/kiosk.cpp/.h`, `menu.cpp:626,1341,1640`, `user_io.cpp:1472` | | 27 | **`zaparoo_` command surface** | `zaparoo_command()` dispatches every `zaparoo_`-prefixed `/dev/MiSTer_cmd` line: `zaparoo_console ...` delegates to `alt_launcher_command()`, plus `zaparoo_kiosk on\|off\|toggle` and `zaparoo_frontend on\|off\|toggle` (both persisted), `zaparoo_osd open\|close\|toggle`, `zaparoo_save`, `zaparoo_mount [path]` and `zaparoo_cheat ...` (row 33). The upstream hook stays one line: the existing `zaparoo_console` prefix test, trailing space included, was widened to `zaparoo_`. `zaparoo_osd` is the everyday admin route under kiosk: a **session-only** bypass that lifts the gates without changing the setting, raising the same `menu_key_set(KEY_F12 \| UPSTROKE)` user_io raises for a real F12 so it works on a game core too. It is deliberately not persisted and dies on the next core load, since that re-execs Main. Cards must be set up before kiosk is switched on | `support/zaparoo/command.cpp/.h`, `support/zaparoo/kiosk.cpp`, `input.cpp` (cmd FIFO dispatch) | diff --git a/support/zaparoo/active_game.cpp b/support/zaparoo/active_game.cpp index e460bc147..c535f4912 100644 --- a/support/zaparoo/active_game.cpp +++ b/support/zaparoo/active_game.cpp @@ -3,9 +3,14 @@ #include #include #include +#include #include "file_io.h" static const char s_active_game_file[] = "/tmp/ACTIVEGAME"; +// Zaparoo Core and mrext generate this MGL for every load_core they send and +// write the real game path to ACTIVEGAME themselves before sending it. The file +// is rewritten on the next launch, so its path never identifies a game. +static const char s_launcher_temp_mgl[] = "/media/fat/.LASTLAUNCH.mgl"; static void active_game_write(const char *path) { @@ -26,6 +31,7 @@ static void active_game_write(const char *path) void zaparoo_active_game_set_core(const char *path) { + if (path && isXmlName(path) == 2 && !strcasecmp(getFullPath(path), s_launcher_temp_mgl)) return; active_game_write(path && isXmlName(path) ? path : ""); }