Port registry, per-call shadow, first port battle/Rand #12

Merged
Gatchan merged 2 commits from registry into main 2026-10-29 08:54:36 +00:00
Owner

Closes the first item of the Phase 1 milestone: the porting scaffold inside the core.

Content

  • core/port: registry (name, address per version, bridge, don't-care set), modes off/shadow/on, deferred per-call shadow on the LakeSnes instruction hook: copy the machine, run the C on the copy, compare when the original returns (CPU registers and flags, WRAM minus dead stack below S, VRAM, CGRAM, OAM). Calls crossing a frame boundary are skipped; bridges refuse unsupported entry states (fallback to the interpreter).
  • First port: battle/Rand (core/game/battle/battle_random.c), game terms only; RNG table through core/res (by id, not address), index through a core/state accessor.
  • Debug API ff6_debug.h: ports, memories, PC, S. ff6cli --port <name|all>=<off|shadow|on>.
  • Test rom.ports.* (label slow): three cores in lockstep over tests/inputs/newgame_first_battle.txt.
  • docs/validation.md.

Validation

  • shadow battle/Rand: US 13/13, JP 16/16 (9500 frames), 0 fallback; ctest release 5/5.
  • Finding (issue #11): with the port on, pictures stay identical but the CPU-side sound driver state ($7E:131E) diverges at frame 8792 and audio from frame 8784: a port does not spend the original's cycles, and FF6 state depending on the CPU/SPC700 handshake timing takes another path. Shadow is therefore the exact criterion; on-mode divergence is reported, not required.

Fixes #5. Refs #11.

🤖 Generated with Claude Code

Closes the first item of the Phase 1 milestone: the porting scaffold inside the core. ## Content - `core/port`: registry (name, address per version, bridge, don't-care set), modes off/shadow/on, deferred per-call shadow on the LakeSnes instruction hook: copy the machine, run the C on the copy, compare when the original returns (CPU registers and flags, WRAM minus dead stack below S, VRAM, CGRAM, OAM). Calls crossing a frame boundary are skipped; bridges refuse unsupported entry states (fallback to the interpreter). - First port: `battle/Rand` (`core/game/battle/battle_random.c`), game terms only; RNG table through `core/res` (by id, not address), index through a `core/state` accessor. - Debug API `ff6_debug.h`: ports, memories, PC, S. `ff6cli --port <name|all>=<off|shadow|on>`. - Test `rom.ports.*` (label `slow`): three cores in lockstep over `tests/inputs/newgame_first_battle.txt`. - `docs/validation.md`. ## Validation - shadow `battle/Rand`: US 13/13, JP 16/16 (9500 frames), 0 fallback; ctest release 5/5. - Finding (issue #11): with the port **on**, pictures stay identical but the CPU-side sound driver state (`$7E:131E`) diverges at frame 8792 and audio from frame 8784: a port does not spend the original's cycles, and FF6 state depending on the CPU/SPC700 handshake timing takes another path. Shadow is therefore the exact criterion; on-mode divergence is reported, not required. Fixes #5. Refs #11. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
refs #5 #11

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
core/port: registry keyed by version and address, bridges with fallback, deferred shadow on
the LakeSnes instruction hook (clone, compare CPU, WRAM minus dead stack, VRAM, CGRAM, OAM),
mode on. core/res (RNG table by id), core/state accessor, debug API (ports, memories, PC, S),
ff6cli --port, test rom.ports.* (label slow). fixes #5

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
Gatchan/FF6Portage!12
No description provided.