Get a real Dragon's Lair frame onto the emulated X68000
First pixels on an actual X68000 screen. Everything up to now was Python-side or a headless -video none run, which cannot snapshot at all. The blocker was not the video controller. The IPL leaves CRTC R20 = 0x0B16, and bit 11 is "G-VRAM set to buffer", which makes MAME's draw_gfx() return early. GVRAM writes still land and read back correctly while the layer is invisible, so six attempts at $E82400/$E82500/$E82600 all rendered black with every register holding the value I intended. Two more facts, both confirmed against MAME 0.277 source rather than assumed: - $E8E001 monitor contrast is left at 14 by the IPL, scaling all output to 93.3%. The player must set it to 15. Contrast 0 blanks the screen, which is a free fade-to-black for scene transitions. - The palette word is GGGGGRRRRRBBBBBI with a shared LSB, expanded as pal6bit((field<<1)|I). With contrast at 15 the render is pixel-exact, not merely close, which also confirms the 1024-byte GVRAM line stride. That exactness gives a new quality ceiling: the 15-bit+I palette alone costs 38.88 dB against the 24-bit palettised source, the same order as the scsi profile's own codec error. scsi is close to display-transparent on hardware, which bounds how much further it is worth raising. Unblocks next step 2, the 68000 decoder skeleton, which now has a known-good reference image to diff against. Claude-Session: https://claude.ai/code/session_01194oWYW8DQXK1SZ2DnChW6
This commit is contained in:
+41
-3
@@ -156,6 +156,41 @@ functional models, not timing-accurate; a KB/s figure from MAME measures the
|
||||
emulator's scheduler. `docs/BENCHMARK.md` covers the three-tier approach
|
||||
(MAME validates the path, derivation bounds it, real hardware settles it).
|
||||
|
||||
## Display path — WORKING, verified end to end (session 3)
|
||||
|
||||
The first real frame is on screen: `docs/images/x68k_first_frame_compare.png`.
|
||||
Full write-up in **FINDINGS 22**. Harness: `tools/bench/show_frame.lua` +
|
||||
`tools/bench/prep_frame.py`.
|
||||
|
||||
Three facts the player MUST honour, none of which were guessable:
|
||||
|
||||
| what | where | value |
|
||||
|---|---|---|
|
||||
| **Un-hide the graphics layer** | CRTC R20 `$E80028` | clear bit 11 ("G-VRAM set to buffer"); IPL leaves `0x0B16` |
|
||||
| Colour setup (256c) | CRTC R20 bits 9-8 | `0x0100` -> `R20 = 0x0116` |
|
||||
| **Monitor contrast** | `$E8E001` bits 3-0 | IPL leaves **14**; write **15** or everything renders 7% dark |
|
||||
|
||||
Bit 11 is the one that cost the most time: GVRAM writes land and read back
|
||||
correctly while the layer is invisible, so the video controller looks guilty and
|
||||
is not. Contrast `0` blanks the screen — free fade-to-black for transitions.
|
||||
|
||||
Palette format is now **confirmed from MAME source**, not assumed:
|
||||
`GGGGGRRRRRBBBBBI` (G 15:11, R 10:6, B 5:1, shared LSB I), expanded as
|
||||
`pal6bit((field<<1)|I)`. With contrast at 15 the render is **pixel-exact**.
|
||||
|
||||
New ceiling: the 15-bit+I palette alone costs **38.88 dB** against the 24-bit
|
||||
palettised source — the same order as the `scsi` profile's own codec error
|
||||
(39.4 dB). `scsi` is close to display-transparent on real hardware. See
|
||||
FINDINGS 22.4 before considering raising quality further.
|
||||
|
||||
Snapshot recipe that works (`-video none` CANNOT snapshot):
|
||||
```
|
||||
SDL_VIDEODRIVER=dummy mame x68000 -bios ipl10 -video soft -window \
|
||||
-sound none -nothrottle -plugins -autoboot_script <script>.lua \
|
||||
-snapshot_directory ./snap -snapview native -seconds_to_run 6
|
||||
```
|
||||
`-snapview native` drops MAME's LED artwork and gives a clean 768x512 screen.
|
||||
|
||||
## Next steps, in priority order
|
||||
|
||||
1. **Full-disc survey.** Only 4 clips of 1.2-1.7 s out of 224 streams have been
|
||||
@@ -164,9 +199,12 @@ emulator's scheduler. `docs/BENCHMARK.md` covers the three-tier approach
|
||||
vs content first (FINDINGS 13) or the averages are diluted by static menus.
|
||||
**Vectorise `_paint` before this run** — it is a Python per-block loop.
|
||||
2. **68000 decoder skeleton.** Parse `DLX1`, expand codebooks to word-per-pixel,
|
||||
blit SKIP/V1/V4/RAW. Measure real cycles with the existing MAME Lua harness —
|
||||
the first time that harness gets used for its actual purpose. Validates the
|
||||
38% full-frame blit estimate that the whole CPU budget rests on.
|
||||
blit SKIP/V1/V4/RAW. Measure real cycles with the existing MAME Lua harness.
|
||||
**Now unblocked** — the display path is verified (FINDINGS 22) and
|
||||
`tools/bench/show_frame.lua` gives a known-good reference image to diff the
|
||||
68000's output against. Validates the 38% full-frame blit estimate that the
|
||||
whole CPU budget rests on. Still needs a real CRTC mode table for 256x256;
|
||||
the harness deliberately borrows the IPL's timing and invents nothing.
|
||||
3. **Wire rate control into `encode.py`.** No longer a blocker (FINDINGS 21), but
|
||||
it is what gives a deterministic ceiling over content not yet measured, which
|
||||
was the original reason for choosing VQ. Insurance, not a fix. Pairs with (1).
|
||||
|
||||
Reference in New Issue
Block a user