-----------Piece of Cake Math---------- A 4am crack 2014-07-25 --------------------------------------- "Early Games: Piece of Cake Math" is a 1983 educational game programmed by Robert Eyestone and distributed by Springboard Software, Inc. [The copy protection is identical to "Piece of Cake," also written by Robert Eyestone. This write-up is therefore quite similar to that one, with a few corrections.] COPYA fails immediately with a disk read error. EDD 4 bit copy gives a read error on track $0A but seems OK on all other tracks. However, the bit copy does not work. It boots as if it's loading DOS 3.3, then displays an inverse "A" in bottom-right corner, then exits to a BASIC prompt with no DOS loaded. My trusty Copy ][+ sector editor in "DOS 3.3 PATCHED" mode (press "P" to get to the Sector Editor Patcher) can read tracks 0-2, but nothing else. 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 SAVING RWTS SAVING IOB 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.) But wait, there's more! The latest feature I added to my AUTOTRACE program is automatic IOB module creation. What the heck is an IOB module? Well, the author of Advanced Demuffin anticipated that he couldn't anticipate everything, so he made the program extensible. Quoting from the Advanced Demuffin softdocs (included on my work disk): --v-- An IOB module is an interface for the source RWTS. Advanced Demuffin uses the IOB module to set up the IOB table and jump to RWTS. The IOB module is stored from $1400-$14FB. When Advanced Demuffin loads in a IOB module, it reads the first sector of the file off the track-sector list and stores it at $13FC-$14FB. When Advanced Demuffin wants to read a sector it JSRs to the IOB module with the phase number, sector number, and the page number stored in the A, Y and X registers respectively. Since the source drive always has to be drive one, Advanced Demuffin can make the IOB module very compact. After it gets the page,track and sector Advanced Demuffin sets up the IOB for RWTS using this infor- mation, and JMPs to RWTS. (It jumps instead of JSRing, because it lets the RWTS do the RTS.) Here is a list of the IOB module that is built in to Advanced Demuffin: ; Convert phase # to track # 1400- 4A LSR ; Store track number 1401- 8D 22 0F STA $0F22 ; Store sector number 1404- 8C 23 0F STY $0F23 ; Store page number ; [note: original docs have incorrect ; hex opcode on this line] 1407- 8E 27 0F STX $0F27 140A- A9 01 LDA #$01 ; Store the drive number 140C- 8D 20 0F STA $0F20 ; Store the read code 140F- 8D 2A 0F STA $0F2A ; With high byte of IOB 1412- A9 0F LDA #$0F ; With low byte of IOB 1414- A0 1E LDY #$1E ; Goto RWTS 1416- 4C 00 BD JMP $BD00 --^-- Basically, Advanced Demuffin only knows how to call a custom RWTS if it 1. is loaded at $B800..$BFFF 2. uses a standard RWTS parameter table 3. has an entry point at $BD00 that takes the address of the parameter tables in A and Y 4. doesn't require initialization As it turns out, that covers a *lot* of copy protected disks, but it doesn't cover this one because the RWTS on disk is loaded at $3800..$3FFF and has its entry point at $3D00. If I told Advanced Demuffin to load this RWTS at $B800 and call it at $BD00, it would crash quite spectacularly. So, I added a check to AUTOTRACE to detect that the RWTS is loaded in a non-standard location (lines 279-300 in the HELLO program on my work disk) and automatically create an IOB file that can tell Advanced Demuffin how to access it. Here's what it looks like: ]BLOAD IOB,A$1400 ]CALL -151 *1400L ; Most of this is identical to the ; standard IOB module that comes with ; Advanced Demuffin (explained above). 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 ; One problem with having an RWTS at ; $3800..$3FFF is that that range is ; normally used to store track data ; during the copy process. If we just ; let Advanced Demuffin run, it will ; overwrite the custom RWTS almost ; immediately and crash. In the ; ADVANCED DEMUFFIN TECH NOTES (also ; included on my work disk), the author ; mentions that you can control how ; many sectors Advanced Demuffin reads ; at a time, and where it puts it in ; memory. Normally $1CF0 is $20 and ; $1CF1 is $90, meaning that it will ; copy 7 tracks worth of data at a time ; into $2000..$8FFF. Changing the end ; parameter to $30 will only copy one ; track at a time, but has the distinct ; advantage of not overwriting the RWTS ; and crashing. 1412- A9 30 LDA #$30 1414- 8D F1 1C STA $1CF1 ; get the address of the RWTS parameter ; table at $0F1E and call the RWTS ; entry point at $3D00 (instead of the ; usual $BD00) 1417- A9 0F LDA #$0F 1419- A0 1E LDY #$1E 141B- 4C 00 3D JMP $3D00 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 (stored in the RWTS file, accessed via the IOB module), then a standard DOS 3.3-compatible RWTS to write out the data, sector by sector. Advanced Demuffin will only load RWTS and IOB 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 16th century monk. [S6,D1=my work disk] ]BRUN ADVANCED DEMUFFIN 1.1 --> LOAD NEW RWTS MODULE At $38, load "RWTS" from D1 --> LOAD NEW IOB MODULE load "IOB" from D1 [S6,D1=original disk] [S6,D2=blank disk] --> CONVERT DISK --> CHANGE DEFAULT VALUES? N 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.1 - COPYRIGHT 1983 WRITTEN BY THE STACK -CORRUPT COMPUTING =======PRESS ANY KEY TO CONTINUE======= TRK:...RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR +.5: 0123456789ABCDEF0123456789ABCDEF012 SC0:...RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR SC1:...RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR SC2:...RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR SC3:...RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR SC4:...RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR SC5:...RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR SC6:...RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR SC7:...RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR SC8:...RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR SC9:...RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR SCA:...RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR SCB:...RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR SCC:...RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR SCD:...RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR SCE:...RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR SCF:...RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR ======================================= 16 SC $00,$00 TO $22,$0F BY $01 TO DRV2 --^-- This is really not going well. Remember when I said the default options don't need to be changed unless something goes horribly wrong? (Seriously, I just said that, like, a minute ago.) This is what "horribly wrong" looks like. The RWTS on the disk can't read, well, the majority of the disk. Perhaps I was too hasty in relying on my automated tools. Perhaps there is more to this disk than meets the eye. Let's back up. ]PR#5 *BLOAD BOOT1,A$3600 *3700L 3700- 8E E9 37 STX $37E9 3703- 8E F7 37 STX $37F7 3706- A9 01 LDA #$01 3708- 8D F8 37 STA $37F8 370B- 8D EA 37 STA $37EA 370E- AD E0 37 LDA $37E0 3711- 8D E1 37 STA $37E1 3714- A9 02 LDA #$02 3716- 8D EC 37 STA $37EC 3719- A9 04 LDA #$04 371B- 8D ED 37 STA $37ED 371E- AC E7 37 LDY $37E7 3721- 88 DEY 3722- 8C F1 37 STY $37F1 3725- A9 01 LDA #$01 3727- 8D F4 37 STA $37F4 372A- 8A TXA 372B- 4A LSR 372C- 4A LSR 372D- 4A LSR 372E- 4A LSR 372F- AA TAX 3730- A9 00 LDA #$00 3732- 9D F8 04 STA $04F8,X 3735- 9D 78 04 STA $0478,X 3738- 20 93 37 JSR $3793 Gah. I'm so comfortable tracing boot1 code in the $B700 range. But this... this is like waking up in a parallel universe where everything is just slightly different. Anyway, this is all bog standard so far. $3793 is the multi-sector read routine that reads the rest of DOS backwards starting at T02,S04. The RWTS parameter table starts at $37E8. 373B- A2 FF LDX #$FF 373D- 9A TXS 373E- 8E EB 37 STX $37EB 3741- 4C C8 3F JMP $3FC8 3744- 20 89 FE JSR $FE89 3747- 4C 03 1B JMP $1B03 That last line looks suspicious, but it's actually not. So far, this code is identical to the DOS 3.3 master disk. The routine at $1B03 is what figures out how much memory there is and moves DOS as high as possible. It makes sense that I haven't found anything unusual yet. Evidence so far suggests that the RWTS on disk can read tracks 0-2 (which is where it's loading DOS), then it switches to a different RWTS that can read the rest of the disk. So whatever this disk is doing to modify its RWTS or load a new one, it's going to do it after loading DOS. And I need to find out where. But that means I need to trace the boot even further. *9600 Success! Let's see what's at $B4BB. *B4BBL ; overwriting the instruction that just ; called this routine -- highly suspect B4BB- A9 AD LDA #$AD B4BD- 8D 84 9D STA $9D84 B4C0- A9 E9 LDA #$E9 B4C2- 8D 85 9D STA $9D85 B4C5- A9 B7 LDA #$B7 B4C7- 8D 86 9D STA $9D86 ; overwriting most of the $B700 code? ; also suspicious B4CA- A2 00 LDX #$00 B4CC- BD BB B3 LDA $B3BB,X B4CF- 5E BB 33 LSR $33BB,X B4D2- 1E BB B3 ASL $B3BB,X B4D5- 9D 00 B7 STA $B700,X B4D8- E8 INX B4D9- E0 B5 CPX #$B5 B4DB- 90 EF BCC $B4CC B4DD- D8 CLD B4DE- AD FF CF LDA $CFFF ; overwriting the language card B4E1- AD 81 C0 LDA $C081 B4E4- AD 81 C0 LDA $C081 B4E7- A2 00 LDX #$00 B4E9- BD 00 F8 LDA $F800,X B4EC- 1E BB 34 ASL $34BB,X B4EF- 9D 00 F8 STA $F800,X B4F2- E8 INX B4F3- D0 F4 BNE $B4E9 B4F5- EE EB B4 INC $B4EB B4F8- EE F1 B4 INC $B4F1 B4FB- D0 EA BNE $B4E7 ; hmm B4FD- AD 00 B7 LDA $B700 B500- F0 12 BEQ $B514 OK, I need to know whether this branch is taken. Let's break here and see. *B4FD:60 *B4BBG *B700 B700- 00 OK, so we continue to $B514. *B514L ; set reset vector (both of them at ; $03F2 and $FFFC) B514- A9 BF LDA #$BF B516- 8D FC FF STA $FFFC B519- 8D F2 03 STA $03F2 B51C- A9 9D LDA #$9D B51E- 8D F3 03 STA $03F3 B521- 8D FD FF STA $FFFD B524- 49 A5 EOR #$A5 B526- 8D F4 03 STA $03F4 ; Aha! Fiddling with RWTS parameters! B529- AC 82 C0 LDY $C082 B52C- A0 DE LDY #$DE B52E- 8C 91 B9 STY $B991 <- RWTS B531- 20 5E B7 JSR $B75E B534- 4C 6F B7 JMP $B76F The value at $B991 is one of the address epilogue bytes. *B75EL ; Double aha! More RWTS fiddling! B75E- AE 07 B7 LDX $B707 B761- 8E 55 B9 STX $B955 <- RWTS B764- AD 97 A3 LDA $A397 B767- C9 60 CMP #$60 B769- D0 03 BNE $B76E B76B- 8D 62 B7 STA $B762 B76E- 60 RTS The value at $B955 is one of the address prologue bytes. *B76FL ; what have we here? B76F- 2C 06 B7 BIT $B706 B772- 10 20 BPL $B794 B774- AE 03 B7 LDX $B703 ; 1 B777- 20 37 B5 JSR $B537 B77A- C9 06 CMP #$06 B77C- B0 23 BCS $B7A1 B77E- AE 04 B7 LDX $B704 ; 2 B781- 20 37 B5 JSR $B537 B784- C9 06 CMP #$06 B786- 90 19 BCC $B7A1 B788- AE 05 B7 LDX $B705 ; 3 B78B- 20 37 B5 JSR $B537 B78E- C9 06 CMP #$06 B790- B0 0F BCS $B7A1 B792- 90 0A BCC $B79E B794- AE 04 B7 LDX $B704 ; 4 B797- 20 37 B5 JSR $B537 B79A- C9 02 CMP #$02 B79C- D0 03 BNE $B7A1 ; continue to normal boot B79E- 4C 84 9D JMP $9D84 So what's at $B537 that's so important that we need to call it up to 4 times? I'm guessing it's a nibble check. *B537L ; read a sector B537- 8E EC B7 STX $B7EC B53A- A9 00 LDA #$00 B53C- 8D F4 B7 STA $B7F4 B53F- A9 B7 LDA #$B7 B541- A0 E8 LDY #$E8 B543- 20 B5 B7 JSR $B7B5 B546- AE E9 B7 LDX $B7E9 ; turn on drive motor manually ; (suspicious) B549- BD 89 C0 LDA $C089,X B54C- BD 8E C0 LDA $C08E,X ; set some counters B54F- A9 19 LDA #$19 B551- 85 0D STA $0D B553- A0 00 LDY #$00 B555- 84 09 STY $09 B557- A0 A0 LDY #$A0 ; oh look, a nibble check B559- BD 8C C0 LDA $C08C,X B55C- 10 FB BPL $B559 B55E- 49 FF EOR #$FF B560- F0 1C BEQ $B57E B562- E6 09 INC $09 B564- F0 24 BEQ $B58A B566- BD 8C C0 LDA $C08C,X B569- 10 FB BPL $B566 B56B- BD 8C C0 LDA $C08C,X B56E- 10 FB BPL $B56B B570- BD 8C C0 LDA $C08C,X B573- 10 FB BPL $B570 B575- BD 8C C0 LDA $C08C,X B578- 10 FB BPL $B575 B57A- 49 FF EOR #$FF B57C- D0 0C BNE $B58A B57E- C8 INY B57F- D0 D8 BNE $B559 B581- C6 0D DEC $0D B583- D0 D4 BNE $B559 B585- A5 09 LDA $09 B587- 18 CLC B588- 90 02 BCC $B58C ; success path is here (failure path ; skips over this and goes to $B58C) B58A- A9 FF LDA #$FF B58C- 48 PHA B58D- BD 88 C0 LDA $C088,X B590- 68 PLA B591- 60 RTS OK, two things here. First of all, nothing happens if the nibble check succeeds. There are no long-term side effects. It just continues booting. So I can just bypass the whole damn thing, which is nice. Second, I can create the RWTS I need to read the rest of the disk. I only need to change two bytes. [rebooting because I've destroyed my work disk's DOS in memory] *C500G ... ]BLOAD RWTS,A$3800 ]CALL -151 *3991:DE ; was "ED" *3955:BB ; was "D5" *BSAVE RWTS 3+,A$3800,L$800 *BRUN ADVANCED DEMUFFIN 1.1 [S6,D1=my work disk] --> LOAD NEW RWTS MODULE At $38, load "RWTS 3+" from D1 --> LOAD NEW IOB MODULE load "IOB" from D1 [S6,D1=original disk] [S6,D2=demuffin'd copy with tracks 0-2] --> CHANGE DEFAULT VALUES? Y ADVANCED DEMUFFIN 1.1 - COPYRIGHT 1983 WRITTEN BY THE STACK - CORRUPT COMPUTING ======================================== INPUT ALL VALUES IN HEX SECTORS PER TRACK? (13/16) 16 START TRACK: $03 ^^ ++-- we have tracks 0-2 already START SECTOR: $00 END TRACK: $22 END SECTOR: $0F INCREMENT: 1 MAX # OF RETRIES: 0 COPY FROM DRIVE 1 TO DRIVE: 2 ======================================== 16 SC $03,$00 TO $22,$0F BY $01 TO DRV 2 Now press RETURN to start the copy... --v-- ADVANCED DEMUFFIN 1.1 - COPYRIGHT 1983 WRITTEN BY THE STACK -CORRUPT COMPUTING =======PRESS ANY KEY TO CONTINUE======= TRK: .......R........................ +.5: 0123456789ABCDEF0123456789ABCDEF012 SC0: .......R........................ SC1: .......R........................ SC2: .......R........................ SC3: .......R........................ SC4: .......R........................ SC5: .......R........................ SC6: .......R........................ SC7: .......R........................ SC8: .......R........................ SC9: .......R........................ SCA: .......R........................ SCB: .......R........................ SCC: .......R........................ SCD: .......R........................ SCE: .......R........................ SCF: .......R........................ ======================================= 16 SC $03,$00 TO $22,$0F BY $01 TO DRV2 --^-- Damn it, now what? Wait, I remember EDD 4 had problems on track $0A as well. Firing up the Copy ][+ nibble editor and looking at track $0A on the original disk, it appears that it is entirely unformatted. I can't read it because there's nothing to read. OK, let's zero out that track and move on. Next up: I need to patch the RWTS to be able to read the disk, now that the entire disk is in a standard format. The only thing non-standard about the RWTS on the original disk was that it had "ED" instead of "DE" for one of the epilogue bytes. (The other oddities where only changed in memory by the copy protection routine, which I'm going to bypass.) T00,S03,$91 change "ED" to "DE" And finally, I need to bypass the copy protection by changing the instruction at $1D84 back to the original code that matches the DOS 3.3 master disk. T00,S0C,$84 change "4C BB B4" to "AD E9 37" Quod erat liberandum. --------------------------------------- A 4am crack No. 95 ------------------EOF------------------