Some Apple II 5.25" floppies used a special pattern of bytes that could not be automatically detected by disk copying software. How could the pattern be invisible to disk copiers but detectable by the program itself?
The Apple II reads disk tracks as a continuous stream of bits. To make sense of the data, it's necessary to figure out where individual bytes start. This is done with self-sync bytes.
Standard self-sync bytes are
FF, followed by two "invisible" zeroes:
byte 0 ** byte 1 ** byte 2 ** 11111111 00 11111111 00 11111111 00
The Apple II will read bits from the bit stream, sliding them in from right to left, until a
1 lands in the high bit of the 8-bit register. If you start reading from a
1, you will read 7 more bits. If you start reading from a
0, you will read 8 or 9 more bits, because the initial zeroes just slide off the left end of the register. With just a few self-sync bytes, we can ensure that we fall into sync with the byte boundaries.
For example, suppose you started reading at an offset of 4 bits into a self-sync pattern:
The code would read
11110011 for the first byte,
11111100 for the second, and
11111111 for the third -- synchronization achieved. The extra zeroes are read, but just slide off the left end of the register, because we're waiting for a
1 to appear in the high bit. The only way to tell the difference between a self-sync
FF, and a regular
FF, is by how long it takes to read. With one bit arriving every 4 CPU cycles, detecting the difference is tricky.
The trick exploited by the bit-slip technique is to follow the self-sync bytes with a pattern that includes additional zeroes between bytes. For example, consider this stream:
If we latch 8-bit bytes as usual, we'll read it like this:
byte 0 * byte 1 ** byte 2 byte 3 11100111 0 11100111 00 11100111 11100111
Because the "extra"
0 bits "between" bytes are ignored, this will be read as
E7 E7 E7 E7. But what happens if we deliberately stall for 12 cycles, ignoring the first three bits?
xxx ** byte 0 * byte 1 ** byte 2 ... 111 00 11101110 0 11100111 00 11111100 111
We get a different pattern:
EE E7 FC. By deliberately desynchronizing the stream, the program can detect the shifted pattern. And because the pattern starts with zeroes, the delay doesn't have to be perfectly cycle-accurate.
Copy programs can pretty reliably detect the difference between "normal" and "long" bytes with a carefully timed loop -- either the byte is ready after 32 cycles, or it isn't. The pattern above uses both 9-bit and 10-bit bytes, so to reproduce it correctly you'd need to accurately detect the difference between a 32-cycle read, a 36-cycle read, and a 40-cycle read. Very difficult to do on a 1MHz 6502.
For additional details, see this article and this comp.sys.apple2 posting.
1There's also this: pferrie.host22.com/papers/apple2_e7.pdf from Peter Ferrie, and Mark Pilgrim's talk here: youtu.be/IGo7wUo64LI?t=6h42m36s– zellynMay 9, 2016 at 20:46
One approach I've been pondering lately would be to have a track which reads almost entirely as a sequence 1010101010... but varying the data rate so that each octet of data on the disk would encode a single 1 or 0 of "hidden" data based upon whether it took more or less time than normal to read. Ever heard of such a thing? I'd think such a thing would be pretty well invisible to any code that wasn't looking for it, and would probably require a custom Woz-machine ROM to create. May 9, 2016 at 22:42
If memory serves, 101010... would normally involve one flux transition every eight cycles. To encode custom data one could have code that would generate a groups of four flux transitions at 7-cycle or 9-cycle intervals depending upon the bits to be encoded, and I would think looking for whether each octet was more or less than 32 cycles would then be pretty reliable. May 9, 2016 at 22:49
1This brings back memories.... I wrote and sold a disk copy protection system that used this method. I called it "Finger Print" protection, the finger print being effectively invisible to most bit copiers. Nov 9, 2017 at 12:28
@AnthonyLambert: Cool. I've just dug my Apple //c out of the garage and would like to start using it. What's the best way of getting software to it? I was thinking that a little microcontroller hooked to the floppy connector and a PC's USB port could probably fake a read-only floppy drive pretty easily (keep count of head movement pulses and simply send one of 35 sets of bit patterns). Any idea of any cheap and simple interfaces? Mar 6, 2018 at 3:52