-------------Dinosaur Days------------- A 4am crack 2015-12-27 --------------------------------------- Name: Dinosaur Days Version: 1.0 Genre: educational Year: 1988 Publisher: Pelican Software Media: two double-sided 5.25-inch disks OS: DOS 3.3 Previous cracks: none Similar cracks: #532 Typing Is A Ball, Charlie Brown #531 Graph Maker #530 Make A Face #296 Creation #198 Working Together #197 American History Adventure #195 Practical Grammar I have two double-sided disks, labeled 1A "program disk" 1B "art disk" 2A "data disk" 2B "data disk" Side A of each disk is bootable but protected. Side B of each disk is unbootable but unprotected. Life is like that. This has not been a haiku. I'll start with disk 1A. ~ Chapter 0 In Which Various Automated Tools Fail In Interesting Ways COPYA immediate disk read error Locksmith Fast Disk Backup unable to read any track EDD 4 bit copy (no sync, no count) no errors, but copy grinds on boot Copy ][+ nibble editor T00 -> standard prologues T01+ --> modified address prologue and epilogue (both inconsistent) --v-- COPY ][ PLUS BIT COPY PROGRAM 8.4 (C) 1982-9 CENTRAL POINT SOFTWARE, INC. --------------------------------------- TRACK: 04 START: 1800 LENGTH: 3DFF 2FA8: 96 96 96 96 96 96 96 96 VIEW 2FB0: 96 96 96 96 96 96 96 96 2FB8: 96 96 96 DE AA EB CD D5 ^^^^^^^^ data epilogue 2FC0: B5 D5 D5 BD D7 BB FB D5 2FC8: FF FE B3 BC D5 FF FE D5 <-2FCD ^^^^^^^^ address prologue (but different on every track) 2FD0: FF FE AA AE AB AA FE FA ^^^^^ ^^^^^ ^^^^^ ^^^^^ v=255 t=$04 s=$02 chksm 2FD8: FF FF 9F E7 F9 FE FF D5 ^^ (no address epilogue?) start of data prologue 2FE0: AA AD 9A 9A 9B 97 96 9A ^^^^^ rest of data prologue 2FE8: 96 9B 9B 97 9A 97 9A 96 --------------------------------------- A TO ANALYZE DATA ESC TO QUIT ? FOR HELP SCREEN / CHANGE PARMS Q FOR NEXT TRACK SPACE TO RE-READ --^-- Disk Fixer no luck beyond track $00 Why didn't COPYA work? modified prologue and epilogue Why didn't Locksmith FDB work? modified prologue and epilogue Why didn't my EDD copy work? I don't know. Maybe a nibble check during boot? Next steps: 1. capture RWTS with AUTOTRACE 2. convert disk to standard format with Advanced Demuffin 3. patch RWTS to read demuffin'd disk 4. find nibble check and bypass it ~ Chapter 1 In Which We Attempt To Use The Original Disk As A Weapon Against Itself [S6,D1=original disk] [S6,D2=blank disk] [S5,D1=my work disk] ]PR#5 CAPTURING BOOT0 ...reboots slot 6... ...reboots slot 5... SAVING BOOT0 /!\ BOOT0 JUMPS TO $08F0 CAPTURING BOOT1 ...reboots slot 6... ...reboots slot 5... SAVING BOOT1 SAVING RWTS Let's start by seeing what's at $08F0. ]BLOAD BOOT0,A$800 ]CALL -151 *8F0L 08F0- A9 AA LDA #$AA 08F2- 85 31 STA $31 <-- ? 08F4- A9 00 LDA #$00 08F6- 8D F1 B6 STA $B6F1 08F9- 4C 00 BB JMP $BB00 <-- ! I've seen this before. The RWTS uses zero page $31 to check some byte of the prologue or epilogue. In this case, probably the data epilogue, since the address prologue and epilogue are non- standard. Then it jumps to $BB00 (from $08F9), which is probably a nibble check. ]BLOAD BOOT1,A$2600 ]CALL -151 *FE89G FE93G ; disconnect DOS *B600<2600.2FFFM ; move RWTS into place *BB00L BB00- A9 59 LDA #$59 BB02- 8D F2 03 STA $03F2 BB05- A9 B7 LDA #$B7 BB07- EA NOP BB08- 8D F3 03 STA $03F3 BB0B- 49 A5 EOR #$A5 BB0D- 8D F4 03 STA $03F4 BB10- 4C 00 B7 JMP $B700 Hmm, not a nibble check. Just setting the reset vector. Now look at this code to match the data epilogue: *B92FL B92F- BD 8C C0 LDA $C08C,X B932- 10 FB BPL $B92F B934- C9 DE CMP #$DE B936- D0 0A BNE $B942 B938- EA NOP B939- BD 8C C0 LDA $C08C,X B93C- 10 FB BPL $B939 B93E- C5 31 CMP $31 <-- ! B940- F0 5C BEQ $B99E B942- 38 SEC B943- 60 RTS There's zero page $31, initialized at $08F0 during boot. Solution: an IOB module that Advanced Demuffin calls before calling the original disk's RWTS. (Read the docs on my work disk.) *C500G ... ]CALL -151 ]BLOAD ADVANCED DEMUFFIN 1.5 ; standard Advanced Demuffin setup ; (unchanged) 1400- 4A LSR 1401- 8D 22 0F STA $0F22 1404- 8C 23 0F STY $0F23 1407- 8E 27 0F STX $0F27 140A- A9 01 LDA #$01 140C- 8D 20 0F STA $0F20 140F- 8D 2A 0F STA $0F2A ; initialize zero page 1412- A9 AA LDA #$AA 1414- 85 31 STA $31 ; call RWTS 1416- A9 0F LDA #$0F 1418- A0 1E LDY #$1E 141A- 4C 00 BD JMP $BD00 *BSAVE IOB $31,A$1400,L$FB *BRUN ADVANCED DEMUFFIN 1.5 ["5" to switch to slot 5] ["R" to load a new RWTS module] --> At $B8, load "RWTS" from drive 1 [press "I" to load a new IOB module] --> load "IOB $31" from drive 1 ["6" to switch to slot 6] ["C" to convert disk] --v-- ADVANCED DEMUFFIN 1.5 (C) 1983, 2014 ORIGINAL BY THE STACK UPDATES BY 4AM =======PRESS ANY KEY TO CONTINUE======= TRK:................................... +.5: 0123456789ABCDEF0123456789ABCDEF012 SC0:................................... SC1:................................... SC2:................................... SC3:................................... SC4:................................... SC5:................................... SC6:................................... SC7:................................... SC8:................................... SC9:................................... SCA:................................... SCB:................................... SCC:................................... SCD:................................... SCE:................................... SCF:................................... ======================================= 16SC $00,$00-$22,$0F BY1.0 S6,D1->S6,D2 --^-- ]PR#5 ]CATALOG,S6,D2 C1983 DSR^C#254 264 FREE A 005 HI B 007 R.LIB B 004 P.R.ASM B 003 SCREEN.R.ASM B 003 INPUT B 002 BACKER.ASM B 002 PAT.PAC B 009 JOY B 002 WAKEMOUSE B 005 WP.ASM B 008 MENUS.LIB A 016 MAIN B 004 ZINFOZ *B 005 OUTLINE.SET *B 005 FLOW.SET B 003 MENU.ASM B 003 OPEN.R.ASM B 002 OPEN.MUS B 020 TITLE.PAC B 014 TITLE.STP B 012 PEL.PAC A 007 SETUP A 007 PRINT B 011 SET.MENUS.LIB B 028 PRINTERS B 016 CARDS B 003 PRINTER B 002 CARD B 008 DUMP B 007 CDUMP T 009 ZINFOZ.S [S6,D1=demuffin'd copy] ]PR#6 ...works... Wait, what? ~ Chapter 2 In Which We Angrily Investigate Why We Suddenly Have A Working Copy [S6,D1=mysteriously working copy] [S5,D1=my work disk] ]BLOAD RWTS,A$2800 ]CALL -151 *FE89G FE93G *B800<2800.2FFFM *B944L ; routine to find address prologue B944- A0 FC LDY #$FC B946- 84 26 STY $26 B948- C8 INY B949- D0 04 BNE $B94F B94B- E6 26 INC $26 B94D- F0 F3 BEQ $B942 ; find prologue nibble #1 B94F- BD 8C C0 LDA $C08C,X B952- 10 FB BPL $B94F B954- 4A LSR B955- C9 6A CMP #$6A B957- D0 EF BNE $B948 ; and again? B959- BD 8C C0 LDA $C08C,X ; Wait, no BPL loop here! It only reads ; the data latch once. B95C- C9 D5 CMP #$D5 ; if data latch is (still) $D5, jump ; right to address field parsing B95E- F0 12 BEQ $B972 ; otherwise continue and look for the ; standard prologue nibble #2 B960- BD 8C C0 LDA $C08C,X B963- 10 FB BPL $B960 B965- C9 AA CMP #$AA B967- D0 DF BNE $B948 ; and the standard prologue nibble #3 B969- BD 8C C0 LDA $C08C,X B96C- 10 FB BPL $B969 B96E- C9 96 CMP #$96 B970- D0 D6 BNE $B948 ; decode address field (standard) B972- A0 03 LDY #$03 B974- A9 00 LDA #$00 B976- 85 27 STA $27 B978- BD 8C C0 LDA $C08C,X B97B- 10 FB BPL $B978 B97D- 2A ROL B97E- 85 26 STA $26 B980- BD 8C C0 LDA $C08C,X B983- 10 FB BPL $B980 B985- 25 26 AND $26 B987- 99 2C 00 STA $002C,Y B98A- 45 27 EOR $27 B98C- 88 DEY B98D- 10 E7 BPL $B976 B98F- A8 TAY B990- D0 02 BNE $B994 ; immediately exit -- no epilogue ; checking at all B992- 18 CLC B993- 60 RTS B994- 38 SEC B995- 60 RTS B996- 00 BRK | These are B997- 00 BRK | really on B998- 00 BRK | the disk, B999- 00 BRK | just taking B99A- 00 BRK | up space, B99B- 00 BRK | much like B99C- 00 BRK | this B99D- 00 BRK | comment. B99E- 18 CLC B99F- 60 RTS This RWTS will accept several different address prologues. If it finds a $D5 followed by a timing bit, that's it; that's the entire address prologue. Without the timing bit, it looks for a three-nibble sequence, but it will accept either a $D4 or a $D5 for the first nibble (because of the LSR/CMP). Turning back to the Copy II Plus nibble editor, I see the crucial detail that I missed the first time. The "D5" that I thought was the third nibble in the address prologue is actually the first, and it is displayed in inverse, meaning it has timing bits after it. (Sorry that doesn't show up in text.) Why didn't the EDD copy work? EDD preserved the original address prologue but not the timing bits. The prologue checker finds the $D5 (at $B955) but no timing bit after it (at $B95C), so the disk can't read itself. There was never any separate nibble check; the structure of the disk itself is designed to foil nibble copiers. Why did the demuffin'd copy work? Advanced Demuffin wrote out the data from each sector onto a standard disk that uses "D5 AA 96" prologue and "DE AA EB" epilogue. The RWTS finds the first $D5, doesn't find a timing bit, but it finds the remaining standard prologue (AA 96) and decides that it found a valid address field. Thus, no RWTS patches are necessary. Disk 2A has identical protection. Quod erat liberandum. ~ Chapter 3 In Which We Patch The RWTS Anyway, And Explain Why Emulators aren't perfect. Real hardware is complicated. The Disk II floppy drive mechanism is especially difficult to emulate (being, as it is, an analog device). Many edge cases are left as "an exercise for the reader." Many copy protection schemes rely on edge cases to work. And as we've seen, this RWTS is a 7-layer cake of insanity. You see where this is going. My crack of this disk works perfectly on real hardware. It also works in most Apple II emulators that run on modern hardware. But it does not work in every emulator, so I set out to discover why. Here is the RWTS code from the original disk, which I have left untouched thus far: ; find address prologue #1 B94F- BD 8C C0 LDA $C08C,X B952- 10 FB BPL $B94F B954- 4A LSR B955- C9 6A CMP #$6A B957- D0 EF BNE $B948 ; read data latch one more time B959- BD 8C C0 LDA $C08C,X ; if the data latch still has $D5 in it ; then we are reading an original disk ; which uses a single nibble + timing ; bit as the address prologue, so jump ; forward to start parsing the address ; field B95C- C9 D5 CMP #$D5 B95E- F0 12 BEQ $B972 ; otherwise we are reading a standard ; disk (like a data disk -- or, in my ; case, a cracked copy), so continue ; checking the prologue for the regular ; second and third nibbles B960- BD 8C C0 LDA $C08C,X B963- 10 FB BPL $B960 B965- C9 AA CMP #$AA B967- D0 DF BNE $B948 B969- BD 8C C0 LDA $C08C,X B96C- 10 FB BPL $B969 B96E- C9 96 CMP #$96 B970- D0 D6 BNE $B948 At $B95C, we're checking the data latch to see if it is still holding the $D5 value. On real Disk II hardware, this will only be true if there was an extra timing bit after the $D5. The timing bit causes the data latch to retain its value for 4 more CPU cycles. This is the crux of the entire copy protection. Here's the problem: some emulators will (incorrectly) retain the $D5 value in the data latch for longer than a real drive would. This makes the RWTS think that it's reading an original disk. Specifically, $B95E (incorrectly) branches to $B972 and tries to start parsing the address field. Of course, on my crack, the address field hasn't started yet -- there are still two more nibbles in the address prologue. The address field checksum fails because we're off by two nibbles, disks grind, programs crash, everything is terrible. The solution is tricky, because we're in the middle of RWTS code so timing is tight (even in misbehaving emulators). But if we change the code at $B958 to branch to $B960, we'll have enough time to catch the second and third nibbles of the standard address prologue. This should work on real hardware, faithful emulators, and misbehaving emulators (since we'll never execute the compare at $B95C that went awry). The patched RWTS code: B94F- BD 8C C0 LDA $C08C,X B952- 10 FB BPL $B94F B954- 4A LSR B955- C9 6A CMP #$6A B957- D0 EF BNE $B948 B959- F0 06 BEQ $B960 ------+ B95B- [C0] \ | B95C- [C9 D5] } never executed | B95E- [F0 12] / | B960- BD 8C C0 LDA $C08C,X <---+ B963- 10 FB BPL $B960 B965- C9 AA CMP #$AA B967- D0 DF BNE $B948 T00,S03,$59 change "BD 8C" to "F0 05" I applied the same patch to disk 2A. --------------------------------------- A 4am crack No. 545 ------------------EOF------------------