Skip to content

denise: early-DDF lo-res picture placement is linear in DDFSTRT#106

Merged
LinuxJedi merged 1 commit into
mainfrom
fix/early-ddf-picture-phase
Jul 4, 2026
Merged

denise: early-DDF lo-res picture placement is linear in DDFSTRT#106
LinuxJedi merged 1 commit into
mainfrom
fix/early-ddf-picture-phase

Conversation

@LinuxJedi

Copy link
Copy Markdown
Owner

Summary

Remove the lo-res FMODE=0 "-1 sample" phase correction for DDFSTRT values
before the standard $38 slot (fetch_origin_native_shift,
src/video/bitplane.rs). Early-DDF picture placement is linear in DDFSTRT:
a $30 picture sits exactly one 8-cck fetch period (16 lo-res pixels) left
of the $38 picture. This is the dominant residual behind the
Agnus/DIW/OLDDIW / Denise/DIW/DIWH vAmigaTS buckets and half of the
"first word after display window start" bug class (issues #68/#69).

Hardware arbitration

Copperline and vAmiga 4.4 disagree by exactly 1 lores px on early-DDF
picture phase, so the verdict was read off real A500 photos in the vAmigaTS
tree (Agnus/DIW/OLDDIW/diw1, OCS and ECS photos).

The discriminating observable is the diw1 block-1 staircase: 10 copper
steps (one per 3 lines) shrink the window by 1 lores px per side
(DIWSTRT hstart $94..$9C,$9E). Which hstart values share a
first-visible-stripe cell depends on the DDF-$30 stripe grid phase:

  • linear grid (vAmiga): onset plateaus of [6,6,6,6,3,4] lines, hstart pairs
    ($94,$95)($96,$97)($98,$99)($9A,$9B)($9C)($9E)
  • Copperline's corrected grid (+1 lores px): plateaus [3,6,6,6,6,4]

Both photos show [6,6,6,6,3,4] (dense subpixel scan; plateau boundaries at
OCS y = 95.5/112/128/144.5/161/169.5, line pitch 2.76 px). Independently,
the first plateau's indent versus the standard rows measures 41.0 fb px
(OCS) / 40.0 fb px (ECS); the linear grid predicts 40, the corrected grid
36. Verdict: real hardware is linear.

The correction (eeb2fe0, "lores HAM edge") was compensating for a separate
error: Copperline's display window edge sits one lores px too far right
(2H-194 for DIWSTRT hstart H; the sblit0_A500_ECS.jpeg partial-swatch
measurement shows the hardware edge at 2H-196, the vAmiga model). With the
too-wide window, a standard DIW overran the fetched row's right edge on
early-DDF screens, and the correction hid that by shifting the picture
right. The window-edge anchor fix lands separately; until then standard-DIW
early-DDF screens show background in the window's last lores px (as the
too-wide window makes unavoidable without the wrong phase).

vAmigaTS scores (Copperline vs vAmiga 4.4 refs, X_SHIFT=0)

test before after
Agnus/DIW/OLDDIW/diw1 59.4% 1.5%
Agnus/DIW/OLDDIW/diw7 65.7% 0.4%
Agnus/DIW/OLDDIW/diw9 58.6% 0.000%
Agnus/DIW/OLDDIW/diw11 58.9% 0.2%
Agnus/DIW/OLDDIW/diwvert1 64.5% 1.2%
Denise/DIW/DIWH/minmax 9.1% 0.6%
Denise/DIW/DIWH/diwtim1b..4b 14.2% 0.4-0.5%
Agnus/DDF/DDF/lupo1 39.8% 9.2%
Agnus/DDF/DDF/hwstop7 22.1% 2.3%
Agnus/Blitter/sblit/sblit0 0.4% 0.3%
Denise/Sprites/general/sprites7 36.7% 24.9%

diw5/diw6 (21-22%) and oldhwstop1-4 (50-60%) remain: separate divergence
classes (the diw1 photos additionally show two behaviours NEITHER emulator
models: DIW register writes take effect only from the next line, and
hstop $A1/$A0 in block 1 caused no right-edge narrowing at all).

Verification

  • cargo test --release green (1269 tests; expectations updated in 2
    tests with hardware-verdict comments, new linearity regression test),
    cargo clippy, cargo fmt --check clean.
  • cargo test --release --test image_regression -- --ignored: 7 pass
    (ocs_bpu7_ham is the documented host-flaky perf test, fails on clean
    main too).
  • Demo screenshots vs main (KICK13 A500 OCS unless noted): Gen-X at
    110/150/220/620s (issue Demo issues #69 scene map), Hamazing, kicka1200 (A1200 KS3.1,
    hires FMODE=3) and Zool (AGA) are byte-identical. Inside the Machine's
    overscan bitmap (early DDF) moves exactly 2 px left, per-row verified
    (content left edge 76 -> 74, colour-anchored effects unmoved) - the
    predicted hardware-correct shift.

Remove the lo-res FMODE=0 "-1 sample" phase correction for DDFSTRT values
before the standard $38 slot. Real hardware places a DDF-$30 lo-res
picture exactly one 8-cck fetch period (16 lo-res pixels) left of the $38
picture: in the vAmigaTS Agnus/DIW/OLDDIW/diw1 A500 photos (OCS and ECS)
the block-1 staircase pairs DIWSTRT hstart values ($94,$95)($96,$97)
($98,$99)($9A,$9B) on shared first-visible-stripe cells with plateau
lengths [6,6,6,6,3,4] lines, matching only the linear grid, and the first
plateau's indent against the standard rows measures 40 framebuffer px
where the corrected grid predicts 36.

The correction was compensating for the display window edge sitting one
lo-res pixel too far right (2H-194 instead of the hardware's 2H-196,
measured on the sblit0_A500_ECS.jpeg partial swatch columns): the too-wide
window overran the fetched row's right edge on early-DDF screens. The
window-edge anchor is fixed separately.

vAmigaTS scores (vs vAmiga 4.4 refs): OLDDIW diw1 59.4%->1.5%, diw7
67.2%->0.4%, diw9 58.6%->0.0%, diwvert1 64.5%->1.2%; DIWH minmax
9.1%->0.6%, diwtim1b-4b 14.2%->0.5%; Agnus/DDF lupo1 39.8%->9.2%,
hwstop7 22.1%->2.3%; Denise/Sprites improve broadly (sprites7
36.7%->24.9%). Gen-X, Hamazing, kicka1200 (hires fm3) and Zool (AGA)
screenshots are byte-identical to main; Inside the Machine's overscan
bitmap moves exactly 2 px left as predicted.
@LinuxJedi LinuxJedi merged commit e5413fb into main Jul 4, 2026
8 checks passed
@LinuxJedi LinuxJedi deleted the fix/early-ddf-picture-phase branch July 4, 2026 10:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant