Put the SPC on the 68000, and find P4 was blocked on a file nobody needed
ROADMAP P4, first half. Every byte the player has ever consumed was placed in emulated RAM by a host: decode.lua preloaded a container, stream.lua answered a mailbox at a modelled rate. src/player/scsi.i selects a SCSI target on a real MB89352 and issues READ(10) itself -- 4,096 B from LBA 0 and 2,048 B from LBA 1000, both byte-for-byte against the host's copy of the same volume, with no IOCS and no host in the transfer path. The non-zero LBA is the half that matters: a driver that emits a malformed LBA field still passes block 0, because zero is what a malformed field usually is. P4 was recorded as blocked in this tree and was not. Session 21's handoff said MAME's x68000 has no MB89352 path; -exp1 cz6bs1 instantiates one next to the HD63450, and FINDINGS 32.4 had read that card's DMA glue in session 9. The session-21 note is a regression in the record, not a discovery. What is genuinely absent is the 8 KB scsiexrom.bin MAME requires to INSTANTIATE the card and the player never executes -- driving the SPC registers directly has been the plan since BENCHMARK item 4 in session 2 -- so scsi_run.sh supplies a zero-filled placeholder on its own rompath, leaves the user's romset alone, and lets MAME print WRONG CHECKSUMS as it should. B3 is untouched: it wants that ROM's bytes disassembled and a blank one has none. The register map is measured, not inferred, and it corrects MAME's own documentation. The probe walks $EA0000..$EA003F one address at a time with a bus-error handler that records the fault and steps the index, because a sequential dump reports the first hole as the answer -- the earlier version took a bus error at $EA0006 and knew nothing about the other 57. 60 of 64 answer; the two holes are exactly the TMOD and EXBF the MB89352 omits and the MB87030 has. MAME leaves HOLES and does not shift the later indices down, which its own device summary claims it does, and that is what keeps DREG at $EA0015. The data register is DMA-only here and a PIO write vanishes. x68k_scsiext.cpp glues $EA0015 and nothing else, and with exown() asserted and DRQ low the byte is discarded: no error bit, no status change, no interrupt. Quieting all four DMAC channels does not change it. Measured rather than reasoned about -- write $5A, read back $00 with the FIFO still empty -- because ten command bytes vanishing without trace looks exactly like a target refusing a command, which is how it first presented. So every transfer runs the SPC in DMA mode and the CPU moves the bytes through the DMAC's own door. That costs the argument something, and it is easy to overclaim here: with exown asserted at idle MAME cannot distinguish a CPU-driven byte at $EA0015 from a DMAC-driven one. This shows the DATA PATH and cannot by itself show that the HD63450 is driving it, which is precisely what ROADMAP calls P4's first job. Whether a real CZ-6BS1 also refuses PIO there is not settled; it is a property of MAME's model and it wants a board. W did not move by one clock, and could not have. MAME's device models are functional rather than transfer-timing accurate and 42.5 reads its DMAC configured in wall-clock attotimes, so this is BENCHMARK Tier 1 -- does the read path work -- and never Tier 2. W is still the largest open number here. Five bugs, four of them silent, recorded in 57.5 because the pattern is the finding: a chain of rol.l #8 that loaded a transfer counter of ZERO from a count of 10; a byte handed to a FIFO mistaken for a byte on the bus; a fixed phase sequence where the bus decides the order; the discarded PIO write; and an initiator that must drop ACK and only then release the bus. The last appeared only once there were TWO reads -- one passed byte-exact and every conclusion from it was sound, and the second could not select. A player issues one command per record, so that failure would have been universal in the ring and invisible in a one-read demonstration. No decoder code changed; decode.bin is still 1,296 B at the same MD5. check.sh gains a SCSI stage that builds the volume out of the same stream_disk.bin the ring rig reads, gates the register window at 60 of 64 and both reads byte-exact, and skips when chdman is absent. ALL GREEN before and after. Claude-Session: https://claude.ai/code/session_01194oWYW8DQXK1SZ2DnChW6
This commit is contained in:
@@ -5229,3 +5229,156 @@ the diff produced is one useful fact about our own input layer, below.
|
||||
generated table carries the attribution. **`tmp/scenegraph.json` is
|
||||
generated, gitignored and derived data**: committing it, or any table built
|
||||
from it, is redistribution and the attribution has to travel with it.
|
||||
|
||||
---
|
||||
|
||||
## FINDINGS 57 — the 68000 reads the disc itself, and P4 was never blocked
|
||||
|
||||
Session 25. ROADMAP P4, first half. Green light ALL GREEN before and after.
|
||||
**Emulated** — MAME 0.277, `x68000 -exp1 cz6bs1`. No real hardware.
|
||||
|
||||
### 57.1 The blocker was a missing FILE, not a missing MODEL, and the tree already knew
|
||||
Session 21 recorded P4 as "blocked in this tree", re-checked rather than
|
||||
assumed, on three grounds. One of them is wrong:
|
||||
|
||||
> there is still no `scsiexrom.bin` anywhere on this machine ... **MAME's
|
||||
> `x68000` has no MB89352 path**, and `hd63450.cpp` decodes no DTYP.
|
||||
|
||||
MAME 0.277's `x68000` **does** have one. `-listslots` offers `cz6bs1` on `exp1`
|
||||
and `exp2`; `-listdevices x68000 -exp1 cz6bs1` shows a *Fujitsu MB89352 SCSI
|
||||
controller @ 5.00 MHz* on a SCSI bus with a hard disk at ID 0, alongside the
|
||||
HD63450. **FINDINGS 32.4 had already established this in session 9** — the
|
||||
CZ-6BS1's DMA glue, `$EA0000`, the data register at `$EA0015` — and 42.5 built
|
||||
on it in session 14. The session-21 note is a regression in the record, not a
|
||||
discovery.
|
||||
|
||||
What is genuinely missing is only the 8 KB `scsiexrom.bin` (CRC `7be488de`),
|
||||
which MAME **requires** to instantiate the card: without it the machine refuses
|
||||
to start at all. **That is the entire blocker, and it is not one**, because the
|
||||
player drives the SPC registers directly and never executes that ROM — which was
|
||||
already the plan in `docs/BENCHMARK.md` item 4, written in session 2, long
|
||||
before the file turned out to be absent. `tools/bench/scsi_run.sh` supplies a
|
||||
zero-filled placeholder on its own rompath, leaves the user's romset untouched,
|
||||
and lets MAME print WRONG CHECKSUMS as it should.
|
||||
|
||||
**The substitution is honest here and would not be everywhere.** Anything that
|
||||
boots from the card, or calls SCSI IOCS, *does* execute that ROM. Do not reuse
|
||||
the rompath for those. **B3 is untouched**: it wants the ROM's bytes
|
||||
disassembled for the DCR it writes, and a blank one has none.
|
||||
|
||||
### 57.2 The register map, measured rather than inferred
|
||||
32.4 quoted one address. `src/player/scsigate.s` probes `$EA0000..$EA003F` one
|
||||
address at a time, with a bus-error handler that records the fault, steps the
|
||||
index and re-enters the loop — so a hole costs an entry in the map rather than
|
||||
the rest of the run. **60 of 64 addresses answer.**
|
||||
|
||||
| | |
|
||||
|---|---|
|
||||
| registers | odd bytes, `$EA0001 + 2n`, `n = 0..14` |
|
||||
| `$EA0007` (n=3, TMOD) | **BUS ERROR** |
|
||||
| `$EA001F` (n=15, EXBF) | **BUS ERROR** |
|
||||
| `$EA0017` (n=11, TEMP) | wrote `$A5`, read back `$A5` |
|
||||
| `$EA0015` (n=10, DREG) | as 32.4 said |
|
||||
|
||||
The two holes are exactly the two registers the **MB89352 omits and the MB87030
|
||||
has**, which independently confirms which part MAME is modelling. It also
|
||||
**corrects the device's own documentation**: the summary of `mb87030.cpp` says
|
||||
the MB89351/352 "skip TMOD and EXBF, shifting subsequent indices accordingly",
|
||||
and the machine says MAME leaves *holes* and shifts nothing — which is what
|
||||
keeps DREG at index 10 and at `$EA0015`. The bytes win. The first version of
|
||||
this probe walked upward with `move.b (a0)+`, took a bus error at `$EA0006`, and
|
||||
knew one address was dead and nothing about the other 57; **a sequential dump
|
||||
reports the first hole as the answer**.
|
||||
|
||||
### 57.3 The data register is DMA-only on this card, and a PIO write vanishes
|
||||
`x68k_scsiext.cpp` installs its own handler on `$EA0015` **and on no other
|
||||
address**:
|
||||
|
||||
write: if (exown()) { if (!drq) dtack_w(1); else dma_w(data); }
|
||||
else dreg_w(data);
|
||||
|
||||
On this machine `exown()` — the HD63450's OWN, fed back to the slot by
|
||||
`x68k.cpp` — is asserted where a PIO write needs it not to be. The `else` arm is
|
||||
unreachable, and **a byte written to `$EA0015` with the SPC in PROGRAM transfer
|
||||
mode is discarded silently**: no error bit, no status change, no interrupt.
|
||||
Quieting all four DMAC channels (`CCR = 0`, `CSR = $FF`) does not change it.
|
||||
|
||||
It was **measured, not reasoned about** — the gate writes `$5A` to `$EA0015` and
|
||||
reads it straight back, and gets `$00` with the FIFO still empty — because ten
|
||||
command bytes vanishing without trace looks exactly like a target refusing a
|
||||
command, and that is how it first presented.
|
||||
|
||||
So every transfer issues `SCMD` **without** the PROGRAM bit, which puts the SPC
|
||||
in DMA mode and makes it raise DRQ, and the CPU then moves the bytes through
|
||||
`$EA0015` itself, in via `dma_w` and out via `dma_r`. **The CPU stands in for
|
||||
the DMAC, through the DMAC's own door.**
|
||||
|
||||
**What that costs the argument, stated because it is easy to overclaim.** With
|
||||
`exown` asserted at idle, MAME **cannot distinguish a CPU-driven byte at
|
||||
`$EA0015` from a DMAC-driven one**. This rig therefore demonstrates the DATA
|
||||
PATH and cannot, on its own, demonstrate that the HD63450 is the thing driving
|
||||
it — which is precisely what ROADMAP calls P4's first job. Whether a real
|
||||
CZ-6BS1 also refuses PIO here is **not settled**: it is a property of MAME's
|
||||
model and it wants a board.
|
||||
|
||||
### 57.4 The result
|
||||
`src/player/scsi.i`, 68000 code, no IOCS and no host in the transfer path:
|
||||
selects the target, and issues **READ(10)** twice.
|
||||
|
||||
READ(10) OK: 4096 B from LBA 0 match the host's image byte for byte
|
||||
READ(10) OK: 2048 B from LBA 1000 match too
|
||||
|
||||
The second one is the half that matters: **a driver that emits a malformed LBA
|
||||
field still passes LBA 0**, because zero is what a malformed field usually is.
|
||||
|
||||
The volume is `tmp/stream_disk.bin` — the *same* file `prep_stream.py` already
|
||||
writes for the ring rig — so the SCSI volume and the host-file pipe carry
|
||||
byte-identical bytes, and a difference between the two rigs cannot be a
|
||||
difference in what they are reading.
|
||||
|
||||
### 57.5 Five bugs, and four of them were silent
|
||||
Recorded because the pattern is the finding: **nothing in a SCSI bring-up tells
|
||||
you what you did wrong.** Every one of these presented as a phase that never
|
||||
arrived.
|
||||
|
||||
1. **`sc_settc` wrote the wrong three bytes.** Three chained `rol.l #8` put the
|
||||
original bits 31..24, 23..16 and 15..8 into TCH/TCM/TCL, so a count of 10
|
||||
loaded a transfer counter of **zero**. MAME completed the TRANSFER instantly
|
||||
and silently, and the bus sat in command phase. Now written low-byte-first
|
||||
with `lsr`. The same trap was live in the CDB's block-count field.
|
||||
2. **A byte handed to a FIFO is not a byte on the bus.** The driver returned
|
||||
from the command phase with the last byte still in the SPC, asked what phase
|
||||
the bus was in, and got COMMAND — which reads as a target refusing the
|
||||
command. Fixed by waiting for `XFER IN PROGRESS` to clear.
|
||||
3. **A fixed phase sequence is wrong.** The first version ran select → command →
|
||||
data → status → message; the target came up in MESSAGE OUT with ATN asserted
|
||||
and the driver called it an unexpected phase. **The bus decides the order.**
|
||||
`scsi_read` is now a phase loop, which is both shorter and correct.
|
||||
4. **The discarded PIO write** of 57.3.
|
||||
5. **The initiator must let go of the bus, in two steps.** After the final
|
||||
message byte the SPC still holds ACK — `PSNS` reads `$4F`, REQ low and ACK
|
||||
high — and a target cannot drop BSY into that. It needs `SCMD` reset-ACK/REQ
|
||||
**and then** bus release. **This one only appeared once there were two
|
||||
reads**: one read passed byte-exact and every conclusion drawn from it was
|
||||
sound, and the second could not select. A player issues one command per
|
||||
record, so the failure would have been universal in the ring and invisible in
|
||||
the demonstration.
|
||||
|
||||
### 57.6 What this does and does not move
|
||||
**Does not move `W`.** Not by one clock. MAME's device models are functional,
|
||||
not transfer-timing accurate (`docs/BENCHMARK.md`), and 42.5 reads its DMAC
|
||||
configured in wall-clock attotimes rather than per-operand cycles. `W` remains
|
||||
the project's largest open number and still wants a board.
|
||||
|
||||
**Does not finish P4.** What is done is the correctness half — BENCHMARK's Tier
|
||||
1, "does our read path work at all". What is left is the half ROADMAP calls
|
||||
P4's first job: **a DMAC configuration that holds the bus**, and then the driver
|
||||
behind `ring.i`'s `XF_*` mailbox in place of `stream.lua`'s modelled transport,
|
||||
gated on the same pixel-exact 120 frames. 57.3 is a warning about the first of
|
||||
those: this apparatus cannot tell a DMAC-driven byte from a CPU-driven one at
|
||||
`$EA0015`, so "the DMAC held the bus" will need evidence that does not come from
|
||||
watching that address.
|
||||
|
||||
**Does move the premise of every delivery rig in the tree.** Until now the
|
||||
bytes came from a host. They now come off a disc, on the machine's own
|
||||
instructions, byte-exact at two different LBAs.
|
||||
|
||||
+34
-1
@@ -5,6 +5,7 @@ Amended end of session 21: P1 done, P2 half done (FINDINGS 53).
|
||||
Amended end of session 22: P3 done (FINDINGS 54).
|
||||
Amended end of session 23: P5 done (FINDINGS 55).
|
||||
Amended end of session 24: G1 done (FINDINGS 56).
|
||||
Amended end of session 25: P4 HALF done (FINDINGS 57).
|
||||
|
||||
**THE COMPLETION TARGET IS M3, THE VERTICAL SLICE** (USER DECISION): one scene
|
||||
tree — a decision point, two outcomes, a death clip — with audio, streaming from
|
||||
@@ -159,7 +160,39 @@ 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. **Session 23
|
||||
**P4. Real transport. HALF DONE, session 25 — FINDINGS 57.**
|
||||
~~Drive the MB89352 instead of a host file.~~ `src/player/scsi.i` selects a SCSI
|
||||
target and issues READ(10) on the 68000, with no IOCS and no host in the
|
||||
transfer path: **4,096 B from LBA 0 and 2,048 B from LBA 1000, both byte-exact**
|
||||
against the host's copy of the same volume.
|
||||
|
||||
**This item was listed as blocked and was not.** Session 21 recorded "MAME's
|
||||
`x68000` has no MB89352 path"; `-exp1 cz6bs1` instantiates one, and FINDINGS
|
||||
32.4 had read that card's DMA glue back in session 9. The real gap was the 8 KB
|
||||
`scsiexrom.bin` MAME needs to instantiate the card and **the player never
|
||||
executes**; a blank placeholder on a separate rompath settles it. **B3 still
|
||||
wants the real ROM's bytes** and is untouched by this.
|
||||
|
||||
**What is left is the half that decides the project**, and it is now two pieces:
|
||||
|
||||
**P4a. A DMAC configuration that HOLDS THE BUS.** Unchanged as the first job,
|
||||
but 57.3 changes how it can be shown: `x68k_scsiext.cpp` glues `$EA0015` so that
|
||||
a write is discarded when `exown()` is asserted and DRQ is low, and on this
|
||||
machine `exown()` is asserted at idle. Every transfer therefore runs the SPC in
|
||||
DMA mode with the CPU moving the bytes through the DMAC's own door — and **MAME
|
||||
cannot then distinguish a CPU-driven byte from a DMAC-driven one at that
|
||||
address**. "The DMAC held the bus" needs evidence that does not come from
|
||||
watching `$EA0015`.
|
||||
|
||||
**P4b. `scsi.i` behind `ring.i`'s `XF_*` mailbox**, in place of `stream.lua`'s
|
||||
modelled transport, gated on the same pixel-exact 120 frames. The seam already
|
||||
exists: `XF_ACK` stops being a word a host synthesises from emulated time and
|
||||
becomes one the 68000 bumps when a transfer lands.
|
||||
|
||||
`W` **did not move by one clock** and is still the largest open number here.
|
||||
|
||||
*(original item, still the standing description of the `W` question:)*
|
||||
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`
|
||||
|
||||
@@ -1,3 +1,94 @@
|
||||
# Status & next-session handoff — end of session 25 (2026-08-24)
|
||||
|
||||
## Session 25: the 68000 reads the disc itself, and P4 was never blocked
|
||||
|
||||
**Green light first and last: `./tools/bench/check.sh` was ALL GREEN before any
|
||||
of this and ALL GREEN after**, plus a new SCSI stage.
|
||||
|
||||
**ROADMAP P4 is HALF DONE. FINDINGS 57.** **Emulated** — MAME 0.277,
|
||||
`x68000 -exp1 cz6bs1`. No real hardware ran.
|
||||
|
||||
**1. THE BLOCKER WAS A MISSING FILE, NOT A MISSING MODEL — and this tree already
|
||||
knew.** Session 21's handoff recorded, re-checked rather than assumed, that
|
||||
"MAME's `x68000` has no MB89352 path". It has one: `-exp1 cz6bs1` instantiates a
|
||||
*Fujitsu MB89352 @ 5.00 MHz* next to the HD63450, and **FINDINGS 32.4 had read
|
||||
that card's DMA glue in session 9**. What is actually absent is the 8 KB
|
||||
`scsiexrom.bin`, which MAME requires to instantiate the card and which **the
|
||||
player never executes** — driving the SPC registers directly has been the plan
|
||||
since `docs/BENCHMARK.md` item 4 in session 2. A zero-filled placeholder on a
|
||||
separate rompath starts the machine; the user's romset is untouched. **B3 is
|
||||
untouched too**: it wants that ROM's bytes disassembled, and a blank one has
|
||||
none. 57.1.
|
||||
|
||||
**2. THE RESULT.** `src/player/scsi.i` on the 68000, no IOCS and no host in the
|
||||
transfer path, selects the target and issues READ(10):
|
||||
|
||||
| | |
|
||||
|---|---|
|
||||
| 4,096 B from LBA 0 | byte-for-byte against the host's image |
|
||||
| 2,048 B from LBA 1000 | byte-for-byte |
|
||||
|
||||
The non-zero LBA is the half that matters: **a driver that emits a malformed LBA
|
||||
field still passes LBA 0**, because zero is what a malformed field usually is.
|
||||
The volume is `tmp/stream_disk.bin`, the same file the ring rig reads, so the two
|
||||
rigs cannot differ in what they are reading. 57.4.
|
||||
|
||||
**3. The register map is measured, and it corrects MAME's own documentation.**
|
||||
The probe walks `$EA0000..$EA003F` one address at a time and survives each bus
|
||||
error. **60 of 64 answer**; the two holes are `$EA0007` and `$EA001F` — exactly
|
||||
the TMOD and EXBF the **MB89352 omits and the MB87030 has**. MAME leaves HOLES
|
||||
and does *not* "shift subsequent indices", which its own device summary claims,
|
||||
and that is what keeps DREG at index 10 and at `$EA0015`. TEMP took `$A5` and
|
||||
gave it back. 57.2.
|
||||
|
||||
**4. THE DATA REGISTER IS DMA-ONLY, AND A PIO WRITE VANISHES.** `x68k_scsiext.cpp`
|
||||
glues `$EA0015` and nothing else: with `exown()` asserted and DRQ low a write is
|
||||
**discarded silently** — no error bit, no status change, no interrupt. Quieting
|
||||
all four DMAC channels does not change it. So every transfer runs the SPC in DMA
|
||||
mode and the CPU moves the bytes through `$EA0015` itself, via `dma_w`/`dma_r`:
|
||||
**the CPU standing in for the DMAC, through the DMAC's own door.**
|
||||
|
||||
**The cost to the argument, stated because it is easy to overclaim:** with
|
||||
`exown` asserted at idle, **MAME cannot distinguish a CPU-driven byte at
|
||||
`$EA0015` from a DMAC-driven one.** This rig shows the DATA PATH and cannot, by
|
||||
itself, show that the HD63450 is driving it — which is exactly what ROADMAP
|
||||
calls P4's first job. Whether a real CZ-6BS1 also refuses PIO here is **not
|
||||
settled**; it is a property of MAME's model. 57.3.
|
||||
|
||||
**5. `W` DID NOT MOVE. Not by one clock.** MAME's device models are functional,
|
||||
not transfer-timing accurate, and 42.5 reads its DMAC configured in wall-clock
|
||||
attotimes rather than per-operand cycles. `W` is still the project's largest
|
||||
open number and still wants a board.
|
||||
|
||||
**6. Five bugs, four of them silent** (57.5), recorded because the pattern is the
|
||||
finding: a chained-`rol` transfer counter that loaded ZERO; a FIFO byte mistaken
|
||||
for a bus byte; a fixed phase sequence where the bus decides the order; the
|
||||
discarded PIO write; and an initiator that must drop ACK *and then* release the
|
||||
bus. The last **only appeared once there were two reads** — one read passed
|
||||
byte-exact and the second could not select. A player issues one command per
|
||||
record, so that failure would have been universal in the ring and invisible in a
|
||||
one-read demonstration.
|
||||
|
||||
**New in the tree:** `src/player/scsi.i` (the driver), `src/player/scsigate.s`
|
||||
(the probe and gate front-end), `tools/bench/scsi.lua`, `tools/bench/scsi_run.sh`,
|
||||
and a `check.sh` stage that builds the volume with `chdman`, gates the register
|
||||
window at 60 of 64 and both reads byte-exact, and is skipped when `chdman` is
|
||||
absent.
|
||||
|
||||
**No decoder code changed.** `decode.bin` is still 1,296 B at the same MD5.
|
||||
|
||||
**Next:** **P4's other half**, in two pieces. (a) The HD63450 driving the data
|
||||
phase in a configuration that HOLDS THE BUS — and 57.3 is a warning about how it
|
||||
will have to be shown, because this apparatus cannot tell a DMAC-driven byte
|
||||
from a CPU-driven one at `$EA0015`. (b) `scsi.i` behind `ring.i`'s `XF_*`
|
||||
mailbox in place of `stream.lua`'s modelled transport, gated on the same
|
||||
pixel-exact 120 frames — the seam is already there, and `XF_ACK` becomes
|
||||
something the 68000 bumps when a transfer lands rather than something a host
|
||||
synthesises. **P2's remaining half** (reserve index 0 as black) is unchanged and
|
||||
still bundled with the two other re-encode-class questions from 55.
|
||||
|
||||
---
|
||||
|
||||
# Status & next-session handoff — end of session 24 (2026-08-24)
|
||||
|
||||
## Session 24: the scene graph is in, and the worst gap between two decision points is zero
|
||||
|
||||
Reference in New Issue
Block a user