Import the scene graph, and find the worst gap between two branch points is zero

ROADMAP G1, scheduled early because it is a measurement input, and it paid for
that immediately. 51.3 established that a ring's lookahead is accumulated out of
pipe - wire and that a seek spends all of it, so what a branch point costs is
set by the time since the last one. 55.5 rehearsed a seek on the machine and
said out loud that it could not ask the question, because nothing here knew
where the branch points are.

They are everywhere, and 5.4% of them are free of charge to the player and not
to us. Over 612 distinct transitions into a seek, taking the earliest instant
each input window opens: worst 0.000 s, p10 0.950, median 3.473, best 82.497.
33 open on the first frame of a clip the disc SEEKED to -- press right as
flaming_ropes.enter_room appears and you are in fall_to_death, two seeks with no
play between them. 51.2's slack rule can therefore be answered NO by the
content rather than by the buffer, and no amount of ring is a defence.

It does not break the design. A branch on an empty ring costs the 2-record
prefill, 149.7 ms at 488 KB/s, not the climb. What it removes is margin: at that
rate in a 256 KB ring, 76% of this game's branch points arrive before the ring
has refilled, and a 512 KB ring makes that 90%, because doubling the ceiling
does not touch the surplus. The ring is not the lever; the surplus is.

CORRECTION to FINDINGS 16: there is only one transcription. The SNES chapter
set says in its own README that it is derived from DirkSimple, so the planned
diff of two independent sources catches conversion errors only. Run anyway:
durations agree 388/505 within a frame, branch structure 470/505, and of the 35
differences 16 are renames and 18 of the other 19 are that port dropping the
arcade's diagonals. Zero transcription discrepancies, and none were findable.

Two constraints on the input layer come free: the arcade needs eight directions,
and the shortest input window is 98 ms against 54.4's 72.13/90.16 ms frame slot,
so input cannot be polled on the frame tick.

The coupling to outside source is contained to one file (USER DECISION).
tools/import/scenegraph.py is the only code here that knows those projects
exist -- their paths, table names, timing formulas, constants -- and it writes
DLXSCENE1, this project's own schema, into gitignored tmp/ with the sources'
licences inside it. tools/analysis/25_scene_graph.py reads only that. Nothing is
vendored and nothing outside-derived is committed. The split was made after the
measurement and the whole output was re-run byte for byte to show it moved no
number.

Both import gates are negative-tested: deleting one sequence upstream fails the
516/906 count, and closing the table early fails the constructor-end check,
which replaced one that was vacuous.

No 68000 code ran or changed; decode.bin is still 1,296 B at the same MD5.
check.sh gains an import stage that skips when there is no checkout. ALL GREEN
before and after.

Claude-Session: https://claude.ai/code/session_01194oWYW8DQXK1SZ2DnChW6
This commit is contained in:
prosolis
2026-08-24 22:11:04 -07:00
parent 2676f3b835
commit 00232bb22b
7 changed files with 1187 additions and 13 deletions
+34 -1
View File
@@ -126,6 +126,28 @@ at 488 KB/s a one-deep request queue gives away **6.8% of the pipe and underruns
59 of 120 frames**, a two-deep one gives away 3.4% and underruns none — on a
container whose whole surplus over the wire is 8.7% (FINDINGS 55).
**The scene graph is in, and the worst gap between two decision points is
zero.** `tools/import/scenegraph.py` imports the arcade scene graph — 40 scenes,
516 sequences, 906 input windows — and 5.4% of the game's 612 branch transitions
open an input window on the first frame of a clip the disc *seeked to*, so two
seeks can fall back to back with no play between them. A rule of the form "has
there been enough play since the last branch" can therefore be answered no by
the **content**, not by the buffer. It does not break the design: a branch on an
empty ring costs the 2-record prefill, **149.7 ms at 488 KB/s**, not the climb.
What it removes is margin — at that rate in a 256 KB ring, **76% of this game's
branch points arrive before the ring has refilled**, and a 512 KB ring makes it
90%, because doubling the ceiling does not touch `pipe - wire` (FINDINGS 56).
**Nothing outside-derived is committed here.** The scene graph is not
redistributable from this tree; it is regenerated from a reader's own clones
into gitignored `tmp/`, and `tools/import/scenegraph.py` is the single file in
the repo coupled to those projects — everything downstream reads `DLXSCENE1`,
this project's own schema, with the sources' attribution carried in it.
DirkSimple is zlib (Ryan C. Gordon); the SNES chapter set is MIT (Chad
Doebelin) and, by its own README, *derived* from DirkSimple rather than an
independent transcription, which struck a cross-check this project had planned
on for eight sessions.
**Current encode:** 496.7 KB/s at 29.19 dB, 1 frame of 120 over the 12fps
budget, and that one is frame 0, the intra frame, late on purpose.
@@ -133,7 +155,8 @@ budget, and that one is frame 0, the intra frame, late on purpose.
mounted) re-runs both display regression tests, the rate-control drift gate, the
display-path coherency counterexample, a 120-frame 68000 decode on two CPU
cores, the ring and paced-ring passes, the DMAC configuration gate and the
load-time transforms on both cores, then prints `ALL GREEN`.
load-time transforms on both cores, then imports and gates the scene graph
when a DirkSimple checkout is present, then prints `ALL GREEN`.
## Reproducing this
@@ -316,6 +339,16 @@ tools/bench/c68k/ headless px68k C68K harness, a SECOND emulator for every
which MAME cannot report. The Makefile's -no-pie and the
harness's MAP_32BIT arena are load-bearing: C68K truncates
host pointers to 32 bits.
25 imports nothing itself: it reads the DLXSCENE1 scene
table and reports the worst gap between two decision points,
what the input layer has to survive, and what both cost in
51.3's accumulated slack across explicit rates.
tools/import/ the ONLY code in this tree coupled to somebody else's source.
scenegraph.py reads a DirkSimple checkout (and optionally the
SNES chapter XMLs) and writes tmp/scenegraph.json in this
project's own DLXSCENE1 schema, with the sources' licences and
attribution inside it. Nothing is vendored and the output is
gitignored derived data.
tools/media/ builds docs/img/ from a paced recording run
tools/vasm/ vasm m68k assembler, binary plus source tarball
tools/encoder/ hybrid VQ encoder and DLX3 container writer.