----------The Queen of Phobos---------- A 4am crack 2018-03-18 --------------------------------------- Name: The Queen of Phobos Genre: adventure Year: 1982 Credits: story & artwork by William R. Crawford; programming by Paul L. Berker; thanks to Dav Holle & Adrian Ferret Publisher: Phoenix Software Platform: Apple ][+ or later Media: 5.25-inch disk Sides: 1 OS: custom Previous cracks: none (Asimov has an uncracked .nib image) ~ Chapter 0 In Which Various Automated Tools Fail In Interesting Ways COPYA - immediate disk read error - 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 - T00-T1A have modified epilogues ($ED ** instead of $DE $AA) - some tracks (2, 3, 6, 7, &c.) also have modified address prologue ($D4 $AA $96 instead of $D5 $AA $96) - T1B+ unformatted (hi-res disk scan confirms this) Disk Fixer - T00 -> custom bootloader - ignoring epilogues, I can read 0, 1, 4, 5, ... - using address prologue $D4 $AA $96, I can read the other tracks as well (2, 3, 6, 7, ...) - no sign of DOS, disk catalog, or any normalcy - disk volume is $00, which is probably going to be significant given who was mentioned on the credits page (Dav Holle, who wrote the protection for Thunderbombs and Crime Wave -- see cracks #1697 and #1676 for details) Why didn't COPYA work? hahahahahahahahaha Why didn't Locksmith FDB work? ditto EDD worked. What does that tell us? Probably no nibble check, quarter tracks, half tracks, spiral tracks, timing bits. Just a custom bootloader and a flexible RWTS that accepts both $D4 and $D5. Next steps: 1. Passport to convert the disk to a standard format (normalizing the prologues and epilogues) 2. Patch the RWTS to read standard prologues and epilogues (might not even be necessary, depending on how it's written) 3. Declare victory (*) (*) go to the gym ~ Chapter 1 In Which Our Automated Tools Take Us Just About As Far As They Can The 2017-12-27 development version of Passport successfully auto-converted the disk to a standard format. The built-in RWTS was designed to read this kind of alternating D4/D5 prologue (it was very common), and the adaptive RWTS correctly determined the first epilogue nibble (DA) and enforced it on the rest of the sectors. All in all, I have high confidence in the integrity of this conversion. Here is the Passport transcript: --v-- READING FROM S6,D1 USING BUILT-IN RWTS T22 IS UNFORMATTED WRITING TO RAM DISK T21 IS UNFORMATTED T20 IS UNFORMATTED T1F IS UNFORMATTED T1E IS UNFORMATTED T1D IS UNFORMATTED T1C IS UNFORMATTED T1B IS UNFORMATTED WRITING TO S5,D2 THE DISK WAS COPIED SUCCESSFULLY, BUT PASSPORT DID NOT APPLY ANY PATCHES. --^-- The copy that Passport produces can not read itself, which is not entirely unexpected. It is most likely enforcing the custom $ED epilogue, which is now the standard $DE $AA $EB. A quick sector search for "BD 8C C0" (the 6502 opcode for "LDA $C08C,X", which reads the data latch from a drive indexed by the X register) finds two clusters of RWTS code. That's one more RWTS than I was hoping for, but okay. --v-- ------------- DISK SEARCH ------------- $00/$0D-$26 $00/$0D-$30 $00/$0D-$3B $00/$0D-$76 $00/$0D-$8C $00/$0D-$97 $00/$0D-$A2 $00/$0D-$AF $00/$0D-$B7 $00/$0D-$C9 $04/$04-$01 $04/$04-$0B $04/$04-$15 $04/$04-$90 $04/$04-$A4 $04/$05-$1C $04/$05-$32 $04/$05-$54 $04/$05-$66 $04/$05-$71 $04/$05-$7C $04/$05-$89 $04/$05-$91 $04/$05-$A4 $04/$06-$C7 --^-- The code on T00,S0D is straightforward. As I expected, it matches a single $ED for the epilogue of both the address and data fields. --v-- T00,S0D ----------- DISASSEMBLY MODE ---------- ; match data field epilogue 006C:BC 8C C0 LDY $C08C,X 006F:10 FB BPL $006C 0071:D9 D6 02 LDA $02D6,Y 0074:D0 09 BNE $007F 0076:BD 8C C0 LDA $C08C,X 0079:10 FB BPL $0076 007B:C9 ED CMP #$ED <-- ! 007D:F0 53 BEQ $00D2 007F:38 SEC 0080:60 RTS ... ; parse address field into $F7..$FA in ; zero page 00B7:BD 8C C0 LDA $C08C,X 00BA:10 FB BPL $00B7 00BC:25 F4 AND $F4 00BE:99 F7 00 STA $00F7,Y 00C1:45 F5 EOR $F5 00C3:88 DEY 00C4:10 E7 BPL $00AD 00C6:A8 TAY 00C7:D0 B6 BNE $007F ; match address field epilogue 00C9:BD 8C C0 LDA $C08C,X 00CC:10 FB BPL $00C9 00CE:C9 ED CMP #$ED <-- ! 00D0:D0 AD BNE $007F 00D2:18 CLC 00D3:60 RTS --^-- While we're admiring custom RWTS code, I want to point out this beauty, which I've never seen done quite this way before: --v-- ; match $D4 or $D5 for the first nibble ; of the address prologue 008C:BD 8C C0 LDA $C08C,X 008F:10 FB BPL $008C 0091:09 01 ORA #$01 <-- ! 0093:C9 D5 CMP #$D5 0095:D0 EE BNE $0085 --^-- The more common technique takes the nibble from the data latch and LSRs it, then compares it to #$6A. That will match both $D4 and $D5. But "ORA #$01" plus "CMP #$D5" accomplishes the same thing in the same number of CPU cycles. ~ Chapter 2 In Which It Pays To Pay Attention Patching the two epilogue nibbles T00,S0D,$7C: ED -> DE T00,S0D,$CF: ED -> DE is necessary but not sufficient. My copy still refuses to boot, making no more progress than before I reset the epilogues. It's not clear why. But I have a secret weapon: knowledge of other Dav Holle protections. Do you remember that the disk volume was 000 on the original disk? Dav enjoys using that for unrelated purposes. The address field parser stored each sector's address field values into zero page $F7..$FA. That means the disk volume will end up in $FA. A quick search for "A5 FA" finds that, indeed, the RWTS is using this value and assuming it is zero. (It isn't; on my copy, the disk volume number is the default, 254.) --v-- T00,S0D ----------- DISASSEMBLY MODE ----------- ; last nibble of data prologue 0039:A0 56 LDY #$56 003B:BD 8C C0 LDA $C08C,X 003E:10 FB BPL $003B 0040:C9 AD CMP #$AD 0042:D0 E7 BNE $002B ; beginning of data field decoding 0044:A5 FA LDA $FA <-- ! 0046:E6 00 INC $00 0048:88 DEY 0049:84 F4 STY $F4 004B:BC 8C C0 LDY $C08C,X 004E:10 FB BPL $004B 0050:59 D6 02 EOR $02D6,Y --^-- Aha! We are using the disk volume in $FA to initialize the checksum for the data field. Since my disk volume is no longer 000, this custom RWTS is using the wrong initial checksum (254) and thinks that every sector is damaged. The solution is to initialize the accumulator with #$00 as a constant, instead of relying on the (unrelated) disk volume number. T00,S0D,$44: A5FA -> A900 Now my copy boots much further -- all the way to displaying the graphical title page! Then it starts grinding. It's almost like there are two RWTS--- oh, right. There are. ~ Chapter 3 In Which It Looks Like Everything Is Going To Go Right For Five Minutes My initial scan for "BD 8C C0" found two clusters of RWTS-looking code. The first, on track 0, appears to be sufficiently patched now. But it also appears that it's only used for the initial load, as far as the title page, before control transfers to the second RWTS on track 4. Sure enough, the second RWTS on track 4 is just as strict about enforcing the non-standard epilogues: --v-- T04,S04 ----------- DISASSEMBLY MODE ---------- ; match data field epilogue 0090:BD 8C C0 LDA $C08C,X 0093:10 FB BPL $0090 0095:C9 ED CMP #$ED <-- ! 0097:D0 02 BNE $009B 0099:18 CLC 009A:24 38 BIT $38 009C:68 PLA 009D:A0 55 LDY #$55 009F:91 10 STA ($10),Y 00A1:60 RTS ... [continued on T04,S05] ; parse address field into $18..$1B ; in zero page 0091:BD 8C C0 LDA $C08C,X 0094:10 FB BPL $0091 0096:25 03 AND $03 0098:99 18 00 STA $0018,Y 009B:45 02 EOR $02 009D:88 DEY 009E:10 E7 BPL $0087 00A0:A8 TAY 00A1:D0 1E BNE $00C1 00A3:EA NOP ; match address field epilogue 00A4:BD 8C C0 LDA $C08C,X 00A7:10 FB BPL $00A4 00A9:C9 ED CMP #$ED <-- ! 00AB:D0 14 BNE $00C1 00AD:18 CLC 00AE:60 RTS --^-- But wait! This second RWTS also does the same trick of relying on the disk volume number (now in zero page $1B): --v-- T04,S04 ----------- DISASSEMBLY MODE ---------- 0001:BD 8C C0 LDA $C08C,X 0004:10 FB BPL $0001 0006:49 D5 EOR #$D5 0008:D0 F4 BNE $FFFE 000A:EA NOP 000B:BD 8C C0 LDA $C08C,X 000E:10 FB BPL $000B 0010:C9 AA CMP #$AA 0012:D0 F2 BNE $0006 0014:EA NOP 0015:BD 8C C0 LDA $C08C,X 0018:10 FB BPL $0015 001A:C9 AD CMP #$AD 001C:D0 E8 BNE $0006 001E:A0 AA LDY #$AA 0020:A5 1B LDA $1B <-- ! 0022:E6 4E INC $4E 0024:85 03 STA $03 0026:AE 8C C0 LDX $C08C 0029:10 FB BPL $0026 002B:BD 00 B7 LDA $B700,X 002E:99 56 02 STA $0256,Y 0031:45 03 EOR $03 --^-- Furthermore, this is a full read/write RWTS, so there are additional instances of $ED in the disk writing code that will also need to be reset to $DE. All told: T04,S05,$A9: ED -> DE ; addr read T04,S04,$96: ED -> DE ; data read T04,S06,$B5: ED -> DE ; addr write T04,S05,$45: ED -> DE ; data write T04,S04,$20: A51B -> A900 ; disk volume ]PR#6 ...boots into game, everything works... Except... ~ Chapter 4 In Which Everything Goes Wrong Again, Very Rapidly The first thing I did in-game is push the button on my ship's console. It is supposed to do this: --v-- **>COMMAND? PUSH BUTTON A VOICE CRACKLES OVER THE RADIO:'WHAT ARE YOU DOING SITTING IN YOUR SHIP?! GET THAT MASK!' --^-- On the original disk, it stops there. But on my copy, it continues... --v-- SUDDENLY, THE WALLS AROUND YOU DISSOLVE IN A SHEET OF NUCLEAR FIRE, AND YOU FEEL THE FLESH MELTING FROM YOUR BONES. YOU HAVE JUST GIVEN YOUR LIFE FOR YOUR PLANET. PRESS [RETURN] TO RESTART. --^-- If the game detects you're using a pirated copy, it literally melts your flesh off. That's great. DRM is great. On a hunch, I went back to my trusty sector editor and searched for "A5 1B" (the instruction to get the disk volume number, as stored in zero page by the RWTS on track 4). And I got a hit, not on track 4, but far away on track 8. --v-- T08,S01 ----------- DISASSEMBLY MODE ---------- 00FA:A5 1B LDA $1B 00FC:F0 0C BEQ $010A 00FE:A9 01 LDA #$01 --^-- I don't even know where the rest of this code is. (It doesn't appear to continue on either T08,S00 or T08,S02.) But it is most definitely checking if zero page $1B is 0 and going down two different code paths. So, maybe... T08,S01,$FA: A51B -> A900 ]PR#6 ...no longer melts your flesh off... Quod erat liberandum. ~ Acknowledgments Thanks to Ian Baronofsky for lending me original disk. --------------------------------------- A 4am crack No. 1723 ------------------EOF------------------