-----------Spelling Carnival----------- A 4am crack 2015-06-14 --------------------------------------- Name: Spelling Carnival Genre: educational Year: 1981 Authors: Marley W. Watkins Publisher: Softsmith 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: Microzine 3 (no. 332) ~ Chapter 0 In Which Various Automated Tools Fail In Interesting Ways What does the boot look and sound like? 1. Softsmith animated title screen 2. several sequential track reads 3. track seek (maybe to T11?) 4. more disk activity (back and forth like file access) 5. program title screen 6. main menu Does it access the disk after boot? Yes, repeatedly. Does it have an option to read, write, or format user-supplied data disks? No, but the "Sentence Editor" can edit data on the program disk itself. COPYA immediate disk read error Locksmith Fast Disk Backup unable to read any track EDD 4 bit copy (no sync, no count) no read errors, but copy hangs after reading one track Copy ][+ nibble editor T00 -> standard prologues, modified epilogues (FF FF EB) T01..T02 -> corrupted address fields, claim to be track $00 T03..T04 -> not full tracks? looks like they have some standard-ish sectors, but not 16 per track (also claim to be track $00) T05..T13 -> standard prologues, modified epilogues (FF FF EB), standard address fields T14+ -> unformatted --v-- COPY ][ PLUS BIT COPY PROGRAM 8.4 (C) 1982-9 CENTRAL POINT SOFTWARE, INC. --------------------------------------- TRACK: 01 START: 1D86 LENGTH: 1896 ^^ 1D60: FF FF FF FF FF FF FF FF VIEW 1D68: FF FF FF FF FF FF FF FF 1D70: FF FF FF FF FF FF FF FF 1D78: FF FF FF FF FF FF FF FF 1D80: FF FF FF FF FF D5 AA 96 <-1D85 ^^^^^^^^ address prologue 1D88: AA AA AA AA AA AA AA AA ^^^^^ ^^^^^ ^^^^^ ^^^^^ V000 T00 S00 chksm 1D90: FF FF E9 BF E7 F9 FE FF ^^^^^^^^ address epilogue 1D98: FF D5 AA AD E6 E6 F9 F2 ^^^^^^^^ data prologue 1DA0: 9B FC F4 DA DA ED FF FD --------------------------------------- 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 $01. 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..T04 unreadable (no option to ignore the corrupted address field) T05..T13 readable T14+ unreadable (unformatted) 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" T00, T05..T13 readable ["P" -> "Sector Editor Patcher"] set CHECK TRACK to "NO" T01, T02 readable! only parts of T03 and T04 readable: T03: S03,04,05,06,07,0A,0B,0C,0D,0E T04: 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, complete, and uncorrupted 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.AAAA...............AAAAAAAAAAAAAAA 1.AAAA...............AAAAAAAAAAAAAAA 2.AAAA...............AAAAAAAAAAAAAAA 3.AAAA...............AAAAAAAAAAAAAAA 4.AAAA...............AAAAAAAAAAAAAAA 5.AAAA...............AAAAAAAAAAAAAAA 6.AAAA...............AAAAAAAAAAAAAAA 7.AAAA...............AAAAAAAAAAAAAAA 8.AAAA...............AAAAAAAAAAAAAAA 9.AAAA...............AAAAAAAAAAAAAAA A.AAAA...............AAAAAAAAAAAAAAA B.AAAA...............AAAAAAAAAAAAAAA C.AAAA...............AAAAAAAAAAAAAAA D.AAAA...............AAAAAAAAAAAAAAA 12 E.AAAA...............AAAAAAAAAAAAAAA F.AAAA...............AAAAAAAAAAAAAAA [ ] PRESS [RESET] TO EXIT --^-- That's about what I expected. It can't read tracks $01-$04 because the address field is intentionally corrupted, and it can't read tracks $14-$22 because they're unformatted. Other than that, it worked great. Let's go see what's on those unreadable tracks. [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 up ($3E) to call disk controller ; ROM routine from the boot slot 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 ; hmm 080A- A9 04 LDA #$04 080C- 48 PHA ; machine initialization (memory banks, ; TEXT, IN#0, PR#0, &c.) 080D- 2C 81 C0 BIT $C081 0810- 20 2F FB JSR $FB2F 0813- 2C 52 C0 BIT $C052 0816- 20 89 FE JSR $FE89 0819- 20 93 FE JSR $FE93 081C- 20 58 FC JSR $FC58 081F- 2C 51 C0 BIT $C051 0822- 2C 54 C0 BIT $C054 0825- 2C 52 C0 BIT $C052 ; finish setting up ($3E) 0828- A9 5C LDA #$5C 082A- 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 082C- A9 60 LDA #$60 082E- 8D 01 08 STA $0801 ; hmm 0831- A9 72 LDA #$72 0833- 48 PHA OK, we've now pushed $04/$72 on the stack. That's probably important. ; multi-sector read ; Y = start logical sector ($01) ; X = end logical sector ($09) ; A = start address high byte ($50) 0834- A0 00 LDY #$00 0836- 84 FC STY $FC 0838- C8 INY 0839- A9 50 LDA #$50 083B- A2 09 LDX #$09 083D- 20 52 08 JSR $0852 ; call the code we just read (I'll bet ; my hat that this displays the ; animated Softsmith logo) 0840- 20 00 50 JSR $5000 0843- 2C 50 C0 BIT $C050 ; another sector read, 3 more sectors ; ($0A..$0C) into $9D00..$9FFF 0846- A0 0A LDY #$0A 0848- A9 9D LDA #$9D 084A- A2 0C LDX #$0C 084C- 20 52 08 JSR $0852 ; another sector read, this time just ; one sector, into $0400 (X is already ; less than Y on entry, so loop will ; exit after one read) 084F- A9 04 LDA #$04 0851- AA TAX ; falls through to multi-sector read ; entry point (was also called earlier ; from $083D and $084C) 0852- 85 27 STA $27 0854- E8 INX 0855- 86 49 STX $49 0857- 84 F9 STY $F9 ; map logical into physical sector and ; store it in zero page where the disk ; controller ROM will look for it 0859- B9 70 08 LDA $0870,Y 085C- 85 3D STA $3D ; read sector via disk controller ROM 085E- 20 6B 08 JSR $086B ; loop until done 0861- A4 F9 LDY $F9 0863- C8 INY 0864- C4 49 CPY $49 0866- 90 EF BCC $0857 0868- A5 27 LDA $27 086A- 60 RTS 086B- A6 2B LDX $2B 086D- 6C 3E 00 JMP ($003E) 0870- [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. 9 pages at $5000. 3 pages at $9D00. 1 page at $0400. Of course, we manually pushed $04/$72 on the stack earlier, so once we fall through to the sector read routine and it hits the RTS at $088F, it will "return" to $0472 + 1 = $0473. 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 241D- 24 4A BIT $4A 241F- 30 03 BMI $2424 2421- B9 63 04 LDA $0463,Y ; store physical sector in $3D (again, ; used by the disk controller ROM) 2424- 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 2426- 20 00 04 JSR $0400 ; increment sector index 2429- A4 F9 LDY $F9 242B- C8 INY ; are there more sectors to read? 242C- C4 49 CPY $49 ; yes, branch back and repeat 242E- 90 EA BCC $241A ; 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) 2430- A5 27 LDA $27 2432- 60 RTS But wait, it gets better. Not only do we use this call-and-fall pattern to advance a whole track (at $0433, which calls $0436), but we also use it at $040B, which calls $040E (to advance a whole track and read a whole track) and falls through to... $040E! So, with one call to $040B, we can read two tracks into consecutive memory; in this case, $A000..$BFFF. Fun(*) fact: they're not used on this disk, but you could call $0408 to read three tracks, or $0405 to read four. It's call-and-fall all the way down. (*)not guaranteed, actual fun may vary And that brings us all the way back to $0478. ~ Chapter 3 Every Byte Is Sacred, Every Byte Is Great, If A Byte Gets Wasted, Woz Gets Quite Irate *2478L 2478- 20 95 04 JSR $0495 *2495L ; advance to track 3 2495- 20 33 04 JSR $0433 ; more zero page fiddling 2498- A9 00 LDA #$00 249A- 85 41 STA $41 ; set high bit of zero page $4A 249C- 38 SEC 249D- 66 4A ROR $4A ; read 5 sectors into $4000..$44FF 249F- A9 40 LDA #$40 24A1- A0 01 LDY #$01 24A3- A2 05 LDX #$05 24A5- 20 15 04 JSR $0415 ; move the drive head one phase only, ; to the next HALF track 24A8- 20 36 04 JSR $0436 ; read more sectors ($06..$0A) from ; track 3.5 24AB- A2 0A LDX #$0A 24AD- 20 15 04 JSR $0415 ; advance another half track 24B0- 20 36 04 JSR $0436 ; read more sectors ($0B..$0F) from ; track 4 24B3- A2 0F LDX #$0F 24B5- 20 15 04 JSR $0415 ; fiddle with $4A again 24B8- 46 4A LSR $4A 24BA- 60 RTS So here's the deal with $4A: we initialized it at $0473 by a blind LSR, which clears the high bit. This tells the multi-sector read routine at $0415 to use logical sectors. Then we set the high bit at $049C with SEC + ROR, indicating we want $0415 to read physical sectors. Then we read a few sectors from track 3, a few from track 3.5, and a few from track 4. 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 3, a few on track 3.5, and a few on track 4. 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. 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... *247BL ; now put slot number (x16) into... ; an RWTS parameter table?!? 247B- A6 2B LDX $2B 247D- 8E E9 B7 STX $B7E9 ; set up DOS globals (tracking where ; the drive head is) 2480- 20 8E BE JSR $BE8E 2483- A5 FC LDA $FC 2485- 99 78 04 STA $0478,Y 2488- 4A LSR 2489- 8D 78 04 STA $0478 ; push $B7/$3A on the stack 248C- A9 B7 LDA #$B7 248E- 48 PHA 248F- A9 3A LDA #$3A 2491- 48 PHA ; and exit through HOME 2492- 4C 58 FC JMP $FC58 Execution continues at $B73B (because we just pushed $B7/$3A on the stack). ~ Chapter 4 In Which We Can See The Light At The End Of The Tunnel And We Just Hope It's Not An Oncoming Train I can interrupt the boot by changing the values pushed on the stack at $048C and $048F. *9600 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 $05-$13. Let me save these chunks before I forget. *2000