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:
prosolis
2026-08-24 22:53:58 -07:00
parent 00232bb22b
commit e935d8661c
8 changed files with 1262 additions and 1 deletions
+91
View File
@@ -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