feat(zaparoo): auto-save cartridge SRAM on a timer#9
Conversation
Periodically pulse the core's "Save Backup RAM" / "Save Memory Card" status bit so dirty SRAM flushes to the mounted save file without the user opening the OSD. The pulse is identical to selecting the OSD menu item, so no new write path to the SD card is introduced. Guard chain before each pulse: conf-string trigger discovered at core load, .fla (N64 FlashRAM) deny, 5s post-mount settle, 1s sector-write quiet window, OSD closed, and the core's own H/D menumask honored via UIO_GET_OSDMASK (masks no-battery games, GBA's write-gated bk_ena, etc). Recovery layers per save: rolling .bak.0..2 generations with atomic tmp+fsync+rename copies, a per-mount .mount anchor, an all-zero/all-FF/ shrink sanity abort, and an external-modification disarm (mtime/size). Saves are tracked per SD slot (N64 mounts several save files; PSX mounts its memcard at slot 2). Off by default; enable with AUTO_SAVE=N seconds in MiSTer.ini. Mechanism credit: Biduleman's SNES_MiSTer_DirectSave (skip-osd-save). Design doc and per-core verification: AUTO_SAVE_PLAN.md.
📝 WalkthroughWalkthroughThis PR introduces an auto-save subsystem for the MiSTer emulator that periodically pulses core save menu triggers to flush SRAM and memory card data without user intervention, protected by seven guards (menu visibility, timers, menumask gating, external-modification detection, corruption checks) and four durability layers (rolling backups, per-mount anchors, sanity validation, atomic operations). ChangesAuto-save Feature Implementation
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@AGENTS.md`:
- Around line 33-38: The fenced code block containing the docker-build.sh
examples is missing a language identifier; update the opening fence to "```bash"
(i.e., change the block that lists "./docker-build.sh", "./docker-build.sh
clean", etc.) so the snippet is labeled as bash for proper syntax highlighting
and to satisfy the linter.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 9bcd24b0-8296-4974-a0be-2edea87c59da
📒 Files selected for processing (8)
AGENTS.mdAUTO_SAVE_PLAN.mdcfg.cppcfg.hscheduler.cppsupport/zaparoo/auto_save.cppsupport/zaparoo/auto_save.huser_io.cpp
support/zaparoo/auto_save.{cpp,h}: a poll-driven module that periodically pulses the core's "Save Backup RAM" / "Save Memory Card" status bit so dirty cartridge SRAM flushes to the mounted save file without opening the OSD. The pulse is byte-for-byte what the OSD menu item does (menu.cpp firesuser_io_status_set(opt, 1)then(opt, 0)), so no new write path to the SD card exists..flaN64 FlashRAM deny, 5s post-mount settle window, 1s sector-write quiet window, OSD-closed check, and the core's live H/D menumask read viaUIO_GET_OSDMASK— auto-save can only fire when the user could select the menu item themselves (masks no-battery games, GBA's write-gatedbk_ena, SRAM-as-RAM quirk titles)..bak.0–.bak.2generations via atomic tmp+fsync+rename copies, a once-per-mount.mountanchor, an all-zero/all-0xFF/shrink corruption check that aborts the cycle, and an external-modification disarm (mtime/size baseline) so FTP-imported saves are never stomped.use_saveglobal.scheduler.cpppoll call,user_io.cppmount/unmount + sector-write notifications, and anAUTO_SAVEini var incfg.{h,cpp}(seconds between attempts,0= disabled = default).AUTO_SAVE_PLAN.mddocuments the design, the per-core verification against MiSTer-devel core sources (conf-string bits andbk_savewiring), the safety analysis, the recovery procedure, and the on-hardware verification matrix../docker-build.shas the preferred build path in AGENTS.md.Mechanism credit: Biduleman's SNES_MiSTer_DirectSave fork (branch
skip-osd-save).Refs MiSTer-devel#789
Summary by CodeRabbit
New Features
Documentation