The previous article compiled the four components into four binaries. Now those binaries have to go onto a disk, and not just anywhere: each one belongs at specific physical sectors on the first three tracks, in an order that is not the order it sits in memory. This article is the placement step, and it is where the sector interleave from article three finally has to be dealt with.
A disk is tracks and sectors
A 5.25-inch Apple floppy is 35 concentric tracks, each holding 16 sectors of 256 bytes. The operating system lives in the first three: tracks 0, 1, and 2, the reserved system area the machine reads at boot before it ever shows you a file. Everything from track 3 outward is the file system. So placing the operating system means writing it into 48 sectors, 16 per track, across those first three tracks.
The interleave, paid at last
Here is the part the earlier articles kept promising would come back. The operating system does not go onto the disk in memory order.
When the boot loader reads the system area, it reads logical sectors in sequence but lays them into contiguous memory, and the mapping between the two is the sector interleave, a fixed permutation built into how Apple disks are laid out so the drive can keep up with the processor. The upshot is that runtime page N of the operating system does not live on sector N of the disk. It lives on whatever sector the loader happened to read into that memory page.
To write the operating system back onto a disk correctly, the placement step has to undo what the source build did. The source is decoded in memory order, contiguous and sensible. The disk needs it scattered back through the interleave, each 256-byte runtime page written to the exact physical sector the loader will later read it from. The map that does this is cpm_pipeline/deskew.py: for every runtime page it records which disk sector that page came from, and the placement step writes each page straight back to that sector.
Where each binary lands
With the interleave handled, the layout of the three boot tracks is:
- Track 0, the boot stub. The 6502 boot loader is laid down as eleven sectors on track 0. Sector 0 is the one the Disk II PROM reads and runs at power-on; it pulls in the rest of the loader from the neighboring sectors.
- Tracks 0 to 2, the CCP and BDOS. The 22 runtime pages that make up the CCP (
$9400to$9BFF) and the BDOS ($9C00to$A9FF) are scattered across the remainder of tracks 0 through 2, each page to the sector the loader reads it from. - Track 2, the BIOS. The six BIOS pages (
$AA00to$AFFF) land on six sectors of track 2.
The whole declarative layout, which binary, which page, which track and sector, is in the chunk map at cpm_pipeline/chunk_map.py. It is a list of placements: take this slice of this binary, write it to this physical sector. Reading it is the clearest single description of how the operating system is laid out on the medium.
The tool that writes the disk
One driver compiles every source and lays the results onto a disk image. From the repository root:
source shared/toolchain/env.sh
python -m cpm_pipeline.reconstruct \
softcard/reference/softcard-cpm-archive/os/softcard-cpm2.20-44k-system-1980.dsk \
softcard-cpm2.20-44k-built.dsk --variant 220-44k
The first argument is an existing disk image, which supplies the file-system tracks (3 and up); the second is the disk image written out. The driver assembles all four sources, scatters their pages onto the first three tracks through the interleave, carries the file system across unchanged, and writes the result. The placement logic is cpm_pipeline/reconstruct.py; the boot-track recipe is also written out plainly in CPMV220-44K/README.md.
The proof is in the comparison
The driver does one more thing, and it is the thing that makes the whole exercise trustworthy: it compares the disk it just built against the original 1980 disk, byte for byte, and refuses to claim success unless they are identical. They are. Zero differences across all 143,360 bytes. A regression suite runs that comparison on every change, so the source tree cannot quietly drift away from the disk it describes.
That byte-identity is what separates this from a plausible reconstruction. It means the four source files, compiled and scattered onto three tracks, are the operating system’s boot tracks, not an approximation of them. Edit a source, rebuild, and the difference in the disk is exactly the difference you made, nothing else.
There is, however, a quiet dependency in that build command: it starts from an existing disk image, because the file-system tracks, everything from track 3 out, do not come from these four sources. We rebuilt the operating system. We have not yet built a disk. The final article is about what stands between three reconstructed boot tracks and a floppy you can boot from nothing but source.
Comments
Nothing yet. Say the first thing.
Sign in to join the conversation.