-------------Borrowed Time------------- A 4am crack 2016-11-19 --------------------------------------- Name: Borrowed Time Genre: adventure Year: 1985 Authors: Rebecca Heineman, Interplay Productions Publisher: Activision Platform: Apple ][+ or later (64K) Media: double-sided 5.25-inch floppy OS: custom Previous cracks: The Talisman / First Class another uncredited crack ~ Chapter 0 In Which Various Automated Tools Fail In Interesting Ways COPYA immediate disk read error, but it gets a participation trophy just for showing up Locksmith Fast Disk Backup unable to read any track EDD 4 bit copy (no sync, no count) works Copy ][+ nibble editor data fields seem normal, but there's no stable prologue/epilogue pattern for address field at all -- not even within each track(!) --v-- COPY ][ PLUS BIT COPY PROGRAM 8.4 (C) 1982-9 CENTRAL POINT SOFTWARE, INC. --------------------------------------- TRACK: 01 START: 2B7A LENGTH: 1825 2B58: FF FF FF FF FF FF FF FF VIEW 2B60: FF FF FF FF FF FF FF FF 2B68: FF FF FF FF FF FF FF FF 2B70: FF FF FF FF FF FF FF FF 2B78: FF FF FF FF D5 D5 97 EE ^^^^^^^^ address prologue 2B80: AA AB AA AB AA AA AA AA ^^^^^ ^^^^^ ^^^^^ ^^^^^ V=001 T=$01 S=$00 chksm 2B88: 96 ED EB FF FF FF FF FF ^^^^^^^^ address epilogue 2B90: FF FF FF D5 AA AD 96 96 ^^^^^^^^ data prologue (normal) 2B98: 96 96 96 96 96 96 96 96 --------------------------------------- A TO ANALYZE DATA ESC TO QUIT ? FOR HELP SCREEN / CHANGE PARMS Q FOR NEXT TRACK SPACE TO RE-READ --^-- But again, EVERY SECTOR IS DIFFERENT, even the other sectors on the same track. Here is track 1, sector 1: --v-- COPY ][ PLUS BIT COPY PROGRAM 8.4 (C) 1982-9 CENTRAL POINT SOFTWARE, INC. --------------------------------------- TRACK: 01 START: 2E02 LENGTH: 1825 2F68: 96 96 96 96 96 96 96 96 VIEW 2F70: 96 96 D6 DE AA EB FF FF 2F78: FF FF FF FF FF FF FF FF 2F80: FF FF FF FF D5 D5 97 EE ^^^^^^^^ address prologue (same) 2F88: AA AB AA AB AA AB AA AB ^^^^^ ^^^^^ ^^^^^ ^^^^^ V=001 T=$01 S=$01 chksm 2F90: 97 EE EB FF FF FF FF FF ^^^^^^^^ address epilogue (different) 2F98: FF FF FF D5 AA AD B7 B7 2FA0: 9D F3 EE AF AE B7 B7 9D 2FA8: F3 EE AF AE B7 B7 9D F3 --------------------------------------- A TO ANALYZE DATA ESC TO QUIT ? FOR HELP SCREEN / CHANGE PARMS Q FOR NEXT TRACK SPACE TO RE-READ --^-- And the address prologues on other tracks are completely different. Whee. Disk Fixer Given the right combination of prologue and epilogue, I can read each sector on the disk. (I didn't really try them all, but I was able to read all the ones I tried.) So... probably no custom nibble translate table or other encoding weirdness. Also, this: --v-- -------------- DISK EDIT -------------- TRACK $00/SECTOR $0F/VOLUME $FE/BYTE$00 --------------------------------------- $00: P L E A S E D O N ' T $10: B R E A K O R C O P Y $20: T H I S P R O G R A M I $30: S P E N T A L O N G $40: T I M E P E R F E C T I N G $50: T H E P U L L - D O W N $60: M E N U S Y S T E M A N D $70: I W O U L D B E $80: D I S A P P O I N T E D I N $90: Y O U I F Y O U B R O K E $A0: T H I S P R O G R A M $B0: $C0: S I G N E D $D0: $E0: B I L L H E I N E M A N $F0: ( 7 1 4 ) X X X - X X X X --------------------------------------- BUFFER 0/SLOT 6/DRIVE 1/MASK OFF/NORMAL --------------------------------------- COMMAND : _ --^-- I've masked out the phone number here because it's obviously not valid any longer. But I asked Rebecca Heineman (formerly Bill) about it, and she confirmed that the phone number listed was her direct office line at Interplay Productions. And no, no one ever called her about breaking it. Why didn't COPYA work? modified prologues and epilogues (every track) Why didn't Locksmith FDB work? ditto EDD worked. What does that tell us? no half or quarter tracks almost certainly no nibble check (just structural changes to prologues and epilogues) Next steps: 1. Trace the boot 2. Capture the original RWTS that can read this mess 3. Convert the disk to a standard format with Advanced Demuffin 4. Declare victory (*) (*) go to the gym ~ Chapter 1 In Which We Will Not Be Going To The Gym Anytime Soon The floppy drive firmware code at $C600 is responsible for aligning the drive head and reading sector 0 of track 0 into main memory at $0800. Because the drive can be connected to any slot, the firmware code can't assume it's loaded at $C600. If the floppy drive card were removed from slot 6 and reinstalled in slot 5, the firmware code would load at $C500 instead. To accommodate this, the firmware does some fancy stack manipulation to detect where it is in memory (which is a neat trick, since the 6502 program counter is not generally accessible). However, due to space constraints, the detection code only cares about the lower 4 bits of the high byte of its own address. $C600 (or $C500, or anywhere in $Cx00) is read-only memory. I can't change it, which means I can't stop it from transferring control to the boot sector of the disk once it's in memory. BUT! The disk firmware code works unmodified at any address. Any address that ends with $x600 will boot slot 6, including $B600, $A600, $9600, &c. Thus, from the monitor: ; copy drive firmware to $9600 *9600 to avoid Diversi-DOS relocating to the language card... OK, I have a DOS-shaped RWTS at $B800 that can read standard disks. ]BLOAD ADVANCED DEMUFFIN 1.5 ]CALL -151 ; standard "IOB" interface -- ; A = phase (track x 2) ; Y = sector ; X = address high 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 1412- AD 22 0F LDA $0F22 ; before we call $BD00 to read a sector ; we need to munge the RWTS like the ; routine at $11CD on the original disk ; (see listings below) 1415- 20 CD 14 JSR $14CD 1418- AC 23 0F LDY $0F23 141B- 20 EC 14 JSR $14EC ; now call the RWTS to read a sector ; off the original disk 141E- A9 0F LDA #$0F 1420- A0 1E LDY #$1E 1422- 4C 00 BD JMP $BD00 And here are the two functions that set up our RWTS to read a specific sector, choosing the right combination of address prologue and epilogue out of the 256 (!) possibilities. *14CDL ; verbatim logic from $11CD on original ; to set the second and third nibbles ; of the address prologue (at $B95F and ; $B96A in a standard DOS-shaped RWTS) 14CD- 09 00 ORA #$00 14CF- F0 16 BEQ $14E7 14D1- 29 0F AND #$0F 14D3- A8 TAY 14D4- B9 AD 14 LDA $14AD,Y 14D7- 8D 5F B9 STA $B95F 14DA- B9 BD 14 LDA $14BD,Y 14DD- 8D 6A B9 STA $B96A 14E0- 60 RTS ; special case for track 0 14E1- A9 AA LDA #$AA 14E3- 8D 5F B9 STA $B95F 14E6- A9 96 LDA #$96 14E8- 8D 6A B9 STA $B96A 14EB- 60 RTS ; given the sector number (in Y), set ; the expected address epilogues (at ; $B991 and $B99B) from the same lookup ; tables 14EC- B9 AD 14 LDA $14AD,Y 14EF- 8D 91 B9 STA $B991 14F2- B9 BD 14 LDA $14BD,Y 14F5- 8D 9B B9 STA $B99B 14F8- 60 RTS And these two lookup tables are copied verbatim from $11AD and $11BD on the original disk: *14AD.14BC 14AD- .. .. .. .. .. 96 97 9A 14B0- 9B 9D 9E 9F A6 ED EE EF 14B8- F2 F3 F4 F5 F6 *14BD.14CC 14BD- .. .. .. .. .. ED EE EF 14C0- F2 F3 F4 FF F7 96 A6 AA 14C8- D5 DF EA AE FE *BSAVE IOB,A$1400,L$100 ; let's do this thing! *800G There's nothing left to configure, because both the RWTS and our custom IOB are already in memory, so... [press "C" to convert disk] --v-- ADVANCED DEMUFFIN 1.5 (C) 1983, 2014 ORIGINAL BY THE STACK UPDATES BY 4AM =======PRESS ANY KEY TO CONTINUE======= TRK:RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR +.5: 0123456789ABCDEF0123456789ABCDEF012 SC0:................................... SC1:RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR SC2:RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR SC3:RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR SC4:RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR SC5:................................... SC6:RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR SC7:RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR SC8:RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR SC9:RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR SCA:................................... SCB:RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR SCC:RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR SCD:RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR SCE:RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR SCF:................................... ======================================= 16SC $00,$00-$22,$0F BY1.0 S6,D1->S6,D2 --^-- Read errors on 75% of the disk. And not just any 75% -- 12 out of 16 sectors on each track. And not just any 12... I've made a grave error of logic somewhere. Let's back up. ~ Chapter 4 When I Was Young, It Seemed That Life Was So Wonderful, A Miracle Oh It Was Beautiful, Magical It took me a long time to figure out why this didn't work. The logic is impeccable. Every track gets two prologue values from our lookup tables; every sector gets two epilogue values from the same tables. The data field prologues and epilogues are entirely standard, and the nibble translate table that converts the data field from nibbles to bytes is entirely standard. What. Is. The. Difference. Finally I set up the IOB to break into the monitor after reading a sector, so I could examine the RWTS in situ. 141E- A9 0F LDA #$0F 1420- A0 1E LDY #$1E 1422- 20 00 BD JSR $BD00 1425- 4C 59 FF JMP $FF59 <-- ! Then I re-ran Advanced Demuffin and converted a single sector: T01,S01. This is the earliest sector that uses both custom prologues and epilogues. I know the same failure pattern occurs on track 0, but I also know that track 0 is a special case on the original disk. Anyway, that was my thinking. Here's what my RWTS looks like after it fails to read T01,S01: *B94FL B94F- BD 8C C0 LDA $C08C,X B952- 10 FB BPL $B94F B954- C9 D5 CMP #$D5 (1) B956- D0 F0 BNE $B948 B958- EA NOP B959- BD 8C C0 LDA $C08C,X B95C- 10 FB BPL $B959 B95E- C9 97 CMP #$97 (2) B960- D0 F2 BNE $B954 B962- A0 03 LDY #$03 B964- BD 8C C0 LDA $C08C,X B967- 10 FB BPL $B964 B969- C9 EE CMP #$EE (3) B96B- D0 E7 BNE $B954 B96D- A9 00 LDA #$00 B96F- 85 27 STA $27 B971- BD 8C C0 LDA $C08C,X B974- 10 FB BPL $B971 B976- 2A ROL B977- 85 26 STA $26 B979- BD 8C C0 LDA $C08C,X B97C- 10 FB BPL $B979 B97E- 25 26 AND $26 B980- 99 2C 00 STA $002C,Y B983- 45 27 EOR $27 B985- 88 DEY B986- 10 E7 BPL $B96F B988- A8 TAY B989- D0 B7 BNE $B942 B98B- BD 8C C0 LDA $C08C,X B98E- 10 FB BPL $B98B B990- C9 97 CMP #$97 (4) B992- D0 AE BNE $B942 B994- EA NOP B995- BD 8C C0 LDA $C08C,X B998- 10 FB BPL $B995 B99A- C9 EE CMP #$EE (5) B99C- D0 A4 BNE $B942 B99E- 18 CLC B99F- 60 RTS Five values, all as expected: (1) D5 \ (2) 97 } address prologue (3) EE / (4) 97 \ (5) EE / address epilogue And here's what T01,S01 looks like on the original disk: --v-- COPY ][ PLUS BIT COPY PROGRAM 8.4 (C) 1982-9 CENTRAL POINT SOFTWARE, INC. --------------------------------------- TRACK: 01 START: 1800 LENGTH: 3DFF 2138: 96 96 96 96 96 96 96 96 VIEW 2140: 96 D6 DE AA EB FF FF FF 2148: FF FF FF FF FF FF FF FF 2150: FF FF FF FF D5 D5 97 EE ^^^^^^^^ address prologue 2158: AA AB AA AB AA AB AA AB <-215C ^^^^^ ^^^^^ ^^^^^ ^^^^^ V=001 T=$01 S=$01 chksm 2160: 97 EE EB FF FF FF FF FF ^^^^^ address epilogue 2168: FF FF FF D5 AA AD B7 B7 2170: 9D F3 EE AF AE B7 B7 9D FIND: 2178: F3 EE AF AE B7 B7 9D F3 AA AB --------------------------------------- A TO ANALYZE DATA ESC TO QUIT ? FOR HELP SCREEN / CHANGE PARMS Q FOR NEXT TRACK SPACE TO RE-READ --^-- The address prologue is "D5 97 EE", and the address epilogue is "97 EE". What. Is. The. Difference. [...time passes...] [...time passes...] [...it is pitch black...you are likely to be eaten by a grue...] In desperation, I consulted "Beneath Apple DOS," which is actually not a bad choice if you're ever at the point of desperation for any reason. And there, on page 3-23, was the answer that had eluded me. --v-- COMPARISON OF SECTOR SKEWING PHYSICAL | LOGICAL SECTOR | DOS 3.3 ----------+--------- 0 | 0 <-- 1 | 7 2 | E 3 | 6 4 | D 5 | 5 <-- 6 | C 7 | 4 8 | B 9 | 3 A | A <-- B | 2 C | 9 D | 1 E | 8 F | F <-- --^-- The address field on disk contains the metadata for the data that follows: disk volume number, track, sector, and a checksum. But the "sector" is not a logical sector number (that DOS 3.3 expects), but a physical sector number. As shown in the table above, the logical sectors are "skewed" -- out of order, originally thought to provide a good compromise so that sequential decrementing sector reads would be faster. (In fact, this disk's RWTS reads every sector it finds and converts the data field quickly enough that it can read an entire track in one revolution, regardless of the skewing. And DOS 3.3 managed to add an unnecessary memory move so it "misses" the next sector and has to wait an entire disk revolution for it to come around again. This is why Apple DOS 3.3 is so slow and third-party products like Pronto-DOS and Diversi-DOS are so much faster. But never mind that.) The point is this: Advanced Demuffin, calling a DOS-shaped RWTS, deals in logical sectors, but the address field deals in physical sectors. There's a lookup table to convert between them, but in the absence of that conversion, there are only 4 sectors where the physical and logical sector numbers are the same: $00, $05, $0A, and $0F. And those were the sectors that I was able to read -- totally by accident, because the physical and logical sector numbers happened to line up. Now let's take another look at the original disk's RWTS: ; Y = PHYSICAL sector number (just ; parsed from the address field) 09F4- A4 57 LDY $57 09F6- BD 8C C0 LDA $C08C,X 09F9- 10 FB BPL $09F6 ; look up the first epilogue in the ; first lookup table, with the PHYSICAL ; sector number as the index 09FB- D9 AD 11 CMP $11AD,Y 09FE- D0 AB BNE $09AB 0A00- EA NOP 0A01- BD 8C C0 LDA $C08C,X 0A04- 10 FB BPL $0A01 ; and look up the second epilogue in ; the second lookup table, using the ; PHYSICAL sector number as the index 0A06- D9 BD 11 CMP $11BD,Y 0A09- D0 A0 BNE $09AB 0A0B- 18 CLC 0A0C- 60 RTS So there it is. That's the difference. It's only logical. ~ Chapter 5 Then We Shall Make Another! As I mentioned, a standard DOS-shaped RWTS has a lookup table to convert logical to physical sectors, at $BFB8. BFB8- 00 0D 0B 09 07 05 03 01 BFC0- 0E 0C 0A 08 06 04 02 0F So I can add two lines to my IOB code to convert the logical sector numbers I'm using to read from the original disk to the physical sector numbers required to look up the proper address prologues and epilogues in the lookup tables. That sentence was too long, but I don't know how to make it simpler. Sorry. *C500G ... ]BLOAD ADVANCED DEMUFFIN 1.5 ]BLOAD IOB ]CALL -151 14EC- B9 B8 BF LDA $BFB8,Y <-- 14EF- A8 TAY <-- 14F0- B9 AD 14 LDA $14AD,Y 14F3- 8D 91 B9 STA $B991 14F6- B9 BD 14 LDA $14BD,Y 14F9- 8D 9B B9 STA $B99B 14FC- 60 RTS *BSAVE IOB,A$1400,L$100 *800G [press "C" to convert disk] --v-- ADVANCED DEMUFFIN 1.5 (C) 1983, 2014 ORIGINAL BY THE STACK UPDATES BY 4AM =======PRESS ANY KEY TO CONTINUE======= TRK:................................... +.5: 0123456789ABCDEF0123456789ABCDEF012 SC0:................................... SC1:................................... SC2:................................... SC3:................................... SC4:................................... SC5:................................... SC6:................................... SC7:................................... SC8:................................... SC9:................................... SCA:................................... SCB:................................... SCC:................................... SCD:................................... SCE:................................... SCF:................................... ======================================= 16SC $00,$00-$22,$0F BY1.0 S6,D1->S6,D2 --^-- \o/ Hooray! It worked! (I converted side B the same way.) Now I have a 100% standard disk that boots and immediately hangs because it can't read itself, because it's looking for 256 flavors instead of 1. Let's fix that. Turning to my trusty Disk Fixer sector editor, I found the original nibble munger (the subroutine at $11CD) on T00,S09. That entire routine can just be an "RTS". T00,S09,$CD: 09 -> 60 But there's still the matter of the epilogue checking. That code is spread across sectors 1 and 2: T00,S01,$FB -> C9 DE EA T00,S02,$06 -> C9 AA EA ]PR#6 ...boots to title screen, then I press "1" to select a new game, it asks me to flip the disk, I do so, and it refuses to accept that I have done so... That's odd. I used Advanced Demuffin to convert side B, and it converted all tracks, all sectors. It has the same 256-flavors-of-evil structure as the boot disk, but suddenly the RWTS can't read it? On a lark, I inserted the original disk side B, and it worked. Whoa! Curiouser and curiouser. Do it undo my patches to the RWTS? No, a much simpler explanation: there is a second RWTS. Turning to my trusty Disk Fixer sector editor, I searched for the hex sequence "BD 89 C0" and found an entirely separate RWTS on track $03. (It loads into a different range in memory, which I suppose is why it exists. Not just to f--- with me. Not everything is about me.) This second RWTS uses the same basic technique to modify itself just before matching an address field prologue, then using the lookup tables directly to match the address epilogue. Here are the necessary patches (still on side A, the boot disk): ; disable the prologue modifications T03,S0D,$3B: 09 -> 60 ; restore standard epilogue checking T03,S0B,$56 -> C9 DE EA T03,S0B,$61 -> C9 AA EA ]PR#6 ...works, and it is glorious... Quod erat liberandum. ~ Easter Eggs Type "REGRUB" during the scrolling credits on the title page to see a secret screen. Type "BURGER" as a command in the game for an alternate ending. (Save your game first!) --------------------------------------- A 4am crack No. 900 ------------------EOF------------------