mirror of
https://github.com/libretro/virtualjaguar-libretro.git
synced 2026-11-10 17:28:58 -10:00
Both ROMs assembled and booted but never wrote a result signature, so
the acid suite reported them as NOT-RUN-YET on every build. Each was
violating a documented hardware contract; the emulator was right in both
cases, so the fix is in the test ROMs.
pit_countdown_rate: the IRQ handler acked TOM's INT1 copy but never
cleared JERRY's own pending latch. JERRY drives TOM INT1 bit 4 for as
long as an enabled source has an uncleared latch (tom.c:TOMPendingMask),
and m68k_execute re-presents that level-2 request at every instruction
boundary, so the 68K re-entered the handler forever: ~2200 IRQs/frame
with the busy-loop counter d2 frozen, i.e. 100% of the frame's 227k
cycles spent in exception entry plus handler. JINTCTRL's low byte is the
enable mask and its high byte is write-1-to-clear, so writing the enable
bit alone cleared nothing. Handler now writes IRQ2_TIMER1_CLR too.
The PIT period itself was never wrong: with the storm gone the test
measures 395 IRQs/sec against a [385, 426] window. Do not widen that
window if it drifts -- this test is the only acid coverage of the
dram_timing model, and it has already been churned once (209e5b2).
unaligned_word: address error is a group 0 exception and stacks 14
bytes, not 6. The handler treated SP+2 as the return PC (it is really
the fault address), bumped it, then RTE'd off the long frame -- popping
the special status word as SR and the fault address as PC, running away
into zeroed RAM. The 14-byte frame is deliberate (cpuextra.c:Exception,
issue #138 / Pitfall), so "fixing the emulator" would mean reverting a
real bug fix. Handler now discards the 8 extra bytes before RTE, and
additionally asserts the frame layout in place so a regression back to a
short frame reports a clean FAIL rather than a silent runaway --
verified by temporarily forcing a 6-byte frame, which yields
detail=0x2 observed=0x0080202a expected=0x00080001.
Also fixed, both of which let this class of failure hide:
- test/acid/Makefile: `make baseline` extracted the ROM path with
awk '{print $1, $3}'. That works for the padded `[PASS ]` and
`[FAIL ]` lines but not `[NOT-RUN-YET]`, which is unpadded and
carries a trailing message -- field 3 there is part of the message, so
the row was written without a .jag path, failed check-baseline.py's
regex, and vanished from BASELINE.txt. The test then read as
"NEW (OK)" forever, so a ROM that stopped booting looked green.
Extract by pattern instead of field index.
The recipe's `sort` is also now pinned to LC_ALL=C. It previously
inherited the caller's locale while the committed BASELINE.txt was
collated differently, so `make baseline` churned unrelated lines and
buried the real change. BASELINE.txt is re-sorted once here to match;
that hunk is ordering-only (verified set-identical), and the recipe
now reproduces the file byte-for-byte.
- docs/jtrm-jerry.md: both JINTCTRL bit tables were off by one and
omitted J_DSPENA/J_DSPCLR, so J_TIM1CLR read as bit 9 ($0200) when it
is bit 10 ($0400). Since these docs supersede source comments, that
would have reproduced the storm above. Added the clear-bit values and
the handler-must-clear rule.
- test/acid/scripts/gen-jaguar-regs.py: emit IRQ2_*_CLR constants
(enable << 8) so tests name the clear bit instead of hard-coding it.
BASELINE.txt's statuses are unchanged: it already recorded both as PASS,
and they pass again. Note the suite still has one unrelated,
deterministic regression, tests/op/op_gpu_int_object.jag (detail=1
observed=0x2800 expected=0x200), which predates this branch and is left
flagged rather than baselined away; it is fixed separately on
fix/acid-op-gpu-int-halted.
Verified: make test exits 0; both ROMs PASS on the production ABI and
the TEST_EXPORTS ABI; acid lint clean; no C sources touched.
Co-Authored-By: Claude Fable 5 <[email protected]>