------------Tangrams Puzzler----------- A 4am crack 2014-09-18 --------------------------------------- "Tangrams Puzzler" is a 1984 educational game developed by Ken Coates and distributed by Milliken Publishing Company. COPYA fails immediately and spectacularly(*). (*)not actually spectacular EDD 4 bit copy gives no read errors, but the copy does not work. It sounds like a standard DOS 3.3 boot, but then it puts a "." in the top-left corner of the screen and reboots. Disk Fixer is a standalone sector editor I just discovered. I've taken to using it for most of the things I used to do in my trusty Copy ][+ sector editor. It's small and fast, and I can launch it from ProDOS with the help of DOS 3.3 Launcher. Anyway, in Disk Fixer, in the Input/ Output Control settings (press "O"), I turn off checksums. This ignores the address and data epilogue bytes, and also the checksum byte after the data field. And lo and behold, I can read every sector on every track! It does indeed appear to be a modified version of DOS 3.3. T11,S0F looks like a standard VTOC directory sector with filenames and pointers to track/sector lists and whatnot. Based on my limited experience cracking other disks, I would guess that this disk has - Standard prologue bytes before the address and data fields [otherwise Disk Fixer would give read errors, even after ignoring checksums] - Non-standard epilogue bytes after the address and data fields [otherwise COPYA would work] - Some secondary protection [otherwise the bit copy created with EDD 4 would work] Given the (relatively) weak structural protection, I used to turn to the DOS 3.3 master disk, patch the RWTS to ignore checksums and epilogue bytes (changing $B942 from "SEC" to "CLC"), and run COPYA. Then, one fine day, and completely by accident, I came across an original disk with a bad sector. I suppose this shouldn't surprise me. These floppies are decades old by now; it's amazing any of them work at all. The point is, I shouldn't be using tools that ignore potentially serious read errors. So, no more COPYA+B942:18 patch. From now on, it's Super Demuffin or Advanced Demuffin to convert disks to a standard format. Since this disk looks like DOS 3.3 and sounds like DOS 3.3, I'm going to see what my AUTOTRACE program can do with it. [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 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.) [S6,D1=original disk] [S6,D2=blank disk] [S5,D1=my work disk] ]PR#5 ... ]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:..R................................ SC6:................................... SC7:................................... SC8:................................... SC9:................................... SCA:................................... SCB:................................... SCC:................................... SCD:................................... SCE:................................... SCF:................................... ======================================= 16SC $00,$00-$22,$0F BY1.0 S6,D1->S6,D2 --^-- The disk's own RWTS gave one read error on track $02, but the rest of the disk copied without a hitch. The original disk gives no indication of a bad sector, so either this sector is unused (and I got lucky) or this is part of the copy protection. Let's see if I can launch the program from my work disk. ]PR#5 ... ]CATALOG,S6,D2 C1983 DSR^C#254 149 FREE ERROR #8 I/O ERR Wait, what? I'm pretty sure I saw a disk catalog on track $11. So where is it? Turning to my trusty Disk Fixer sector editor, I see the problem. Track $11 does have a catalog, but the pointer to the first directory sector has been intentionally corrupted. --v-- -------------- DISK EDIT -------------- TRACK $11/SECTOR $00/VOLUME $FE/BYTE$00 --------------------------------------- $00: 00 F1 0F 03 00 00 FE 00 @qOC@@~@ ^^ ^^ track,sector (should be 11,0F) $08: 00 00 00 00 00 00 00 00 @@@@@@@@ $10: 00 00 00 00 00 00 00 00 @@@@@@@@ $18: 00 00 00 00 00 00 00 00 @@@@@@@@ $20: 00 00 00 00 00 00 00 7A @@@@@@@: $28: 00 00 00 00 00 00 00 00 @@@@@@@@ $30: 06 FF 00 00 23 10 00 01 F.@@#P@A $38: 00 00 00 00 00 00 00 00 @@@@@@@@ $40: 00 00 00 00 FF FF 00 00 @@@@..@@ $48: FF FF 00 00 FF FF 00 00 ..@@..@@ $50: 7F FF 00 00 00 00 00 00 ?.@@@@@@ $58: 00 00 00 00 00 00 00 00 @@@@@@@@ $60: 00 00 00 00 3F FF 00 00 @@@@?.@@ $68: 00 00 00 00 00 00 00 00 @@@@@@@@ $70: 3F FF 00 00 00 00 00 00 ?.@@@@@@ $78: 00 00 00 00 00 00 00 00 @@@@@@@@ --------------------------------------- BUFFER 0/SLOT 6/DRIVE 1/MASK OFF/NORMAL --------------------------------------- COMMAND : --^-- Third-party utilities can not catalog this disk or work with any of its files (every DOS file function routes through this pointer), but the original disk obviously has no problem. But how does the original disk know? I scoured "Beneath Apple DOS" until I found the answer on page 8-28: --v-- 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. --^-- 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 TF1,S0F" so DOS goes and tries to read track $F1, sector $0F, which obviously won't work. But the DOS on this disk made one small modification to that routine. (This is stored on T01,S0F.) 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 11 LDX #$11 << 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 $11. 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 (T11,S0F), DOS 3.3 or any other copy utility should be able to read the entire catalog. This disk doesn't care either way, since it never looks at it. T11,S00,$01 change "F1" to "11" Now I should be able to catalog it from my work disk. ]PR#5 ... ]CATALOG,S6,D2 C1983 DSR^C#254 149 FREE *A 011 BOOT *B 010 JCODE.2048 *B 005 CS4 *A 019 MANAGER.BAS *B 012 INS1 *B 009 INS2 *B 015 T.TPGS *B 017 PLAY.DATA *B 017 DATA.EDIT *T 002 INTERFACE *B 058 OBJ.PLAY *B 057 OBJ.EDIT B 007 EDIT.DATA T 002 STDTAN T 065 STDTA B 034 PIC.LOGO B 007 A.LOGO ]RUN BOOT The game loads without complaint. (It even runs from drive 2!) There doesn't appear to be any further protection beyond the custom RWTS and DOS. There are two problems with this copy: 1. Depending on how the original RWTS was written, a demuffin'd disk may not be able to read itself. Some developers just patch the RWTS to ignore epilogue bytes, while others patch the RWTS to look for specific non-standard epilogue bytes. Demuffin'd disks in the latter category will grind immediately on boot, since as soon as the RWTS is loaded, all further disk reads will look for the original (non-standard) epilogue bytes and not find them. 2. Even if it can read itself, it won't run. The copies I tried to make -- even the bit copies -- just rebooted endlessly, which means there is some code being executed during boot to check if the disk is original. (Hint: it's not.) This disk appears to be in the "strict RWTS" category. My demuffin'd copy just grinds on boot, which tells me that the RWTS is looking for specific (non- standard) epilogue bytes and failing to find them. So I need to patch the RWTS to undo the modifications and look for the standard epilogue bytes instead. 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 the RWTS stores $B700 in T00,S01 (most do), then $B8xx will be in T00,S02; $B9xx in T00,S03; and so on. 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 ---------------+-------+------- I spent way too much time making that. Here are the patches to normalize the RWTS. (Note to self: make an RWTS comparison tool.) T00,S02,$9E change "DF" to "DE" T00,S03,$35 change "DF" to "DE" T00,S03,$91 change "DF" to "DE" T00,S06,$AE change "DF" to "DE" Now my demuffin'd copy boots, loads DOS, puts a "." in the top-left of the screen, then -- and I am not making this up -- displays the following message and hangs: --v-- ATTENTION! THE DISK DRIVE YOU ARE USING IS OPERATING AT AN UNSAFE SPEED. OPERATION OF THIS PROGRAM ON THIS DRIVE MAY DESTROY THE PROGRAM. PLEASE HAVE YOUR DRIVE SPEED CHECKED, OR USE ANOTHER DISK DRIVE. --^-- I should note at this point that my "demuffin'd copy" is actually a disk image being managed by a CFFA 3000 card. I copied the disk image back to a physical floppy and booted it, and it displayed the behavior I was expecting (load DOS, print ".", then reboot -- just like my failed bit copy). Then I copied the disk image to a modern PC and ran it in two different emulators; each time, it gave me the message about the drive operating at an unsafe speed. I'm about to give up on this DOS and just blow it away and replace it with a fresh copy of DOS 3.3. I've already confirmed that the program itself loads when I boot from my work disk. But now I want to know whether this DOS is really checking the drive speed, or if that's just bullshit and misdirection. So here we go. ]PR#5 ... ]BLOAD BOOT0 ]CALL -151 *801L . . nothing unusual . *BLOAD BOOT1 *FE89G FE93G ; disconnect DOS *B600<2600.2FFFM ; move RWTS into place *B700L . . nothing unusual, until . B747- 4C 03 9B JMP $9B03 This usually jumps to $9D84, the DOS cold start vector. I don't know what's at $9B03 yet, but I can find out. *C500G ; because I overwrote DOS ... ]CALL -151 *9600