---The World's Greatest Baseball Game-- A 4am crack 2014-07-21 --------------------------------------- "The World's Greatest Baseball Game" is a 1984 sports simulation distributed by Epyx. COPYA fails miserably and immediately. EDD 4 bit copy gives no read errors, but the copy just reboots endlessly. In my experience, programs do not spontaneously reboot unless someone tells them to. Turning to my trusty Copy ][+ sector editor, I press "P" to enter the Sector Editor Patcher, then select "DOS 3.3 PATCHED" (which ignores address field checksums and epilogue bytes). Behold! All tracks and sectors are readable. 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] Given the (relatively) weak structural protection, I used to turn to the DOS 3.3 master disk, patch the RWTS to ignore checksums and epilogue bytes (changing $B942 from "SEC" to "CLC"), and run COPYA. Then, one fine day, and completely by accident, I came across an original disk with a bad sector. I suppose this shouldn't surprise me. These floppies are decades old by now; it's amazing any of them work at all. The point is, I shouldn't be using tools that ignore potentially serious read errors. There are other tools, like Super Demuffin, that can convert a disk like this (with non-standard epilogue bytes) into a standard format. It requires figuring out what the actual epilogue bytes are, but it has the advantage of surfacing a read error if the original disk actually has a read error. So... no more COPYA+B942:18 patch. From now on, it's Super Demuffin or Advanced Demuffin to convert disks to a standard format. Just by looking at the first few sectors, it appears that this disk uses a DOS 3.3-derived RWTS, which means that my AUTOTRACE program should be able to extract the RWTS from the original disk. [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 SAVING RWTS For those of you just tuning in, my work disk uses a custom program that I affectionately call "AUTOTRACE" to automate the process of boot tracing as far as possible. For some disks, this just captures track 0, sector 0 (saved in a file called "BOOT0") and stops. For other disks that load in the same way that an unprotected DOS 3.3 disk loads, it captures the next stage of the boot process as well (in a file called "BOOT1"). BOOT1 contains sectors 0-9 on track 0, which are loaded into memory at $B600..$BFFF. This generally contains the RWTS routines which the program uses to read the rest of the disk. If the RWTS is fairly normal as well (and my AUTOTRACE program just spot- checks a few memory locations to guess at its "normalcy"), there's a good chance I'll be able to use a tool called Advanced Demuffin (written in 1983 by The Stack) to convert the disk from whatever weird format it uses to store its sector data into a standard disk readable by unprotected DOS 3.3 disks or any other third-party tools. In this case, AUTOTRACE extracts the RWTS routines (generally loaded from track 0, sectors 2-9 into $B800..$BFFF) and saves *that* into a third file called "RWTS". If anything looks fishy or non- standard, AUTOTRACE just stops, and I have to check the files it saved so far to determine why. But in this case, it ran all the way through, automatically capturing BOOT0, BOOT1, and RWTS files. Now I can use Advanced Demuffin to convert the disk to a standard format. (It uses the disk's own RWTS to read the original, then a standard DOS 3.3- compatible RWTS to write out the data, sector by sector.) Advanced Demuffin will only load RWTS files from a drive in slot 6, which is annoying since mine is in slot 5. Note to self: patch that someday. In the meantime, I'm swapping floppy disks like some kind of 20th century peasant. [S6,D1=my work disk] ]PR#6 ]BRUN ADVANCED DEMUFFIN 1.1 --> LOAD NEW RWTS MODULE At $B8, load "RWTS" from drive 1 [S6,D1=original disk] [S6,D2=blank disk] --> FORMAT TARGET DISK ...grind grind grind... --> CONVERT DISK This disk is 16 sectors, and the default options (copy the entire disk, all tracks, all sectors) don't need to be changed. ADVANCED DEMUFFIN 1.1 - COPYRIGHT 1983 WRITTEN BY THE STACK -CORRUPT COMPUTING =======PRESS ANY KEY TO CONTINUE======= TRK:................................... +.5: 0123456789ABCDEF0123456789ABCDEF012 SC0:................................... SC1:................................... SC2:................................... SC3:................................... SC4:................................... SC5:................................... SC6:................................... SC7:................................... SC8:................................... SC9:................................... SCA:................................... SCB:................................... SCC:................................... SCD:................................... SCE:................................... SCF:................................... ======================================= 16 SC $00,$00 TO $22,$0F BY $01 TO DRV2 The disk's own RWTS gave no read errors on any track. That's the power and the genius of Advanced Demuffin. Every disk must be able to read itself. So, let it read itself, then capture the data and write it out in a standard format. There are two problems with this 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. [S6,D1=my work disk] ]PR#6 ... ]BLOAD BOOT1,A$2600 ]CALL -151 *FE89G FE93G ; disconnect DOS *B600<2600.2FFFM ; move RWTS into place *B700L ; hey now, what's all this then? B700- 20 00 BB JSR $BB00 Highly suspect. I definitely want to see what evil lurks at $BB00. That area of memory is normally reserved for the denibblizing process when reading data from a sector. It's scratch space, essentially. It's overwritten every time the disk reads itself (after boot1 is loaded). *BB00L ; this is the instruction I expected to ; see at $B700 BB00- 8E E9 B7 STX $B7E9 ; save zero page BB03- A2 00 LDX #$00 BB05- B5 00 LDA $00,X BB07- 9D 00 50 STA $5000,X BB0A- CA DEX BB0B- 10 F8 BPL $BB05 ; hmm BB0D- 20 00 BC JSR $BC00 ; restore zero page BB10- 08 PHP BB11- A2 00 LDX #$00 BB13- B9 00 50 LDA $5000,Y BB16- 95 00 STA $00,X BB18- CA DEX BB19- 10 F8 BPL $BB13 BB1B- 28 PLP ; hmm, branching based on the carry bit BB1C- 90 0F BCC $BB2D ; The Badlands (the point of no return) ; this takes the slot (x16) and munges ; it into a $Cx value, like $C6 for ; slot 6 BB1E- A5 2B LDA $2B BB20- 4A LSR BB21- 4A LSR BB22- 4A LSR BB23- 4A LSR BB24- 09 C0 ORA #$C0 ; ...then decrements it BB26- A8 TAY BB27- 88 DEY BB28- 98 TYA ; ...pushes it to the stack BB29- 48 PHA ; ...now pushes $FF to the stack BB2A- A9 FF LDA #$FF BB2C- 48 PHA BB2D- A6 2B LDX $2B ; ...and "returns" to that address (+1) ; which will reboot. You know, just in ; case you were searching for the magic ; string "4C 00 C6" to find where the ; program rebooted, you won't find it. BB2F- 60 RTS Let's see what wonderfulness awaits us at $BC00. *BC00L ; set the reset vector to reboot BC00- A5 2B LDA $2B BC02- 4A LSR BC03- 4A LSR BC04- 4A LSR BC05- 4A LSR BC06- 09 C0 ORA #$C0 BC08- 8D F3 03 STA $03F3 BC0B- 49 A5 EOR #$A5 BC0D- 8D F4 03 STA $03F4 BC10- A9 00 LDA #$00 BC12- 8D F2 03 STA $03F2 ; and jump back to $BB30 BC15- A6 2B LDX $2B BC17- 4C 30 BB JMP $BB30 *BB30L ; Oh look, we're turning on the drive ; motor manually. Will this ever not ; be suspicious? Every nibble check ; does it, and it's always suspicious. BB30- A6 2B LDX $2B BB32- BD 89 C0 LDA $C089,X BB35- BD 8E C0 LDA $C08E,X BB38- A9 AE LDA #$AE BB3A- 85 1E STA $1E BB3C- A9 BB LDA #$BB BB3E- 85 1F STA $1F BB40- A9 0A LDA #$0A BB42- 85 09 STA $09 BB44- A9 80 LDA #$80 BB46- 85 08 STA $08 ; looks like the beginnings of a nibble ; check, with the failure path leading ; to $BBA8 BB48- C6 08 DEC $08 BB4A- F0 5C BEQ $BBA8 BB4C- 20 44 B9 JSR $B944 BB4F- B0 57 BCS $BBA8 BB51- A5 2D LDA $2D BB53- C9 0A CMP #$0A BB55- D0 F1 BNE $BB48 BB57- A0 00 LDY #$00 BB59- BD 8C C0 LDA $C08C,X BB5C- 10 FB BPL $BB59 BB5E- 88 DEY BB5F- F0 47 BEQ $BBA8 BB61- C9 D5 CMP #$D5 BB63- D0 F4 BNE $BB59 ; 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 didn'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.) BB65- A0 00 LDY #$00 BB67- BD 8C C0 LDA $C08C,X BB6A- 10 FB BPL $BB67 BB6C- 88 DEY BB6D- F0 39 BEQ $BBA8 BB6F- C9 E7 CMP #$E7 BB71- D0 F4 BNE $BB67 BB73- BD 8C C0 LDA $C08C,X BB76- 10 FB BPL $BB73 BB78- C9 E7 CMP #$E7 BB7A- D0 2C BNE $BBA8 BB7C- BD 8C C0 LDA $C08C,X BB7F- 10 FB BPL $BB7C BB81- C9 E7 CMP #$E7 BB83- D0 23 BNE $BBA8 BB85- BD 8D C0 LDA $C08D,X BB88- A0 10 LDY #$10 BB8A- 24 FF BIT $FF BB8C- BD 8C C0 LDA $C08C,X BB8F- 10 FB BPL $BB8C BB91- 88 DEY BB92- F0 14 BEQ $BBA8 BB94- C9 EE CMP #$EE BB96- D0 F4 BNE $BB8C BB98- A0 07 LDY #$07 BB9A- BD 8C C0 LDA $C08C,X BB9D- 10 FB BPL $BB9A BB9F- D1 1E CMP ($1E),Y BBA1- D0 05 BNE $BBA8 BBA3- 88 DEY BBA4- 10 F4 BPL $BB9A ; success path is here -- clear carry ; and exit BBA6- 18 CLC BBA7- 60 RTS ; failure path is here -- after enough ; tries, give up and set carry and exit BBA8- C6 09 DEC $09 BBAA- D0 98 BNE $BB44 BBAC- 38 SEC BBAD- 60 RTS Which gets us all the way back to the branch-if-carry-is-clear at $BB1C. So basically, this entire routine is unnecessary. If the nibble check succeeds, it clears the carry ($BBA6) and returns to code that checks if the carry is clear ($BB1C) and if so just returns to the caller ($B700). If the nibble check fails, it sets the carry ($BBAC) and returns to code that is somewhat obfuscated but ends up rebooting (which matches the behavior I saw in my failed bit copy). The first instruction (at $BB00) is really the code that belongs at $B700, which called this entire mess. So f--- it, let's just restore that instruction and this code will never execute. T00,S01,$00 change "20 00 BB" to "8E E9 B7" Quod erat liberandum. --------------------------------------- A 4am crack No. 91 ------------------EOF------------------