1
0
Fork 0
mirror of https://github.com/imjasonh/nescript synced 2026-07-08 00:45:38 +00:00
Commit graph

2 commits

Author SHA1 Message Date
Claude
a5f508a678
linker+ci: fix .dbg seg.ooffs to include iNES header + deepen probe
The `seg.ooffs` field in our ca65 .dbg output was off by 16 — it was
emitting the PRG-relative fixed-bank offset when ca65's convention
(and Mesen's DbgImporter.cs:301 math:
`Address = val - seg.start + ooffs - headerSize`) expects the raw
output-file offset, *including* the iNES header. The practical
consequence: every label Mesen resolved via the .dbg was 16 bytes
short of its true PRG offset, which silently corrupted source-line
mapping for the first bytes of each function.

Fix is a one-liner — drop the `saturating_sub(16)` and feed
`linked.fixed_bank_file_offset` straight into the ooffs field. Unit
tests in debug_symbols.rs updated to assert the new values (ooffs=16
for NROM, 16+16K*N for banked).

The Mesen probe (`tests/mesen/probe.lua`) is expanded in the same
change, because the sabotage test that caught this bug is also the
cleanest demonstration the probe is working:
 * checks all four entry-point labels resolve and land inside the
   fixed bank's CPU window ($C000-$FFFF);
 * asserts the linker's relative ordering (main_loop < Main_frame
   < nmi);
 * registers a startFrame callback, waits three frames, and verifies
   PC is still in the fixed bank + that `emu.read(main_loop.address,
   nesPrgRom)` returns 0xA5 (the LDA-zp opcode the runtime always
   places as main_loop's first instruction). The 0xA5 constant is
   what catches the ooffs regression — a less-specific "not 0xFF"
   check coincidentally passed even with ooffs=0 because the shifted
   address still landed on real code.

Verified locally by running the probe against hello_sprite's ROM
with four different `.dbg` mutations and confirming each triggers
the expected exit code.

https://claude.ai/code/session_01DfN3pKJLryr7vvNFBpcqmC
2026-04-17 01:27:50 +00:00
Claude
d075bc2c43
ci: add headless Mesen2 .dbg validation workflow
Run Mesen2's `--testRunner` mode in CI, point it at a NEScript-built
ROM + auto-loaded .dbg, and assert via Lua that the four entry-point
labels (`nmi`, `irq`, `Main_frame`, `main_loop`) we promised to emit
actually resolve. Failures encode which assertion broke into the exit
code so CI can report it without stdout (Mesen's emu.log is internal).

The setup needed three workarounds, each documented inline in the
workflow:
  * `touch settings.json` to skip Mesen's first-run GUI wizard, which
    blocks the --testRunner dispatch in Program.cs:74. Contents don't
    matter — Configuration.Deserialize falls back to defaults on parse
    error.
  * `DOTNET_SYSTEM_GLOBALIZATION_INVARIANT=1` to keep .NET from loading
    system libstdc++ via libicuuc. On Ubuntu 24.04 the dual libstdc++
    presence (system + MesenCore.so's bundled static copy) crashes
    MesenCore's static regex initialiser with std::bad_cast before any
    user code runs.
  * `xvfb-run` because Mesen's Avalonia UI calls XOpenDisplay before
    --testRunner is dispatched.

This is a separate workflow file from ci.yml because it depends on the
40 MB Mesen2 binary download + xvfb + sdl2, none of which the existing
jobs need. Cached by Mesen version so reruns are fast.

https://claude.ai/code/session_01DfN3pKJLryr7vvNFBpcqmC
2026-04-17 01:03:23 +00:00