Skip to content

Report sprite collisions read in the middle of a raster line up to the beam - #337

Merged
highbyte merged 1 commit into
feature/cpu-cycle-enginefrom
feature/c64-vic2-midline-collision-reads
Sep 17, 2026
Merged

highbyte merged 1 commit into
feature/cpu-cycle-enginefrom
feature/c64-vic2-midline-collision-reads

Conversation

@highbyte

Copy link
Copy Markdown
Owner

What

Reads of the sprite collision registers ($D01E, $D01F) in the middle of a raster line now report what the chip reports:

  • the collisions of the sprite pixels the beam has passed, up to four pixels before the start of the read's cycle;
  • the register is cleared as the read's cycle ends, so collisions of the twelve pixels in between are lost;
  • what the rest of the line outputs is latched as before and shows in the next read.

Until now both registers were latched only when a line ended, so a program that polls a register twice on a line, or at a fixed cycle, saw the whole line's collisions or none.

How

  • Vic2: the line-end derivation of sprite output runs can run up to a pixel without committing the sprite data registers. A $D01E read derives the current line's runs up to the read's pixel and latches the overlaps in that window; a per-line marker makes the line's end latch only the remainder. Reads after the display decision of cycle 58 are clamped there.
  • Vic2SpriteManager.LatchLineSpriteCollisions(line, fromPixel, toPixel) replaces EndLineSpriteCollisions(line): run masks are clipped to the pixel window.
  • IVic2CycleRenderer.LatchSpriteBackgroundCollisions: for $D01F the sequencer pixel generator catches up, draws the read's own cycle early (a read changes nothing, and the graphics under the last reported pixels are that cycle's), checks the runs against the line's foreground pixels in the window and keeps its own marker for the line-end pass. The background check is one helper shared by both paths. The legacy generator is unchanged (default interface method).
  • The generator's catch-up takes an end cycle; its frame-wrap reset is explicit so that being one cycle ahead is not mistaken for it.

Verification

  • VICE test programs (274 runs, PAL and NTSC): 241 → 245 match. Newly passing: spritevssprite, spriterestart, spritecollisions/sprite-sprite-collision-cycle, spritecollisions/sprite-gfx-collision-cycle. No other result changed.
  • New Vic2CollisionReadTimingTests (10 cases): report threshold, clear at the end of the read's cycle, line-end latch, for both registers.
  • Games (Commando, Giana Sisters; PAL, NTSC, snapshots) and fourteen demos at three frame counts render byte-identically before and after.
  • Performance (MacBook Air M1, For Your Sprites Only, sequencer generator with per-line sprites): 1262–1277 → 1254–1278 µs/frame; other configurations unchanged.

…e beam

A read of $D01E or $D01F during a line reports the collisions of the sprite
pixels the beam has passed, up to four pixels before the start of the read's
cycle, and clears the register as that cycle ends, so the collisions of the
twelve pixels in between are lost and the rest of the line's show in the next
read. Established by VICE's sprite-sprite-collision-cycle,
sprite-gfx-collision-cycle, spritevssprite and spriterestart test programs,
which now pass.

The VIC-II derives the current line's sprite runs up to the read's pixel
without committing the sprite data registers and latches the overlaps in that
window; the line's end latches the remainder. For sprite-to-background the
sequencer pixel generator draws the read's own cycle early and checks the runs
against the line's foreground pixels, through
IVic2CycleRenderer.LatchSpriteBackgroundCollisions.
@sonarqubecloud

Copy link
Copy Markdown

@highbyte
highbyte merged commit fb8e838 into feature/cpu-cycle-engine Sep 17, 2026
9 checks passed
@highbyte
highbyte deleted the feature/c64-vic2-midline-collision-reads branch September 17, 2026 14:26
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