# MegaManX2SNESRecomp Static recompilation of **Mega Man X2 (USA)** built on [snesrecomp](https://github.com/mstan/snesrecomp), sharing the [recomp-ui](https://github.com/mstan/recomp-ui) pre-boot launcher with the other SNES recomp ports. You must supply your own legally-obtained ROM. Nothing ROM-derived is committed here. ## ROM identity | | | |---|---| | file | `mmx2.sfc` at the repo root | | size | headerless, verified against the digest below | | CRC32 | `0x947B0355` | | SHA-256 | `f3246755f608a1e1dc9c848b61da3b824c7853b29b3be40df6fc7f2793a887ed` | A 512-byte SMC copier header is stripped automatically by both the recompiler and the launcher, so headered dumps verify against the same digest. ## Status **Boots to its intro cutscenes.** Verified by screenshot through the debug surface: the opening story scenes render with correct BG layers, sprites, palettes and text, and advance between scenes. Still open: broad gameplay/oracle coverage, audio verification, and the stage-specific widescreen defects recorded in `docs/OAM_SURVEY.md`. This project was stood up from the MegamanXRecomp host layer; every Mega Man X 1 specific finding (the fiber task scheduler, the BG2 widescreen shadow, the MMX1 WRAM stage gates) was deliberately *not* carried over, because none of it is known to hold for Mega Man X2. What that means concretely: * **Execution is LLE-first.** `src/x2_rtl.c` boots the real RESET vector through the interpreter bridge, injects NMI only once the game arms NMITIMEN, and services IRQs as they latch. AOT coverage from `recomp/*.cfg` is layered on as an optimization; anything not covered runs the real ROM bytes. * **`recomp/bank00.cfg` is a one-directive seed** (`auto_vectors` + `tier_down_stubs`). Static coverage grows from there. * **Widescreen is a built-in Mod.** Its HUD anchoring, exact background-margin fill, weather handling, and object-window widening are implemented, while known residual stage-specific defects remain documented. The feature is disabled by default and activated from **Mods**, not generic Settings. * **The interrupt handlers live in WRAM.** The ROM's native NMI/IRQ vectors point at `$00:1FEF` / `$00:1FF3` (the low WRAM mirror), where boot installs `JML` trampolines into a driver block copied out of ROM bank `$08`. That is the same class as SMW's `$7F8000` RAM routine, so the engine's `ram_routine` guarded-AOT mechanism is the eventual path to compiling it; today it runs interpreted. * **An IRQ is delivered only when `P.I` is clear.** `g_snes->inIrq` is the hardware IRQ *line*, which stays asserted until `$4211` is read; the 65816 only takes it while interrupts are enabled. Mega Man X2 plants `NOP / BRA self` at its WRAM IRQ entry as the *un-armed* state and patches it when it actually wants the raster IRQ — so delivering an IRQ without checking `P.I` parks the guest in that spin loop for the rest of the host frame. Symptom: interpreter step-cap bails every frame and `master_cycles` running tens of frames ahead of the deadline, with the screen stuck in forced blank. ### Cx4 — no firmware dump required Mega Man X2 carries Capcom's **Cx4** (a Hitachi HG51B S169 DSP; internal header chipset `$F3`, `$FFBF` sub-type `$10`). The engine emulates it at the **instruction level** (`snesrecomp/runner/src/snes/cx4.c`, from ares, ISC) -- the faithful LLE floor. Without it the game spins forever on the Cx4 status register at `$7F5E` and never lifts forced blank. The chip's internal 1024-entry data ROM is synthesized from six closed-form mathematical tables and has been verified bit-exact against a real dump. No firmware file is needed. An optional 3072-byte `cx4.rom`, supplied beside the executable or through `$SNESRECOMP_CX4_ROM`, only cross-checks the synthesis; the file wins if a platform ever produces a mismatch. Read `docs/CX4.md` before debugging anything Cx4-shaped. ## Debugging The trace build carries a TCP debug server on port 4383 plus the always-on observability rings. Probes QUERY the rings; they never arm a recorder and then run a workload. ```bash python tools/dbgprobe.py ppu # live PPU state python tools/dbgprobe.py offrails # out-of-range cart access ring python tools/dbgprobe.py cx4 # Cx4 command ring + unknown-command count python tools/dbgprobe.py shot x.bmp # screenshot through the debug surface ``` ## Build ```bash git submodule update --init --recursive cp /path/to/your/dump mmx2.sfc bash tools/regen.sh --no-tests # emit src/gen/*.c + recomp/funcs.h cmake -S . -B build -G Ninja -DSNESRECOMP_ENABLE_TRACE=ON cmake --build build ``` `-DSNESRECOMP_ENABLE_TRACE=ON` builds the TCP debug server and the always-on observability rings — the bring-up configuration. Omit it for a release build. This title opts into snesrecomp's package loader. The build preloads a default-disabled Mega Man X2 Widescreen feature under `mods/packages`; users may also install data-only `.snesmod` archives from the launcher's Mods page. ## Disassembly annotations [bogaa/dizProjects](https://github.com/bogaa/dizProjects) is pinned at `third_party/dizProjects`. The tracked [symbol metadata](symbols/README.md) includes 32,462 identified instructions and recorded CPU modes. Upstream currently provides only a reset label. Regeneration applies the annotations; re-import with `python tools/diz_annotations.py --game x2`. ## License PolyForm Noncommercial 1.0.0. See `LICENSE`. Code in this repo is original; vendored dependencies under `third_party/` retain their own licenses. The game ROM and any data extracted from it are **not** in this repo and are not licensed for redistribution. Save-state and rewind controls, compatibility and focused verification: [SAVE_STATES.md](docs/SAVE_STATES.md).