--------------Microzine 6-------------- A 4am crack 2015-08-30 --------------------------------------- Name: Microzine vol. 1, no. 6 Genre: educational Year: 1984 Publisher: Scholastic, Inc. Media: double-sided 5.25-inch floppy OS: DOS 3.3 with custom bootloader Previous cracks: none Similar cracks: Microzine 3 (crack no. 332) Jumble Jet (crack no. 331) Booting side B immediately displays a message telling me to boot side A. So I guess I'll, uh, do that. ~ Chapter 0 In Which Various Automated Tools Fail In Interesting Ways What does the boot look and sound like? 1. immediate blank screen 2. several sequential track reads 3. DOS prompt 4. track seek (maybe to track $11?) 5. more disk activity (back and forth like file access) 6. title screen Does it access the disk after boot? Yes, repeatedly. Does it have an option to read, write, or format user-supplied data disks? Yes. 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 -> corrupted address fields, claim to be track $00 T02..T03 -> not full tracks? looks like they have some standard-ish sectors, but not 16 per track (also corrupted address fields) T04..T22 -> standard prologues, modified epilogues (FF FF EB), standard address fields --v-- COPY ][ PLUS BIT COPY PROGRAM 8.4 (C) 1982-9 CENTRAL POINT SOFTWARE, INC. --------------------------------------- TRACK: 01 START: 2735 LENGTH: 185A ^^ 2710: FF FF FF FF FF FF FF FF VIEW 2718: FF FF FF FF FF FF FF FF 2720: FF FF FF FF FF FF FF FF 2728: FF FF FF FF FF FF FF FF 2730: FF FF FF FF FF D5 AA 96 <-2735 ^^^^^^^^ address prologue 2738: AA AA AA AA AA AA AA AA ^^^^^ ^^^^^ ^^^^^ ^^^^^ V000 T00 S00 chksm 2740: FF FF FF FF FC FF FF FF ^^^^^^^^ address epilogue 2748: FF D5 AA AD F2 FA D7 D7 ^^^^^^^^ data prologue 2750: A6 BE FE F7 FB EC 97 B9 --------------------------------------- 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..T03 unreadable (no option to ignore the corrupted address field) T04..T22 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" T00, T04..T22 readable ["P" -> "Sector Editor Patcher"] set CHECK TRACK to "NO" T01 readable! only parts of T02 and T03 readable: T02: S03,04,05,06,07,0A,0B,0C,0D,0E T03: 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. Trace the boot 2. ??? ~ Chapter 1 In Which We Get Off To A Slow Start ]PR#5 CAPTURING BOOT0 ...reboots slot 6... ...reboots slot 5... SAVING BOOT0 ]BLOAD BOOT0,A$800 ]CALL -151 *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, IN#0, PR#0, HOME, &c.) 081A- 8D 81 C0 STA $C081 081D- 20 2F FB JSR $FB2F 0820- 8D 52 C0 STA $C052 0823- 20 58 FC JSR $FC58 0826- 2C 53 C0 BIT $C053 0829- 20 89 FE JSR $FE89 082C- 20 93 FE JSR $FE93 082F- 20 58 FC JSR $FC58 0832- 8D 51 C0 STA $C051 0835- 8D 54 C0 STA $C054 0838- 8D 52 C0 STA $C052 ; set up ($3E) vector to point to the ; sector read routine in the disk ; controller ROM 083B- A9 5C LDA #$5C 083D- 85 3E STA $3E ; The disk controller ROM always exits ; via $0801, so set that to an "RTS". ; Then we can treat it like any other ; subroutine: JSR to it and continue. 083F- A9 60 LDA #$60 0841- 8D 01 08 STA $0801 ; double hmm 0844- A9 72 LDA #$72 0846- 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 ($0B) ; A = start address high byte ($09) 0847- A0 00 LDY #$00 0849- 84 FC STY $FC 084B- C8 INY 084C- A9 09 LDA #$09 084E- A2 0B LDX #$0B 0850- 20 62 08 JSR $0862 ; call the code we just read 0853- 20 00 09 JSR $0900 Based on listening to the original disk boot, I'm guessing that's the code that displays the title screen. ; another sector read, 3 more sectors ; ($0C..$0E) into $9D00..$9DFF 0856- A9 9D LDA #$9D 0858- A0 0C LDY #$0C 085A- A2 0E LDX #$0E 085C- 20 62 08 JSR $0862 ; 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) 085F- A9 02 LDA #$02 0861- AA TAX ; falls through to multi-sector read ; entry point (was also called earlier ; from $0850 and $085C) 0862- 85 27 STA $27 0864- E8 INX 0865- 86 49 STX $49 0867- 84 F9 STY $F9 ; map logical into physical sector and ; store it in zero page where the disk ; controller ROM will look for it 0869- B9 80 08 LDA $0880,Y 086C- 85 3D STA $3D ; read sector via disk controller ROM 086E- 20 7B 08 JSR $087B ; loop until done 0871- A4 F9 LDY $F9 0873- C8 INY 0874- C4 49 CPY $49 0876- 90 EF BCC $0867 0878- A5 27 LDA $27 087A- 60 RTS ; subroutine to read a sector via ($3E) ; which points to $Cx5C, which exits ; via $0801, which is now an "RTS" ; (HOW F---ING ELEGANT IS THAT, RIGHT?) 087B- A6 2B LDX $2B 087D- 6C 3E 00 JMP ($003E) *880.88F ; logical to physical sector mapping 0880- 00 03 05 07 09 0B 0D 0F 0888- 02 04 06 08 0A 0C 0E 01 That's it. Flexible but compact. So where does this routine go next? Ah! We manually pushed $02/$72 to the stack earlier, so once we fall through to the multi-sector read routine (at $0862) and hit the RTS (at $087A), it will "return" to $0272 + 1 = $0273. Let's interrupt the boot before it gets there. ~ Chapter 2 In Which Things Get Brilliantly Weird *9600 *800.BFFF ... As expected, the only pages loaded are $0900..$13FF, both graphics pages (set by the routine at $0900 which decompresses the title screen), and $9D00..$9FFF, which looks like the first three pages of DOS 3.3. *2900<900.13FFM *3D00<9D00.9FFFM *C500G ... ]BSAVE BOOT1 0200-02FF,A$2200,L$100 ]BSAVE BOOT1 0900-13FF,A$2900,L$B00 ]BSAVE BOOT1 9D00-9FFF,A$3D00,L$300 ]CALL -151 Now let's look at the next stage of the boot. *200<2200.22FFM *273L ; not sure what $4A is for yet 0273- 46 4A LSR $4A 0275- 20 A2 02 JSR $02A2 *2A2L 02A2- 20 33 02 JSR $0233 *233L ; call the following line (then fall ; through and do it again) 0233- 20 36 02 JSR $0236 ; save A and Y 0236- 48 PHA 0237- 98 TYA 0238- 48 PHA ; low-level disk stuff (see below) 0239- A5 FC LDA $FC 023B- 85 FD STA $FD 023D- E6 FC INC $FC 023F- A5 FC LDA $FC 0241- 29 03 AND #$03 0243- 0A ASL 0244- 05 2B ORA $2B 0246- A8 TAY 0247- B9 81 C0 LDA $C081,Y ; wait loop 024A- A9 30 LDA #$30 024C- 20 A8 FC JSR $FCA8 ; more low-level disk stuff 024F- A5 FD LDA $FD 0251- 29 03 AND #$03 0253- 0A ASL 0254- 05 2B ORA $2B 0256- A8 TAY 0257- B9 80 C0 LDA $C080,Y ; more waiting 025A- A9 30 LDA #$30 025C- 20 A8 FC JSR $FCA8 ; restore A and Y on the way out 025F- 68 PLA 0260- A8 TAY 0261- 68 PLA 0262- 60 RTS 0263- [00 03 05 07 09 0B 0D 0F] 026B- [02 04 06 08 0A 0C 0E 01] This is a very clever and compact way to advance the drive head to the next track. Normally DOS 3.3 keeps track of this and has a (much more complicated) routine to move the head back and forth as needed. But this loader only needs to move it forward, so the entire process collapses to this: 1. Set up the Y register to be a slot number (x16) plus the appropriate phase (0-3, depending on which track the drive head is on) 2. LDA $C081,Y to turn on the appropriate stepper motor 3. Wait exactly the right amount of time (as measured in CPU cycles) 4. LDA $C080,Y to turn off the appropriate stepper motor 5. Wait the right amount of time again ...which is exactly what this routine at $0236 is doing. But that only gets us halfway there -- literally, it only moves the drive head by half a track. But! Since $0233 "falls through" to $0236, it ends up doing this twice. Two half tracks equal one whole track, so calling the routine at $0233 will move the drive head to the next whole track. (By the way, this is why it initialized zero page $FC to $00 at $0849. That's the "current" track where the drive head is at boot; it gets updated when the drive head advances.) Everything I know about low-level disk stepping, I learned from this excellent Usenet post: macgui.com/usenet/?group=1&id=31160 ~ Chapter 3 Every Byte Is Sacred, Every Byte Is Great, If A Byte Gets Wasted, Woz Gets Quite Irate So we're on track 1. Continuing the listing from $02A5... ; zero page fiddling (see below) 02A5- A9 00 LDA #$00 02A7- 85 41 STA $41 02A9- 38 SEC 02AA- 66 4A ROR $4A ; This calls another multi-sector read ; routine, similar to the one used in ; boot0, but with a few more tricks up ; its sleeve. ; A = start address high byte ($B1) ; Y = start sector ($01) ; X = end sector ($05) 02AC- A9 B1 LDA #$B1 02AE- A0 01 LDY #$01 02B0- A2 05 LDX #$05 02B2- 20 15 02 JSR $0215 *215L ; store A in zero page $27, used by the ; disk controller ROM routine as the ; target page to store sectors read ; from disk 0215- 85 27 STA $27 ; X is the final sector to read 0217- E8 INX 0218- 86 49 STX $49 ; Y is the current sector to read ; (starting with whatever was passed in ; and incrementing until it equals the ; value passed in the X register) 021A- 84 F9 STY $F9 021C- 98 TYA ; But wait, there's more! Based on the ; high bit of zero page $4A, Y is ; either a logical sector (the map of ; logical->physical 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 ; after reading 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 Continuing from $02B5... ; move the drive head one phase only, ; to the next HALF track 02B5- 20 36 02 JSR $0236 [now on track 1.5] ; read more sectors ($06..$0A) 02B8- A2 0A LDX #$0A 02BA- 20 15 02 JSR $0215 ; advance another half track 02BD- 20 36 02 JSR $0236 [now on track 2] ; read more sectors ($0B..$0F) 02C0- A2 0F LDX #$0F 02C2- 20 15 02 JSR $0215 ; fiddle with $4A again 02C5- 46 4A LSR $4A 02C7- 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 $0415 to use logical sectors. Then we set the high bit at $02A9 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 from track 1, a few from track 1.5, and a few from 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 disk. 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 from $0278... *278L 0278- A9 A0 LDA #$A0 027A- 20 0E 02 JSR $020E *20EL ; advance the drive head a whole track 020E- 20 33 02 JSR $0233 [now on track 3] ; set up the multi-sector read routine ; to read the entire track 0211- A2 0F LDX #$0F 0213- A0 00 LDY #$00 ...and now we fall through to the entry point at $0215. (Just one more little bit of brilliance in this super-compact code.) We have now loaded into memory: - $9D00..$9DFF (earlier, from track 0) - $B100..$BFFF (from tracks 1, 1.5, 2) - $A000..$AFFF (from track 3) We seem to be missing a page at $B000, though. ; copy the code that belongs at $B000 027D- A0 00 LDY #$00 027F- B9 00 BB LDA $BB00,Y 0282- 99 00 B0 STA $B000,Y 0285- 88 DEY 0286- D0 F7 BNE $027F Well there we go. We have now (through the most circuitous route imaginable) loaded a full copy of DOS into memory. ; put slot number (x16) into the RWTS ; parameter table 0288- A6 2B LDX $2B 028A- 8E E9 B7 STX $B7E9 ; set up DOS globals (tracking where ; the drive head is) 028D- 20 8E BE JSR $BE8E 0290- A5 FC LDA $FC 0292- 99 78 04 STA $0478,Y 0295- 4A LSR 0296- 8D 78 04 STA $0478 ; push $B7/$01 on the stack 0299- A9 B7 LDA #$B7 029B- 48 PHA 029C- A9 01 LDA #$01 029E- 48 PHA ; and exit through HOME (which will ; wipe this bootloader from memory) 029F- 4C 58 FC JMP $FC58 Execution continues at $B702 (because we just pushed $B7/$01 on the stack). ~ Chapter 4 In Which We Use The Original Disk As A Weapon Against Itself I can interrupt the boot by changing the values pushed on the stack at $029A and $029D. *9600 *C0E8 *B944L B944- A0 FC LDY #$FC B946- 84 26 STY $26 B948- C8 INY B949- D0 04 BNE $B94F B94B- E6 26 INC $26 B94D- F0 F3 BEQ $B942 B94F- BD 8C C0 LDA $C08C,X B952- 10 FB BPL $B94F B954- C9 D5 CMP #$D5 B956- D0 F0 BNE $B948 B958- EA NOP B959- BD 8C C0 LDA $C08C,X B95C- 10 FB BPL $B959 B95E- C9 AA CMP #$AA B960- D0 F2 BNE $B954 B962- A0 03 LDY #$03 B964- BD 8C C0 LDA $C08C,X B967- 10 FB BPL $B964 B969- C9 96 CMP #$96 B96B- D0 E7 BNE $B954 ... B98B- BD 8C C0 LDA $C08C,X B98E- 10 FB BPL $B98B B990- C9 FF CMP #$FF B992- D0 AE BNE $B942 B994- EA NOP B995- BD 8C C0 LDA $C08C,X B998- 10 FB BPL $B995 B99A- C9 FF CMP #$FF B99C- D0 A4 BNE $B942 B99E- 18 CLC B99F- 60 RTS 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" epilogue bytes. *1D00<9D00.BFFFM ; copy data *C500G ; reboot to work disk ... ]BSAVE BOOT2 9D00-BFFF,A$1D00,L$2300 ]BSAVE RWTS,A$3800,L$800 And now I can use this RWTS to read all the non-corrupted tracks from the original disk. So, everything except tracks $01-$03 (which are intentionally corrupted with bogus address fields). [S6,D1=original disk] [S6,D2=blank disk] ]BRUN ADVANCED DEMUFFIN 1.5 [press "5" to switch to slot 5] [press "R" to load a new RWTS module] --> At $B8, load "RWTS" from drive 1 [press "6" to switch to slot 6] [press "C" to convert disk] [press "Y" to change default values] --v-- ADVANCED DEMUFFIN 1.5 (C) 1983, 2014 ORIGINAL BY THE STACK UPDATES BY 4AM ======================================= INPUT ALL VALUES IN HEX SECTORS PER TRACK? (13/16) 16 START TRACK: $04 <-- change this START SECTOR: $00 <-- change this END TRACK: $22 END SECTOR: $0F INCREMENT: 1 MAX # OF RETRIES: 0 COPY FROM DRIVE 1 TO DRIVE: 2 ======================================= 16SC $04,$00-$22,$0F BY$01 S6,D1->S6,D2 --^-- And here we go... --v-- ADVANCED DEMUFFIN 1.5 (C) 1983, 2014 ORIGINAL BY THE STACK UPDATES BY 4AM ======================================= TRK: ............................... +.5: 0123456789ABCDEF0123456789ABCDEF012 SC0: ............................... SC1: ............................... SC2: ............................... SC3: ............................... SC4: ............................... SC5: ............................... SC6: ............................... SC7: ............................... SC8: ............................... SC9: ............................... SCA: ............................... SCB: ............................... SCC: ............................... SCD: ............................... SCE: ............................... SCF: ............................... ======================================= 16SC $04,$00-$22,$0F BY$01 S6,D1->S6,D2 --^-- The same RWTS works for track $00 (not shown) and all of side B (also not shown). The only thing my copy is missing is the data that was originally on tracks $01-$03. ~ Chapter 5 In Which Simplicity Is In The Eye Of The Beholder Let's write $A000..$BFFF back to tracks $01 and $02, but all regular and normal and stuff. No half tracks, no spirals, no tricks, no traps. Just, you know, sectors on tracks on a disk. [S6,D1=copy of side A with T00,T04-T22] [S5,D1=my work disk, still] ]PR#5 ... ]CALL -151 *300L ; page count (decremented) 0300- A9 20 LDA #$20 0302- 85 FF STA $FF ; logical sector (incremented) 0304- A9 00 LDA #$00 0306- 85 FE STA $FE ; call RWTS to write sector 0308- A9 03 LDA #$03 030A- A0 88 LDY #$88 030C- 20 D9 03 JSR $03D9 ; increment logical sector, wrap around ; from $0F to $00 and increment track 030F- E6 FE INC $FE 0311- A4 FE LDY $FE 0313- C0 10 CPY #$10 0315- D0 07 BNE $031E 0317- A0 00 LDY #$00 0319- 84 FE STY $FE 031B- EE 8C 03 INC $038C ; Convert to the interleave order that ; this disk expects 031E- B9 40 03 LDA $0340,Y 0321- 8D 8D 03 STA $038D ; increment page to write 0324- EE 91 03 INC $0391 0327- C6 FF DEC $FF ; loop until done with all pages 0329- D0 DD BNE $0308 032B- 60 RTS ; sector interleave table *340.34F 0340- 00 06 05 04 03 02 01 0F 0348- 0E 0D 0C 0B 0A 09 08 07 ; RWTS parameter table, pre-initialized ; with slot 6, drive 1, track $01, ; sector $00, address $2000, and RWTS ; write command ($02) *388.397 0388- 01 60 01 00 01 00 FB F7 0390- 00 20 00 00 02 00 00 60 *BSAVE MAKE,A$300,L$98 I'll need to patch the original DOS to read the standard epilogues instead of "FF FF". *BLOAD BOOT2 9D00-BFFF,A$1D00 *389E:DE *38A3:AA *3935:DE *393F:AA *3991:DE *399B:AA *3CAE:DE *3CB3:AA *BSAVE RWTS FIXED,A$3800,L$800 And finally write $A000..$BFFF to disk: *300G ...write write write... Now I need to modify the bootloader at $0273 to read those pages from tracks $01 and $02. Specifically, I need to do three things: 1. Instead of reading tracks 1, 1.5, and 2 into $B100..$BFFF and track 3 into $A000, just read tracks 1 and 2 into $A000..$BFFF. This is one JSR, because $020B is designed to read two tracks in a row. $020B literally calls $020E to advance the drive head and read a full track, then falls through to $020E to do it all again. HOW F---ING ELEGANT IS THAT. 2. Modify the routine that advances the drive head so it updates zero page $41 with the current track. The sector read routine at $C65C compares the track listed in the address field to zero page $41 and loops forever until it matches. $C600 initializes $41 to 0, and the original disk never updates $41, but everything works because the address fields are corrupted and all claim to be track 0. HOW F---ING ELEGANT IS THAT, AGAIN. 3. Skip all the spiral/half track stuff. I now have all the data on consecutive whole tracks. So part of it will be simpler, because we'll no longer be spiraling between tracks. But part of it will actually be more complicated because the address fields are no longer corrupted. Weird. ; skip spiral track reading T00,S07,$75 change "20" to "2C" ; read 2 tracks instead of 1 into $A000 T00,S07,$7B change "0E" to "0B" ; patch "advance track" routine to go ; to a new subroutine which I'm about ; to show you T00,S07,$34 change "36" to "CD" ; new subroutine to increment zp$41 ; when we advance the drive head T00,S07,$CD change to "E6 41 4C 36 02" ]PR#6 ...it all works, and it's glorious... ~ Chapter 6 In Which It Doesn't Work ]PR#6 ...boots to main menu... [select "Fossils Alive"] ...works... [select "Computer Stuff"] [select "Initialize a data disk"] ...works... [select "Return to Table of Contents"] ...grinds and displays error... --v-- THERE IS SOMETHING WRONG WITH YOUR DISK PRESS RETURN TO RESTART: _ --^-- I know I patched the second stage RWTS correctly, because there's plenty of disk activity after the initial boot. Entire programs, even. But after it initializes a data disk, the RWTS is being corrupted -- or reverted. ]PR#5 ... ]CATALOG,S6,D1 C1983 DSR^C#254 015 FREE A 003 MICROZINE SIDE 1 A 004 HELLO A 020 UTILITIES A 063 TWISTAPLOT A 010 CREDITS A 006 LOAD PIC A 023 TABLE OF CONTENTS T 112 TWISTAPLOT FILE B 012 LITTLE APEX B 010 PICDRAW B 002 RUNPACK B 011 UTILITIES.PAK B 002 SOUND MODULE.OBJ B 004 INIT.OBJ B 005 ST.FOSSILS B 002 MAZE1.BD B 002 MAZE2.BD B 002 MAZE3.BD B 006 BELLY.SPC B 010 FIGHT.SPC B 011 KIDS.SPC B 010 MENU.SPC B 003 NOTE.SPC B 005 PAINT.SPC B 010 PLESIO.SPC B 011 PTERO.SPC B 013 RODEO.SPC B 012 SABER.SPC T 005 TWISTAPLOT FILE INDEX B 011 TYRANNO.SPC B 012 VOLCANO.SPC B 013 WOOLY.SPC T 002 MZ.PARAMETER FILE T 002 SIDE B 002 DEC/BIN.OBJ B 022 TITLE.SPC B 002 VOICE B 010 ELEPHANT "UTILITIES" looks promising. ]LOAD UTILITIES ]LIST . . . 2 HIMEM: 37632:DO = 46784:XD = DO + 6:D$ = CHR$ (4):PN$ = "Microzine":ESC$ = CHR$ (27 ):BE$ = CHR$ (7):MICRO = 1: SP$ = " " : GOSUB 21000:AP = ( PEEK ( - 1101) = 6):LK$ = CHR$ (8):R K$ = CHR$ (21):UK$ = CHR$ (11):DK$ = CHR$ (10):K1$ = "<":K2$ = ">": IF AP THEN K1 $ = "`":K2$ = "~" . . . 2005 PRINT H$: VTAB 2: HTAB 10: PRINT "INITIALIZE A DATA DI SK": VTAB 8: PRINT "For your data disk, you can use eith er a": PRINT "new, blank dis k, or an old disk that you": PRINT "no longer need. If there is a write-": PRINT : PRINT "protect tab on the data dis k, take it": PRINT : PRINT " off now." 2007 PRINT D$"BLOAD INIT.OBJ,D1 ,A$9300": GOSUB 900: IF ESC THEN 2050 . . . 3010 PRINT H$: VTAB 12: HTAB 4: PRINT "Please wait. Initial izing disk.":ID% = 1:ER = 0: CALL DO: CALL 37632,SL,D,ER : CALL XD: PRINT H$: IF NOT ER THEN VTAB 12: HTAB 3: PRINT "The data disk has been init ialized.": GOTO 3090 3040 VTAB 11: HTAB 2: PRINT "So mething is wrong. The data d isk has": PRINT : HTAB 5: PRINT "not been initialized. Try a gain." 3090 GOSUB 800: IF D = 1 AND NOT MICRO THEN GOSUB 4000 3099 RETURN Bingo! Line 3010 calls several assembly language routines: CALL DO (set to 46784 on line 3) CALL 37632,SL,D,ER CALL XD (set to 46790 on line 3) Converting to hex, those are $B6C0 $9300 $B6C6 respectively. Line 2007 loaded INIT.OBJ at $9300, so let's take a look at $B6C0. I have that on my work disk -- it was part of the $A000..$BFFF chunk that was originally on the unreadable spiral/half tracks. ]BLOAD BOOT2 9D00-BFFF,A$1D00,S5,D1 ]CALL -151 *B600<3600.36FFM *B6C0L ; entry point #1: ; set A and Y to standard epilogues B6C0- A9 DE LDA #$DE B6C2- A0 AA LDY #$AA B6C4- D0 03 BNE $B6C9 ; entry point #2: ; set A and Y to non-standard epilogues B6C6- A9 FF LDA #$FF B6C8- A8 TAY ; both entry points end up here -- ; change the epilogue bytes in memory ; that the RWTS looks for after both ; address and data fields B6C9- 8D 91 B9 STA $B991 B6CC- 8D 35 B9 STA $B935 B6CF- 8D AE BC STA $BCAE B6D2- 8D 9E B8 STA $B89E B6D5- 8C 9B B9 STY $B99B B6D8- 8C 3F B9 STY $B93F B6DB- 8C B3 BC STY $BCB3 B6DE- 8C A3 B8 STY $B8A3 B6E1- 60 RTS A well-placed "RTS" at $B6C9 should neutralize all this fiddling. A quick sector search for "91 B9" shows that $B600 ended up on T02,S01. (Remember, the sector interleaving is non-standard and I never changed it.) T02,S01,$C9 change "8D" to "60" ]PR#6 ...everything works, including initializing a data disk and returning to the main menu... Quod erat liberandum. --------------------------------------- A 4am crack No. 434 ------------------EOF------------------