--------------Microzine 4-------------- A 4am crack 2015-09-27 --------------------------------------- Name: Microzine vol. 1, no. 4 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: #409 Microzine 5 #332 Microzine 3 #331 Jumble Jet Both sides are bootable to the main menu. I'll start with side A. ~ 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 T11?) 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 that 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. 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 Everything Is Awesome 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 (was DE AA) Data prologue: D5 AA AD Data epilogue: FF FF EB ^^^^^ change (was 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.AAA............................... 1.AAA............................... 2.AAA............................... 3.AAA............................... 4.AAA............................... 5.AAA............................... 6.AAA............................... 7.AAA............................... 8.AAA............................... 9.AAA............................... A.AAA............................... B.AAA............................... C.AAA............................... D.AAA............................... 12 E.AAA............................... F.AAA............................... [ ] PRESS [RESET] TO EXIT --^-- That's about what I expected. It can't read tracks $01-$03 because the address field is intentionally corrupted. 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 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 04 LDA #$04 0819- 48 PHA ; machine initialization (memory banks, ; TEXT, 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 ; clear hi-res screen 1 0829- A2 20 LDX #$20 082B- A0 00 LDY #$00 082D- 84 06 STY $06 082F- A9 20 LDA #$20 0831- 85 07 STA $07 0833- 98 TYA 0834- 91 06 STA ($06),Y 0836- C8 INY 0837- D0 FB BNE $0834 0839- E6 07 INC $07 083B- CA DEX 083C- D0 F6 BNE $0834 ; switch to hi-res screen 1 (blank) 083E- 8D 57 C0 STA $C057 0841- 8D 50 C0 STA $C050 0844- 8D 54 C0 STA $C054 0847- 8D 52 C0 STA $C052 ; set up ($3E) vector to point to the ; sector read routine in the disk ; controller ROM 084A- A9 5C LDA #$5C 084C- 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 084E- A9 60 LDA #$60 0850- 8D 01 08 STA $0801 ; hmm 0853- A9 72 LDA #$72 0855- 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 ($05) ; A = start address high byte ($9D) 0856- A0 00 LDY #$00 0858- 84 FC STY $FC 085A- C8 INY 085B- A9 9D LDA #$9D 085D- A2 05 LDX #$05 ; multi-sector read routine 085F- 20 77 08 JSR $0877 ; another sector read, 9 more sectors ; ($06..$0E) into $6000..$68FF 0862- A9 60 LDA #$60 0864- A2 0E LDX #$0E 0866- 20 77 08 JSR $0877 ; copy a few bytes manually 0869- A2 07 LDX #$07 086B- BD A5 08 LDA $08A5,X 086E- 9D 00 69 STA $6900,X 0871- CA DEX 0872- 10 F7 BPL $086B ; 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) 0874- A9 04 LDA #$04 0876- AA TAX ; falls through to multi-sector read ; entry point (was also called earlier ; from $085F and $0866) 0877- 85 27 STA $27 0879- E8 INX 087A- 86 49 STX $49 087C- 84 F9 STY $F9 ; map logical into physical sector and ; store it in zero page where the disk ; controller ROM will look for it 087E- B9 95 08 LDA $0895,Y 0881- 85 3D STA $3D ; read sector via disk controller ROM 0883- 20 90 08 JSR $0890 ; loop until done 0886- A4 F9 LDY $F9 0888- C8 INY 0889- C4 49 CPY $49 088B- 90 EF BCC $087C 088D- A5 27 LDA $27 088F- 60 RTS 0890- A6 2B LDX $2B 0892- 6C 3E 00 JMP ($003E) 0895- [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 $6000. 5 pages at $9D00. 1 page at $0400 (part of the text page, but it's hidden during boot because we cleared the entire hi-res graphics page and showed that instead). 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 Everything Is Terrible *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 To sum up: These two lines of code... || 247B- A9 A1 LDA #$A1 || || 247D- 20 0E 04 JSR $040E || advanced the drive head from track $00 to track $01 and read the entire track into $A100..$B0FF, despite the fact that every sector's address field was corrupted and claimed to be track $00. Beautiful. ~ Chapter 3 In Which Everything Is Awesomely Terrible 2480- 20 9D 04 JSR $049D *249DL ; advance the drive head to track $02 249D- 20 33 04 JSR $0433 ; zero page fiddling 24A0- A9 00 LDA #$00 24A2- 85 41 STA $41 24A4- 38 SEC 24A5- 66 4A ROR $4A ; call the multi-sector read routine ; again, but this time only read 5 ; sectors, into $B100..$B5FF 24A7- A9 B1 LDA #$B1 24A9- A0 01 LDY #$01 24AB- A2 05 LDX #$05 24AD- 20 15 04 JSR $0415 ; move the drive head one phase only, ; to the next HALF track 24B0- 20 36 04 JSR $0436 [now on track 2.5] ; read more sectors ($06..$0A) from ; track 2.5 24B3- A2 0A LDX #$0A 24B5- 20 15 04 JSR $0415 ; advance another half track 24B8- 20 36 04 JSR $0436 [now on track 3] ; read more sectors ($0B..$0F) from ; track 2 24BB- A2 0F LDX #$0F 24BD- 20 15 04 JSR $0415 ; fiddle with $4A again 24C0- 46 4A LSR $4A 24C2- 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 $04A4 with SEC + ROR, indicating we want $0415 to read physical sectors. Then we read a few sectors from track 2, a few from track 2.5, and a few from track 3. 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 2, a few from track 2.5, and a few from track 3. 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... ; now put slot number (x16) into... ; an RWTS parameter table?!? 2483- A6 2B LDX $2B 2485- 8E E9 B7 STX $B7E9 ; set up DOS globals (tracking where ; the drive head is) 2488- 20 8E BE JSR $BE8E 248B- A5 FC LDA $FC 248D- 99 78 04 STA $0478,Y 2490- 4A LSR 2491- 8D 78 04 STA $0478 ; push $B7/$3A on the stack 2494- A9 B7 LDA #$B7 2496- 48 PHA 2497- A9 3A LDA #$3A 2499- 48 PHA ; and exit through HOME (which will ; wipe this loader from memory) 249A- 4C 58 FC JMP $FC58 Execution continues at $B73B (because we just pushed $B7/$3A on the stack). ~ Chapter 4 In Which Everything Is Terribly Awesome I can interrupt the boot by changing the values pushed on the stack at $0494 and $0497. *9600 "Y" THEN ESC = 1: GOSUB 4 000 2050 PRINT HO$ 2099 RETURN 3000 REM INIT 3005 VN$ = "TABLE OF CONTENTS":D R% = D:QX% = 0 3006 GOSUB 61000: ONERR GOTO 6 2000 3008 IF NOT DER% THEN PRINT H O$: VTAB 12: HTAB 3: PRINT CHR$ (7);"You have the Microzine in the drive!": GOSUB 900: RETURN ,A$9300": GOSUB 900: PRINT H O$: VTAB 11: IF ND = 1 THEN HTAB 1: PRINT "Put disk to be initialized in the drive. ": GOTO 2020 O$: VTAB 12: HTAB 3: PRINT CHR$ (7);"You have the Microzine in the drive!": GOSUB 900: RETURN 3010 PRINT HO$: VTAB 12: HTAB 4 : PRINT "Please wait. Initia lizing disk." 3011 ID% = 1 3015 ER = 0 3017 CALL 46592 3020 CALL 37632,SL,D,ER 3024 CALL 46595 3030 PRINT HO$: IF NOT ER THEN VTAB 12: HTAB 3: PRINT "The data disk has been initiali zed.": 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 900 3095 IF D = 1 AND NOT MICRO THEN GOSUB 4000 3099 RETURN . . . Bingo! Lines 3017-3024 calls several assembly language routines: 3017 CALL 46592 3020 CALL 37632,SL,D,ER 3024 CALL 46595 Converting to hex, those are $B600 $9300 $B603 respectively. Line 2007 loaded INIT.OBJ at $9300, so let's take a look at $B600. 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 A000-BFFF,A$2000,S5,D1 ]CALL -151 *B600<3600.36FFM *B600L ; branch to $B61D B600- 18 CLC B601- 90 1A BCC $B61D ; branch to $B623 B603- 18 CLC B604- 90 1D BCC $B623 ;[not part of this routine, but ; interesting nonetheless -- looks like ; some hooks for DOS functions that set ; or reset the RUN flag and check for ; , probably during boot but ; maybe during LOAD and RUN as well] ;B606- A9 FF LDA #$FF ;B608- 85 D6 STA $D6 ;B60A- AD 00 C0 LDA $C000 ;B60D- C9 83 CMP #$83 ;B60F- D0 06 BNE $B617 ;B611- 2C 10 C0 BIT $C010 ;B614- 6C 94 BA JMP ($BA94) ;B617- A5 39 LDA $39 ;B619- CD 03 9D CMP $9D03 ;B61C- 60 RTS ; from $B600 ; set A and Y to standard epilogues B61D- A9 DE LDA #$DE B61F- A0 AA LDY #$AA B621- D0 03 BNE $B626 ; from $B603 ; set A and Y to non-standard epilogues B623- A9 FF LDA #$FF B625- A8 TAY ; every path ends up here ; change the epilogue bytes in memory ; that the RWTS looks for after both ; address and data fields B626- 8D 91 B9 STA $B991 B629- 8D 35 B9 STA $B935 B62C- 8D AE BC STA $BCAE B62F- 8D 9E B8 STA $B89E B632- 8C 9B B9 STY $B99B B635- 8C 3F B9 STY $B93F B638- 8C B3 BC STY $BCB3 B63B- 8C A3 B8 STY $B8A3 B63E- 60 RTS A well-placed "RTS" at $B626 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,$26 change "8D" to "60" ]PR#6 ...everything works, including initializing a data disk and returning to the main menu... I had to apply this patch to side A as well, since both sides are bootable. Quod erat liberandum. --------------------------------------- A 4am crack No. 464 ------------------EOF------------------