---------The Movie Monster Game-------- A 4am crack 2014-05-06 --------------------------------------- The Movie Monster Game is a 1986 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 reboots endlessly. 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. That means that the easiest way to copy this disk is to use COPYA (from the DOS 3.3 master disk), with one small modification: after booting, I'll go into the monitor and patch the DOS 3.3 RWTS to ignore epilogue bytes. This is similar to what the Copy ][+ Sector Editor Patcher does, and in most cases the difference is immaterial. [S6D1=DOS 3.3 master disk] ]PR#6 ... ]CALL -151 *B942:18 <-- CLC to indicate no error reading epilogue bytes (was SEC, signifying an error) *3D0G ]RUN COPYA [S6D1=original disk] [S6D2=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). Unfortunately, the copy does not work; it just reboots endlessly. There must be some additional code designed to detect that the disk is not original. To find out where this code is, I'll need to trace the boot process until I find the offending code, and remove it or bypass it somehow. [S6D1=original disk] [S5D1=my work disk] ]PR#5 ...reboots slot 6... ...reboots slot 5... SAVING BOOT0 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 (of course), but that's the basic idea. Booting a disk is a cumulative process; each step builds on the previous steps. My work disk automatically runs a program called AUTOTRACE1, 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. I've seen a lot of boot0 code from different copy-protected (and not copy-protected) disks, so I've kind of developed a sense of what a "normal" boot looks like. I can look at almost-but-not-quite normal boot0 code and hone in pretty quickly on the part that's unusual. Maybe it calls a subroutine that isn't normally called, or it does things in a strange order, or it jumps to an unusual place after loading the boot1 code. ]CALL -151 *800<2800.28FFM *801L ... Everything here looks pretty normal (i.e. just like an unprotected DOS 3.3 disk), until it goes to jump to the boot1 code. Usually that happens with an indirect JMP ($08FD), which, in a normal boot0, will end up continuing execution at $B700 which is stored in track 0, sector 1. But in this case, I see: 084A- 4C 00 BB JMP $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). But $BB00 isn't loaded yet, because I interrupted the boot process before it could be loaded. So now I need to trace the boot again, but a little bit further -- far enough for boot0 to load boot1 (including the suspicious code at $BB00), but no further. 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). ]BRUN AUTOTRACE1 ...reboots slot 6... ...reboots slot 5... SAVING BOOT1 Let's see what we have. ]CALL -151 *B600<2000.29FFM *BB00L ; initialize some zero page addresses BB00- A9 00 LDA #$00 BB02- A2 F0 LDX #$F0 BB04- 9A TXS BB05- 95 00 STA $00,X BB07- E8 INX BB08- D0 FB BNE $BB05 BB0A- A9 0A LDA #$0A BB0C- 85 FC STA $FC ; 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. BB0E- A6 2B LDX $2B BB10- BD 89 C0 LDA $C089,X BB13- BD 8E C0 LDA $C08E,X ; a counter of some kind BB16- A9 80 LDA #$80 BB18- 85 FD STA $FD BB1A- C6 FD DEC $FD ; $BB98 is what I call "The Badlands" ; i.e. the code from which there is ; no return. Skipping ahead, I can see ; that $BB98 is one branch away from ; tweaking the reset vector and ; rebooting the computer. Which is, ; you know, not what we want. BB1C- F0 7A BEQ $BB98 ; $BBA5 looks for the standard address ; prologue, as a setup for the real ; test which comes next. BB1E- 20 A5 BB JSR $BBA5 ; If, for some reason, that doesn't ; work, off to The Badlands with you. BB21- B0 75 BCS $BB98 ; 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.) BB23- A5 F9 LDA $F9 BB25- C9 08 CMP #$08 BB27- D0 F1 BNE $BB1A BB29- A0 00 LDY #$00 BB2B- BD 8C C0 LDA $C08C,X BB2E- 10 FB BPL $BB2B BB30- 88 DEY BB31- F0 65 BEQ $BB98 BB33- C9 D5 CMP #$D5 BB35- D0 F4 BNE $BB2B BB37- A0 00 LDY #$00 BB39- BD 8C C0 LDA $C08C,X BB3C- 10 FB BPL $BB39 BB3E- 88 DEY BB3F- F0 57 BEQ $BB98 BB41- C9 E7 CMP #$E7 BB43- D0 F4 BNE $BB39 BB45- BD 8C C0 LDA $C08C,X BB48- 10 FB BPL $BB45 BB4A- C9 E7 CMP #$E7 BB4C- D0 4A BNE $BB98 BB4E- BD 8C C0 LDA $C08C,X BB51- 10 FB BPL $BB4E BB53- C9 E7 CMP #$E7 BB55- D0 41 BNE $BB98 BB57- BD 8D C0 LDA $C08D,X BB5A- A0 10 LDY #$10 BB5C- 24 80 BIT $80 BB5E- BD 8C C0 LDA $C08C,X BB61- 10 FB BPL $BB5E BB63- 88 DEY BB64- F0 32 BEQ $BB98 BB66- C9 EE CMP #$EE BB68- D0 F4 BNE $BB5E BB6A- EA NOP BB6B- EA NOP BB6C- A0 07 LDY #$07 BB6E- BD 8C C0 LDA $C08C,X BB71- 10 FB BPL $BB6E BB73- 99 F0 00 STA $00F0,Y BB76- EA NOP BB77- 88 DEY BB78- 10 F4 BPL $BB6E ; 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 BB7A- A2 03 LDX #$03 BB7C- A9 00 LDA #$00 BB7E- A8 TAY BB7F- 85 F8 STA $F8 BB81- A9 B7 LDA #$B7 BB83- 85 F9 STA $F9 BB85- B5 F0 LDA $F0,X BB87- 51 F8 EOR ($F8),Y BB89- 91 F8 STA ($F8),Y BB8B- 88 DEY BB8C- D0 F7 BNE $BB85 BB8E- E6 F9 INC $F9 BB90- CA DEX BB91- 10 F2 BPL $BB85 ; now that the boot1 code is decrypted, ; jump to it as normal BB93- A6 2B LDX $2B BB95- 6C FD 08 JMP ($08FD) ; The Badlands BB98- C6 FC DEC $FC BB9A- F0 03 BEQ $BB9F BB9C- 4C 16 BB JMP $BB16 BB9F- EE F4 03 INC $03F4 BBA2- 6C FC FF JMP ($FFFC) ; subroutine (called from $BB1E) to ; find the next address prologue and ; skip over the address field to ; position the drive head to read the ; special nibbles in the dead zone BBA5- A0 FD LDY #$FD BBA7- 84 F0 STY $F0 BBA9- C8 INY BBAA- D0 04 BNE $BBB0 BBAC- E6 F0 INC $F0 BBAE- F0 3D BEQ $BBED BBB0- BD 8C C0 LDA $C08C,X BBB3- 10 FB BPL $BBB0 BBB5- C9 D5 CMP #$D5 BBB7- D0 F0 BNE $BBA9 BBB9- EA NOP BBBA- BD 8C C0 LDA $C08C,X BBBD- 10 FB BPL $BBBA BBBF- C9 AA CMP #$AA BBC1- D0 F2 BNE $BBB5 BBC3- A0 03 LDY #$03 BBC5- BD 8C C0 LDA $C08C,X BBC8- 10 FB BPL $BBC5 BBCA- C9 96 CMP #$96 BBCC- D0 E7 BNE $BBB5 BBCE- A9 00 LDA #$00 BBD0- 85 F1 STA $F1 BBD2- BD 8C C0 LDA $C08C,X BBD5- 10 FB BPL $BBD2 BBD7- 2A ROL BBD8- 85 F0 STA $F0 BBDA- BD 8C C0 LDA $C08C,X BBDD- 10 FB BPL $BBDA BBDF- 25 F0 AND $F0 BBE1- 99 F8 00 STA $00F8,Y BBE4- 45 F1 EOR $F1 BBE6- 88 DEY BBE7- 10 E7 BPL $BBD0 BBE9- A8 TAY BBEA- EA NOP BBEB- 18 CLC BBEC- 60 RTS BBED- 38 SEC BBEE- 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 $BB7A..$BB92, then at $BB95 it does an indirect jump to ($08FD) to continue execution at the start of boot1 ($B700, just like a normal DOS 3.3 disk). TRACE1A will let this copy protection run (off the original disk), then interrupt the boot process immediately after the decryption loop, by setting $8FD/$8FE to point to a routine under my control. *9600