--------------C'est La Vie------------- A 4am crack 2018-04-07 --------------------------------------- Name: C'est La Vie Genre: arcade Year: 1983 Publisher: Adventure International Platform: Apple ][+ or later Media: 5.25-inch disk Sides: 1 OS: DOS 3.3 Similar cracks: #1563 The Kingdom of Facts ~ Chapter 0 In Which Various Automated Tools Fail In Interesting Ways COPYA read error on first pass Locksmith Fast Disk Backup unable to read any track EDD 4 bit copy (no sync, no count) error on track $22, copy seeks back and forth between tracks forever Copy ][+ nibble editor track $22 is weeeeeeeird, mostly #$FF and #$DD nibbles, like hundreds and hundreds of them in a row, and timing bits between each nibble Disk Fixer ["O"] for INPUT/OUTPUT CONTROL, then CHECKSUM ENABLED = NO bootloader is standard DOS 3.3 RWTS is standard except it ignores the data field epilogue T01,S09 -> startup program is "HELO" (with 1 "L") T11 -> DOS 3.3 disk catalog ["D"] for DIRECTORY MODE shows that "HELO" exists and mostly just BRUNs the binary file "CLV", which seems to be the entire game no way to read track $22 (no standard structure) Why didn't any of my copies work? probably a runtime check on that weird track $22 Next steps: 1. Find the runtime protection check 2. Disable it 3. Declare victory (*) (*) go to the gym ~ Chapter 1 In Which We Quickly Get To The Point Passport makes short work of converting the disk to a readable format. --v-- READING FROM S6,D1 T00,S00 FOUND DOS 3.3 BOOTLOADER USING DISK'S OWN RWTS T22 FOUND NIBBLE COUNT PROTECTION TRACK WRITING TO S5,D2 T02,S02 VOLUME NAME IS DISK VOLUME 254 THE DISK WAS COPIED SUCCESSFULLY, BUT PASSPORT DID NOT APPLY ANY PATCHES. --^-- As expected, the copy that it produces fares no better than my failed EDD bit copy. Booting from a DOS 3.3 system master, I can CATALOG this non-working copy. ]CATALOG DISK VOLUME 254 I 002 APPLESOFT B 002 B0100 B 131 CLV A 002 HELO ]LOAD HELO ]LIST 10 PRINT "BRUN CLV" 20 PRINT "NOMONCIO": PRINT "BRU N CLV" ]BLOAD CLV ]CALL -151 *AA72.AA73 *AA72.AA73 ; address of last BLOAD AA72- 00 08 *800L 0800- 20 68 27 JSR $2768 OK. *2768L 2768- 20 00 26 JSR $2600 276B- 20 00 20 JSR $2000 276E- A9 00 LDA #$00 2770- A0 02 LDY #$02 2772- 60 RTS OK. *2600L 2600- 4C 04 26 JMP $2604 2603- 60 RTS 2604- 20 57 27 JSR $2757 OK. *2757L ; seek to track 0 2757- A9 00 LDA #$00 2759- 8D F2 B7 STA $B7F2 275C- 8D EC B7 STA $B7EC 275F- A9 B7 LDA #$B7 2761- A0 E8 LDY #$E8 2763- 20 00 BD JSR $BD00 2766- D8 CLD 2767- 60 RTS Continuing from $2607... ; turn on drive motor manually 2607- AE 03 26 LDX $2603 260A- 9D 89 C0 STA $C089,X ; wait for it to spin up 260D- A9 FF LDA #$FF 260F- 20 AB FC JSR $FCAB ; seek to track $22 2612- AE 03 26 LDX $2603 2615- A9 44 LDA #$44 2617- 20 A0 B9 JSR $B9A0 261A- D8 CLD ; initialize counters 261B- A9 00 LDA #$00 261D- 85 F0 STA $F0 261F- 85 F1 STA $F1 2621- 85 F2 STA $F2 2623- 85 F3 STA $F3 2625- 85 F4 STA $F4 2627- 85 F5 STA $F5 2629- 85 F6 STA $F6 262B- 85 F7 STA $F7 ; look for #$DD or #$FF nibble 262D- A0 00 LDY #$00 262F- AE 03 26 LDX $2603 2632- BD 8E C0 LDA $C08E,X 2635- BD 8C C0 LDA $C08C,X 2638- 10 FB BPL $2635 263A- C9 FF CMP #$FF 263C- F0 6A BEQ $26A8 263E- C9 DD CMP #$DD 2640- F0 08 BEQ $264A 2642- C8 INY 2643- C0 14 CPY #$14 2645- 90 EE BCC $2635 2647- 4C 42 27 JMP $2742 There are three ways out of this loop. Two of them are OK -- we find an #$FF nibble and branch to $26A8, or we find a #$DD nibble and branch to $264A. Or we don't find either of those nibbles, Y increments out of range, and we give up and branch to $2742. If we find a #$DD nibble first, we continue to $264A: ; look for #$FF nibble 264A- BD 8C C0 LDA $C08C,X 264D- 10 FB BPL $264A ; branch forward once we find it 264F- C9 FF CMP #$FF 2651- F0 0F BEQ $2662 ; count the non-#$FF nibbles 2653- E6 F6 INC $F6 2655- D0 F3 BNE $264A 2657- E6 F7 INC $F7 2659- A5 F7 LDA $F7 ; give up if we've seen $1000 nibbles ; without finding #$FF 265B- C9 10 CMP #$10 265D- 90 EB BCC $264A 265F- 4C 42 27 JMP $2742 ; bad! ; success path continues here (from the ; BEQ at $2651) -- ; now look for non-#$FF nibble 2662- BD 8C C0 LDA $C08C,X 2665- 10 FB BPL $2662 2667- C9 FF CMP #$FF 2669- D0 0F BNE $267A ; and give up after $1000 wrong nibbles 266B- E6 F0 INC $F0 266D- D0 F3 BNE $2662 266F- E6 F1 INC $F1 2671- A5 F1 LDA $F1 2673- C9 10 CMP #$10 2675- 90 EB BCC $2662 2677- 4C 42 27 JMP $2742 ; bad! ; if the first non-#$FF nibble is #$DD, ; that's good 267A- C9 DD CMP #$DD 267C- F0 07 BEQ $2685 ; otherwise try again (but eventually ; give up after $100 non-#$DD nibbles) 267E- E6 F4 INC $F4 2680- D0 E0 BNE $2662 2682- 4C 42 27 JMP $2742 ; bad! ; execution continues here (from "BEQ" ; at $267C) -- ; count #$DD nibbles (zero page $F2/3) ; but give up after $1000 of them, ; terminate on #$FF nibble, tolerate up ; to 256 other values (zero page $F5) 2685- BD 8C C0 LDA $C08C,X 2688- 10 FB BPL $2685 268A- C9 DD CMP #$DD 268C- F0 0B BEQ $2699 268E- C9 FF CMP #$FF 2690- F0 74 BEQ $2706 ; good 2692- E6 F5 INC $F5 2694- D0 EF BNE $2685 2696- 4C 42 27 JMP $2742 2699- E6 F2 INC $F2 269B- D0 E8 BNE $2685 269D- E6 F3 INC $F3 269F- A5 F3 LDA $F3 26A1- C9 10 CMP #$10 26A3- 90 E0 BCC $2685 26A5- 4C 42 27 JMP $2742 ; bad! This path continues at $2706. This next line is the start of the other major path, from the "BEQ" at $263C, if we initially found an #$FF nibble instead of #$DD. (Tracks are just endless circles, and there's no way to know where in the circle we'll start. Rather than burn through half the track looking for one or the other, this protection check is optimized to start counting either way.) ~ Chapter 2 In Which We Enter The Upside Down This path is just the inverse of the other path. Everything that was #$FF is now #$DD, and vice versa. ; look for #$DD nibble 26A8- BD 8C C0 LDA $C08C,X 26AB- 10 FB BPL $26A8 26AD- C9 DD CMP #$DD 26AF- F0 0F BEQ $26C0 ; count the non-#$DD nibbles, give up ; after $1000 non-#$DD nibbles 26B1- E6 F6 INC $F6 26B3- D0 F3 BNE $26A8 26B5- E6 F7 INC $F7 26B7- A5 F7 LDA $F7 26B9- C9 10 CMP #$10 26BB- 90 EB BCC $26A8 26BD- 4C 42 27 JMP $2742 ; bad! ; execution continues here (from "BEQ" ; at $26AF) -- ; now look for non-#$DD nibble 26C0- BD 8C C0 LDA $C08C,X 26C3- 10 FB BPL $26C0 26C5- C9 DD CMP #$DD 26C7- D0 0F BNE $26D8 ; count the #$DD nibbles, give up after ; $1000 nibbles 26C9- E6 F2 INC $F2 26CB- D0 F3 BNE $26C0 26CD- E6 F3 INC $F3 26CF- A5 F3 LDA $F3 26D1- C9 10 CMP #$10 26D3- 90 EB BCC $26C0 26D5- 4C 42 27 JMP $2742 ; bad! ; if the first non-#$DD nibble is #$FF, ; that's good 26D8- C9 FF CMP #$FF 26DA- F0 07 BEQ $26E3 ; otherwise try again (but eventually ; give up after $100 non-#$FF nibbles) 26DC- E6 F5 INC $F5 26DE- D0 E0 BNE $26C0 26E0- 4C 42 27 JMP $2742 ; bad! ; execution continues here (from "BEQ" ; at $26DA) -- ; count #$FF nibbles (zero page $F0/1) ; but give up after $1000 of them, ; terminate on #$DD nibble, tolerate up ; to $100 other nibbles (zero page $F4) 26E3- BD 8C C0 LDA $C08C,X 26E6- 10 FB BPL $26E3 26E8- C9 FF CMP #$FF 26EA- F0 0B BEQ $26F7 26EC- C9 DD CMP #$DD 26EE- F0 16 BEQ $2706 ; good 26F0- E6 F4 INC $F4 26F2- D0 EF BNE $26E3 26F4- 4C 42 27 JMP $2742 26F7- E6 F0 INC $F0 26F9- D0 E8 BNE $26E3 26FB- E6 F1 INC $F1 26FD- A5 F1 LDA $F1 26FF- C9 10 CMP #$10 2701- 90 E0 BCC $26E3 2703- 4C 42 27 JMP $2742 ; bad! ; execution continues here (from "BEQ" ; at $26EE) -- ; if we found too many of either nibble ; then the protection check has failed 2706- A5 F4 LDA $F4 2708- C9 10 CMP #$10 270A- B0 36 BCS $2742 270C- A5 F5 LDA $F5 270E- C9 10 CMP #$10 2710- B0 30 BCS $2742 ; count of #$FF nibbles needs to be ; between #$0E68 and #$0E9C 2712- A5 F1 LDA $F1 2714- C9 0E CMP #$0E 2716- D0 2A BNE $2742 2718- A5 F0 LDA $F0 271A- C9 68 CMP #$68 271C- 90 24 BCC $2742 271E- C9 9C CMP #$9C 2720- B0 20 BCS $2742 ; count of #$DD nibbles needs to be ; between #$0568 and #$059C 2722- A5 F3 LDA $F3 2724- C9 05 CMP #$05 2726- D0 1A BNE $2742 2728- A5 F2 LDA $F2 272A- C9 68 CMP #$68 272C- 90 14 BCC $2742 272E- C9 9C CMP #$9C 2730- B0 10 BCS $2742 ; Success! All nibble counts were ; within acceptable ranges. Now seek ; back to track 0, turn off the drive ; motor, and return to the caller. 2732- AE 03 26 LDX $2603 2735- A9 00 LDA #$00 2737- 20 A0 B9 JSR $B9A0 273A- D8 CLD 273B- AE 03 26 LDX $2603 273E- BD 88 C0 LDA $C088,X 2741- 60 RTS ; All failures lead here. Seek back to ; track 0, then track $22, and start ; over. 2742- AE 03 26 LDX $2603 2745- A9 00 LDA #$00 2747- 20 A0 B9 JSR $B9A0 274A- D8 CLD 274B- A9 44 LDA #$44 274D- AE 03 26 LDX $2603 2750- 20 A0 B9 JSR $B9A0 2753- D8 CLD 2754- 4C 1B 26 JMP $261B There are no side effects to this protection check. If it fails, it tries forever. If it succeeds, it restores all state before returning to the caller. It doesn't even set or clear the carry flag. I can bypass it by changing the JMP at $2600 to "RTS". T1F,S00,$04: 4C -> 60 ]PR#6 ...works, and it is glorious... Quod erat liberand one more thing... ~ Chapter 3 I Mean, It's One Bit, Michael. What Could It Cost? Ten Dollars? The sequence of bits on track $22 is very specific. It was designed to fool the best bit copiers, and it does. But why? How does it work? Why can't bit copiers duplicate it? This game was published by Adventure International, better known for its Scott Adams adventure games, and it shares the protection bitstream with those famous adventures. The earliest sample in my collection is "Graphic Adventure #1; Adventureland," dated 1982, but the protection may date back even further. That's a long time to reuse a copy protection. Heck, six months was a long time to reuse a copy protection. This one is obviously durable. Here is the original disk, as seen through the Copy II Plus nibble editor. (The editor indicates timing bits after a nibble with inverse. I've displayed them here as "+" signs.) --v-- COPY ][ PLUS BIT COPY PROGRAM 8.4 (C) 1982-9 CENTRAL POINT SOFTWARE, INC. --------------------------------------- TRACK: 22 START: 1800 LENGTH: 3DFF 1CB0: DD+DD+DD+DD+DD+DD+DD+DD+ 1CB8: FF 9F E7 F9 FE+FF+FF+FF+ 1CC0: FF+FF+FF+FF+FF+FF+FF+FF+ ... 2B30: FF+FF+FF+FF+FF+FF+FF+FF+ 2B38: FF+FF+FF+FF+FF+FF+E9 BA+ 2B40: DD+DD+DD+DD+DD+DD+DD+DD+ ... 30B0: DD+DD+DD+DD+DD+DD+DD+DD+ 30B8: DD+DD+DD+DD+DD+DD+FF 9F 30C0: E7 F9 FE+FF+FF+FF+FF+FF+ --^-- The offsets ($1CB0, $2B30, $30B0) are not important here; in fact, they will vary on every read. There's no defined "start" to a track; it's an unending circle of bits. The offsets depend on the physical rotation of the disk when Copy II Plus started reading. It's the nibble counts that matter. That's what the protection check cares about. - $DD (repeated $057E times) - $FF $9F $E7 $F9 $FE - $FF (repeated $0E81 times) - $E9 $BA And, as indicated, there are timing bits between most nibbles. But that's it; in this view, the $9F nibble at offset $1CB9 is the same as the $9F nibble at offset $30BF. Those are the same bits. That's the point at which, pardon the pun, we've literally come full circle. Now let's copy the disk with a bit copy program. I used EDD 4.4 for this test, one of the most advanced bit copiers ever developed. --v-- TRACK: 22 START: 1800 LENGTH: 3DFF 24C0: FF+FF+FF+FF+FF+FF+FF+FF+ 24C8: E9 BA DD DD+DD+DD+DD+DD+ 24D0: DD+DD+DD+DD+DD+DD+DD+DD+ ... 2A40: DD+DD+DD+DD+DD+DD+DD+DD+ 2A48: FF 9F E7 F9 FE FE DB AD 2A50: D6 EB EB+EB+EB+EB+EB+EB+ 2A58: EB+EB+EB+EB+EB+EB+EB+EB+ ... 2C90: EB+EB+EB+EB+EB+EB+EB+EB+ 2C98: FE+FF+FF+FF+FF+FF+FF+FF+ 2CA0: FF+FF+FF+FF+FF+FF+FF+FF+ ... 3B10: FF+FF+FF+FF+FF+FF+FF+FF+ 3B18: FF+FF+FF+FF+FF+E9 BA DD 3B20: DD+DD+DD+DD+DD+DD+DD+DD+ --^-- $057E $DD nibbles -- exactly the same as the original disk. (The acceptable range was $0568..$059C.) And $0E84 $FF nibbles -- a few more than the original disk, but still within acceptable range ($0E68..$0E9C). But what's all that in between? After the $DD nibbles, we see the sequence $FF $9F $E7 $F9 $FE, but then it goes off into the weeds. $FE $DB $AD $D6, then a long sequence of... $EB? Where did $EB come from? And by the way, how can all these extra nibbles fit on a track that is supposed to be the same size as the original disk? In retrospect, that last question points the way to the real answer, but I could not see it at the time. For me, the answer did not come from within the Apple II, because, like so many copy protection questions, the answer is not directly visible from within the Apple II. I had to jump out of the system. With modern tools, we can now create bit-perfect images of physical Apple II floppy disks, then examine those images on modern systems. Here is what I found on my bit-perfect image of this 35-year old floppy disk: /--DD--\ /--DD--\ /--DD--\ 110111010011011101001101110100 ... Over and over and over and over. Those are the $DD nibbles we saw earlier in Copy II Plus, the ones that EDD 4 was able to count and copy successfully... or did it? On the original disk, each $DD nibble is followed by 2 "timing" (0) bits. Since each valid nibble needs to start with a "1" bit, those "0" bits between nibbles are ignored. Even the copy protection code ignores them. But that doesn't mean they're useless. Looking at the failed bit copy (again from outside the system, via a disk image that I could only examine on a modern PC), those $DD nibbles look like this: /--DD--\ /--DD--\ /--DD--\ 110111010110111010110111010 ... Each $DD nibble is followed by only 1 "timing" (0) bit! They will still be read as $DD nibbles; in fact, the copy protection code successfully reads and counts them. But the underlying bits on the disk are very different. The original disk had a 10-bit pattern; the copy has a 9-bit pattern. What's going on? Disks spin independently from the Apple II's CPU, which is very slow (1 Mhz). There is barely enough time to read the bits as they spin by the drive head, and there is no way to slow down the disk to read them more accurately. The drive controller card (the thing in slot 6) had to "help" by accumulating the bits into an 8-bit value which could be read by the main CPU. Standard floppy disks were designed to compensate for the limits of the hardware; protected disks were designed to exploit them. EDD 4 devised a clever algorithm to detect the presence or absence of timing bits after a nibble. But it couldn't tell *how many* timing bits are after any particular nibble: 1 or 2. There just wasn't enough time to tell the difference before the next bits started coming in. EDD 4 isn't making a perfect copy of this disk, because no Apple II program could make a perfect copy of any disk. It's making a reconstruction. EDD 4 knows there is at least 1 timing bit after each $FF nibble. It decides to write out 2 timing bits after the first four $FF nibbles, because $FF is often used as a "self-synchronizing" nibble value with the 10-bit pattern 1111111100 repeated four times. (See p. 3-8 of "Beneath Apple DOS" for a more detailed explanation of how this works, and why four 10-bit nibbles is sufficient to synchronize.) For the rest of the $FF nibbles, EDD 4 guesses 1 timing bit, creating a 9-bit pattern 111111110. This is wrong, by the way; the original disk had a 10-bit pattern 1111111100. But in the absence of perfect information, EDD 4 decides that it's better to drop bits and have too few than to add bits and have too many. If it guessed 2 timing bits where the original had only 1, too often, it could end up overwriting the start of the track. The original disk also used 2 timing bits after each $DD nibble. This is an unusual nibble value, so EDD 4 guesses, incorrectly, that there is only one timing bit after every $DD nibble. It writes the 9-bit repeating pattern 110111010, which is different than the original disk's 10-bit pattern of 1101110100. Now EDD 4 has a problem: the track it's reconstructed is too short, and it doesn't know why. With the benefit of hindsight and being able to jump out of the system, we can see why: EDD 4 is writing out 9-bit $DD nibbles instead of 10-bit, and, with few exceptions, 9-bit $FF nibbles instead of 10-bit. That's $057E + $0E80 bits short! Then, like it always does, EDD 4 writes out the track data again, from where it ended the first time (more or less). Now our copy has the wrong data twice, part of which gets overwritten by the wrong data from the first time and part of which doesn't. I believe the technical term for this is "a complete mess." Wait, it gets worse. ~ Chapter 4 Now You See It, Now You Don't There's only one thing you can put on a disk that will change every time you read it: nothing. And by "nothing," I mean "a long sequence of zero bits." And that's what is on the original disk between each of these long groups of nibbles: nothing. A bit of background. When we say a "zero bit," we really mean "the lack of a magnetic state change." The Disk II drive isn't digital; it's analog. If it doesn't see a state change in a certain period of time, it calls that a "0". If it does see a change, it calls that a "1". But the drive can only tolerate a lack of state changes for so long -- about as long as it takes for two bits to go by. Fun fact(*): this is why you need to use nibbles as an intermediate on-disk format in the first place. No valid nibble contains more than two zero bits consecutively, when written from most- significant to least-significant bit. (*) not guaranteed, actual fun may vary So what happens when a drive doesn't see a state change after the equivalent of two consecutive zero bits? The drive thinks the disk is weak, and it starts increasing the amplification to try to compensate, looking for a valid signal. But there is no signal. There is no data. There is just a yawning abyss of nothingness. Eventually, the drive gets desperate and amplifies so much that it starts returning random bits based on ambient noise from the disk motor and the magnetism of the Earth. Seriously. It's trivial to write zero bits to a disk; just write a #$00 nibble to write 8 zero bits -- like any other 8-bit nibble. You can write whatever you want to a disk; it doesn't need to be what DOS would consider a "valid" nibble. But when you read that nibble back, the drive can't handle 8 zero bits in a row, so it will actually return some random bits. Which is why no one does that. Returning random bits doesn't sound very useful for a storage device, but it's exactly what the developer wanted, and that's exactly what this copy protection scheme depends on. Here's why: Bit copiers can't duplicate a long sequence of zero bits. Why? Because that's not what they see. What they see is some random bits -- the real zero bits interspersed with phantom "1" bits. So that's what they write to the target disk. Whatever randomness they get when they read the original disk will essentially get "frozen" onto the copy. As far as I can tell, the sequence of 10-bit $FF nibbles is followed by 12 extra zero bits, for a total of 14 after the final $FF nibble. (All others have 2 zero bits.) Here's what's on the disk between the last half of the last $FF nibbles and the first two $DD nibbles: F--\ /--DD--\ /--DD--\ 11110000000000000011011101001101110100 ^^^^^^^^^^^^ More than two consecutive zero bits will form an "abyss" that the floppy drive will fill with randomness. Some of the zero bits in the abyss (shown here above the "^^^^^^^^^^^" line) will randomly transform into "1" bits. And it will be a different set every time you read the disk. Seriously. Here's one of many possible bitstreams that might come out of the abyss: F--\ /--E9--\/--BA--\ /--DD--\ 11110000000111010011011101001101110100 ^^^^^^^^^^^^ That's what I saw the first time I read the original disk with the Copy II Plus nibble editor: the abyss coalesces into one full nibble ($E9). But if you look closely, you'll see that the $E9 nibble is stealing a bit from the first $DD nibble. The number of $DD nibbles will be one fewer this time, because the $E9 nibble swallowed the first one. Now we're out of phase from the start of the $DD nibbles, because the $E9 nibble stole a bit. After $E9, we see a $BA nibble made up of bits 2-8 of what ought to be the first $DD nibble, plus one of the timing bits as its least significant bit. Then we ignore one timing bit after $BA, and now we're back in phase, reading 10-bit $DD nibbles again. Then I read the original disk again and got a completely different bitstream between the last $FF and the first $DD. It looked like this: F--\ /--ED--\ /--9B--\/--A6--\/--E9--\ 111100111011010100110111010011011101001 ^^^^^^^^^^^^ /--BA--\ /--DD--\ /--DD--\ /--DD--\ 101110100110111010011011101001101110100 Again, the random bits in the abyss are interpreted as real bits, and they fool the disk reading code into reading a long sequence of out-of-phase nibbles, $ED $9B $A6 $E9 $BA, before we finally get back in phase and start reading 10-bit $DD nibbles again. I say "finally" get back in phase, but it really didn't take that long. No matter how many bits get swallowed by the abyss, the 10-bit $DD pattern will always resynchronize. We'll always get back in phase in time to find at least $0570 $DD nibbles. Now let's consider what happens on our attempted copy. First of all, there is no randomness, no abyss. Whatever random bits it read from the original disk, it writes those bits to the copy, followed by the 9-bit $DD nibbles. F--\ /--ED--\ /--9B--\/--AD--\/--D6--\ 11110111011010100110111010110111010110 ^^^^^^^^^^^^ /--EB--\ /--EB--\ /--EB--\ /--EB--\ 111010110111010110111010110111010110 The initial sequence of out-of-phase nibbles is different, between the number of timing bits is different. But we never get back to $DD. In fact, we quickly reach a steady state where we're reading out-of-phase $EB nibbles over and over again. The 9-bit $DD pattern will never resynchronize itself. If you ever get out of phase, you're going to stay out of phase. Of course, you might not ever get out of phase; it depends on which bits come out of the abyss. But that's where the $EB comes from: it's the 9-bit $DD, shifted by 3 bits. Wait, it gets worse. ~ Chapter 5 In Which Everything Is Designed To Be As Bad As Possible, And Succeeds Track $22 on the original disk is split up roughly 70/30, like this: 1111111100 1101110100 |-----------------------|?|----------|? (10-bit $FF) (10-bit $DD) The first, longer section is full of 10-bit $FF nibbles. The second, shorter section is full of 10-bit $DD nibbles. The two "?" areas are the "weak" bits, the abyss, which appear different every time you read the disk and consume a small number of the nibbles that follow (but only a small number, because both 10-bit $FF and 10-bit $DD nibbles will resynchronize). The failed bit copy looks like this: 111111110 110111010 |------------------|?|---------|?|///// (9-bit $FF) (9-bit $DD) The "/////" at the end of the track is not modified (yet), because EDD 4 is writing 9-bit nibbles instead of 10-bit nibbles, so the track is shorter than the original. But then EDD 4 writes the data again, starting in the "/////" region and wrapping around to overwrite most (but not all) of the track it just wrote: 111111110 110111010 1101 |------------------|?|---------|?|----| (9-bit $FF) (9-bit $DD) That last section is detritus, leftover 9-bit $DD nibbles from the previous write. Of course, these may also end up out of phase, depending on how the bits in the abyss come out. And as we've seen, once a 9-bit $DD nibble gets out of phase, it stays out of phase. All of which explains what I initially saw when I examined my failed bit copy in the Copy II Plus nibble editor: --v-- TRACK: 22 START: 1800 LENGTH: 3DFF : FF+FF+FF+FF+FF+FF+FF+FF+ : E9 BA DD DD+DD+DD+DD+DD+ | 9-bit $DD : DD+DD+DD+DD+DD+DD+DD+DD+ | nibbles ... : DD+DD+DD+DD+DD+DD+DD+DD+ : FF 9F E7 F9 FE FE DB AD | abyss : D6 EB EB+EB+EB+EB+EB+EB+ : EB+EB+EB+EB+EB+EB+EB+EB+ | detritus ... : EB+EB+EB+EB+EB+EB+EB+EB+ : FE+FF+FF+FF+FF+FF+FF+FF+ | 9-bit $FF : FF+FF+FF+FF+FF+FF+FF+FF+ | nibbles ... : FF+FF+FF+FF+FF+FF+FF+FF+ : FF+FF+FF+FF+FF+E9 BA DD | abyss : DD+DD+DD+DD+DD+DD+DD+DD+ --^-- Astute readers may complain that I've oversimplified, and they would be technically correct (the best kind of correct). There's no guarantee that the detritus is $DD nibbles; it could be any part of the track, depending on where the bit copier decides the track starts and ends. There's no guarantee that another bit copier would write the track data twice. Other bit copiers might make different guesses about the number of timing bits. It appears that one of the choices EDD 4 made -- adding 2 timing bits after the first few $FF nibbles -- fixed the desynchronization caused by the random bits after the $DD nibbles. But this countermeasure was not enough on its own. This protection check is very strict. It expects a track with a range of $DD nibbles and a range of $FF nibbles and very little else. To fool it, you'd need to make a perfect bit copy. To do that, you'd need to make a perfect bit copier. No one ever did. Quod erat liberandum. --------------------------------------- A 4am crack No. 1735 ------------------EOF------------------