When talking about floppy disc copy protection code, I find it useful to split into two separate pieces:
- The on-disc bits that are tricky to replicate.
- The loader code that obfuscates the check of the on-disc bits and the game code, making the check hard to "patch out".
This post concerns the former: on-disc bits. Some of my favorite on-disc schemes include the so-called "Spiradisc" protection scheme and the fuzzy bits scheme used by Dungeon Master for the Atari ST, as explained in excellent detail in this article. I also recommend this great overview of Commodore 64 disc protection schemes. To be charitable, the Commodore 64 had a.... "quirky" disc drive setup.
I recently encountered an on-disc scheme on a BBC Micro disc that was more sophisticated than I was expecting: weak bits. Weak bits and similar schemes were celebrated in the 16-bit era but here we have it in the 8-bit era.
Floppy what now?
|Only the left two are actually "floppy", and the middle 5.25" disc is actually called a "mini" floppy!
Floppy disc drives and controllers are likely simpler than you think. The job of the floppy drive is to take the analog magnetic information on a disc surface and turn it into a series of digital pulses. The job of the floppy controller is to take the series of digital pulses, discern timing, and generate a string of data bytes. The floppy controller usually also has the responsibility of spotting special marker bytes in the pulse stream so that distinct sectors can be identified.
This oscilloscope trace from a 1980s disc drive may help you visualize things better:
|Blue line is the analog amplified read head signal; yellow pulses are the digital read output from the drive
Every peak in the blue line is the drive head sensing a magnetic flux reversal on the disc surface. Upper and lower peaks are treated identically and result in a digital pulse getting sent to the disc controller, which is the yellow line.
Note that tools such as an OmniFlop, KryoFlux or GreaseWeazle might occasionally refer to "raw flux" reads or dumps but beware they that only get to see the yellow line in the trace above, which is a lossy view of the blue line.
Looking at the yellow line, you may notice that there's a fairly regular cadence to the peaks. In fact, every 4 microseconds, there is a timing "slot" and there will either be a pulse or no pulse. If there's a pulse, that's a 1 bit. No pulse and that's a 0 bit. And as simple as that, there's a bit stream for the disc controller to interpret and hand off to the host computer.
Different computers use different encoding schemes. We're focusing on the BBC Micro this post, where most discs used FM encoding, aka. single density. This is a very simple encoding, an evidenced by the fact we can eyeball the 0 and 1 bits in the scope trace above. MFM encoding was generally more common in the era.
Sectors in the stream
The disc controller takes the pulse stream and makes sense of it. As mentioned above, in FM (sometimes called DFM) encoding, each pulse or non-pulse represents a 1 or 0 bit. These bits are a mix of clock bits and actual data bits. Clock bits are needed for a couple of reasons: as a source of timing to sync to, and also to prevent the disc drive from thinking it has lost the signal. There must be a pulse at least every 8us to keep everything reliable. FM encoding takes the simple route: every other on-disc bit is a clock bit and they will all be 1 almost all of the time.
So now we know how to separate data bits from clock bits, let's have a quick look at what a sequence of data bytes on the disc surface might look like. There's a simple protocol for describing sectors on the disc, called the "IBM Diskette", which is described in the 8271 datasheet.
It's fairly simple and it looks like this in hex:
FF FF FF 00 00 00 FE 00 00 00 01 F1 D3 FF FF FF 00 00 00 FB 01 02 03 04 05 ..
The green data bytes are padding between sectors, or between sector headers and sector data. They help the controller maintain correct synchronization, and to re-gain synchronization at the correct point. The padding sequences are typically longer on a real disc, but are shortened above for clarity; they would still suffice.
The sector header identification byte is the FE, which is followed by 4 bytes of sector header and a 2-byte CRC. The sector is declaring it is on track 0, head 0, and it is sector 0, sized 256 bytes. The CRC is correct. The sector data identification byte for non-deleted data is FB, and 256 bytes of data are expected to follow, then another 2-byte CRC. A typical track might contain 10 such padding + sector header + padding + sector data sequences.
The astute reader would ask: "oh! but what if the FE or FB bytes occur in actual sector data, as they are bound to do from time to time?"
That is a great question and the answer lies in the clock bits. Every byte above has 0xFF for its clock bits (all set) except 0xFE and 0xFB, which have 0xC7 for the clock bits. i.e. some of the clock bits are missing! That makes it possible to identify sector header and sector data markers accurately. Note that the combination of these special data bytes plus clock byte is chosen so that still, the invariant is keep that there are never 2 0 bits in a row on the disc surface.
BBC Micro disc protection journey
The BBC Micro disc protection journey is a fairly meandering one. It seems to have been based on a classical arms race approach: a software publisher would publish a new disc with some new quirk on it, and then a new disc copy program would come out which understood the quirk. And repeat a few iterations!
The journey is also complicated by two very different disc controller chips being used during the machine's lifetime: the Intel 8271 and the Western Digital 1770/1772. Both chips had different capabilities and quirks. A good copy protection on one of the chips might be trivial to copy on the other. Also, some earlier BBC Micro discs were made that did not end up being compatible with 1770 based systems.
To enumerate some of the techniques seen:
- Early Micro Power titles, such as Ghouls, used non-standard numbers of sectors on many tracks, such as 5 sectors of 512 bytes each instead of 10 sectors of 256 bytes each. This is easy to copy if you have a copy program that checks the sector headers first and then decides how many there are and what sizes based on that. It would be easy to scoff at such a simple protection but it's likely it did what it needed to at the time of launch: prevent casual disc copying using the built-in DFS (Disc Filing System) commands *COPY or *BACKUP (both of which expected well-formatted DFS discs, which meant 10 sectors per track).
- The Superior Software classic, Citadel, used "deleted data". Every sector on a disc can be marked as either normal or deleted by the one byte mark that occurs directly before the sector data bytes. This is again a simple protection that a copier can handle as long as it knows about the concept of deleted data. What's interesting is that Superior did release a few titles with more advanced protection -- most notably the legendary Exile. However there are stories about the protection not loading correctly with some setups, so Superior discs from then on can all be seen using just the simple deleted data protection. Presumably: once bitten, twice shy.
- The most iconic game on the BBC Micro may well be Elite. One of the tricks it used was an "unformatted track" in the middle of the disc. An unformatted track does not have any recognizable sector headers. This is perhaps the first protection that made disc copy programs sweat. Particularly on the 8271 floppy controller, there is no "unformat" command, only a "format" command. This was resolved decisively in favor of the disc copy programs, though, with a clever trick: if you format a track as one giant 4096 byte sector, you win immediately. What happens is that the single sector header is written at the start of the track, but then the 4096 bytes of sector data wrap around across the end of the track (which is 3125 bytes long) and trash the only sector header! So the track isn't really unformatted, but all that is needed is that the disc controller doesn't see any sector headers -- mission accomplished.
- Another fairly ubiquitous protection was mismatched physical / logical track IDs in the sector header. This was also used by Elite, which also used unusually large logical sector IDs. This is easy to copy if you know you're looking for the situation. Normally, the disc controller (particularly the 8271) will get upset if it sees a track mismatch but you can fake the controller out by setting its internal track register to match, with a special command.
- Later on in the BBC Micro's life, some publishers of software on disc upped their game. It became common to see extra data bytes "hidden" in between sectors. Simplistic attempts to copy these bytes would fail by overwriting a following sector. 1770-based disc copiers can handle this situation easily unless the hidden bytes are "reserved" in the 1770's write track protocol. It is possible to copy these situations well with both an 8271 or 1770 based copier, but I haven't yet found one that makes a decent effort. It is necessary to do things like take direct control of the disc controller chip, and issue commands with precise timing, and abort the controller mid-command with similarly precise timing.
Another favorite pastime of disc protection authors was a creative way of reducing copying without necessarily improving the underlying protection mechanism: attack the copy program itself. The copy programs needed a bunch of logic to work out what sector setup they were encountering. It's not easy logic, so breaking it was fruitful. Here's a few shots (under emulation, but real hardware behaves identically :) of Exile breaking Vector 2:
|Loading Vector 2
|Second track correctly identified as having 18 sectors
|A beeeeeep and a crash / hang processing the second track
Sherston Software weak bits protection: introducing "soft lock"
Given the copy protection arms race described for games above, it was a surprise to find a smaller educational software house with an on-disc protection format light years ahead. Sherston Software had a great catalog of software that my kids still enjoy today, with our current favorite being Space Mission Mada.
Many Sherston Software discs use weak bits protection. We should briefly define terms because they are not consistently used; the most sensible and broadly agreed terms appear to be:
- Flaky bits. Any on-disc bits that do not read back consistently. They are flaky.
- Weak bits. Flaky bits caused by a weak signal or non-existent magnetic signal on the disc surface. You might also see the term no-flux area (NFA), which is the same as a non-existent signal. Weak bits are almost always a non-existent signal, as opposed to a weak signal. The flaky nature of weak bits actually comes out of the drive electronics: when there are no clear flux changes, the drive just amplifies harder until it starts seeing and signaling ghosts within the noise.
- Fuzzy bits. Flaky bits caused by a strong, clear signal but where the timings of the read pulses are borderline. The borderline timing means the disc controller chip cannot be sure whether a pulse is supposed to be a 1 bit or a 0 bit. It'll change its mind from read to read.
The use of weak bits is advanced because it's one of the on-disc protections that arise when you do a first principles analysis:
- Weak bits give a "reliable" read result: you can reliably depend on them to read back differently from read-to-read!
- Weak bits cannot be written by the standard disc controllers. The disc controllers do everything in their power to lay down bits that read back deterministically. That's their job! There's no "write weak signal" flag and there's no "write timing violations" flag.
I wrote to the author of Space Mission Mada, Simon Hosler. It turns out he also devised the weak bits protection, along with his electronics geek next door neighbor! In Simon's words:
"Soft lock (was what we called it) was actually my system, so what I remember… This came about because I lived next door to an electronics geek! 😊 So break the write data line of the parallel disk cable. Add a bit of electronics to this line. (thank you Mike) Most of the time this electronics does nothing – lets the data go through as normal. If you turn it on (I think I did this through the serial port) and write to a single sector - it would count the bits going through say 256 – and then stop the next 256 bits going through"
I happen to have an original Sherston disc with weak bits protection, Animated Alphabet. Here's what the weak bits patch of disc looks like with the drive wired up to an oscilloscope:
|The blue line shows the on-disc magnetic signal come and go as Simon's widget toggles on and off. The yellow line shows the drive still emitting read pulses to the floppy controller (quasi-randomly) even in patches of no signal
The effect of Simon's widget in creating batches of weak bits can clearly be seen. This really was genius for the time, being one of the earlier swings at creating disc surfaces fundamentally uncopyable without special hardware. Not only that, but it works the same on both 8271 and 1770 based systems since it's the drive electronics that are being induced to create the quasi-randomness. This leads to a simpler, more reliable setup with just a single code path. It is also very compatible with all the myriad of different DFS (Disc Filing System) variants because the code to check the copy protection doesn't need fancy DFS calls. It just needs to read a sector -- very standard! -- a few times and see if the bytes coming back vary or not.
State of the art
I don't know when the first flaky bits based disc protection was released. There's probably someone out there who can point to an example from the 1970s! But it's worth comparing dates on some examples we do know about.
Dating the first Sherston Software title to use weak bits protection is tough. I have an image of Mr. Yog and the Nippet, (c) 1984, with weak bits protection. There's even an image of Short Vowel Sounds, (c) 1983, with weak bits protection. However, we also have seen the same Sherston title released with multiple different disc revisions with different copy protection systems. We can establish an initial latest bound on the weak bits protection with an image of The Wizard's Revenge that happens to use the weak bits protection and also includes a commercial duplicator fingerprint on its one-past-the-end track, as seen here in this hex editor view:
|This data, starting with 01 02 03 04 05 on the first line, appears to be added by a commercial duplicator from the era
Fingerprints of this nature contain a date and time: 87 01 05, or Jan 5th, 1987 in this case.
So in terms of release timing of early flaky bits based protection, we have:
- Weak bits: The Wizard's Revenge, Sherston Software, Jan 5th 1987.
- Fuzzy bits: Dungeon Master, Dec 15th 1987.
So it seems likely that the Sherston weak bits went to production at least a year prior to the Dungeon Master fuzzy bits. Although these disc protections are not identical, they have very similar properties and capabilities.
What's further interesting is that the Dungeon Master fuzzy bits were the subject of a patent filed in 1986. This could be one of those cases where other clever people had come up with prior art. It happens a lot.
Copying weak bits with original 1980s BBC Micro drives and controllers
No retro research would be complete without an attempt to push the bounds of what was thought possible back in the day. Accordingly, would it be possible to create a software only solution to write weak bits to discs? Another way to ask the same question is: would it have been possible to create a disc copier that copied weak bits correctly?
It turns out the answer is yes! Or more specifically, the answer is a double yes. Using two different tricks, it is possible to create actual weak bits with the 8271 disc controller, and non-deterministic reads (resulting in the same sort of read effects as weak bits) with the 1770 disc controller.
The 8271 is a slightly strange chip to program. One thing is has is the concept of "special registers" which can be read and written. One such special register is the "Drive Control Output Port":
The special registers aren't particularly well covered in the data sheet, perhaps because they aren't supposed to be necessary for usage. That said, most 8271 driver implementations write this register to spin up the drive (by setting the LOAD HEAD bit and appropriate drive SELECT bit) in order to control the 8271's propensity to fail read/write commands with "drive not ready".
The trick is to use this register to set the WRITE ENABLE bit as well as the LOAD HEAD and SELECT bits. This can only be done outside any other command, because Write Special Register is itself a command and selecting it will abort any other in-progress command. When WRITE ENABLE is active outside of a command, the disc drive's write head will be energized but no data pulses will be transmitted on the write data pin to the disc drive. The result is that the write head sweeps the disc surface clean of flux transitions. That creates weak bits / a no flux area. With a bit of careful timing, the write head can be energized and de-energized and any point(s) needed on a track to create weak bits where desired.
The trick on the 1770 is different. It may be possible to directly create weak bits by creatively programming the 1770 -- but if it is, I haven't found it. Instead, we focus on the BBC Micro's 1770 control register. This is a register external to the 1770 that is necessary to control external 1770 pins. For example, unlike the 8271, the 1770 selects disc drive 0 vs. drive 1 via an external pin instead of as parameters passed to controller commands. The "Drive Control Register" is documented well at the bottom of this document.
Since this register is external to the 1770, we can mess with it while a command is in progress. The specific trick we use is to start a single density write command and then flip to double density some number of bytes in. Double density (MFM) timing is completely different to single density timing, so reading back the resulting patterns as single density read confuses the disc controller significantly, to the point that non-deterministic read results are returned. This is not weak bits on the disc but the effect is the same as far as the copy protection check is concerned: read the sector twice and check the result varies! The bits definitely end up flaky.
Does it work? Yes. Here's a video of me using my work-in-progress "discbeast" utility. We fix a failed copy of Sherston weak bits by using commands to directly and precisely create flaky bits at the correct point on the disc.