video: do not synthesize a picture for a line whose fetch never ran#167
Merged
Conversation
Agnus arms a line's bitplane fetch run at the DDFSTRT comparator match. When BPLCON0 is raised mid-line only after that point has passed (the Rampage bottom-scroller band entry: display off since v227, then at WAIT v248,h14 the copper re-points BPLxPT and lands DDFSTRT $38->$28 at ~h42 and BPLCON0=$3200 at ~h50), no run starts until the next line. The DMA side already models this (the line allocates no bitplane slots), but the renderer's register-derived fallback still synthesized a fetch for the line, painting a phantom, per-plane word-skewed copy of the first bitmap row one line above the real first fetch row. Gate the synthesized re-fetch path on the DMA capture: when the frame carries captured bitplane rows, a line whose capture slot is empty fetched nothing and paints no playfield. A captured row that merely disagrees with the register-derived geometry still takes the re-fetch path, and frames rendered without any capture (COPPERLINE_RENDER_LIVE_CHIP_RAM) keep the synthesized path. This is the same capture-authority rule the sub-$18 DDFSTRT gate (vAmigaTS oldhwstop3/4) already applied, generalized. The faint second dot row on the line below is authentic: the demo's scroller ring buffer carries stray bits in its first bitmap row, and the real fetch displays them. Regression test: bus::tests::line_without_captured_fetch_paints_no_playfield (fails without the gate). Golden probe renders are unchanged; gen-x 80s/150s screenshots are byte-identical.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
In the Rampage (TEK, 1994) end scroller, a row of bright, word-skewed dots appears one line above the big letters (reported with
copperline-state-20260711154559.clstate/ the matching screenshot).The demo's copper list turns the display off (
BPLCON0=$0000) at line 227, then atWAIT v248,h14re-points BPLxPT at the scroller bitmap, rewrites DDFSTRT$38->$28(landing ~h42, after the line's comparator point at h40 has passed), and re-enablesBPLCON0=$3200(~h50). Agnus therefore starts no fetch run on line 248; the first bitmap row is fetched on line 249, and the letters start at 250.Copperline's DMA side models this correctly - the slot map shows zero bitplane slots on line 248 and a full 69-slot run on 249. But the renderer's legacy register-derived fallback (used when a line has no captured DMA row) synthesized a fetch for line 248 anyway, painting a phantom copy of bitmap row 0 with per-plane word skew (planes 1+3 shifted +16 lores px, plane 2 +32 px - the pattern of joining the lores fetch unit mid-way).
Fix
Gate the synthesized re-fetch path on the DMA capture: when the frame carries captured bitplane rows, a line whose capture slot is empty fetched nothing and paints no playfield.
COPPERLINE_RENDER_LIVE_CHIP_RAM) keep the synthesized path.The remaining faint dot row on line 249 is authentic: the demo's scroller ring buffer carries stray bits in its first bitmap row (identical across all three planes, scrolling along with the letters), and the real fetch displays them. vAmiga could not be used as a cross-check for this scene - VAHeadless sticks on the demo's dunes scene from ~350s and never reaches the scroller.
Verification
bus::tests::line_without_captured_fetch_paints_no_playfield- fails without the gate, passes with it.cargo test --releasegreen, including the golden probe render suite (goldens unchanged, no re-bless).cargo clippyandcargo fmt --checkclean.