-----Stickybear Spellgrabber rev. 2---- A 4am crack 2016-02-23 --------------------------------------- Name: Stickybear Spellgrabber rev. 2 Version: (*) see below Genre: educational Year: 1985 Authors: Richard Hefter and Steve Worthington Publisher: Optimum Resource, Inc. Media: single-sided 5.25-inch floppy OS: custom Previous cracks: Asimov has a different version (*) Similar cracks: #611 Stickybear Reading #610 Stickybear Word Problems #609 Stickybear Math 2 #586 Stickybear Parts of Speech #585 Map Skills #336 Car Builder Neither the disk label nor the title screen contain any visible version information. There is no disk catalog, so there is no file metadata. Many Optimum Resource disks don't even include a copyright year; I had to look up this game's release date online. Despite this information vacuum, I have used modern tools (xxd and diff) to compare the disk image I have with all the other images I can find, online and in my private collection. This copy has significant differences on almost every track. I don't know which version was released first, but this crack is a first-time preservation. ~ Chapter 0 In Which Various Automated Tools Fail In Interesting Ways COPYA read error on first pass Locksmith Fast Disk Backup fails to read T01,S0F; copy hangs EDD 4 bit copy (no sync, no count) no read errors, but copy hangs Disk Fixer unable to read T01,S0F by any obvious combination of parameters Why didn't COPYA work? intentionally bad sector on track $01 Why didn't Locksmith FDB work? probably a nibble check during boot that centers around the bad sector Why didn't my EDD copy work? ditto Next steps: 1. Trace the boot 2. Find the nibble check and skip it 3. There is no step 3 (I hope) ~ Chapter 1 Hello, I'd Like To Have An Argument On The Stack, Please [S6,D1=original disk] [S5,D1=my work disk] ]PR#5 ... CAPTURING BOOT0 ...reboots slot 6... ...reboots slot 5... SAVING BOOT0 CAPTURING BOOT1 ...reboots slot 6... ...reboots slot 5... SAVING BOOT1 SAVING RWTS ]BLOAD BOOT1,A$2600 ]CALL -151 *B600<2600.2EFFM ; move RWTS into place ; (but don't overwrite ; Diversi-DOS @ $BF00) *B700L ; clear hi-res graphics screen 1 B700- A9 00 LDA #$00 B702- A8 TAY B703- 85 10 STA $10 B705- A2 20 LDX #$20 B707- 86 11 STX $11 B709- 91 10 STA ($10),Y B70B- C8 INY B70C- D0 FB BNE $B709 B70E- E6 11 INC $11 B710- CA DEX B711- D0 F6 BNE $B709 ; and show it (blank) B713- 8D 50 C0 STA $C050 B716- 8D 57 C0 STA $C057 B719- 8D 54 C0 STA $C054 B71C- 8D 52 C0 STA $C052 ; hmm, a JSR followed by garbage code B71F- 20 5D B6 JSR $B65D B722- 01 0E ORA ($0E,X) B724- 00 BRK B725- 08 PHP B726- 18 CLC *B65DL ; Ah! This subroutine uses the stack to ; pass in multiple arguments and store ; them in zero page B65D- 68 PLA B65E- 85 F0 STA $A0 B660- 68 PLA B661- 85 F1 STA $A1 B663- A0 01 LDY #$01 B665- B1 F0 LDA ($A0),Y B667- 85 54 STA $54 B669- C8 INY B66A- B1 F0 LDA ($A0),Y B66C- 85 55 STA $55 B66E- C8 INY B66F- B1 F0 LDA ($A0),Y B671- 85 58 STA $58 B673- C8 INY B674- B1 F0 LDA ($A0),Y B676- 85 59 STA $59 B678- C8 INY B679- B1 F0 LDA ($A0),Y B67B- 85 67 STA $67 B67D- 18 CLC B67E- A5 F0 LDA $A0 B680- 69 05 ADC #$05 B682- A8 TAY B683- A5 F1 LDA $A1 B685- 69 00 ADC #$00 [Note to self: this routine uses ($A0), while other Optimum Resource disks use ($F0). Otherwise identical. Could be useful if I were making a program to identify Optimum Resource disks.] ; then munges the stack pointer to ; "return" to the next real instruction ; after the parameters B687- 48 PHA B688- 98 TYA B689- 48 PHA B68A- A9 00 LDA #$00 B68C- 85 5A STA $5A B68E- 85 5B STA $5B B690- 85 5E STA $5E B692- 85 53 STA $53 B694- A9 01 LDA #$01 B696- 85 50 STA $50 B698- 85 52 STA $52 B69A- 85 60 STA $60 B69C- 85 62 STA $62 B69E- A9 60 LDA #$60 B6A0- 85 51 STA $51 B6A2- 85 5F STA $5F B6A4- A9 00 LDA #$00 B6A6- 85 57 STA $57 B6A8- A9 61 LDA #$61 B6AA- 85 56 STA $56 B6AC- A9 EF LDA #$EF B6AE- 85 63 STA $63 B6B0- A9 D8 LDA #$D8 B6B2- 85 64 STA $64 B6B4- A5 67 LDA $67 B6B6- D0 01 BNE $B6B9 B6B8- 60 RTS B6B9- A9 01 LDA #$01 B6BB- 85 5C STA $5C B6BD- A9 00 LDA #$00 B6BF- A0 50 LDY #$50 B6C1- 20 B5 B7 JSR $B7B5 B6C4- E6 59 INC $59 B6C6- C6 67 DEC $67 B6C8- C6 55 DEC $55 B6CA- 10 E8 BPL $B6B4 B6CC- A9 0F LDA #$0F B6CE- 85 55 STA $55 B6D0- E6 54 INC $54 B6D2- D0 E0 BNE $B6B4 This is a multi-sector read loop. It calls the regular $B7B5 entry point to read sectors (at $B6C1). Interestingly, the RWTS parameter table is actually on zero page, starting at $50. That would mean that the parameters passed in (on the stack, after the JSR $B65D) are 1. start track ($54) 2. start sector ($55) 3. start address - low ($58) 4. start address - high ($59) 5. sector count ($67) It uses logical sectors (via the RWTS). Sectors count down from $0F to $00, and tracks are decremented once the sector wraps around to $0F. The target address is incremented monotonically, and the sector count is decremented until it hits 0. Revisiting the caller with this new understanding... ; read $18 sectors into $0800 starting ; from T01,S0E B71F- 20 5D B6 JSR $B65D B722- [01 0E 00 08 18] ; continue in the code we just read B727- 4C 00 08 JMP $0800 That's where I'll interrupt the boot. ~ Chapter 2 Bootus Interruptus *9600