-------The Sporting News Baseball------ A 4am crack 2014-05-27 --------------------------------------- "The Sporting News Baseball" is a 1988 arcade game distributed by Epyx, Inc. Trying to copy the original disk with COPYA fails immediately with a disk read error. EDD 4 bit copy gives no read errors, but the copy it produces just boots, swings the disk out to track $22 (or thereabouts), then reboots. Firing up my trusty Copy ][+ sector editor, I press "P" to get to the Sector Editor Patcher and selected "DOS 3.3 Patched." This option ignores the epilogue bytes after the address field and data field (normally "DE AA EB"). It doesn't work on every disk; lots of disks use non-standard prologue bytes as well, or don't use 16 sectors, or any one of a hundred different ways to deviate from the norm within the tolerance of the Disk II hardware. But it works with this one! Ignoring epilogue bytes, the sector editor can whiz through the entire disk and read all the data from every sector on every track. Based on my limited experience cracking other disks, I would guess that this disk has - Standard prologue bytes before the address and data fields [otherwise Copy ][+ sector editor would give read errors, even with the "DOS 3.3 PATCHED" option] - Non-standard epilogue bytes after the address and data fields [otherwise COPYA would work] - Some secondary protection [otherwise the bit copy created with EDD 4 would work] The easiest way to convert the disk to standard epilogue bytes is to use COPYA with a patched RWTS that accepts any epilogue bytes on read but includes standard epilogue bytes on write. [S6,D1=DOS 3.3 master disk] ]PR#6 ... ]CALL -151 *B942:18 <-- CLC to indicate no error reading epilogue bytes (was SEC, signifying an error) *RUN COPYA [S6,D1=original disk] [S6,D2=blank disk] ...read read read... ...grind grind grind... ...write write write... (I do this for both sides.) OK, now I have two disks with standard prologue and epilogue bytes, which can be read by any standard tool (including COPYA without any RWTS patches). There are two problems with my copy: 1. Depending on how the original disk was written, this copy may or may not be able to read itself. I may need to patch the disk's RWTS to deal with the fact that the disk is now in a standard format. 2. Even if it can read itself, it won't run. The copies I tried to make -- even the bit copies -- just rebooted endlessly, which means there is some code being executed during boot to check if the disk is original. (Hint: it's not.) Just by booting the copy, I can rule out problem #1. The disk seems to read itself just fine. It makes it exactly as far as the failed bit copy -- far enough to figure out that it's not an original disk and reboot. Time for boot tracing with AUTOTRACE. [S6,D1=original disk] [S5,D1=my work disk] ]PR#5 ... CAPTURING BOOT0 ...reboots slot 6... ...reboots slot 5... SAVING BOOT0 CAPTURING BOOT1 ...reboots slot 6... ...reboots slot 5... SAVING BOOT1 OK, now I have the very early boot code (colloquially called "boot0") which is loaded by the disk controller ROM from track 0, sector 0. This code's job is to load the next section of code, commonly called "boot1" (usually by re-using part of the disk controller ROM routine at $C600). Then "boot1" either loads the rest of the disk operating system or (in many commercial games) simply loads the game code directly off the disk and jumps to it. There are variations (oh so many variations), but that's the basic idea. Booting a disk is a cumulative process; each step builds on the last. My work disk automatically runs a program called AUTOTRACE0, which interrupts the boot process immediately after the disk controller ROM routine loads the code from track 0, sector 0. It relocates this code (up to 256 bytes worth) to address $2800, then reboots and saves it to a file called BOOT0. Then my work disk inspects the "BOOT0" file to see if it's relatively close (or even identical) to the standard DOS 3.3 boot0 code. If so, my work disk has another program, unimaginatively named AUTOTRACE1, which does just that. It loads track 0, sector 0, then patches the boot0 code at $084A to call back to a routine under my control (instead of jumping to the original disk's boot1 code). A surprisingly number of copy protected disks work this way (virtually all pre- ProDOS educational programs, but also many commercial games). Implementing this small amount of automation has made boot tracing much easier and less error-prone for me. Another benefit of AUTOTRACE is that I look at how much of the boot tracing process it was able to automate, and ignore everything but the last step. In this case, I don't need to look at the boot0 code, because I already know it's just like standard DOS 3.3. So I'll start with the boot1 code. ]BLOAD BOOT1,A$2600 ]CALL -151 *B600<2600.2FFFM *B700L B700- A0 00 LDY #$00 B702- B9 0E B7 LDA $B70E,Y B705- 99 00 60 STA $6000,Y B708- C8 INY B709- D0 F7 BNE $B702 B70B- 4C 00 60 JMP $6000 Weird, but OK. Let's patch it and let it run so I don't have to do mental hex math trying to follow the rest of the code. *B70B:60 *B700G *6000L ; get slot number and ORA with $C0 so ; we can call the disk controller ROM ; routine to read some more sectors 6000- A6 2B LDX $2B 6002- 8A TXA 6003- 4A LSR 6004- 4A LSR 6005- 4A LSR 6006- 4A LSR 6007- 09 C0 ORA #$C0 6009- 8D 62 60 STA $6062 ; this subroutine moves the drive head ; to a specific track, given in the ; accumulator (times 2 -- so $44 moves ; to track $22) 600C- A9 44 LDA #$44 600E- 20 A0 BA JSR $BAA0 6011- 20 40 60 JSR $6040 *6040L ; initialize some zero page addresses 6040- A2 07 LDX #$07 6042- 8A TXA 6043- 95 F0 STA $F0,X 6045- CA DEX 6046- 10 FA BPL $6042 ; Turn on the disk motor. Zero page $2B ; contains the slot number x 16. This ; is the standard way to access low- ; level disk commands. 6048- A6 2B LDX $2B 604A- BD 89 C0 LDA $C089,X 604D- BD 8E C0 LDA $C08E,X ; a counter of some kind 6050- A9 0B LDA #$0B 6052- 85 F0 STA $F0 6054- C6 F0 DEC $F0 6056- D0 0B BNE $6063 ; The Badlands -- munge reset vector ; and call it (reboots unconditionally) 6058- EE F4 03 INC $03F4 605B- 6C FC FF JMP ($FFFC) . . . 6063- A9 80 LDA #$80 6065- 85 F1 STA $F1 6067- C6 F1 DEC $F1 6069- F0 E9 BEQ $6054 606B- 20 44 BA JSR $BA44 606E- B0 E4 BCS $6054 6070- A5 2D LDA $2D 6072- C9 0D CMP #$0D 6074- D0 F1 BNE $6067 ; Search for a specific sequence of ; nibbles in the "dead zone" between ; the address field and data field. ; This area is normally not important, ; so COPYA doesn't copy it precisely ; because normal disks don't care. ; (Actually, it's even more evil than ; that, because the original disk is ; written with timing bits in specific ; non-standard places between the ; nibbles in the dead zone. This code ; not only requires the right nibbles ; in the right order, it reads them ; just slightly faster than normal. So ; the timing bits need to be in the ; right places too, or the disk will ; get out of sync and read the wrong ; nibble values. This will trip up even ; the best bit copiers. And you can ; forget about making a disk image for ; emulators -- those don't store timing ; bits at all.) 6076- A0 00 LDY #$00 6078- BD 8C C0 LDA $C08C,X 607B- 10 FB BPL $6078 607D- 88 DEY 607E- F0 D4 BEQ $6054 6080- C9 D5 CMP #$D5 6082- D0 F4 BNE $6078 6084- A0 00 LDY #$00 6086- BD 8C C0 LDA $C08C,X 6089- 10 FB BPL $6086 608B- 88 DEY 608C- F0 C6 BEQ $6054 608E- C9 E7 CMP #$E7 6090- D0 F4 BNE $6086 6092- BD 8C C0 LDA $C08C,X 6095- 10 FB BPL $6092 6097- C9 E7 CMP #$E7 6099- D0 B9 BNE $6054 609B- BD 8C C0 LDA $C08C,X 609E- 10 FB BPL $609B 60A0- C9 E7 CMP #$E7 60A2- D0 B0 BNE $6054 60A4- BD 8D C0 LDA $C08D,X 60A7- A0 10 LDY #$10 60A9- 24 80 BIT $80 60AB- BD 8C C0 LDA $C08C,X 60AE- 10 FB BPL $60AB 60B0- 88 DEY 60B1- F0 A1 BEQ $6054 60B3- C9 EE CMP #$EE 60B5- D0 F4 BNE $60AB 60B7- EA NOP 60B8- EA NOP 60B9- A0 07 LDY #$07 60BB- BD 8C C0 LDA $C08C,X 60BE- 10 FB BPL $60BB 60C0- 99 F0 00 STA $00F0,Y 60C3- EA NOP 60C4- 88 DEY 60C5- 10 F4 BPL $60BB ; Wait, it gets better -- this disk ; actually uses the raw nibble data it ; stores in this "dead zone" AS THE ; DECRYPTION KEY FOR THE REST OF BOOT1 60C7- A2 04 LDX #$04 60C9- A0 00 LDY #$00 60CB- 84 F8 STY $F8 60CD- BD EB 60 LDA $60EB,X 60D0- 86 FA STX $FA 60D2- 85 F9 STA $F9 60D4- 98 TYA 60D5- 29 07 AND #$07 60D7- AA TAX 60D8- B5 F0 LDA $F0,X 60DA- 51 F8 EOR ($F8),Y 60DC- 91 F8 STA ($F8),Y 60DE- C8 INY 60DF- D0 F3 BNE $60D4 60E1- E6 F9 INC $F9 60E3- A6 FA LDX $FA 60E5- CA DEX 60E6- 10 E5 BPL $60CD ; now that the boot1 code is decrypted, ; return gracefully and the caller can ; do whatever it needs to do 60E8- A6 2B LDX $2B 60EA- 60 RTS Because the next stage of the boot is encrypted, I can't simply bypass this copy protection routine. I need to let it run at least once, from the original disk, so that it can decrypt the rest of the code. The decryption happens at $60C7..$60E7, then execution returns to $6014. *6014L ; Set up zero page to read track $22, ; sector $00 into $B700, using the disk ; controller ROM routine at $C65C. 6014- A9 22 LDA #$22 6016- 85 41 STA $41 6018- A9 00 LDA #$00 601A- 85 3D STA $3D 601C- A9 B7 LDA #$B7 601E- 85 27 STA $27 6020- A9 00 LDA #$00 6022- 85 26 STA $26 6024- AD 01 08 LDA $0801 6027- 48 PHA 6028- A9 60 LDA #$60 602A- 8D 01 08 STA $0801 ; this calls the disk controller ROM ; routine 602D- 20 5E 60 JSR $605E ; restore $801 (probably unnecessary) 6030- 68 PLA 6031- 8D 01 08 STA $0801 ; move drive head back to track 0 6034- A6 2B LDX $2B 6036- A9 00 LDA #$00 6038- 20 A0 BA JSR $BAA0 ; continue with the real boot1 code as ; if this nibble check never happened 603B- A6 2B LDX $2B 603D- 4C 00 B7 JMP $B700 Looking at T22,S00 in a sector editor confirms that my reading of this code is correct. Once I decrypt the rest of the boot1 code, I should be able to just copy that sector back to T00,S01 and wipe out the copy protection altogether. DECRYPT BOOT1 will let the copy protection run once (off the original disk), then interrupt the boot process immediately after the decryption loop and jump to a routine under my control. Then I can capture the decrypted RWTS and save it to my work disk, and eventually, to track 0 of my non- working copy to make it boot properly. *C500G ; reboot since I overwrote DOS ; earlier while inspecting *9600