Skip to content

Draw palette and port 0x31 changes from the scan line they land on - #16

Merged
bubio merged 1 commit into
mainfrom
feat/raster-video
Sep 17, 2026
Merged

bubio merged 1 commit into
mainfrom
feat/raster-video

Conversation

@bubio

@bubio bubio commented Sep 17, 2026

Copy link
Copy Markdown
Owner

Stacked on #15.

vraminfo found the palette latched per scan line — 「PC88 のパレットの反映は hblank 毎(?)に行われる」 — and tried switching settings halfway down the display: 200 → 400 lines and graphics on → off both work (「可能なようです」). Port 0x32 digital → analog has no effect, and port 0x30's 80/40 columns and colour/mono garble the screen. We drew every frame with the registers as they stood at the frame boundary, so VRAMTEST T showed one flat colour where the page shows bands, and U used one mode for the whole screen. This is VRAMTEST #13.

Change

  • Log: the bus records the registers the page saw take effect mid-frame (palette 0x54-0x5B, background 0x52, the analog background, and port 0x31's graphics on / colour / 200-line bits) with the CRTC scan line of each write that changes something (RasterVideo.swift). The log is kept per frame and handed over when the scan line counter wraps to 0 (CRTC.onFrameStart), so it does not depend on runFrame. Reset and state load clear it.
  • Bands: RasterFrame.bands() turns the finished frame into bands of output rows. A display change takes effect from the next line, and CRTC lines are scaled to the 400-row picture (×2 at 15kHz). Retrace changes are moved ahead of the display changes, register by register. A program that sets the top in the retrace and changes it partway down (T, U, and any raster effect written the usual way) then gets the frame the hardware draws every time.
  • Drawing: FrameCompositor draws each band with its values; the four renderers take the rows to write (default 0..<400). A frame with one state all the way down takes the old path with the old values.
  • Ports 0x30 and 0x32 stay per frame. Reproducing the garbling is out of scope.

Results

  • VRAMTEST T: 8 digital / 32 analog bands at 24kHz and 15kHz. U-1: the R plane in 400-line form below the switch. U-2: no graphics below it. U-0/3/4 unchanged.

  • Tests: 917 pass (8 new in RasterVideoTests; the end-to-end one fails if bands are switched off). Release builds pass.

  • Regression: identical to Let the V1S text DMA take CPU time while the display runs #15 (the TheHospital difference is the same 1297 px, everything else identical).

  • 1,102 disks booted for 60 s in V2, Let the V1S text DMA take CPU time while the display runs #15 vs this branch: 1,092 identical and 10 different. All 10 are palette writes that land during the display and now split the frame:

    • palette animation: Crystal Prison, Tritorn, Sylpheed, Melt Down, Alpha DEMO, Seena, Scotty, Storm
    • a fade or flash caught mid-frame: Emerald Dragon, Navitune

    That is what the page describes. Whether the hardware also splits these frames can't be checked without one. If any of these titles is meant to write only in the retrace, this is where to look.

🤖 Generated with Claude Code

https://claude.ai/code/session_01EtarYVwQy1YVfWGChE5eg4

vraminfo: 「PC88 のパレットの反映は hblank 毎(?)に行われる」, and switching to
400 lines or turning graphics off halfway down the display splits the
screen (「可能なようです」 for both). We drew each frame with the registers
as they stood at the frame boundary, so VRAMTEST T showed one flat color
where the page shows bands, and U took whichever mode came last for the
whole screen.

The bus now logs the palette, the background registers and port 0x31's
display bits with the CRTC scan line each change lands on, one frame at a
time, handed over when the scan line counter wraps. The compositor turns
the finished frame's log into bands of output rows and draws each with the
values it had; the four renderers take the rows to write. Changes made in
the retrace are moved ahead of those made during the display, register by
register, so a program that sets the top in the retrace and changes it
partway down gets the picture the hardware draws every frame.

A frame whose display shows one state all the way down takes the same path
as before with the same values, so nothing that does not change these
registers mid-display draws any differently: the regression screenshots are
untouched. T now shows 8 digital / 32 analog bands at 24kHz and 15kHz, U-1
the R plane in 400-line form below the switch and U-2 no graphics below it.
Port 0x30 and 0x32 stay per frame (the page found the one garbles the screen
and the other does nothing).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EtarYVwQy1YVfWGChE5eg4
Base automatically changed from feat/text-dma-cycle-steal to main September 17, 2026 13:58
@bubio
bubio merged commit 1dec15c into main Sep 17, 2026
3 checks passed
@bubio
bubio deleted the feat/raster-video branch September 17, 2026 13:58
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