--------------The Playroom------------- A 4am crack 2015-02-14 --------------------------------------- Name: The Playroom Version: 1.0 Genre: educational Year: 1989 Authors: Leslie Grimm, Dennis Caswell, Lynn Kirkpatrick, D. Buttlaire, D. Albrecht Publisher: Broderbund Software, Inc. OS: ProDOS (unknown version) Media: two double-sided 5.25-inch floppy disks Other versions: Asimov archive has an uncredited crack of the 3.5-inch version; the 5.25-inch version is preserved here for the first time Disk 1 has sides "A" and "B"; disk 2 has sides "C" and "D". The game refers to the sides by letter. Only side A is bootable, so I'll start there. ~ Chapter 0 In Which Various Automated Tools Fail In Interesting Ways COPYA no errors, but copy displays the Broderbund splash screen then exits to the ProDOS program selector Locksmith Fast Disk Backup ditto EDD 4 bit copy (no sync, no count) ditto Copy ][+ nibble editor nothing unusual Disk Fixer T00 looks like ProDOS T00,S0B has a ProDOS disk catalog Why didn't my copies work? Probably a nibble check in the first SYSTEM file after displaying the splash screen Next steps: 1. Boot up a ProDOS hard drive and get a catalog listing 2. Find nibble check and bypass it 3. There is no step 3 ~ Chapter 1 In Which We Learn That Compatibility Checking Got Really Complicated By 1989 [S6,D1=original disk, side A] [S7,D1=my ProDOS hard drive] ]PR#7 ]CAT,S6,D1 /PLAYROOM NAME TYPE BLOCKS MODIFIED PRODOS SYS 32 26-SEP-89 PLAYROOM.SYSTEM SYS 14 28-JAN-90 PARAMETERS BIN 1 29-JAN-90 TITLE.PAC BIN 16 1-NOV-89 TOOLKIT DIR 1 PLAYROOM DIR 1 INSERTA.PAC BIN 5 12-AUG-89 INSERTD.PAC BIN 5 12-AUG-89 INSERTC.PAC BIN 5 13-AUG-89 INSERTB.PAC BIN 5 12-AUG-89 *,,,,,, $AC 44032 BLOCKS FREE: 41 BLOCKS USED: 239 Some weirdness at the end of the disk catalog, but the files look accessible. ProDOS always loads the first .SYSTEM file at $2000 and jumps to it. ]PREFIX /PLAYROOM ]BLOAD PLAYROOM.SYSTEM,A$2000,TSYS ]CALL -151 *2000L 2000- 2C 82 C0 BIT $C082 2003- 20 58 FC JSR $FC58 2006- A9 00 LDA #$00 2008- 8D CF 03 STA $03CF ; standard machine identification logic ; c.f. "Apple II Family Identification" ; technote 200B- AD B3 FB LDA $FBB3 200E- C9 06 CMP #$06 2010- D0 35 BNE $2047 2012- 38 SEC 2013- 20 1F FE JSR $FE1F 2016- 90 5C BCC $2074 2018- AD C0 FB LDA $FBC0 201B- D0 2A BNE $2047 My enhanced Apple //e branched here, so I'll continue at $2047. *2047L ; test for AUX memory (128K) 2047- 8D 01 C0 STA $C001 204A- 2C 55 C0 BIT $C055 204D- A9 88 LDA #$88 204F- AC 00 04 LDY $0400 2052- 8D 00 04 STA $0400 2055- AD 00 04 LDA $0400 2058- 8C 00 04 STY $0400 205B- 2C 54 C0 BIT $C054 205E- 8D 00 C0 STA $C000 2061- C9 88 CMP #$88 2063- D0 D3 BNE $2038 ; moving code to zero page? suspicious 2065- A2 2A LDX #$2A 2067- BD 98 20 LDA $2098,X 206A- 95 7F STA $7F,X 206C- CA DEX 206D- D0 F8 BNE $2067 206F- 4C 80 00 JMP $0080 *206F:60 *2000G *80L ; false alarm, it's more compatibility ; checking (for double hi-res graphics, ; I think) 0080- 8D 03 C0 STA $C003 0083- 8D 05 C0 STA $C005 0086- A9 EE LDA #$EE 0088- 8D 00 08 STA $0800 008B- AD 00 0C LDA $0C00 008E- C9 EE CMP #$EE 0090- D0 0E BNE $00A0 0092- 0E 00 0C ASL $0C00 0095- AD 00 08 LDA $0800 0098- CD 00 0C CMP $0C00 009B- D0 03 BNE $00A0 009D- 38 SEC 009E- B0 01 BCS $00A1 00A0- 18 CLC 00A1- 8D 02 C0 STA $C002 00A4- 8D 04 C0 STA $C004 00A7- 4C 72 20 JMP $2072 *2072L ; branch if test on zero page failed 2072- B0 C4 BCS $2038 Boy, compatibility checking had gotten complicated by 1989. ; memory move $20EB --> $6000 2074- A2 1A LDX #$1A 2076- A9 EB LDA #$EB 2078- 85 28 STA $28 207A- A9 20 LDA #$20 207C- 85 29 STA $29 207E- A9 00 LDA #$00 2080- 85 2A STA $2A 2082- A9 60 LDA #$60 2084- 85 2B STA $2B 2086- A0 00 LDY #$00 2088- B1 28 LDA ($28),Y 208A- 91 2A STA ($2A),Y 208C- C8 INY 208D- D0 F9 BNE $2088 208F- E6 29 INC $29 2091- E6 2B INC $2B 2093- CA DEX 2094- D0 F2 BNE $2088 2096- 4C 00 60 JMP $6000 *2096:4C 59 FF *2074G *6000L ; activate 80-column mode 6000- 2C 10 C0 BIT $C010 6003- 2C 82 C0 BIT $C082 6006- 20 00 C3 JSR $C300 ; set reset vector 6009- A9 69 LDA #$69 600B- 8D F2 03 STA $03F2 600E- A9 FF LDA #$FF 6010- 8D F3 03 STA $03F3 6013- 49 FF EOR #$FF 6015- 8D F4 03 STA $03F4 ; setting up for double hi-res splash ; screen 6018- 8D 57 C0 STA $C057 601B- 8D 52 C0 STA $C052 601E- 8D 5E C0 STA $C05E 6021- 8D 0D C0 STA $C00D 6024- 8D 00 C0 STA $C000 6027- 8D 02 C0 STA $C002 602A- 8D 04 C0 STA $C004 602D- 8D 08 C0 STA $C008 6030- 2C 54 C0 BIT $C054 6033- A2 17 LDX #$17 6035- BD DE 62 LDA $62DE,X 6038- 9D 58 BF STA $BF58,X 603B- CA DEX 603C- 10 F7 BPL $6035 603E- A2 3F LDX #$3F 6040- BD 80 02 LDA $0280,X 6043- 9D 0B 63 STA $630B,X 6046- CA DEX 6047- 10 F7 BPL $6040 6049- AE 0B 63 LDX $630B 604C- F0 18 BEQ $6066 604E- BD 0B 63 LDA $630B,X 6051- 29 7F AND #$7F 6053- C9 2F CMP #$2F 6055- F0 05 BEQ $605C 6057- CA DEX 6058- D0 F4 BNE $604E 605A- F0 0A BEQ $6066 605C- CA DEX 605D- 8E 0B 63 STX $630B ; call ProDOS MLI with "set prefix" ; command ($C6) 6060- 20 00 BF JSR $BF00 6063- [C6 CB 62] ; call ProDOS MLI with "get prefix" ; commadn ($C7) 6066- 20 00 BF JSR $BF00 6069- [C7 CB 62] ; clear both hi-res screens 606C- 8D 01 C0 STA $C001 606F- 2C 55 C0 BIT $C055 6072- 20 4E 62 JSR $624E 6075- 2C 54 C0 BIT $C054 6078- 20 4E 62 JSR $624E ; and show it 607B- 2C 50 C0 BIT $C050 ; subroutine at $6262 opens, reads, and ; closes a file using ProDOS MLI calls ; based on the pathname given at the ; address immediately following the JSR 607E- A9 00 LDA #$00 6080- A2 08 LDX #$08 6082- 20 62 62 JSR $6262 6085- [56 63] --> "toolkit/toolkitz.o" 6087- A9 0C LDA #$0C 6089- 85 3C STA $3C 608B- A9 6D LDA #$6D 608D- 85 3D STA $3D ; nothing interesting 608F- 20 F9 09 JSR $09F9 ; another file read 6092- A9 00 LDA #$00 6094- A2 08 LDX #$08 6096- 20 62 62 JSR $6262 6099- [69 63] --> "parameters" ; display Broderbund screen (animated) 609B- AD 03 08 LDA $0803 609E- 48 PHA 609F- 20 8A 09 JSR $098A 60A2- 68 PLA 60A3- C9 FF CMP #$FF 60A5- F0 0E BEQ $60B5 60A7- 20 93 09 JSR $0993 60AA- 90 09 BCC $60B5 60AC- AD 03 08 LDA $0803 60AF- 4A LSR 60B0- 29 C0 AND #$C0 60B2- 4C A7 60 JMP $60A7 60B5- AD 03 08 LDA $0803 60B8- 20 93 09 JSR $0993 ; set machine speed (on IIgs) 60BB- 20 9C 09 JSR $099C ; load more files 60BE- A9 01 LDA #$01 60C0- 8D 01 08 STA $0801 60C3- AD 00 08 LDA $0800 60C6- F0 0C BEQ $60D4 60C8- A9 00 LDA #$00 60CA- A2 40 LDX #$40 60CC- 20 62 62 JSR $6262 60CF- [92 63] --> "inserta.pac" 60D1- 4C DD 60 JMP $60DD 60D4- A9 00 LDA #$00 60D6- A2 40 LDX #$40 60D8- 20 62 62 JSR $6262 60DB- [9E 63] --> "insert3.pac" ; execution always continues here 60DD- 20 F6 09 JSR $09F6 60E0- [00 00 40 04 00 D0 00 0D] 60E8- 20 D8 09 JSR $09D8 ; "set prefix" again 60EB- 20 00 BF JSR $BF00 60EE- [C6 CE 62] 60F1- 90 0D BCC $6100 . . . 6100- AD 00 08 LDA $0800 6103- D0 50 BNE $6155 *800 0800- FF (I think this is a flag that differs between the 5.25-inch and 3.5-inch versions.) *6155L ; save slot+drive 6155- AD 30 BF LDA $BF30 6158- 8D D2 62 STA $62D2 ; raw disk read (suspicious) 615B- 20 00 BF JSR $BF00 615E- [80 D1 62] 6161- B0 D8 BCS $613B *613BL 613B- 2C 51 C0 BIT $C051 613E- 20 00 C3 JSR $C300 6141- 2C 82 C0 BIT $C082 6144- AD CF 03 LDA $03CF 6147- F0 06 BEQ $614F 6149- A9 01 LDA #$01 614B- 48 PHA 614C- 20 C7 C7 JSR $C7C7 ; call ProDOS quit handler 614F- 20 00 BF JSR $BF00 6152- [65 D7 62] OK, $613B is The Badlands. We do not want to end up at $613B. *6163L ; set machine speed (on IIgs) 6163- 20 9C 09 JSR $099C ; munge slot+drive (ProDOS format) ; into slot x 16 and store it in $2B ; (mildly suspicious -- ProDOS doesn't ; ever need this) 6166- AD D2 62 LDA $62D2 6169- 29 70 AND #$70 616B- 85 2B STA $2B ; don't know what this does yet 616D- 20 B9 63 JSR $63B9 ; ...but if it fails, it's fatal 6170- B0 C9 BCS $613B I smell a nibble check. ~ Chapter 2 In Which We Run Into An Old Friend, And Our Adventure Comes To A Satisfying End *63B9L ; save zero page 63B9- A2 F0 LDX #$F0 63BB- B5 00 LDA $00,X 63BD- 9D 00 BA STA $BA00,X 63C0- E8 INX 63C1- D0 F8 BNE $63BB ; initialize the Death Counter 63C3- A9 0A LDA #$0A 63C5- 85 F4 STA $F4 ; turn on drive motor manually (always ; suspicious) 63C7- A6 2B LDX $2B 63C9- BD 89 C0 LDA $C089,X 63CC- BD 8E C0 LDA $C08E,X ; init low byte of the Death Counter 63CF- A9 80 LDA #$80 63D1- 85 F5 STA $F5 63D3- C6 F5 DEC $F5 ; if the Death Counter hits 0, fail 63D5- F0 5D BEQ $6434 ; position drive head over magic nibble ; sequence 63D7- 20 5B 64 JSR $645B ; if that didn't work, fail 63DA- B0 58 BCS $6434 63DC- A5 F1 LDA $F1 63DE- C9 07 CMP #$07 63E0- D0 F1 BNE $63D3 ; Search for a specific sequence of ; nibbles in the "dead zone" between ; the address field and data field. ; This area is normally not important, ; so COPYA didn't copy it precisely ; because normal disks don't care. ; (Actually, it's even more evil than ; that, because the original disk is ; written with timing bits in specific ; non-standard places between the ; nibbles in the dead zone. This code ; not only requires the right nibbles ; in the right order, it reads them ; just slightly slower than normal. So ; the timing bits need to be in the ; right places too, or else this code ; will read the wrong nibble values ; while it's out of sync. This will ; trip up even the best bit copiers. ; And you can forget about making a ; disk image for emulators -- those ; don't store timing bits at all.) 63E2- A0 00 LDY #$00 63E4- BD 8C C0 LDA $C08C,X 63E7- 10 FB BPL $63E4 63E9- 88 DEY 63EA- F0 48 BEQ $6434 ; fail 63EC- C9 D5 CMP #$D5 63EE- D0 F4 BNE $63E4 ; fail 63F0- A0 00 LDY #$00 63F2- BD 8C C0 LDA $C08C,X 63F5- 10 FB BPL $63F2 63F7- 88 DEY 63F8- F0 3A BEQ $6434 ; fail 63FA- C9 E7 CMP #$E7 63FC- D0 F4 BNE $63F2 63FE- BD 8C C0 LDA $C08C,X 6401- 10 FB BPL $63FE 6403- C9 E7 CMP #$E7 6405- D0 2D BNE $6434 ; fail 6407- BD 8C C0 LDA $C08C,X 640A- 10 FB BPL $6407 640C- C9 E7 CMP #$E7 640E- D0 24 BNE $6434 ; fail ; kill some time to get out of sync ; with the "proper" start of nibbles) 6410- BD 8D C0 LDA $C08D,X 6413- A0 10 LDY #$10 6415- 24 06 BIT $06 ; now start looking for nibbles that ; don't really exist (except they do, ; because we're out of sync and reading ; timing bits as data) 6417- BD 8C C0 LDA $C08C,X 641A- 10 FB BPL $6417 641C- 88 DEY 641D- F0 15 BEQ $6434 ; fail 641F- C9 EE CMP #$EE 6421- D0 F4 BNE $6417 ; check for nibble sequence stored ; in reverse order at $6453 6423- A0 07 LDY #$07 6425- BD 8C C0 LDA $C08C,X 6428- 10 FB BPL $6425 642A- D9 53 64 CMP $6453,Y 642D- D0 05 BNE $6434 642F- 88 DEY 6430- 10 F3 BPL $6425 6432- 30 03 BMI $6437 ; failure path is here, jumps below 6434- 4C 47 64 JMP $6447 ; success path continues here -- ; restore zero page 6437- A0 F0 LDY #$F0 6439- B9 00 BA LDA $BA00,Y 643C- 99 00 00 STA $0000,Y 643F- C8 INY 6440- D0 F7 BNE $6439 ; turn off drive motor 6442- BD 88 C0 LDA $C088,X ; clear carry and exit via RTS 6445- 18 CLC 6446- 60 RTS ; failure path continues here -- ; decrement Death Counter, eventually ; give up 6447- C6 F4 DEC $F4 6449- F0 03 BEQ $644E 644B- 4C CF 63 JMP $63CF ; final failure path -- turn off drive ; motor, set carry, and exit via RTS 644E- BD 88 C0 LDA $C088,X 6451- 38 SEC 6452- 60 RTS This nibble check clears the carry on success and sets the carry on failure, and it returns either way. There are no other side effects. I can change it to unconditionally clear the carry and exit, and the caller will be none the wiser. T05,S0B,$A4 change "A2 F0" to "18 60" Sides B, C, and D are unprotected. Quod erat liberandum. --------------------------------------- A 4am crack No. 225 ------------------EOF------------------