----------------Math Man--------------- A 4am crack 2014-04-15 --------------------------------------- Math Man is a 1984 educational action game (seriously). It was developed by Applied Systems Knowledge, Ltd. and distributed by Scholastic. The original disk appears to copy with COPYA, but the copy does not work. It loads DOS, displays the usual "]" prompt, then reboots. If I try to Ctrl-C break into BASIC, it reboots. If I try to Ctrl-Reset break, I can get to a prompt, but any command (CATALOG, LIST, &c.) reboots. Firing up my trusty Copy ][+ sector editor, I searched for "4C 00 C6" and found a suspicious instance on T00,S0C. This sector is normally part of DOS, and a quick glance at the surrounding code seems to confirm that it is part of DOS. But DOS does not usually include any explicit reboots. Let's remove it and see what happens. T00,S0C,$49 change "4C" to "2C" OK, a small amount of progress. The game still reboots after the "]" prompt, but Ctrl-C breaks instead of rebooting, and commands like LIST and CATALOG work. ]CATALOG PRONTO-DOS V254 FS=81 B 005 BUCK2 B 013 BUCK2.S B 026 DATA B 034 FRONT A 002 HELLO T 002 LOADER B 026 MAIN1 B 121 MAIN1.S B 002 MAN1 B 013 MAN2 B 061 MAN2.S B 002 MOVE B 003 MOVE.S B 034 PIC B 002 PLAER B 009 RAIL3 B 039 RAIL3.S B 005 RAND .S Pronto-DOS on a commercial disk. Nice. And the original disk appears to include source code for most of the code files, which is very unusual. (There was no Free Software movement in the 1980s. The GNU GPL didn't exist until 1989, and didn't take off until version 2 of the license was released in 1991.) (Edit from the future: yup, all the .S files are Merlin source code files. No copyright license mentioned.) ]LIST 10 D$ = CHR$ (4) 20 PRINT D$;"BRUN MAN1" 30 PRINT D$;"EXEC LOADER" 40 END Initial plan of action: copy all of these files to a freshly formatted Pronto-DOS disk (who knows what other surprises lurk in this customized DOS), seek and destroy the nibble check (my intuition tells me it's in MAN1), declare victory and go home. Stumbling block #1: Copy ][+ tells me that the disk is empty. Well, not empty exactly, but no files. CATALOG DISK SLOT 6 DRIVE 1 DISK VOLUME 254 NO FILES SECTORS FREE:81 USED:479 TOTAL:560 PRESS [RETURN] Curiouser and curiouser: the free sector count matches the output I got when I booted the disk and ran the CATALOG from there. So Copy ][+ is reading part of the catalog (the part that tracks which sectors are used), but it's missing the rest of the catalog (the part that tracks which files are on the disk). Never a dull moment in the land of Apple II copy protection. Poking around with a sector editor, it appears that the VTOC starts on T11,S00 as usual, and this points to T11,S0F as usual. But T11,S0F is empty, so if you haven't booted from the disk, the disk catalog appears to have no files. Furthermore, I found the rest of the VTOC on track 3. Based on the order of the files in the CATALOG, it appears to start on T03,S0F and work backwards through track 3. But how does the original disk know that? I scoured "Beneath Apple DOS" until I found the answer on page 8-28: [begin quote] B011-B036 Read a directory sector ; (If CARRY flag is zero on entry, read first directory sector. If CARRY is one, read next) ; Memorize entry code. ; Set buffer pointers (B045). ; First or next? ; If first, get track/sector of directory sector from VTOC at offset +1,+2. ; Otherwise, get track/sector from directory sector at offset +1,+2. If track is zero, exit with error code (end of directory). ; Call RWTS to read sector. ; Exit with normal return code. [end quote] So, to read the first sector of file names and other metadata, this routine is supposed to look at the VTOC sector buffer (read from T11,S00 and stored at $B3BB..$B4BA). The VTOC says "hey, the first sector of files and stuff is in T11,S0F" so this routine is supposed to read T11,S0F. But the DOS on this disk made one small modification to that routine: B011- 08 PHP B012- 20 45 B0 JSR $B045 B015- 28 PLP B016- B0 08 BCS $B020 B018- AC BD B3 LDY $B3BD ------ B01B- A2 03 LDX #$03 << hey B01D- EA NOP << now ------ B01E- D0 0A BNE $B02A B020- AE BC B4 LDX $B4BC B023- D0 02 BNE $B027 B025- 38 SEC B026- 60 RTS B027- AC BD B4 LDY $B4BD B02A- 8E 97 B3 STX $B397 B02D- 8C 98 B3 STY $B398 B030- A9 01 LDA #$01 B032- 20 52 B0 JSR $B052 B035- 18 CLC B036- 60 RTS Instead of getting the track number from the VTOC, it hard-codes track 3. Now that I've identified the problem, the fix is straightforward. If I change the VTOC header (T11,S00) to point to the actual first directory sector (T03,S0F), DOS 3.3 or any other copy utility should be able to read the entire catalog. DOS 3.3 is certainly flexible enough to handle this. Storing the entire VTOC on track $11 is just a convention; DOS doesn't actually care where directory sectors are stored as long as it can find the next one. T11,S00,$01 change "11" to "03" As I suspected, Copy ][+ now correctly displays the disk catalog, and I can copy all the files to a freshly formatted Pronto-DOS disk. [S6D1=freshly formatted disk] [S6D2=non-working copy] Copy ][+ --> COPY --> FILES --> S6,D2 to S6,D1 Now I have two non-working copies: one (in drive 2) with the modified version of Pronto-DOS (but a neutralized reboot instruction on T00,S0C and a fixed up VTOC on T11,S00), and another (in drive 1) with a standard Pronto-DOS and all the files copied over. I'm done with the copy in drive 2. But there is still the matter of the copy protection that fails and reboots. Let's go back and take a second look at that HELLO program. ]PR#6 BREAK ]LIST 10 D$ = CHR$ (4) 20 PRINT D$;"BRUN MAN1" 30 PRINT D$;"EXEC LOADER" 40 END ]BLOAD MAN1 ]CALL -151 *AA72.AA73 AA72- 00 90 *9000L ; get RWTS parameter table address 9000- 20 E3 03 JSR $03E3 9003- 85 FB STA $FB 9005- 84 FA STY $FA ; manually pushing stuff onto the stack ; is always suspicious 9007- A9 C5 LDA #$C5 9009- 48 PHA 900A- A9 00 LDA #$00 900C- 85 FC STA $FC ; set track and sector for nibble check 900E- A2 03 LDX #$03 9010- BC 35 90 LDY $9035,X 9013- 91 FA STA ($FA),Y 9015- CA DEX 9016- 10 F8 BPL $9010 9018- 8A TXA ; another stack push 9019- 48 PHA ; read sector 901A- 20 28 90 JSR $9028 ; call nibble check 901D- A0 01 LDY #$01 901F- B1 FA LDA ($FA),Y 9021- AA TAX 9022- 20 39 90 JSR $9039 ; undo stack pushes and exit normally 9025- 68 PLA 9026- 68 PLA 9027- 60 RTS ; read sector 9028- 20 E3 03 JSR $03E3 902B- 20 D9 03 JSR $03D9 902E- A9 00 LDA #$00 9030- 85 48 STA $48 9032- B0 52 BCS $9086 9034- 60 RTS 9035- 08 PHP 9036- 04 ??? 9037- 0C ??? 9038- 03 ??? ; nibble check starts here 9039- BD 89 C0 LDA $C089,X 903C- A9 56 LDA #$56 903E- 85 FD STA $FD 9040- A9 08 LDA #$08 9042- C6 FC DEC $FC 9044- D0 04 BNE $904A 9046- C6 FD DEC $FD 9048- F0 3C BEQ $9086 904A- BC 8C C0 LDY $C08C,X 904D- 10 FB BPL $904A 904F- C0 FB CPY #$FB 9051- D0 ED BNE $9040 9053- F0 00 BEQ $9055 9055- EA NOP 9056- EA NOP 9057- BC 8C C0 LDY $C08C,X 905A- C0 08 CPY #$08 905C- 2A ROL 905D- B0 0B BCS $906A 905F- BC 8C C0 LDY $C08C,X 9062- 10 FB BPL $905F 9064- C0 FF CPY #$FF 9066- D0 D8 BNE $9040 9068- F0 EB BEQ $9055 906A- BC 8C C0 LDY $C08C,X 906D- 10 FB BPL $906A 906F- 84 FC STY $FC 9071- C9 0A CMP #$0A 9073- D0 CB BNE $9040 9075- BD 8C C0 LDA $C08C,X 9078- 10 FB BPL $9075 907A- 38 SEC 907B- 2A ROL 907C- 25 FC AND $FC 907E- 49 FF EOR #$FF 9080- D0 04 BNE $9086 ; success path appears to do nothing, ; i.e. no side effects 9082- DD 88 C0 CMP $C088,X 9085- 60 RTS ; The Badlands, from which there is no ; return 9086- A8 TAY 9087- DD 88 C0 CMP $C088,X 908A- 68 PLA 908B- 68 PLA 908C- 99 00 90 STA $9000,Y 908F- C8 INY 9090- C0 8B CPY #$8B 9092- D0 F8 BNE $908C 9094- 60 RTS OK, it appears that this nibble check has no side effects. I should be able to bypass it entirely by just not calling it. Since it was BRUN from the HELLO program, that means just deleting the line of BASIC that BRUN'd it. (I have no idea how to turn "BRUN" into a past tense verb.) *3D0G ]20 ]SAVE HELLO ]PR#6 Success! The game boots and loads without complaint. Quod erat liberandum. --------------------------------------- A 4am crack No. 17 -------------------EOF-----------------