Put the ring on the 68000, and find the disc stops whenever the player is not asking
ROADMAP P5. The loader moved in session 21 and the frame clock in 22; the ring producer was the last policy living outside the machine. src/player/ring.i does `aligned` placement, the descriptor ring, a prefill, 51.2's slack rule and a seek, and the host keeps only the transport. It needed a container change. `aligned` asks whether the next record fits before the end of the ring -- a length asked BEFORE the record is fetched -- and every reader in this tree answered that by walking the frame stream, which is exactly what a player streaming off a disc cannot do. DLX4 carries nframes u16 record lengths in the scene header. Frame payloads are byte-identical to the DLX3 encode, so no fitted constant moves; the scene header goes 5,920 to 6,164 B. The producer reproduces the host's tiling exactly: 18 wraps, 14.7 KB mean hole, pixel-exact, a third independent implementation of the same policy. What it exposed is bigger than the item. A channel only moves bytes while it has a request and only the CPU can issue one, so the disc stands still between records by an amount the PLAYER sets, not the medium -- and no host-filled run could see it. At 488 KB/s in a 256 KB ring a one-deep request queue gives away 6.8% of the pipe and underruns 59 of 120 frames; two-deep gives away 3.4% and underruns none. The container's whole surplus over the wire is 8.7%, so the player's own loop was spending most of the slack a branch point saves up. Prefill is the weaker lever: six records of it still leaves 24 underruns. Three silent bugs are recorded in FINDINGS 55.7 -- all produced wrong pixels or a desync rather than a fault -- plus a rig one: MAME renders a screen line by line, so snapshotting the frame the decoder finished in captures a tear that reads exactly like a decoder bug. check.sh gains the machine-owned ring and a seek with the decode after it. decode.bin is unchanged at 1,296 B and a host-filled run executes none of the new code, so every FINDINGS 49/51 figure stands. ALL GREEN before and after. Claude-Session: https://claude.ai/code/session_01194oWYW8DQXK1SZ2DnChW6
This commit is contained in:
@@ -4814,3 +4814,206 @@ accumulator fits 16 bits. `decode.s` and `frame.i` were checked for stack tricks
|
||||
before the mask was lowered: the only `a7` use in either is one `move.l a1,-(sp)`
|
||||
pair, so an interrupt cannot corrupt decoder state. The 120-frame self-paced
|
||||
decode being pixel-exact is the test of that, and it is gated.
|
||||
|
||||
---
|
||||
|
||||
## 55. The 68000 fills its own ring, and the player's request loop costs more than the medium does (session 23)
|
||||
|
||||
ROADMAP P5, the last M2 item this tree could build. FINDINGS 49 and 51 measured
|
||||
a ring that a HOST filled: `tools/bench/stream.lua` held the record index, chose
|
||||
where every record went, wrote the descriptor and advertised it. The 68000 only
|
||||
consumed. That is the same shape session 21 found in the loader and session 22
|
||||
in the frame clock — a policy living outside the machine that has to run inside
|
||||
it — and it was the last one in the delivery path.
|
||||
|
||||
`src/player/ring.i` is that policy on the 68000: `aligned` placement, the
|
||||
descriptor ring, a prefill, an accumulated-slack rule and a seek. The rig keeps
|
||||
only what is genuinely not the CPU's — a transport that answers one request at a
|
||||
time at a modelled rate, which is what an SPC and one DMAC channel are.
|
||||
|
||||
### 55.1 The container had to change: DLX4 carries a record index
|
||||
|
||||
`aligned` asks whether the NEXT record fits before the end of the ring, which is
|
||||
a question about a record's length asked **before it is fetched**. Every reader
|
||||
in this tree learned record boundaries by **walking** the frame stream — reading
|
||||
each record's length word to find the next — and that is exactly what a player
|
||||
streaming off a disc cannot do: the length word of record *i+1* is one of the
|
||||
bytes it has not fetched. A branch point needs the same table a second time, to
|
||||
seek to record *j* without reading what lies between.
|
||||
|
||||
DLX4 adds `nframes` u16 longword-counts to the scene header, ahead of the frame
|
||||
stream. Costs, measured on the gate container:
|
||||
|
||||
| | DLX3 | DLX4 |
|
||||
|---|---:|---:|
|
||||
| scene header | 5,920 B | **6,164 B** (+240 index, +4 header) |
|
||||
| frame payloads | — | **byte-identical**, all 120 |
|
||||
|
||||
The payloads being byte-identical is asserted rather than assumed: the same
|
||||
encode was written both ways and compared record for record, so **no constant
|
||||
fitted to the gate container moves**. `dlx.py` cross-checks the index against
|
||||
its own walk of the stream and refuses a container where they disagree, and
|
||||
`prep_stream.py` checks it again against the disk image it lays out. Lengths
|
||||
rather than offsets: 2 bytes a frame instead of 4, and the disc offsets are a
|
||||
running sum the player builds once at scene load (`ROFF`, 4 B/record of RAM).
|
||||
|
||||
In 53.5's currency the 244 bytes are small — 0.5 ms of pipe at 488 KB/s — but
|
||||
they are on the same side of the ledger as the 5,920 that section priced, and
|
||||
the scene header is now **6,164 B that must arrive before frame 0**.
|
||||
|
||||
### 55.2 It reproduces the host producer's tiling exactly
|
||||
|
||||
Third independent implementation of `aligned`, on the gate container in a 256 KB
|
||||
ring:
|
||||
|
||||
| producer | wraps | mean hole | pixel-exact |
|
||||
|---|---:|---:|:--:|
|
||||
| `19_ring_stream.py` (Python, from record sizes) | 18 | 14.7 KB | — |
|
||||
| `stream.lua` (host, driving the 68000) | 18 | 14.7 KB | yes |
|
||||
| **`ring.i` (the 68000 itself)** | **18** | **14.7 KB** | **yes** |
|
||||
|
||||
The host now **audits** rather than produces: every placement the machine makes
|
||||
is checked against the host's own index and its own list of records the decoder
|
||||
has not consumed, and the run is refused on the first disagreement. That is what
|
||||
makes the pixel-exact result a statement about `ring.i` and not about a new rig.
|
||||
|
||||
### 55.3 THE ONE THAT MOVES SOMETHING: the channel is idle whenever the player is not asking
|
||||
|
||||
A channel only moves bytes while it has a request, and only the CPU can give it
|
||||
one. Between the completion of record *i* and the issue of record *i+1* the disc
|
||||
**stands still**, and the length of that gap is a property of the player's loop,
|
||||
not of the medium. No host-filled run could see it — the host producer placed
|
||||
records whenever it liked — so **no rate table in this tree contains it**.
|
||||
|
||||
Measured on the machine, same container, same 256 KB ring, same 488 KB/s, the
|
||||
only difference being how many requests the player may have outstanding:
|
||||
|
||||
| queue | channel idle | gaps | underruns | slack ceiling | mean slack | bound by |
|
||||
|---:|---:|---:|---:|---:|---:|---|
|
||||
| **1 request** | **669.0 ms, 6.8%** | 119 | **59/120** | 2 | 1.0 | rate |
|
||||
| **2 requests** | **317.5 ms, 3.4%** | 9 | **0/120** | 5 | 3.5 | ring |
|
||||
|
||||
The surplus this container has over the wire at 488 KB/s is 8.7% of the pipe,
|
||||
and a one-deep request loop spends 6.8% of it on nothing. **That is most of the
|
||||
surplus 51.3's lookahead is accumulated out of**, which is why the same ring at
|
||||
the same rate goes from rate-bound with a ceiling of 2 to ring-bound with a
|
||||
ceiling of 5 on a change with no bytes in it at all.
|
||||
|
||||
A second queued slot costs the 68000 nothing per frame and is available on the
|
||||
hardware: the HD63450 has four channels and the IPL programs all of them (52.1).
|
||||
|
||||
### 55.4 Prefill is the weaker lever, and now there is a number for it
|
||||
|
||||
Prefill in whole records, at 488 KB/s in a 256 KB ring, every cell pixel-exact:
|
||||
|
||||
| prefill | 1 | 2 | 3 | 4 | 6 |
|
||||
|---|---:|---:|---:|---:|---:|
|
||||
| underruns, 1-deep queue | 66 | 59 | 49 | 47 | 24 |
|
||||
| underruns, 2-deep queue | 1 | **0** | **0** | **0** | **0** |
|
||||
|
||||
**A prefill buys a one-off cushion that a rate-bound pipe spends immediately; a
|
||||
queued request buys the rate back every frame.** Six records of prefill is half
|
||||
a second of black screen at the start of every scene and still leaves 24
|
||||
underruns; a second slot leaves none for nothing. The policy `ring_prefill`
|
||||
implements is therefore small — 2 records — and the reason it is not 1 is 51.2:
|
||||
*n* resident records buy *n-1* frame times, so releasing at 1 starts a scene
|
||||
with a stall budget of zero.
|
||||
|
||||
### 55.5 The slack rule is in the player now, and so is a seek
|
||||
|
||||
`ring_may_seek` answers 51.2's rule as arithmetic the player can run — "resident
|
||||
minus one, against the frames this branch will cost" — instead of a line in a
|
||||
rig's log. `ring_seek` takes a record number, waits the channel quiet (an
|
||||
outstanding transfer is bytes already on their way to an address about to be
|
||||
declared free), takes the disc address out of the index, and empties the ring.
|
||||
|
||||
Rehearsed as a second pass over the same scene: **240 records placed, the seek
|
||||
at 12.87 s, the ring refilled from empty, 0 underruns after it, and the final
|
||||
frame of the second pass pixel-exact**. The seek's cost shows up exactly where
|
||||
55.3 says it would — as the worst channel gap of the run, **397.5 ms** — and
|
||||
that is the disc idle, not a mechanical seek, which is still unmodelled (51.7.5).
|
||||
|
||||
### 55.6 An independent model, and where it does and does not agree
|
||||
|
||||
`tools/analysis/24_ring_owner.py` is the same producer written from record
|
||||
sizes and per-frame decode costs, sharing no code with the rig — the 49.4/51.5
|
||||
arrangement. It reads the DLX4 index the machine reads, and it reproduces 54.4's
|
||||
4-or-5-refresh cadence rather than averaging it away.
|
||||
|
||||
| 488 KB/s | rig Q=1 | model Q=1 | rig Q=2 | model Q=2 |
|
||||
|---|---:|---:|---:|---:|
|
||||
| channel idle | 6.8% | 8.8% | 3.4% | 5.3% |
|
||||
| slack ceiling | 2 | 3 | 5 | 6 |
|
||||
| mean slack | 1.0 | 1.1 | 3.5 | 4.2 |
|
||||
| underruns | 59/120 | 11/120 | 0/120 | 0/120 |
|
||||
|
||||
The model runs **one record ahead** of the rig, which is the same one-record
|
||||
bracket 51.5 recorded and reported rather than tuned away. The underrun count at
|
||||
Q=1 is the one number that disagrees badly, and it is a threshold statistic on a
|
||||
quantity sitting at 1: with a mean slack of one record, whether each individual
|
||||
frame's record lands before or after its tick is decided by details neither model
|
||||
has. **The agreement that matters is the resource statement** — a one-deep queue
|
||||
loses 7-9% of the pipe and two-thirds of the lookahead — and on that they agree.
|
||||
|
||||
The model's mean decode cost, 561,126 clk/frame, lands within 0.07% of the
|
||||
561,532 the ring pass measured under MAME (49.7.5), from the encoder's own
|
||||
constants.
|
||||
|
||||
### 55.7 Three bugs and one instrument correction, recorded because they were all silent
|
||||
|
||||
1. **The reader's wrap rule was not the writer's.** Stepping the read cursor
|
||||
past record *i* lands on the end of record *i*, which is where record *i+1*
|
||||
went only if it FITTED there. Using the wrong record's length left the cursor
|
||||
inside the hole, and one more retirement pushed it past the end of the ring
|
||||
and wrapped it to an address unrelated to any record. The live span computed
|
||||
from that is *shorter* than the truth, so the producer places over a record
|
||||
the decoder has not read. Symptom: a bitstream desync, not a fault.
|
||||
2. **The free-space test decided the wrap before it knew the shape.** When the
|
||||
LIVE span is the one that wraps, the ring base is not free and `aligned` may
|
||||
not restart there. Deciding from `WCUR + len > SZ` alone overwrote live
|
||||
records. Same symptom.
|
||||
3. **The queue was gated on completion instead of retirement.** A slot stays in
|
||||
use until the descriptor has been read out of it, which happens one poll after
|
||||
the ack at the earliest. Gating on the ack let the CPU overwrite a slot whose
|
||||
descriptor had not been published; `DESC` for that frame stayed zero and the
|
||||
decoder decoded address zero. This one only exists at a queue depth above 1,
|
||||
and it is why the two-deep result took three attempts to obtain.
|
||||
4. **The rig was capturing a torn screen.** MAME renders a screen line by line
|
||||
and the machine-frame notifier fires at the END of that frame, so a bitmap for
|
||||
a frame in which GVRAM changed holds lines from before and after the change.
|
||||
Snapshotting it captures a tear, which reads as a pixel-exactness failure in
|
||||
the bottom blocks plus a broken double-scan pairing. It only bites when the
|
||||
decoder finishes its last frame late in a screen frame, so it appeared for the
|
||||
first time in a run with underruns. The rig now waits one whole frame before
|
||||
the capture. **No previously reported result is affected** — every one of them
|
||||
finished its last frame with idle to spare — but the check.sh gates would have
|
||||
been flaky under any future run that did not.
|
||||
|
||||
An instrument note, not a bug: under the self-clock the host's "records late"
|
||||
report grades arrivals against the tick times it OBSERVED, which are up to
|
||||
17.64 ms late (54.5), so it understates lateness — 6 records late where the
|
||||
68000 itself counted 59 frames that had to wait. The decoder's own stall counter
|
||||
is the sharp instrument. Host-paced runs take their deadlines from a host model
|
||||
and are exact, so 49.6's table is unaffected.
|
||||
|
||||
### 55.8 What this does NOT establish
|
||||
|
||||
1. **The transport is still a model.** It delivers at a chosen byte rate with an
|
||||
exact clock; it is not an MB89352. No command overhead, no arbitration, no
|
||||
sector granularity, no mechanical seek. `W` — the clocks the DMAC steals per
|
||||
delivered byte — is still undecided and still unmeasurable here (P4, 52.5).
|
||||
**A zero-underrun result means the bytes were in time, not that the frames
|
||||
fit.**
|
||||
2. **The rates are chosen inputs.** FINDINGS 50 stands: every column is a
|
||||
sensitivity, not a claim about a BlueSCSI.
|
||||
3. **One container, one scene, one ring size.** The ceilings are in whole
|
||||
records and move with record size (51.7.3).
|
||||
4. **The seek is a rewind, not a branch.** It exercises the machinery — quiet
|
||||
the channel, empty the ring, address record *j* out of the index, refill —
|
||||
against a container that has one scene in it. What the worst gap between two
|
||||
real decision points is still needs the scene graph (ROADMAP G1).
|
||||
5. **`decode.s` and `frame.i` are unchanged** and `decode.bin` is still 1,296 B
|
||||
at the same MD5. `stream.s` grew to 2,814 B: the ring producer, plus a
|
||||
two-instruction test at the top of the pace wait that routes a self-filled
|
||||
run into a polling wait loop. The legacy wait loops are byte for byte the ones
|
||||
FINDINGS 51 measured and a host-filled run executes none of the new code.
|
||||
|
||||
+32
-4
@@ -157,7 +157,10 @@ period from `htotal - 8`), so the tree's "1/55.46 s granularity" was 1/56.69 s
|
||||
throughout. No 68000 cycle figure moves — the CPU clock is unrelated to the
|
||||
screen — but anything paced by the raster does. 54.5.
|
||||
|
||||
**P4. Real transport.** Drive the MB89352 instead of a host file. The `W`
|
||||
**P4. Real transport.** Drive the MB89352 instead of a host file. **Session 23
|
||||
added a second axis to it:** `W` is the clocks stolen per delivered byte, and
|
||||
55.3 measured that the player's own request loop gives away 3-7% of the pipe
|
||||
before `W` is even asked about. A transport design has to answer both. The `W`
|
||||
handshake — clocks stolen per delivered byte, bracketed 5..12 by MC68450 Fig
|
||||
4-25 — is listed in "Decisions locked" as UNDECIDED and as the thing that
|
||||
decides the project: `W<=6` fits 0/120 frames, `W=8` misses 47/120. It is a
|
||||
@@ -178,11 +181,36 @@ first job rather than its last.
|
||||
clocks per WORD and FINDINGS 43 voided it; 52.5 cited it in byte units when
|
||||
first written and strikes it.
|
||||
|
||||
**P5. Seek and branch.** Per-record index (the `aligned` producer needs one
|
||||
anyway, 49.3), prefill policy, and the accumulated-slack rule from 51.3 made
|
||||
explicit in the player rather than implied by the rig.
|
||||
~~**P5. Seek and branch.**~~ **DONE, session 23 — FINDINGS 55.**
|
||||
`src/player/ring.i` fills the ring on the 68000: `aligned` placement, the
|
||||
descriptor ring, a prefill policy, 51.2's slack rule as arithmetic the player
|
||||
can run (`ring_may_seek`), and a seek that quiets the channel and re-addresses
|
||||
the stream out of the index. It reproduces the host producer's tiling exactly —
|
||||
18 wraps, 14.7 KB mean hole, pixel-exact — and the host now AUDITS every
|
||||
placement instead of making it.
|
||||
|
||||
The index is a **container change**: DLX4 carries `nframes` u16 record lengths
|
||||
in the scene header, because `aligned` needs a record's length before it fetches
|
||||
it and walking the stream is precisely what a player cannot do. Frame payloads
|
||||
are byte-identical to the DLX3 encode; the scene header goes 5,920 to 6,164 B.
|
||||
|
||||
**What it exposed is bigger than the item.** A channel only moves bytes while it
|
||||
has a request and only the CPU can issue one, so the disc **stands still between
|
||||
records** by an amount set by the player's loop rather than by the medium — and
|
||||
no host-filled run could see it. At 488 KB/s in a 256 KB ring, 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. The container's whole surplus
|
||||
over the wire at that rate is 8.7%, so the player's own loop was spending most
|
||||
of the slack 51.3 accumulates. **Prefill is the weaker lever** — six records of
|
||||
it still leaves 24 underruns at depth 1 — and the fix costs no clocks and no
|
||||
bytes. 55.3, 55.4.
|
||||
|
||||
**P5a (open, and it belongs with P4).** The two-deep queue is modelled as two
|
||||
mailbox slots. On the machine it is two DMAC channels or one channel with a
|
||||
chained descriptor array, and which of those is affordable is a `W` question.
|
||||
|
||||
**P7. Boot.** The player as an executable loading from the SCSI volume.
|
||||
Buildable, and empty until P4: there is nothing to boot from yet.
|
||||
|
||||
---
|
||||
|
||||
|
||||
+106
@@ -1,3 +1,109 @@
|
||||
# Status & next-session handoff — end of session 23 (2026-08-24)
|
||||
|
||||
## Session 23: the 68000 fills its own ring, and the player's request loop turns out to cost more than the medium does
|
||||
|
||||
**Green light first and last: `./tools/bench/check.sh` was ALL GREEN before any
|
||||
of this and ALL GREEN after**, 120/120 on both cores, no `TRUNCATED`, plus two
|
||||
new ring stages.
|
||||
|
||||
**ROADMAP P5 is DONE. FINDINGS 55.** P5 was the last M2 item buildable in this
|
||||
tree, and it is the third and last policy to move off the host: the loader went
|
||||
in session 21, the frame clock in 22, and the ring producer now.
|
||||
|
||||
**1. The container had to change, and it is the first format change since
|
||||
session 12.** `aligned` asks whether the next record fits before the end of the
|
||||
ring — a question about a record's length asked **before it is fetched** — and
|
||||
every reader in this tree answered it by WALKING the frame stream, which is
|
||||
exactly what a player streaming off a disc cannot do. **DLX4** carries
|
||||
`nframes` u16 record lengths in the scene header. The frame payloads are
|
||||
**byte-identical** to the DLX3 encode, asserted record for record, so no
|
||||
constant fitted to the gate container moves; the scene header goes 5,920 →
|
||||
**6,164 B**. `dlx.py` refuses a container whose index disagrees with its own
|
||||
walk. 55.1.
|
||||
|
||||
**2. `src/player/ring.i` reproduces the host producer exactly.** Same 18 wraps,
|
||||
same 14.7 KB mean hole, pixel-exact — a third independent implementation of
|
||||
`aligned` landing on the same tiling (55.2). The host now **audits** every
|
||||
placement instead of making it.
|
||||
|
||||
**3. THE ONE THAT MOVES SOMETHING: the disc stands still whenever the player is
|
||||
not asking.** A channel only moves bytes while it has a request and only the CPU
|
||||
can issue one, so there is a gap between every pair of records that is a
|
||||
property of the **player's loop, not the medium** — and no host-filled run could
|
||||
see it, so no rate table in this tree contains it. At 488 KB/s in a 256 KB ring,
|
||||
changing nothing but how many requests the player may have outstanding:
|
||||
|
||||
| queue | channel idle | underruns | slack ceiling | bound by |
|
||||
|---:|---:|---:|---:|---|
|
||||
| 1 request | **6.8%** | **59/120** | 2 | rate |
|
||||
| 2 requests | **3.4%** | **0/120** | 5 | ring |
|
||||
|
||||
This container's surplus over the wire at 488 KB/s is 8.7% of the pipe, and a
|
||||
one-deep request loop spends 6.8% of it on nothing — **most of the surplus
|
||||
51.3's lookahead is accumulated out of**. A second slot costs no clocks and the
|
||||
hardware has four channels (52.1). 55.3.
|
||||
|
||||
**4. Prefill is the weaker lever, and now it has a number.** Six records of
|
||||
prefill — half a second of black at every scene start — still leaves 24
|
||||
underruns at a one-deep queue; a second queue slot leaves none. **A prefill buys
|
||||
a one-off cushion a rate-bound pipe spends immediately; a queued request buys
|
||||
the rate back every frame.** The shipped policy is 2 records, and it is not 1
|
||||
because 51.2 measured that *n* resident records buy *n-1* frame times. 55.4.
|
||||
|
||||
**5. The slack rule and a seek are in the player.** `ring_may_seek` is 51.2's
|
||||
rule as arithmetic the player runs; `ring_seek` quiets the channel, takes record
|
||||
*j*'s disc address out of the index and empties the ring. Rehearsed as a second
|
||||
pass: 240 records, seek at 12.87 s, refill from empty, **0 underruns after it
|
||||
and the last frame of the second pass pixel-exact**. The seek shows up as the
|
||||
run's worst channel gap, **397.5 ms** — disc idle, not mechanical seek, which is
|
||||
still unmodelled. 55.5.
|
||||
|
||||
**6. Three silent bugs and one instrument correction**, all written up in 55.7,
|
||||
because every one of them produced wrong pixels or a desync rather than a fault:
|
||||
the read cursor's wrap rule not matching the writer's; the free-space test
|
||||
deciding a wrap before it knew whether the LIVE span was the wrapping one; the
|
||||
request queue gated on completion instead of retirement (only reachable above
|
||||
depth 1). The fourth is the rig's: MAME renders a screen line by line, so
|
||||
snapshotting the frame in which the decoder finished captures a **tear** — it
|
||||
looked exactly like a decoder bug and was not. The rig now settles one frame
|
||||
before capturing. No previously reported result is affected.
|
||||
|
||||
**New in the tree:** `src/player/ring.i` (the producer, the prefill, the slack
|
||||
rule and the seek); `tools/analysis/24_ring_owner.py` (an independent model of
|
||||
all of it, sharing no code with the rig). `encode.py`/`dlx.py` gain DLX4 and its
|
||||
index cross-check; `prep_stream.py` emits the index and checks it against the
|
||||
disk image; `load.i` accepts DLX3 or DLX4. `stream.s` gains the ring hooks and a
|
||||
polling wait loop; `stream.lua` becomes a **transport** built out of memory taps
|
||||
(exact issue and completion times — see 55.7 for why nothing in a tap may touch
|
||||
the memory space); `pace_run.sh` gains `DLX_RINGOWN`, `DLX_QDEPTH`,
|
||||
`DLX_PREFILL_FR`, `DLX_ITER`. `check.sh` gains two stages: the machine-owned
|
||||
ring, and a seek with the decode after it.
|
||||
|
||||
**`decode.s` and `frame.i` are unchanged**, `decode.bin` still 1,296 B at the
|
||||
same MD5, and a host-filled run executes none of the new code — so every
|
||||
FINDINGS 49/51 figure stands.
|
||||
|
||||
**Still open in P2:** unchanged — the encoder does not reserve a black entry
|
||||
(23.4).
|
||||
|
||||
**Next:** M2 has no item left that this tree can build. **P4** (drive the
|
||||
MB89352, settle `W`) still decides the project and still needs hardware or a
|
||||
MAME that models the SPC; 55.3 sharpens what to ask of it, because the ladder
|
||||
now has a second axis — the clocks stolen per byte AND the fraction of the pipe
|
||||
the player's own loop gives away. **G1** (import the scene graph) is what would
|
||||
let this tree ask the question 55.5 rehearsed but could not pose: what is the
|
||||
worst gap between two real decision points, and does the refill climb survive
|
||||
it. **P7** (boot from the volume) is buildable but empty until P4.
|
||||
|
||||
**A question 55.3 raises and does not answer:** the encoder is fitted to a pipe
|
||||
that delivers continuously. It does not, and by 3-7% depending on the player's
|
||||
queue. Whether the rate point should be set against the *delivered* rate rather
|
||||
than the nominal one is the same class of change as the reserved black entry and
|
||||
the short-slot question from 54.4 — a re-encode plus a re-measurement, and all
|
||||
three should be decided together.
|
||||
|
||||
---
|
||||
|
||||
# Status & next-session handoff — end of session 22 (2026-08-24)
|
||||
|
||||
## Session 22: the frame clock moves onto the 68000, and the 12 fps frame turns out not to exist
|
||||
|
||||
Reference in New Issue
Block a user