Repository navigation
feat(cheat): implement Game Genie + Pro Action Replay cheat codes (T-81-003) - #54
Conversation
…81-003) Adds rustysnes_core::cheat, decoding SNES Game Genie (XXXX-XXXX, 16-char alphabet) and Pro Action Replay (8 hex digits, no scrambling) codes into a 24-bit CPU-bus (address, value) patch. Ported from bsnes's CheatEditor::decodeSNES and cross-checked bit-for-bit against Mesen2's independent decoder; unit tests use real commercial codes from Mesen2's shipped cheat database as an external oracle. A decoded patch is applied via Bus::poke_wram (the same WRAM accessor the T-81-002 scripting/movie work already built), so a cheat is host-applied external input, not emulated hardware, and the determinism contract holds unchanged when the new `cheats` feature is off. Wires a Tools -> Cheats... window (native and wasm32 both, since decoding is pure computation with no mlua-style platform constraint) for adding/enabling/removing codes, applied every real frame before it runs. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
There was a problem hiding this comment.
Code Review
This pull request introduces Game Genie and Pro Action Replay cheat-code support under a new cheats feature flag, adding a decoding module in rustysnes-core and a dedicated UI window in the frontend to manage and apply patches. The review feedback highlights a critical correctness issue: Game Genie codes target ROM addresses rather than WRAM, meaning applying them via poke_wram will have no effect; instead, read operations should be intercepted. Additionally, the reviewer suggests avoiding heap allocations and double passes during decoding, resolving a potential lossy truncation in character casting, preserving specific parsing errors during format dispatch, and suffixing egui widget labels with unique IDs to prevent ID clashes in the cheat list.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
There was a problem hiding this comment.
Pull request overview
Adds SNES cheat-code support (Game Genie + Pro Action Replay) to RustySNES, introducing a core decoder and a feature-gated frontend UI + per-frame WRAM patch application, with accompanying documentation/changelog updates.
Changes:
- Add
rustysnes-core::cheatwith Game Genie / Pro Action Replay decoding + unit tests. - Add
rustysnes-frontendcheatsfeature: in-session cheat list, Tools → Cheats… UI, and per-frameBus::poke_wramapplication. - Update sprint tracking,
docs/STATUS.md, andCHANGELOG.mdto reflect T-81-003 completion and feature details.
Reviewed changes
Copilot reviewed 10 out of 10 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| to-dos/phase-8-reach/sprint-1-instrumentation.md | Marks T-81-003 acceptance criteria and sprint checklist as completed with implementation notes. |
| docs/STATUS.md | Updates frontend status to mention the new cheats feature and where it lives. |
| crates/rustysnes-frontend/src/ui_shell.rs | Adds Cheats window state and renders a new Cheats UI entry under Tools. |
| crates/rustysnes-frontend/src/lib.rs | Feature-gates and exports the new cheats module. |
| crates/rustysnes-frontend/src/cheats.rs | Implements cheat entry parsing/storage and per-frame WRAM application, plus tests. |
| crates/rustysnes-frontend/src/app.rs | Stores cheat list in Active and applies enabled cheats before each emulated frame. |
| crates/rustysnes-frontend/Cargo.toml | Introduces the cheats feature flag for the frontend. |
| crates/rustysnes-core/src/lib.rs | Exposes the new cheat module from core. |
| crates/rustysnes-core/src/cheat.rs | Implements the decoders + tests for Game Genie and Pro Action Replay. |
| CHANGELOG.md | Documents the new cheats feature for the upcoming release entry. |
…#54 - CRITICAL: real Game Genie/Pro Action Replay codes overwhelmingly target cartridge ROM (a pass-through cart intercepting CPU-visible reads), not WRAM. Applying decoded patches via Bus::poke_wram made virtually every real Game Genie code a silent no-op. Fixed by adding a Bus::set_cheats/read24 CPU-read intercept: Bus checks an installed patch list once per read (empty and one branch when unused) and substitutes a matching patch's value, without modifying the underlying ROM/RAM byte. crate::cheats::apply_all (WRAM poke) becomes crate::cheats::sync (installs the enabled set into Bus). - cheat.rs: genie_nibble no longer lossily casts a non-ASCII char to u8 (could alias onto a valid alphabet byte); decode_game_genie/ decode_pro_action_replay avoid the earlier Vec<char> allocation (no_std-conscious) while still checking shape (length/dash) before character content, which decode()'s corrected fallback depends on; decode() now only falls through to Pro Action Replay on a genuine UnrecognizedFormat, not any Game Genie error, so a Game-Genie-shaped code with an invalid character reports that specific error instead of a misleading "wrong format". - ui_shell.rs: the cheat list's per-row widgets (identical "" checkbox and "Remove" button labels in a loop) collided IDs across rows in egui; wrapped each row in ui.push_id(i, ...). Regression tests added for all four; full verification matrix (build/test/clippy default + cheats+scripting, wasm-winit/wasm-canvas clippy, no_std gate, fmt, doc gate) re-run clean. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Summary
Implements T-81-003's full stated scope, behind a new
cheatsflag:rustysnes_core::cheatmodule decodes SNES Game Genie codes (XXXX-XXXX, 9 characters including the dash, the 16-character alphabetDF4709156BC8A23E) and Pro Action Replay codes (8 hex digits,AAAAAADD— 6 hex-digit address, 2 hex-digit value, no scrambling) into a plain 24-bit CPU-bus(address, value)patch. Ported from bsnes'sCheatEditor::decodeSNES(ref-proj/bsnes/bsnes/target-bsnes/tools/cheat-editor.cpp) and cross-checked bit-for-bit against Mesen2's independentCheatManager::ConvertFromSnesGameGenie/ConvertFromSnesProActionReplay— both codebases compute an identical address/value for any given code. Unit tests decode real commercial codes drawn from Mesen2's shippedCheatDb.Snes.jsonas an external-oracle check.Bus::poke_wram(the same bank/mirror-aware accessor T-81-002's scripting/movie work already built), applied every real frame before it runs. A cheat is host-applied external input (docs/adr/0004), not emulated hardware — withcheatsoff, or no entries enabled, nothing executes and the determinism contract is untouched.address=value), gated#[cfg(feature = "cheats")]. Unlikescripting'smlua, cheat decoding is pure computation with no platform constraint, so this works on native and wasm32 both — verified via clippy on bothwasm-winitandwasm-canvas.Test plan
cargo test --workspace(357 tests, incl. 8 newrustysnes_core::cheatunit tests against real commercial-code oracles, 4 newrustysnes-frontend::cheatsunit tests)cargo clippy --workspace --all-targets -- -D warningscargo clippy -p rustysnes-frontend --all-targets --features cheats -- -D warningsand--features cheats,scriptingcargo clippy -p rustysnes-frontend --target wasm32-unknown-unknown --no-default-features --features wasm-winit,cheats --lib -- -D warningsandwasm-canvas,cheatscargo build -p rustysnes-core --target thumbv7em-none-eabihf --no-default-features(no_std gate)cargo fmt --checkRUSTDOCFLAGS="-D warnings" cargo doc --workspace --no-depsand-p rustysnes-frontend --features cheats,scriptingcheatsoff, full default-feature workspace build/test/clippy/fmt/doc verified unaffected🤖 Generated with Claude Code