Read the entire contents of the hard disk connected via the SV-608M controller and stream the data to the PicoExpander for storage to flash. The dump utility is a standalone ROM cartridge (no BIOS or CP/M dependencies).
The hard disk is partitioned into 4 CP/M drives, addressed by a flat numbering of 1,160 tracks. Each track contains 32 sectors of 256 bytes (8,192 bytes per track).
| Partition | CP/M Drive | Tracks | Count | Capacity |
|---|---|---|---|---|
| 1 | B: | 0–257 | 258 | 2,113K |
| 2 | C: | 258–513 | 256 | 2,048K |
| 3 | D: | 514–769 | 256 | 2,048K |
| 4 | E: | 770–1159 | 390 | 3,120K |
Drive letters shown are for the floppy BIOS. When booted from HDD (T0T1.SYS), partitions 1–4 map to A:–D: instead, with E: as the floppy. | Total | | 0–1159 | 1,160 | 9,329K |
Note: partition B includes 2 reserved system tracks (OFF=2). The counts above reflect the total physical track range for each partition, including reserved tracks.
The SV-608M controller accepts a 16-bit linear sector address, computed as:
linear_sector = track × 32 + sector
where track = 0..1159 and sector = 0..31.
Address range: 0x0000 (track 0, sector 0) to 0x911F (track 1159, sector 31).
The dump reads sequentially:
for track = 0 to 1159:
for sector = 0 to 31:
read_sector(track × 32 + sector)
send_to_pico(256 bytes)
Total sectors: 1,160 × 32 = 37,120 sectors = 9,502,720 bytes of raw data.
Each sector’s 256 raw data bytes are streamed directly to the PicoExpander
via its dump disk interface (OUT (14h), byte). The Pico accumulates data into
a double-buffered 8K flash buffer, flushing each 4K half to flash as it fills.
The resulting disk image is a flat binary in sequential sector order — no framing or headers, identical to what the existing floppy dumper produces.
Total image size: 37,120 × 256 = 9,502,720 bytes.
Derived from the BIOS read path and confirmed against the WD1002-SHD OEM Manual. The SV-608M host adapter exposes the standard SASI bus phases through ports 40h\u201346h.
1. BUS FREE — Poll SV608M_STATUS (port 46h AND 1Fh) until == 00h
2. TARGET SELECTION — Write 01h to SV608M_DATA_OUT (41h), then 01h to SV608M_SEL (43h)
3. COMMAND PHASE — For each of the 6 command bytes:
Poll SV608M_STATUS until == 0Bh (Command phase)
Write byte to SV608M_DATA_OUT (41h)
4. DATA IN PHASE — Poll SV608M_STATUS:
If == 13h → read 256 bytes from SV608M_DATA_IN (42h) via INIR
If == 1Bh → no data, skip to Status phase
5. STATUS PHASE — Poll SV608M_STATUS until == 1Bh
Read result byte from SV608M_DATA_IN (42h) (00h = success)
6. MESSAGE IN PHASE — Poll SV608M_STATUS until == 1Fh
Read completion byte from SV608M_DATA_IN (42h)
| Byte | Value | Description |
|---|---|---|
| 0 | 08h | Read opcode |
| 1 | 00h | LUN (bits 7-5) + addr bits 20-16 (4-0) |
| 2 | addr_hi | Sector address bits 15-8 |
| 3 | addr_lo | Sector address bits 7-0 |
| 4 | 01h | Block count (1 sector) |
| 5 | 47h | Control: retries on, ECC, step=15µs |
| Value | SASI Phase | Signals | Action |
|---|---|---|---|
| 00h | Bus Free | (none) | Safe to initiate Target Selection |
| 03h | Data Out | BSY+REQ | Write data byte to SV608M_DATA_OUT |
| 0Bh | Command | BSY+REQ+C/D | Send next command byte |
| 13h | Data In | BSY+REQ+I/O | INIR 256 bytes from SV608M_DATA_IN |
| 1Bh | Status | BSY+REQ+C/D+I/O | Read result from SV608M_DATA_IN |
| 1Fh | Message In | all five | Read completion from SV608M_DATA_IN |
The complete Z80 source is in hdd-dump.asm — a standalone ROM (org 0000h) with no BIOS or CP/M dependencies.
The PicoExpander writes the raw sector data sequentially to flash. The resulting image is a flat binary:
Offset 0x000000: Track 0, Sector 0 (256 bytes)
Offset 0x000100: Track 0, Sector 1 (256 bytes)
...
Offset 0x001F00: Track 0, Sector 31 (256 bytes)
Offset 0x002000: Track 1, Sector 0 (256 bytes)
...
Offset 0x90FF00: Track 1159, Sector 31 (256 bytes)
Total image size: 9,502,720 bytes.
Once captured, extract the partitions from the flat image:
# Partition 1: tracks 0–257 (258 tracks × 8192 bytes/track)
dd if=hdd_dump.img of=partition_1.img bs=8192 skip=0 count=258
# Partition 2: tracks 258–513
dd if=hdd_dump.img of=partition_2.img bs=8192 skip=258 count=256
# Partition 3: tracks 514–769
dd if=hdd_dump.img of=partition_3.img bs=8192 skip=514 count=256
# Partition 4: tracks 770–1159
dd if=hdd_dump.img of=partition_4.img bs=8192 skip=770 count=390
Each partition image can then be analysed with CP/M filesystem tools
(e.g., cpmtools with an appropriate disk definition).
The ROM runs with interrupts permanently disabled (DI at entry).
The SASI bus polling and INIR block transfers require uninterrupted
operation.
The SASI bus polling loops have no timeout, matching the original BIOS behaviour. If the WD1002-SHD does not respond (hardware absent or malfunctioning), the program will hang at the Bus Free or phase-wait step. A production version would add a timeout counter to each polling loop.