------------Mind Over Matter----------- A 4am crack 2014-09-09 --------------------------------------- "Mind Over Matter" is a 1984 educational game written by Michael Heins, Deneen Melander, and Dave Mark, and distributed by Learning Well. It comes on one double-sided disk and uses both sides. [The copy protection is identical to several other disks in my collection, including - "Computer Literacy" (Control Data Corporation) - "Warrior of Ras, Volume One: Dunzhin" (Screenplay) - "Gulf Strike" (Microcomputer Games) - "MasterType" (Scarborough Systems) - "Treasure Hunter" (Intentional Educations, Inc.) Somebody been sellin' copy protection! This write-up is based on my previous write-ups of those disks, with a few updates because my AUTOTRACE program has gotten smarter over time.] COPYA fails miserably and immediately with a disk read error. EDD 4 bit copy gives no read errors, but the copy does not work; it just hangs on boot. Turning to my trusty Copy ][+ sector editor, I press "P" to get to the Sector Editor Patcher, and select "DOS 3.3 PATCHED". This option ignores checksum bytes and epilogue sequences -- as long as the address and data prologue are standard ("D5 AA 96" and "D5 AA AD", respectively), this will allow me to read each sector. And lo and behold, it works! I can read the data from every sector on every track, with one exception: T00,S0A. Given that the original disk boots correctly, I'm going to guess that this sector is either unused (in which case, I have a damaged original disk but caught a lucky break) or part of a copy protection scheme (in which case I don't care). Let's see if I can capture the RWTS from the original disk. [S6,D1=original disk, side A] [S5,D1=my work disk] ]PR#5 CAPTURING BOOT0 ...reboots slot 6... ...reboots slot 5... SAVING BOOT0 /!\ BOOT0 JUMPS TO ($BBFE) 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". Now then... what's all this about "BOOT0 JUMPS TO ($BBFE)"? This is another feature I recently added to AUTOTRACE. Instead of simply bailing out at the first sign of abnormalcy, it checks a few common patterns (like jumping to a nibble check at $BB00, or in this case, doing so indirectly via ($BBFE)), prints a warning, and continues the trace if it's safe to do so. So let's see what's at ($BBFE). ]BLOAD BOOT1,A$2600 ]CALL -151 *FE89G FE93G ; disconnect DOS *B600<2000.29FFM ; move RWTS in place *BBFE.BBFF BBFE- 00 BB *BB00L BB00- A9 00 LDA #$00 BB02- 85 D6 STA $D6 BB04- BD 8D C0 LDA $C08D,X BB07- A9 FF LDA #$FF BB09- EA NOP BB0A- 30 05 BMI $BB11 BB0C- A2 B1 LDX #$B1 BB0E- 4C F0 BB JMP $BBF0 BB11- AD FD FF LDA $FFFD BB14- A9 00 LDA #$00 BB16- F0 05 BEQ $BB1D BB18- A2 B2 LDX #$B2 BB1A- 4C F0 BB JMP $BBF0 ; search for a nibble sequence BB1D- BD 8C C0 LDA $C08C,X BB20- A9 00 LDA #$00 BB22- 8D 00 02 STA $0200 BB25- BD 8C C0 LDA $C08C,X BB28- 10 FB BPL $BB25 BB2A- C9 EB CMP #$EB BB2C- D0 F7 BNE $BB25 BB2E- BD 8C C0 LDA $C08C,X BB31- 10 FB BPL $BB2E BB33- C9 D5 CMP #$D5 BB35- D0 EE BNE $BB25 BB37- BD 8C C0 LDA $C08C,X BB3A- 10 FB BPL $BB37 BB3C- C9 AA CMP #$AA BB3E- D0 E5 BNE $BB25 ; wipe most of memory ($0800..$95FF) ; although, ironically, not the part ; I'm using for boot tracing BB40- A9 4C LDA #$4C BB42- A0 00 LDY #$00 BB44- 99 00 95 STA $9500,Y BB47- 88 DEY BB48- D0 FA BNE $BB44 BB4A- CE 46 BB DEC $BB46 BB4D- AD 46 BB LDA $BB46 BB50- C9 07 CMP #$07 BB52- D0 EC BNE $BB40 ; fiddle with RWTS to ignore epilogue ; bytes (WTF) BB54- A9 18 LDA #$18 BB56- 8D 42 B9 STA $B942 BB59- A9 0A LDA #$0A ; read T00,S0A into $4000 (hey, this ; means that unreadable sector was part ; of the copy protection after all) BB5B- 8D ED B7 STA $B7ED BB5E- D0 05 BNE $BB65 ... BB65- A9 00 LDA #$00 BB67- 8D EC B7 STA $B7EC BB6A- 8D F0 B7 STA $B7F0 BB6D- A9 40 LDA #$40 BB6F- 8D F1 B7 STA $B7F1 BB72- A9 01 LDA #$01 BB74- 8D F4 B7 STA $B7F4 BB77- 8D F8 B7 STA $B7F8 BB7A- 8D EA B7 STA $B7EA BB7D- 8E E9 B7 STX $B7E9 BB80- 8E F7 B7 STX $B7F7 ; more RWTS fiddling, so sector reads ; save raw nibble data in $6C00 range BB83- A0 6C LDY #$6C BB85- 8C 10 B9 STY $B910 BB88- 8C CE B8 STY $B8CE BB8B- 8C D2 B8 STY $B8D2 BB8E- 88 DEY BB8F- 8C 21 B9 STY $B921 ; another sector read, with modified ; RWTS BB92- 20 E7 BB JSR $BBE7 ; copy the raw nibble data elsewhere BB95- A0 55 LDY #$55 BB97- B9 00 6C LDA $6C00,Y BB9A- 99 00 5C STA $5C00,Y BB9D- 88 DEY BB9E- 10 F7 BPL $BB97 BBA0- AD 02 6B LDA $6B02 BBA3- 85 06 STA $06 ; another sector read BBA5- 20 E7 BB JSR $BBE7 BBA8- AD 02 6B LDA $6B02 BBAB- 85 07 STA $07 BBAD- 20 E7 BB JSR $BBE7 BBB0- AD 02 6B LDA $6B02 BBB3- 85 08 STA $08 ; compare this read's nibble data to ; the previous read's nibble data BBB5- A0 55 LDY #$55 BBB7- B9 00 6C LDA $6C00,Y BBBA- D9 00 5C CMP $5C00,Y BBBD- D0 2F BNE $BBEE BBBF- 88 DEY BBC0- 10 F5 BPL $BBB7 ; some more comparisons, just because BBC2- A5 06 LDA $06 BBC4- C5 07 CMP $07 BBC6- D0 04 BNE $BBCC BBC8- C5 08 CMP $08 BBCA- F0 17 BEQ $BBE3 ; success path is here -- ; first, restore the RWTS code BBCC- A9 38 LDA #$38 BBCE- 8D 42 B9 STA $B942 BBD1- A0 BC LDY #$BC BBD3- 8C 10 B9 STY $B910 BBD6- 8C CE B8 STY $B8CE BBD9- 8C D2 B8 STY $B8D2 BBDC- 88 DEY BBDD- 8C 21 B9 STY $B921 ; then continue with boot1 as normal BBE0- 4C 00 B7 JMP $B700 BBE3- 4C 54 BB JMP $BB54 ... BBE7- A9 B7 LDA #$B7 BBE9- A0 E8 LDY #$E8 BBEB- 4C B5 B7 JMP $B7B5 ; failure path is here BBEE- A2 B3 LDX #$B3 BBF0- 20 58 FC JSR $FC58 BBF3- 20 2D FF JSR $FF2D BBF6- 8E 03 04 STX $0403 BBF9- 4C 5B B7 JMP $B75B The important takeaway here is that there don't appear to be any long-term side effects of this copy protection. If it succeeds, it restores everything that it modified (in the RWTS code), then it just jumps to $B700 to start the boot1 phase. But that's it; nothing else seems to rely on some magic number that it pulls from the raw nibbles or anything. It doesn't decrypt anything. It doesn't even clear the carry flag. 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. [S6,D1=original disk, side A] [S6,D2=blank disk] [S5,D1=my work disk] *C500G ; because I overwrote DOS ... ]BRUN ADVANCED DEMUFFIN 1.5 [press "5" to switch to slot 5] [press "R" to load a new RWTS module] --> At $B8, load "RWTS" from drive 1 [press "6" to switch to slot 6] [press "C" to 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 unless something goes horribly wrong. --v-- ADVANCED DEMUFFIN 1.5 (C) 1983, 2014 ORIGINAL BY THE STACK UPDATES BY 4AM =======PRESS ANY KEY TO CONTINUE======= TRK:R.................................. +.5: 0123456789ABCDEF0123456789ABCDEF012 SC0:................................... SC1:................................... SC2:................................... SC3:................................... SC4:................................... SC5:................................... SC6:................................... SC7:................................... SC8:................................... SC9:................................... SCA:R.................................. SCB:................................... SCC:................................... SCD:................................... SCE:................................... SCF:................................... ======================================= 16SC $00,$00-$22,$0F BY1.0 S6,D1->S6,D2 --^-- The disk's own RWTS gave a read error on T00,S0A, but that's OK. I already know that that's part of the copy protection, so I don't care about it. The rest of the disk reads just fine. This is 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, my 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, because it's executing a copy protection routine during boot to check if the disk is original. (Hint: it's not.) I already have enough information to fix problem #2. The copy protection is located at $BB00, and it is executed immediately after boot0 (T00,S00) loads boot1 (T00,S01-09). This line of code: 084A- 6C FE BB JMP ($BBFE) ...needs to look like this: 084A- 6C FD 08 JMP ($08FD) T00,S00,$4B change "FE BB" to "FD 08" Now the disk boots far enough to start grinding because it can't read itself. The RWTS still expects the rest of the disk to be in a non-standard format, but that's no longer true -- Advanced Demuffin wrote out each sector in a standard format. So I need to patch the RWTS on my copy so it can read itself. The original disk uses a modified version of DOS 3.3. (It's so close, that I was able to capture it with my automated tools.) So I'm really just reverting the modifications they made 30 years ago. Better late than never. For future reference (mostly mine), here's a nice chart of the memory locations for all the prologues and epilogues in a DOS 3.3-shaped RWTS. If $B700 is stored on T00,S01 (like this disk), then $B800 will be on T00,S02; $B900 on T00,S03; &c. 0x | read | write ---------------+-------+------- D5 | $B955 | $BC7A prologue AA | $B95F | $BC7F / 96 | $B96A | $BC84 ADDRESS -------+-------+------- \ DE | $B991 | $BCAE epilogue AA | $B99B | $BCB3 EB | | $BCB8 ---------------+-------+------- D5 | $B8E7 | $B853 prologue AA | $B8F1 | $B858 / AD | $B8FC | $B85D DATA ----------+-------+------- \ DE | $B935 | $B89E epilogue AA | $B93F | $B8A3 EB | | $B8A8 ---------------+-------+------- Using my trusty Copy ][+ sector editor, I found 7 bytes that differ from the standard DOS 3.3 RWTS: T00,S02,$9E change "FF" to "DE" T00,S02,$A3 change "FF" to "AA" T00,S02,$A8 change "FF" to "EB" T00,S03,$35 change "FF" to "DE" T00,S03,$3F change "FF" to "AA" T00,S03,$91 change "FF" to "DE" T00,S03,$9B change "FF" to "AA" (Note to self: I should make an RWTS comparison tool.) With these patches in place, my copy can now boot and read itself. It loads and runs without complaint. There doesn't appear to be any further copy protection. Side B has identical protection. It even has the same nibble check. Which seems like overkill, since the only thing booting side B does is print an error telling you to boot side A. But whatever. I did the same things to it, and now it works too. Quod erat liberandum. --------------------------------------- A 4am crack No. 129 ------------------EOF------------------