Files
Dragon-s-Lair-X68k/README.md
T
prosolis e00264a058 Find the sustained action sequence: it breaks both profiles
The open risk since session 2 was "a sustained action sequence could still
break the bitrate", with every clip measured so far being 1.2-1.7 s. Closed by
measurement rather than by sampling clips by hand.

07_motion_survey.py scans a whole stream at 96x72 for the hottest sliding
window of inter-frame difference. On 00223 the spread between the quietest and
hottest sustained 10 s windows is 10.6x, which is the argument for not eyeballing
it. Hottest is t=539.4s, the Singe endgame.

There, with the fixed lam the CLI uses, sasi overshoots 110 -> 129.6 KB/s (+18%)
and scsi 280 -> 373.8 KB/s (+34%). Rate control moves from "insurance, not a
fix" to required, and is promoted above the full-disc survey. The bus is not
broken -- 381.6 KB/s still fits the 488 KB/s figure -- so FINDINGS 21 survives,
at 78% of the pipe instead of a comfortable margin.

Three further corrections fall out:

- The two largest streams on the disc are bonus material. 00216 is the feature
  with a burned-in commentary PiP; 00215 is the commentary. 00223 is the clean
  9.4 min. A size-ranked survey would have encoded live action.
- On hard content the 256-colour scene palette (31.33 dB) binds well before the
  X68000 display (40.81 dB); scsi is already within 0.51 dB of it.
- FINDINGS 24.5's architecture question resolves to "both paths, chosen per
  frame": 30-53% of frames sit above the 70% crossover. Picking per frame costs
  a median 37.0% of the frame budget and caps at 53.6%. Reporting for this is
  wired into encode.py, which previously only printed a mean over all frames --
  the one statistic that cannot answer a per-frame question.

extract.py takes optional start/dur; 08_mode_map.py renders source | decoded |
block-mode map to .webm.

Claude-Session: https://claude.ai/code/session_01194oWYW8DQXK1SZ2DnChW6
2026-08-23 14:00:12 -07:00

3.6 KiB

Dragon's Lair — Sharp X68000 port

Porting Dragon's Lair to a stock X68000 (68000 @ 10MHz, 2MB, SASI/SCSI).

This is fundamentally a video codec problem, not a game-logic problem: the game logic is a scene table with branching input windows; the difficulty is pushing ~22 minutes of Don Bluth animation through a 10MHz 68000.

Green-light check: ./tools/bench/check.sh (~40 s, needs the Blu-ray mounted) re-runs both display regression tests and prints ALL GREEN.

Read first

  • docs/FINDINGS.md — measured hardware facts, content statistics, codec decision, and a section on measurement traps that produced three separate false results. Read §4 before trusting any pipeline number.
  • docs/STATUS.md — current state, working setup, blockers, next steps. Start here. It also lists what has been explicitly abandoned, so old ideas do not get re-proposed.
  • docs/BENCHMARK.md — how to measure the storage subsystem, and why a bandwidth figure out of MAME would be meaningless.
  • docs/HARDWARE.md — X68000 GVRAM/CRTC reference.

Layout

docs/            findings, status, hardware reference
tools/analysis/  measurement scripts, numbered in the order they were written
                 (01/02 marked BROKEN deliberately, kept as regression refs).
                 Run from the repo root — they import from tools/encoder/.
                 07 finds the hottest sustained window in a stream; 08 renders
                 source | decoded | block-mode map as .webm.
tools/bench/     MAME Lua injection harness + 68000 benchmark sources.
                 `check.sh` re-runs both display regression tests (~40 s).
                 `blit.s`/`blit.lua` time the full-frame GVRAM blit on the
                 68000 itself (FINDINGS 24) — not part of check.sh, because
                 wall timings would make the green-light check host-sensitive.
                 `crtc_mode.lua` is the single source of truth for CRTC R00-R08
                 and R20 — do not write CRTC values anywhere else.
tools/vasm/      vasm m68k assembler (built from source)
tools/encoder/   hybrid VQ encoder + DLX1 container writer (working)
src/player/      68000 player (not yet written)
assets/          extracted frames/audio (gitignored)

Encoder

python3 tools/encoder/extract.py 00020 /tmp/fr 12 crop
python3 tools/encoder/encode.py  /tmp/fr out.dlx --profile sasi --preview p.png

Two quality profiles ship from one codec and one decoder — sasi (110 KB/s) and scsi (280 KB/s) are two points on the same rate-distortion curve. The codec is a Cinepak-style hybrid: each 4x4 block is coded as SKIP, one 4x4 codeword, four 2x2 codewords, or RAW literal pixels, chosen per block by rate-distortion.

The RAW escape means lam=0 is pixel-exact against the palettised frame, so the quality knob spans lossless to heavily-compressed without changing the bitstream.

Profiles are derived from a bandwidth figure, not chosen by eye:

python3 tools/encoder/profile_gen.py --bw-mbps 4 --name scsi

On reading docs/FINDINGS.md: it is append-only and several later sections overturn earlier ones. Superseded sections carry a blockquote at the top pointing to the correction — heed those, especially 18 (reversed by 21).

Source media (DRAGONS_LAIR.iso) and ROMs are gitignored — supply your own.

Not every large stream is game footage. 00216 is the feature with a burned-in commentary picture-in-picture and 00215 is the commentary itself — the two largest files on the disc. The clean 9.4-minute animation is 00223. See FINDINGS 25.1 before running any size-ranked survey.