Move the loader onto the 68000, and find 5,920 bytes nobody counted
src/player/load.i expands both codebooks to word-per-pixel form and packs the palette to GGGGGRRRRRBBBBBI out of the RAW container header, byte-exact against tools/bench/dlxload.py on both CPU cores. The palette half is gated on words read back out of the palette registers at $E82000, so "the words reached the hardware" is part of what passes. ROADMAP P1 is done; P2's encoder half (a reserved black entry, 23.4) is not, and is a re-encode rather than an edit. A scene change costs 18.96 ms of 68000 time, 22.8% of one 12 fps frame; boot costs 24.70 ms. The scratch tables describe the CRTC, not the scene, so pal_tables is a separate entry point built once at boot -- 5.29 ms off every scene change. The one that moves something: the scene header is 5,920 B that no rate table in this tree included, because it belongs to no frame record. In FINDINGS 51.3's currency it is divided by the surplus pipe - wire, so it is hypersensitive: 138 ms of extra refill climb at 488 KB/s and 1.099 s at 451.4 KB/s, for the same bytes. tools/analysis/22_scene_load.py prices it across explicit rates. Recorded as open: the two CPU cores agree to <3% on every stage but the table build, where they differ by 16.4%. px68k's C68K charges a flat 50 clocks for MULU/MULS (c68kmacro.h:1869) where the 68000 charges 38+2n, which explains 4,608 of the 8,703 clock gap. 4,095 clocks are unexplained. Nothing else in src/player/ multiplies, so no figure in FINDINGS 24-52 is affected. decode.s and stream.s are untouched; decode.bin is still 1,296 B at the same MD5. check.sh gains a stage that gates byte-exactness on both cores and deliberately does not gate the cycle counts -- MAME's clock is 1/55.46 s and a wall timing would make the green light host-sensitive. Claude-Session: https://claude.ai/code/session_01194oWYW8DQXK1SZ2DnChW6
This commit is contained in:
@@ -103,14 +103,26 @@ the disk it is where nothing fits at any container size. The ROM drives SASI
|
||||
rather than the MB89352, so it does not settle W, but a cheap configuration is
|
||||
now the thing that has to be shown rather than assumed (FINDINGS 52).
|
||||
|
||||
**The player builds its own codebooks and palette now.** The two load-time
|
||||
transforms — codebooks to word-per-pixel form, palette to `GGGGGRRRRRBBBBBI`
|
||||
with the shared LSB picked per entry — ran host-side until session 21 and now
|
||||
run on the 68000, out of the raw container header, byte-exact against the host
|
||||
implementation on both CPU cores and with the palette read back out of the
|
||||
hardware registers. A scene change costs **18.96 ms**, a third of one 12fps
|
||||
frame slot. The finding underneath it is a cost nothing had counted: a scene
|
||||
header is **5,920 bytes** that must arrive before frame 0, and in the currency
|
||||
of seek slack those bytes lengthen the refill climb by 138 ms at 488 KB/s and by
|
||||
**1.099 s at 451.4 KB/s**, because the surplus they are divided by goes to zero
|
||||
(FINDINGS 53).
|
||||
|
||||
**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.
|
||||
|
||||
**Green-light check:** `./tools/bench/check.sh` (~3 min, needs the Blu-ray
|
||||
**Green-light check:** `./tools/bench/check.sh` (~4 min, needs the Blu-ray
|
||||
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 and the DMAC configuration gate, then
|
||||
prints `ALL GREEN`.
|
||||
cores, the ring and paced-ring passes, the DMAC configuration gate and the
|
||||
load-time transforms on both cores, then prints `ALL GREEN`.
|
||||
|
||||
## Reproducing this
|
||||
|
||||
@@ -255,6 +267,10 @@ tools/analysis/ measurement scripts, numbered in the order they were written.
|
||||
model, sharing no code with the Lua producer it checks.
|
||||
21 decodes the IPL ROM's HD63450 configuration and gates on the
|
||||
bytes being where it says they are.
|
||||
22 prices a scene change: header bytes, load-time clocks and
|
||||
what both cost in accumulated seek slack, across explicit
|
||||
rates. Its cycle counts are PARSED out of the rig's log, not
|
||||
pasted in, so they cannot go stale silently.
|
||||
buscost.py is the shared bus-cycle table. The per-block
|
||||
constants live in tools/encoder/vq_hybrid.py and are imported,
|
||||
never copied.
|
||||
@@ -275,7 +291,12 @@ tools/bench/ MAME Lua injection harness and 68000 benchmark sources.
|
||||
through a bounded ring at a modelled pipe rate, so the rig is
|
||||
not bounded by the emulated machine's RAM and a stock 2 MB
|
||||
machine runs the whole window. dlxload.py holds the
|
||||
codebook/palette load-time maths both preps share.
|
||||
codebook/palette load-time maths both preps share -- and
|
||||
the reference src/player/load.i is gated against.
|
||||
prep_load.py/load.lua/verify_load.py/load_run.sh run those
|
||||
transforms ON the 68000 and compare all 10,752 output bytes
|
||||
with dlxload.py's, palette words read back out of the palette
|
||||
registers rather than a RAM shadow.
|
||||
tools/bench/c68k/ headless px68k C68K harness, a SECOND emulator for every
|
||||
68000 cycle figure. Links only px68k's CPU core: no SDL, no
|
||||
ROMs, no emulated machine. `make PX68K=~/src/px68k` then
|
||||
@@ -296,6 +317,11 @@ tools/encoder/ hybrid VQ encoder and DLX3 container writer.
|
||||
dlx.py is the reference DECODER, ground truth for the 68000.
|
||||
src/player/ decode.s is the 68000 DLX3 decoder with a preloaded-stream
|
||||
front-end. stream.s is the same decoder behind a bounded ring.
|
||||
load.i is the LOAD-time half: codebook expansion and palette
|
||||
packing, out of the raw container header, with loadgate.s as
|
||||
its rig front-end. Its three scratch tables describe the
|
||||
machine rather than the scene, so they are a separate entry
|
||||
point a player calls once at boot.
|
||||
Both include frame.i (the block loop and span chain) and
|
||||
geom.i (the constants), so there is exactly ONE copy of the
|
||||
bytes every cycle constant is fitted to. The span pass is
|
||||
|
||||
Reference in New Issue
Block a user