# Ch418 — authentic SH3 display presentation mapping (prefit)

## Objective

Fix the large presentation mismatch between the accepted Ch417 framebuffer and
the PCSX2 224139 frame without changing any rasterized framebuffer byte.  Ch418
is scanout-only: it maps the captured GS display source onto the board's
640x480 HDMI/VGA active raster.

## Captured register evidence

The vendored PCSX2 `GSPrivRegSet` layout was used to decode the initial and all
eight per-vsync register snapshots in dump 224139.  The active context is
DISPLAY2 (`PMODE.EN2=1`), stable in every snapshot:

- `DISPFB2 = 0x0001000000009000` (FBP rotates later), `FBW=8`, `PSM=1`,
  `DBX=0`, `DBY=32`;
- `DISPLAY2 = 0x0037f9ff0203228c`, `DX=652`, `DY=50`, `MAGH=4`,
  `MAGV=0`, `DW=2559`, `DH=895`.

Therefore the display source is 512 pixels wide (`FBW*64`) and 448 interlaced
source lines beginning at framebuffer line 32.  DISPLAY2 expands each source
pixel to five VCKs (`MAGH+1`) across 2560 display clocks.  Reducing that
captured display to the board raster gives the exact integer maps:

```
source_x = floor(output_x * 4 / 5)       // 0..639 -> 0..511
source_y = 32 + floor(output_y * 14 / 15) // 0..479 -> 32..479
```

## RTL change

`gs_lpddr_scanout_lb` now has opt-in divider-free presentation mapping:

- a five-state horizontal phase accumulator implements 512 -> 640;
- a fifteen-state vertical phase accumulator implements 448 -> 480;
- vertical prefetch starts at captured `DBY=32`;
- buffer parity, prefetch throttling, and underflow checks use mapped source y;
- all default parameters retain the legacy 1:1 behavior.

Only `GS_SH3_LPDDR_FB_640` enables the mapping in the DE25 top.  The OSD remains
in the 640x480 output domain and the LPDDR framebuffer/dump remains byte-exact
to Ch417.

The mapper contains no `/` or variable multiply in synthesizable RTL.  Its
datapath is one small phase decrement and one coordinate increment per output
pixel/line, both in the 25 MHz video domain.

## Prefit verification

- New two-axis scanout oracle: 600/600 RGB pixels exact, including horizontal
  repeats, vertical repeats, DBY offset, alternating line buffers, zero
  underflow, and zero AXI read errors.
- Legacy PSMCT16 line-buffer regression: PASS, underflow=0, read errors=0.
- Legacy PSMCT32 line-buffer/concurrency regression: 49,152 pixels exact,
  underflow=0, read errors=0, 325/325 probes good.
- The actual QSF profile macros plus `USE_QSYS_TOP` elaborate cleanly under
  Icarus (unavailable vendor IP treated as black boxes); no RTL binding or
  syntax errors.
- `git diff --check` and the preview utility's Python compile pass.

Expected HDMI preview:

`sim/data/top_psmct32_raster_demo/sh3_zsrt139f17_ch418_scanout.png`

Preview SHA-256:

`b710aa7a09db6992faacdaa5a6257d490f1d4fa0112f6c6d20fc388f4b580a63`

The preview moves the already-rendered lamppost and character onto the PCSX2
landmark positions.  Full-frame RGB MAE rises from 20.12 to 21.02 because the
board is still missing large bright/background draws that the transform now
spreads over more output pixels; that global statistic is a coverage metric at
this stage, not an alignment metric.  The mapping is justified by the captured
registers and visible landmark alignment, not by claiming a false MAE win.

## Owner fit gate

Ready for the owner-controlled Quartus 26.1 GUI compile.  Required acceptance:

- Analysis & Synthesis succeeds with no inferred display divider;
- setup, hold, recovery, removal, and minimum pulse all close;
- after deployment, the unchanged 263-epoch board run still passes and the
  framebuffer dump remains byte-identical to Ch417;
- HDMI shows the 512x448 captured source presented across 640x480.
