Denise: horizontal DIW comparator flip-flop model#103
Merged
Conversation
Replace the span-based horizontal display-window clip with the hardware comparator model (vAmiga Denise::updateBorderBuffer, hardware-verified): Denise keeps one window flip-flop that is SET on an exact 9-bit HSTART counter match and CLEARED on an exact HSTOP match, evaluated per lores position with the register values current at that position. No match means no change, so degenerate windows never open or never close and the state carries across lines and frames. The per-line scan follows the hardware counter: it starts each line at the hblank edge (lores 0x24), wraps 0x1C8 -> 2 near the line end (so positions 2..0x23 are a line's tail, not its head), and on OCS lines 0-8 free-runs modulo 0x200, which lets otherwise-unreachable stop values (0x1C8..0x1FF) fire during vertical blank. Vertical sync leaves the flip-flop set. DIWSTRT/DIWSTOP writes reach the comparators one colour clock after the write cycle. Per-row open spans now drive the background border split, a per-pixel window gate in the playfield painter (replacing the display_window_x span pair), and a post-compositing mask that repaints closed intervals as border (keeping sprites out of closed regions; border sprites exempt). The painter's shifter-origin anchor stays paired with the DIWSTRT value whose comparator fired, so mid-line rewrites move where the window opens without moving the fetched picture. Also fix a palette bleed the diw tests exposed: a colour write in the horizontal-blank tail attributes to the previous output row, behind same-beam-line events that already seeded the next row's base palette; the written entry is now patched into that base so a one-line COLOR00 marker set during hblank still paints its row. Three unit tests encoded artifacts of the old span clip (re-clipping an already-open window on a later-HSTART rewrite, a window edge at the write position instead of the comparator match, and a never-closing OCS stop byte >= 0xC8 treated as closing); they now assert the comparator behaviour. vAmigaTS Agnus/DIW/OLDDIW: diw10 28.3% -> 9.0%, diw9 65.5% -> 60.0%, diw1 63.5% -> 60.7%, diw8 57.1% -> 54.7%, diw2 50.3% -> 48.0%; diw1's remaining divergence is a single uniform 2-lores-pixel picture offset (the Agnus/DDF fetch-placement class, tracked separately) - with that shift factored out diw1 measures 7.9%. Denise/DIW/DIWH and Agnus/DIW/ DIWV also improve across the board. KS3.1/A1200 boot, Zool, Gen-X, Inside The Machine, and Hamazing screenshots are byte-identical to main.
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.
What
Replaces the span-based horizontal display-window clip with the hardware comparator model (vAmiga
Denise::updateBorderBuffer, hardware-verified): one window flip-flop, SET on an exact 9-bit HSTART counter match, CLEARED on an exact HSTOP match, evaluated per lores position with the register values current at that position. No match = no change, so degenerate windows never open or never close, and the state carries across lines and frames.Hardware details modelled:
Consumers converted: background border split, a per-pixel window gate in the playfield painter (replacing the
display_window_xspan pair and itsstop <= start -> +0x100heuristics at that site), and a post-compositing mask that repaints closed intervals as border (keeps sprites out of closed regions; border sprites exempt). The painter's shifter-origin anchor stays paired with the DIWSTRT value whose comparator fired, so mid-line rewrites move where the window opens without moving the fetched picture.Also fixes a palette bleed the diw tests exposed: a colour write in the horizontal-blank tail attributes to the previous output row, behind same-beam-line events that already seeded the next row's base palette - the written entry is now patched into that base. Previously a one-line COLOR00 marker set during hblank (vAmigaTS diw1 block 1) vanished entirely.
Test updates
Three unit tests encoded artifacts of the old span clip and now assert comparator behaviour:
New unit test covers cross-line carry (unreachable HSTART + late stop rewrite).
Results (vAmigaTS, % pixel divergence)
Agnus/DIW/DIWV improves slightly across the board (one +0.3 on onoff1).
The dominant residual in the OLDDIW bucket is not the window model: the whole bucket runs DDFSTRT $30, and Copperline places that early-DDF picture 2 lores pixels left of vAmiga (a uniform shift; with it factored out diw1 measures 7.9%). That is the Agnus/DDF fetch-placement class (oldhwstop* cases at 50-65%) and is tracked separately.
Verification
cargo test --release: 1266 + 30 + 4 pass.cargo clippy/cargo fmt --check: clean.image_regression --ignored: 7 pass + the documented host-flakyocs_bpu7_ham(fails on clean main too).