Need help getting started? Try the player guide. These notes include older work; the game overview explains what’s ready now.
Level selection and saved data
Single Player now lists New Game, Select Level, Password in that order. Select Level uses the original small font and localized level names from ROM text entries48..59, with two fixed chapter pages of six levels (1..6 and7..12). Up/Down selects levels and crosses the chapter boundary between6and7. Left/Right and clickable arrows switch chapters while preserving the row; at the first/last chapter they keep the selection. The pages are named Egypt and Rome (localized in German/French), and level names have no number prefixes. Mouse hover/click selects a visible row. Six rows use16-pixel spacing starting atY40; the final row is atY120 and status stays atY144. Each row uses a separate original-font overlay batch so long localized names plus the header/status do not exceed the128-glyph batch limit. Original map-view output and structure layout remain unchanged. Padlocks identify locked maps; the selected row also explains Locked or Not Yet Available. No multiplayer maps appear. All12 campaign names are listed; the current port admits all12. The user requested manual campaign validation; availability is no longer gated on automated playthrough results.
Level1 is always unlocked. Level N requires the completion bit for N-1, on any difficulty. A password/direct start does not grant completion. Actually beating such a level does unlock its successor; unrelated preceding levels stay locked. New Game does not erase existing progress. Selecting a level then choosing a difficulty uses original loadout setting difficulty*12+level+1, including level0. Ordinary New Game retains setting0, and normal level advancement still carries earned equipment. The save does not store in-level state or inventory.
The Windows frontend saves language immediately when Options changes it and records completion on the first successful native tick with a real VM exit, finished state and a living player. It saves before an Enter advancement or application close can discard that completed game. Restart cannot award a completion. Original simulation and script rules are unchanged.
play-native.cmd runs from the workspace, so its persistent file is save.dat
beside the launcher. Direct executable launches use their working directory;
--save-file PATH overrides it. Automated startup/smoke diagnostics use defaults
without reading/writing the user's save unless an explicit test path is given.
All save validation uses isolated files under build/profile/.
The16-byte portable format is independent of C structure layout:
| Bytes | Value |
|---|---|
| 0..7 | ASCII SSA-SAVE |
| 8 | Version1 |
| 9 | Language0..2 |
| 10..11 | Little-endian12-bit completion mask |
| 12..15 | Little-endian CRC32 of bytes0..11 |
Wrong lengths, magic, version, checksum, language and reserved completion bits are rejected without modifying the decoder's output. A missing file is a fresh profile. Invalid/unreadable saves produce an error and default settings; loading alone does not overwrite them. A subsequent settings/completion/reset action can write a valid replacement. Save failures are logged and do not crash gameplay.
profile_win32.c locks writers through a transient .lock file, reloads the
latest valid profile, applies only the current event, writes a unique temporary
file, flushes its data and replaces the destination using MoveFileExW with
REPLACE_EXISTING/WRITE_THROUGH. A failed replacement preserves the existing
save. Temporary/lock handles are cleaned up. Separate sessions preserve each
other's completion/language changes; a stale session cannot restore progress
removed by Clear Data merely by saving its older local copy.
Options now has Music, Credits, Language, Clear Data. Clear Data opens a warning that saved progress and language will be deleted, with Yes/No and No selected initially. No or Esc returns unchanged. Confirming Yes writes a default profile, resets language to English immediately and locks all levels after level1. Music is not part of the saved data and is unaffected. This is a requested native PC save feature, not a claim to have recovered an original GBA save routine.
Validation commands:
.\decomp.ps1 test-profile
.\decomp.ps1 test-menu
.\decomp.ps1 test-menu-rom
powershell -ExecutionPolicy Bypass -File scripts/test-profile.ps1 -SkipBuild
powershell -ExecutionPolicy Bypass -File scripts/test-native-menu.ps1 -SkipBuild
profile-validation.json covers590142 sanitizer/leak checks,1239 menu frames,
90 selected-level starts over3 languages/difficulties, all12 campaign names,
all4096 completion masks,128 single-bit file corruptions, fixed six-level chapter
pages, page-arrow and level6/7 transitions, complete localized row pixels, locked/unavailable
choices, mouse input and reset cancellation/confirmation. menu-validation.json
passes72577checks/9547frames/18New Games, including the later typed-password
padding fix. The ROM fixture still compares8694
original menu frames and15552000 pixels. It explicitly skips the inserted PC
selection in its two-row original Single Player navigation and draws the added
labels with the actual original font routine; it does not claim original ROM
callbacks for the new level-select or reset screens.
windows-profile-validation.json adds37 file/host checks, corrupt/read-only file
handling, interleaved writers and reset, plus a genuine5110-frame normal-input
level1 completion saved by the exact frontend tick hook. Separate game processes
then load that file, retain German and select the newly unlocked level2 with its
original starting loadout and entry restart in both renderers. Physical input
and arbitrary interruption/power-loss fault injection remain untested.