---------------Jumble Jet-------------- A 4am crack 2015-06-02 --------------------------------------- Name: Jumble Jet Genre: educational Year: 1984 Authors: Brett W. Sperry, June Stark Publisher: Unicorn Software Media: single-sided 5.25-inch floppy OS: DOS 3.3 with custom bootloader Other versions: none (preserved here for the first time) Similar cracks: Agent U.S.A. (crack no. 306) ~ Chapter 0 In Which Various Automated Tools Fail In Interesting Ways What does the boot look and sound like? 1. immediate blank screen 2. many sequential track reads 3. DOS prompt near top of the screen 4. more disk activity (back and forth like file access) 5. animated graphical title screen Is the disk accessed after boot? Yes, repeatedly. Also, there is an option to initialize a data disk and load/save your own word lists. COPYA immediate disk read error Locksmith Fast Disk Backup unable to read any track EDD 4 bit copy (no sync, no count) read errors on tracks $1C..$22 copy hangs during boot Copy ][+ nibble editor T00 -> standard prologues, modified epilogues (FF FF EB) T01..T02 -> not full tracks? looks like they have some standard-ish sectors, but not 16 per track T01..T0B -> corrupted address fields, claim to be track $00 T0C..T1B -> standard prologues, modified epilogues (FF FF EB) T1C..T22 -> unformatted --v-- COPY ][ PLUS BIT COPY PROGRAM 8.4 (C) 1982-9 CENTRAL POINT SOFTWARE, INC. --------------------------------------- TRACK: 03 START: 2755 LENGTH: 187F ^^ 2730: EB EB E7 F9 FE FF FF FF VIEW 2738: FF FF FF FF FF FF FF FF 2740: FF FF FF FF FF FF FF FF 2748: FF FF FF FF FF FF FF FF 2750: FF FF FF FF FF D5 AA 96 <-2755 ^^^^^^^^ address prologue 2758: FF FE AA AA AA AA FF FE ^^^^^ ^^^^^ ^^^^^ ^^^^^ v254 T00 S00 chksm 2760: FF FF EB FF E7 F9 FE FF ^^^^^^^^ address epilogue 2768: FF FF FF FF D5 AA AD 96 ^^^^^^^^ data prologue 2770: 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 --^-- The disk is lying to me. The address field claims to be track $00, but it's really track $03. Bad disk! Stop lying! Disk Fixer ["O" -> "Input/Output Control"] set Address Epilogue to "FF FF EB" set Data Epilogue to "FF FF EB" T00 readable T01..T0B unreadable (no option to ignore the corrupted address field) T0C..T1B readable T11 looks like DOS 3.3 catalog Copy ][+ sector editor ["P" -> "Sector Editor Patcher"] set type to "CUSTOM" set Address Epilogue to "FF FF" set Data Epilogue to "FF FF EB" T0C..T1B readable ["P" -> "Sector Editor Patcher"] set CHECK TRACK to "NO" T03..T0B readable only parts of T01 and T02 readable: T01: S03,04,05,06,07,0A,0B,0C,0D,0E T02: S01,02,04,08,09,0C,0F Why didn't COPYA work? modified epilogue bytes (every track) Why didn't Locksmith FDB work? modified epilogue bytes (every track) Why didn't my EDD copy work? I don't know. Maybe a nibble check during boot? Next steps: 1. Super Demuffin to convert the tracks that have modified epilogue bytes but are otherwise normal (T00, T0C..T1B) 2. Trace the boot 3. See what happens ~ Chapter 1 In Which We'll Take What We Can Get When you first run Super Demuffin, it asks for the parameters of the original disk. In this case, the prologue bytes are the same, but the epilogues are "FF FF EB" instead of "DE AA EB". --v-- SUPER-DEMUFFIN AND FAST COPY Modified by: The Saltine/Coast to Coast Address prologue: D5 AA 96 Address epilogue: FF FF EB DISK ^^^^^ ORIGINAL change from DE EA----+++++ Data prologue: D5 AA AD Data epilogue: FF FF EB ^^^^^ change from DE AA----+++++ Ignore write errors while demuffining! D - Edit parameters - Advance to next parm - Exit edit mode R - Restore DOS 3.3 parameters O - Edit Original disk's parameters C - Edit Copy disk's parameters G - Begin demuffin process --^-- Pressing "G" switches to the Locksmith Fast Disk Copy UI. It assumes that both disks are in slot 6, and that drive 1 is the original and drive 2 is the copy. [S6,D1=original disk] [S6,D2=blank disk] --v-- LOCKSMITH 7.0 FAST DISK BACKUP R.***********................******* W*********************************** HEX 00000000000000001111111111111111222 TRK 0123456789ABCDEF0123456789ABCDEF012 0.AAAAAAAAAAA................AAAAAAA 1.AAAAAAAAAAA................AAAAAAA 2.AAAAAAAAAAA................AAAAAAA 3.AAAAAAAAAAA................AAAAAAA 4.AAAAAAAAAAA................AAAAAAA 5.AAAAAAAAAAA................AAAAAAA 6.AAAAAAAAAAA................AAAAAAA 7.AAAAAAAAAAA................AAAAAAA 8.AAAAAAAAAAA................AAAAAAA 9.AAAAAAAAAAA................AAAAAAA A.AAAAAAAAAAA................AAAAAAA B.AAAAAAAAAAA................AAAAAAA C.AAAAAAAAAAA................AAAAAAA D.AAAAAAAAAAA................AAAAAAA 12 E.AAAAAAAAAAA................AAAAAAA F.AAAAAAAAAAA................AAAAAAA [ ] PRESS [RESET] TO EXIT --^-- That's about what I expected. It can't read tracks $01-$0B because the address field is intentionally corrupted. It can't read tracks $1C-$22 because they are unformatted. Other than that, it worked great. Let's not try to boot it quite yet, though. [S6,D1=original disk] [S5,D1=my work disk] ]PR#5 CAPTURING BOOT0 ...reboots slot 6... ...reboots slot 5... SAVING BOOT0 ]CALL -151 *800<2800.28FFM *801L ; set reset vector 0801- 8A TXA 0802- 4A LSR 0803- 4A LSR 0804- 4A LSR 0805- 4A LSR 0806- 09 C0 ORA #$C0 0808- 85 3F STA $3F 080A- 8D F3 03 STA $03F3 080D- 49 A5 EOR #$A5 080F- 8D F4 03 STA $03F4 0812- A9 00 LDA #$00 0814- 8D F2 03 STA $03F2 ; hmm 0817- A9 02 LDA #$02 0819- 48 PHA ; machine initialization (memory banks, ; TEXT, HOME, IN#0, PR#0, &c.) 081A- 8D 81 C0 STA $C081 081D- 20 2F FB JSR $FB2F 0820- 8D 52 C0 STA $C052 0823- 20 89 FE JSR $FE89 0826- 20 93 FE JSR $FE93 0829- 20 58 FC JSR $FC58 082C- 8D 51 C0 STA $C051 082F- 8D 54 C0 STA $C054 0832- 8D 52 C0 STA $C052 ; set up ($3E) vector to point to the ; sector read routine in the disk ; controller ROM 0835- A9 5C LDA #$5C 0837- 85 3E STA $3E ; the disk controller ROM always exits ; via $0801, so set that to an RTS so ; we can JSR and not have to set up a ; loop 0839- A9 60 LDA #$60 083B- 8D 01 08 STA $0801 ; hmm 083E- A9 72 LDA #$72 0840- 48 PHA OK, we've now pushed $02/$72 on the stack. That's probably important. ; multi-sector read ; Y = start logical sector ($01) ; X = end logical sector ($07) ; A = start address high byte ($83) 0841- A0 00 LDY #$00 0843- 84 FC STY $FC 0845- C8 INY 0846- A9 83 LDA #$83 0848- A2 07 LDX #$07 ; multi-sector read routine 084A- 20 57 08 JSR $0857 ; another sector read of three more ; sectors ($08, $09, $0A) into $9D00 084D- A9 9D LDA #$9D 084F- A2 0A LDX #$0A 0851- 20 57 08 JSR $0857 ; another sector read, this time just ; one sector, into $0200 (X is already ; less than Y on entry, so loop will ; exit after one read) 0854- A9 02 LDA #$02 0856- AA TAX ; falls through to multi-sector read ; entry point (was also called earlier ; from $084A and $0851) 0857- 85 27 STA $27 0859- E8 INX 085A- 86 49 STX $49 085C- 84 F9 STY $F9 ; map logical into physical sector and ; store it in zero page where the disk ; controller ROM will look for it 085E- B9 75 08 LDA $0875,Y 0861- 85 3D STA $3D ; read sector via disk controller ROM 0863- 20 70 08 JSR $0870 ; loop until done 0866- A4 F9 LDY $F9 0868- C8 INY 0869- C4 49 CPY $49 086B- 90 EF BCC $085C 086D- A5 27 LDA $27 086F- 60 RTS 0870- A6 2B LDX $2B 0872- 6C 3E 00 JMP ($003E) 0875- [00 03 05 07 09 0B 0D 0F] [02 04 06 08 0A 0C 0E 01] That's it. Flexible but compact. It's a weird combination of reads, though. Some stuff at $8300. A bit at $9D00. One page at $0200. Of course, we manually pushed $02/$72 on the stack earlier, so once we fall through to the sector read routine and it hits the RTS at $086F, it will "return" to $0272+1 = $0273. Let's interrupt the boot before it gets there. ~ Chapter 2 In Which Things Get Brilliantly Weird *9600physical sectors is at ; $0263) or a physical sector 021D- 24 4A BIT $4A 021F- 30 03 BMI $0224 0221- B9 63 02 LDA $0263,Y ; store physical sector in $3D (again, ; used by the disk controller ROM) 0224- 85 3D STA $3D ; read sector by jumping to ($003E), ; which points to $Cx5C (e.g. $C65C if ; booting from slot 6) and exit via ; $0801, which is an RTS by now, so ; this just continues to the next line 0226- 20 00 02 JSR $0200 ; increment sector index 0229- A4 F9 LDY $F9 022B- C8 INY ; are there more sectors to read? 022C- C4 49 CPY $49 ; yes, branch back and repeat 022E- 90 EA BCC $021A ; no, exit with last page (+1) in A ; (disk controller ROM increments this ; after storing sector data, so on exit ; this will be the first page that was ; NOT filled with data in this loop) 0230- A5 27 LDA $27 0232- 60 RTS We called this routine at $02B0 with A=$8A, Y=$01, and X=$05, so that read sectors $01..$05 into $8A00..$8EFF. Continuing... *2B3L ; move the drive head one phase only, ; to the next HALF track 02B3- 20 36 02 JSR $0236 ; read more sectors ($06..$0A) from ; track 1.5 02B6- A2 0A LDX #$0A 02B8- 20 15 02 JSR $0215 ; advance another half track 02BB- 20 36 02 JSR $0236 ; read more sectors ($0B..$0F) from ; track 2 02BE- A2 0F LDX #$0F 02C0- 20 15 02 JSR $0215 ; fiddle with $4A again 02C3- 46 4A LSR $4A 02C5- 60 RTS So here's the deal with $4A: we initialized it at $0273 by a blind LSR, which clears the high bit. This tells the multi-sector read routine at $0215 to use logical sectors. Then we set the high bit at $02A7 with SEC + ROR, indicating we want $0215 to read physical sectors. Then we read a few sectors from track 1, a few from track 1.5, and a few from track 2. Then we reset $4A with another LSR, and we're back to using logical sectors. This explains why my EDD bit copy failed. This disk is storing data on half tracks. Worse, it's storing data on *adjacent* half tracks -- a few on track 1, a few on track 1.5, and a few on track 2. Due to limitations of the Disk II drive mechanism, that would be virtually impossible for a generic bit copier to reproduce on a blank floppy. Continuing... *278L 0278- A9 13 LDA #$13 027A- 20 08 02 JSR $0208 027D- 20 05 02 JSR $0205 *205L ; This is a fascinating and compact ; way to read multiple tracks -- just ; call one of these lines ($0205, ; $0208, or $020B) and have them call ; the "read entire track" routine at ; $020E (which itself falls through to ; the "read partial track" routine at ; $0215) and keep falling through until ; it finally hits the RTS at $0232 and ; returns to the caller. 0205- 20 0E 02 JSR $020E 0208- 20 0E 02 JSR $020E 020B- 20 0E 02 JSR $020E 020E- 20 33 02 JSR $0233 0211- A2 0F LDX #$0F 0213- A0 00 LDY #$00 0215- 85 27 STA $27 0217- E8 INX 0218- 86 49 STX $49 021A- 84 F9 STY $F9 021C- 98 TYA 021D- 24 4A BIT $4A 021F- 30 03 BMI $0224 0221- B9 63 02 LDA $0263,Y 0224- 85 3D STA $3D 0226- 20 00 02 JSR $0200 0229- A4 F9 LDY $F9 022B- C8 INY 022C- C4 49 CPY $49 022E- 90 EA BCC $021A 0230- A5 27 LDA $27 0232- 60 RTS So the first call, to $0208, will read three tracks into $1300..$32FF. The accumulator holds the starting page on entry, and $0230 loads the accumulator with the next page on exit, so you can just chain calls as often as you like to read multiple tracks into memory. The second call, to $0205, reads an additional four tracks, picking up where the previous read left off (at $3300). Every part of this code is brilliant. AND it fits in a single sector in low memory. AND it's flexible enough to read from virtually uncopyable disks. Continuing... *280L 0280- 20 C6 02 JSR $02C6 ; read two tracks into $A000..$BFFF 02C6- A9 A0 LDA #$A0 02C8- 4C 0B 02 JMP $020B *283L ; now put slot number (x16) into... ; an RWTS parameter table?!? 0283- A6 2B LDX $2B 0285- 8E E9 B7 STX $B7E9 ; turn off drive motor 0288- BD 88 C0 LDA $C088,X ; set up DOS globals (tracking where ; the drive head is) 028B- 20 8E BE JSR $BE8E 028E- A5 FC LDA $FC 0290- 99 78 04 STA $0478,Y 0293- 4A LSR 0294- 8D 78 04 STA $0478 ; push $B7/$01 on the stack 0297- A9 B7 LDA #$B7 0299- 48 PHA 029A- A9 01 LDA #$01 029C- 48 PHA ; and exit through HOME 029D- 4C 58 FC JMP $FC58 Execution continues at $B702 (because we just pushed $B7/$01 on the stack). ~ Chapter 4 In Which All Is Laid Bare I can interrupt the boot by changing the values pushed on the stack at $0297 and $029A. *9600 *2300<1300.1FFFM *C500G ... ]BSAVE BOOT2 1300-1FFF,A$2300,L$D00 ]BRUN TRACE2 ...reboots slot 6... ...read read read... *C500G ... ]BSAVE BOOT2 2000-5FFF,A$2000,L$4000 ]BRUN TRACE2 ...reboots slot 6... ...read read read... *2000<6000.9FFFM *C500G ... ]BSAVE BOOT2 6000-9FFF,A$2000,L$4000 ]BRUN TRACE2 ...reboots slot 6... ...read read read... *B702L ; literally just an "RTS" B702- 20 00 BB JSR $BB00 ; zero page $3F was set way back in ; boot0 (at $0808) to be the boot slot ; in $Cx format B705- A5 3F LDA $3F B707- 8D 01 B7 STA $B701 B70A- EA NOP B70B- EA NOP B70C- EA NOP B70D- EA NOP B70E- 4C 3B B7 JMP $B73B *B73BL B73B- A2 FF LDX #$FF B73D- 9A TXS B73E- 8E EB B7 STX $B7EB B741- 20 69 BA JSR $BA69 B744- 20 89 FE JSR $FE89 B747- 4C 84 9D JMP $9D84 At this point, we have a full copy of DOS 3.3 in memory, albeit put there in the most roundabout way. Spot checking the RWTS, it's perfectly normal except it expects "FF FF EB" epilogue bytes. Which, by the way, is just the sort of RWTS that could read tracks $0C-$1B. Let me save this last chunk before I forget. *2000