Skip to content

RustyNES v2.6.8 — "Arrears" (a deny list is an assertion about the thing under test, and nobody re-measured it)

Choose a tag to compare

@github-actions github-actions released this 31 Aug 14:36
3c616c6

RustyNES v2.6.8 "Arrears"

A deny list is an assertion about the thing under test, and nobody re-measured it.

Arrears are debts carried forward: obligations correctly deferred, which then go on being deferred after the reason expires. Every item here is one. v2.6.7 fixed real defects and left the gates narrowed around the places it fixed — which was right at the time, and nothing re-opened the question afterwards.

The emulation core is unchanged. No chip crate changes, so AccuracyCoin 141/141 (RAM decoder) and nestest 0-diff hold by construction. The work is in the co-simulation harness.

The gate

# criterion result
1 nestest runs to the golden's depth 5,062,680 cycles compared, 0 divergences; window derived from the manifest, not a literal
2 nestest compared on nine fields ckpt:nestest passes over 1,237 checkpoints
3 C4 closed by demonstration an nmi_line mutation, previously uncatchable, is CAUGHT at checkpoint 28
4 the deny list is current 2 entries, each with its divergence named; the 4 removed each shown passing
5 no regression 128 passed, 0 failed, 0 skipped (from 123); nine-field comparisons 51 → 57

Four of six denied streams were passing

v2.6.7 changed the DUT (the $4017 interrupt-clear split) and the harness (the Observable completed at end-of-cycle, nmi_line wired to the effective line rather than the testbench's injection pin). Both re-open every exclusion. Neither prompted a re-measurement.

golden v2.6.7 re-measured
irqlat048 checkpoint 21 PASS — 22 identical, through cycle 89,341
ppuvbl023 checkpoint 13 PASS — 175 identical, through 714,737
ppuvbl024 checkpoint 13 PASS — 291 identical, through 1,191,227
ppuvbl025 checkpoint 13 PASS — 175 identical
apuconflict039 checkpoint 8 still differs — a declared diagnostic
ppuoamcorrupt052 checkpoint 17 still differs — genuine hash mismatch

Three of them were not run by the suite at all. ppuvbl023/024/025 have a committed golden, ROM and manifest and appeared nowhere in regress.sh except the deny list — which only ever governed the auto-attach. So taking them off it was inert until they were also iterated. Retiring an exclusion adds coverage only if something reaches the thing excluded.

nestest: 19× deeper, and nine fields

The gate compared 265,000 cycles against a 5,062,688-cycle golden. That cap was correct while caveat C6 was open — it sat just short of the first divergence, named rather than hidden — and was left behind the moment C6 closed inside the same release. The window now comes from the golden's manifest, because a literal is exactly how this gate went wrong twice: once naming 5,002,992 against a 59,562-cycle golden, once capping at 265,000 against a fixed one.

Caveat C4 is closed, and the stimulus existed the whole time. C4 said the checkpoint gate could not catch an nmi_line defect because no gated golden raised an NMI. nestest's golden sets nmi_line on 3,592 cycles and irq_line_at_low on 62,516, and its checkpoint golden was already committed at 1,237 checkpoints — it just used nestest-gate rather than cpu-bus-gate, so the auto-attach could not reach it, and it was absent from the explicit loop.

Reverting o.nmi_line to the constant false it held before v2.6.7 is now CAUGHT, at checkpoint 28 of 1,237. The shape of that result is the argument for nine fields: in the same run the bus gate still passed all 5,062,680 cycles, because it compares four and is structurally blind to it.

ppuspr0 was the last golden with a checkpoint stream and no nine-field coverage. Measured (44 checkpoints identical) and wired, the set closes: 59 = 40 loop + 16 auto-attached + nestest + 2 denied, none unreached.

Two findings recorded rather than quietly fixed

The widened gate's first catch was this release's own change. The nestest window was first derived from obs.bin's size, which is wrong by exactly eight — the obs stream begins at cycle 8. ckpt_diff.py compares the final partial window by cycle and said so, while the bus gate passed the identical run because it compares overlapping cycles and a short stream simply overlaps less.

A hypothesis refuted before a fix was written. Re-measuring ppuoamcorrupt052 died with cannot open ../RustyNES_MiSTer/tb/roms/..., which read as a latent harness bug. It is not: regress.sh does cd "$(dirname "$0")" and validates from tb/, where that path correctly fails and the absolute fallback correctly fires. The defect was in the ad-hoc measurement script, which ran from the repo root and resolved by coincidence. Checked from both working directories.

Also

tb/fb_to_png.py renders an index_fb.bin to a PNG using the vendored 2C02G palette, stdlib only. It refuses a wrong-sized buffer rather than drawing a plausible picture from a truncated capture. Used to confirm the RTL renders Super Mario Bros.: at frame 80 the DUT's framebuffer is byte-identical to the oracle's over all 61,440 pixels. It shows geometry, not colour — the ladder gates the pre-palette buffer precisely so a palette difference cannot masquerade as a rendering one.

Release-note titles are also normalised here. The v2.6.x headers had drifted to a median far above the corpus, v2.6.7's being the longest ever written at 498 characters against a 26-release median of 78; the seven affected CHANGELOG headers and their published release titles are shortened to one clause each, with the detail left where it belongs, in the body.

Not closed

Rung 6. No DE10-Nano and no SuperStation One are attached to this machine — confirmed by checking the USB bus, serial devices, removable block devices and mounts, not assumed. No hardware has run the bitstream.

apuconflict039 and ppuoamcorrupt052 genuinely differ. Each needs its own diagnosis; neither is a gate-widening task.