← Back to Courses
module
37

Appendix VII - The disc format

Not needed for building a game - nothing in the main course touches a disc. Putting a finished game onto a disc image for a real machine is Appendix VIII's job, and the tool it uses does all of this for you. This appendix exists because the format itself was not well understood, and because a reader curious enough to ask deserves an honest answer instead of silence.

Like Appendix IV, this is a working document, and it uses the same honesty about how much is known:

Mark Means
## Established by running code on the machine.
~~ From documentation. Cited, plausible, not tested here.
?? Unknown. Nobody has looked, or looking was inconclusive.

Everything below is ~~ - nothing in this project has run its own experiment against the floppy controller yet. But it is no longer thin: five independent sources agree - including MOS's own assembler source, which defines the geometry as named constants (NTRAX EQU 40, NSECT EQU 10, BUFSIZ EQU 512) rather than describing it - several numbers below are checked in the source material itself against a real file's real location on a real disc, and Digital Research CP/M 2.2 compatibility is stated outright by the people who wrote MOS, not inferred from the code's shape. Full citations and detail are in the shared reference, references/disc.md.

The physical disc

~~ 40 tracks, 10 sectors per track, 512 bytes per sector, single-sided as standard (double-sided discs exist and address 20 sector positions via a side-select bit, though that half of the picture rests on less checking than the rest of this appendix). Soft-sectored - the sector layout is written by formatting, not built into the medium.

The logical layout - CP/M 2.2, by design

~~ Crystal Research say so directly: MOS presents the disc as 128-byte CP/M sectors, four to a physical 512-byte one, "in order to be compatible with the Digital Research CP/M 2.2 operating system." Everything below follows that shape.

  • Tracks 0-1 are reserved for the system (the DOS loader) - 10K, which is exactly two tracks' worth of physical sectors.

  • Track 2, sectors 0-3 (2K) is the directory: 64 entries of 32 bytes each, in the standard CP/M FCB shape - filename, extension, extent, record count, and sixteen single-byte pointers to 2K allocation blocks. An unused entry's first byte is E5H.

  • Everything after that is file data, addressed in 2K blocks. A block's track and sector come from one formula:

    track  = floor(block_number * 4 / 10) + 2
    sector = (block_number * 4) mod 10
    

The source doesn't just state that formula - it checks it. It says XBAS.COM's first block sits at track 2, sector 4, and separately that XBAS.COM occupies blocks 1 through 8. Put block 1 through the formula and the answer is track 2, sector 4 - exactly what the same source states independently elsewhere. That is a real file's real disc location, confirmed twice, by two different routes, inside the source material itself. It is the strongest single piece of evidence in this appendix.

The boot sequence

~~ On power-up: the whole 64K is written to FFH (not zeroed - filled); interrupt vectors and scratch-pad go into place; the CTC and serial chip are configured; the VDP is set up and the ROM's font copied into VRAM; the ***EINSTEIN*** logo prints; a second ROM socket is checked and control handed off if one is fitted and enabled; then drive 0 is checked, and if a disc is present, its first reserved track is read into memory and executed - the DOS loader. Otherwise MOS drops to its own monitor prompt.

Once loaded, XtalDOS's memory map matches standard CP/M addresses exactly - warm-boot jump at 0000H, BDOS entry at 0005H, default FCB at 005CH, default DMA buffer at 0080H - which is itself more evidence for the CP/M compatibility claim: these are not numbers Crystal Research had to invent.

What building a .dsk reader/writer actually needs

The honest answer has changed twice since this appendix was first written. Every number - geometry, reserved tracks, directory format and location, block size, the block-to-sector formula - is documented, checked against a real file in the source material itself, AND a complete, working Z80 program exists (~~ "The Source", ch.14) that opens, reads, writes, creates and closes files using the machine's actual CP/M BDOS calls - real code, not a description of one. It even shows, working, exactly how a file's 128-byte record number splits into an extent and an in-extent offset, which is the mechanism byte 12 of a directory entry depends on. A Python tool built on this is a port, not a guess.

What is still missing is this project's OWN check: nothing here has been confirmed by formatting a disc and reading the result back byte for byte, the way every other fact in this course's references/ was earned. That remains worth doing before trusting these numbers for anything that WRITES to a disc a reader might care about - reading is lower stakes, since a wrong read just fails; a wrong write can silently corrupt a directory. The method is unchanged from when this appendix first raised it: format a disc under real MOS/XtalDOS in MAME, write one short file with a name and contents you chose, and check that the file turns up exactly where the formula above says it should.

Is this its own project?

Yes - see the separate Disc Project, spun off for exactly this. It has since produced the disc tool that Appendix VIII uses, which creates images, adds files and makes a disc boot straight into a program. The marks in this appendix have not yet been updated to reflect that project's results.

Get the Newsletter

New guides, disk images and community finds, roughly once a quarter. No spam, we promise, this isn't Tatung's marketing department.
Your subscription could not be saved. Please try again.
Your subscription has been successful.

Newsletter

Subscribe to our newsletter and stay updated.