NOTE: The following works only with a real disk][ controller. See the source for more details.
Have you ever owned an Apple ][ series computer? Ever do stupid, yet highly amusing stuff with it? I have, just to (re)learn my machine.
Ok, I admit I hadn't had much sleep the previous night, but when I woke up, I thought, "Hrrrmm... what if I could boot from drive 2?" So the disassembling of PROMs and stuff began. Herein is a howto.
Altering the boot PROM
In order to boot drive 2, you must somehow activate drive 2. The following snippet is from the Cx00 PROM for the disk][ controller:
*C62FL
C62F- BD 8E C0 LDA $C08E,X
C632- BD 8C C0 LDA $C08C,X
C635- BD 8A C0 LDA $C08A,X ;THIS IS THE DRIVE ACTIVATOR
C638- BD 89 C0 LDA $C089,X ;MOTOR ON
The X register has the slot number*16 in it on entry to these instructions. The byte at $C636 needs to be changed to 8B in order to make drive 2 active, however. So, we move the entire $C6 page to another $x600 location. The location MUST be at $xs00, tho, where x will be "4" in my example, and s is the slot number ("6" in most apples), hence, we will "move" the PROM to $4600 with this command:
*4600<C600.C6FFM
There. We now have a writable "PROM." Let's make drive 2 be active:
*4636:8B
The "PROM" in RAM will now boot off of drive 2... for the FIRST sector.
The reason our fake PROM needs to be at $xs00 is because of this code:
*C621L
C621- 20 58 FF JSR $FF58 ;"GUARANTEED" RTS
C624- BA TSX ;RETRIEVE PAGE WE'RE ON
C625- BD 00 01 LDA $0100,X ;FROM THE STACK
C628- 4A ASL ;MULTIPLY PAGE BY 16
C629- 4A ASL ;TO GET SLOT*16
C62A- 4A ASL
C62B- 4A ASL
C62C- 85 2B STA $2B ;SAVE OFF IN ZP
Woz pulled nifty "latent stack byte" tricks to get our slot number. Mmmmmm, hackery.
Making DOS use drive 2
If we were to try booting our fake PROM at this point, we'd succeed in loading track 0, sector 0 off of drive 2. We'd also get any sectors the boot sector loads until the loading routine for DOS 3.3 assumes we're on drive 1! for DOS 3.3, we get 9 sectors loaded at $B700 (this is all of RWTS, I believe) so that it can load the rest of DOS using the "read group of pages" routine found at $B793.
Our area of interest starts at $B700, where the $801 loader jumps, oddly enough:
*B700L
B700- 8E E9 B7 STX $B7E9 ;SLOT*16 IN X, GOES INTO IOB
B703- 8E F7 B7 STX $B7F7 ;"LAST ACCESSED" SLOT*16
B706- A9 01 LDA #$01 ;ASSUME DRIVE 1
B708- 8D F8 B7 STA $B7F8 ;INTO IOB
B70B- 8D EA B7 STA $B7EA
We need to change the byte at $B707 to $02 to make DOS use drive 2.
Making PROM stubs
Normally, this wouldn't be so involved. However, there exist diskettes on which there resides a relocatable DOS that loads in at $1600-$3FFF, getting relocated up to $9600 for your 64k apple. This makes for an interesting situation. Booting relocatable DOS without providing for it will result in an unspectacular crash. Therefore, we must find out where the DOS loaded up. This is rather easy, as the byte at $08FE contains the page location of our RWTS loader at $B700 for a 64k fixed DOS. This is constant, no matter what DOS 3.3 you're booting, so we can use that byte to modify our "PROM" stub detailed below.
Making the PROM modify things
The following original instructions must be modified:
46F8- 4C 01 08 JMP $0801 ;JUMP TO 2ND STAGE LOADER
084A- 6C FD 08 JMP ($08FD) ;JUMP TO DOS RWTS LOADER
The code at $084A is simple. Our PROM will modify this line to be:
084A- 4C 0A 47 JMP $470A ;JUMP TO PROM STUB
The stub code that replaces the instruction at $46F8 and would otherwise run into the next slot is this:
46F8- A9 4C LDA #$4C ;JMP
46FA- 8D 4A 08 STA $084A ;MODIFY $0801 LOADER
46FD- A9 0A LDA #$0A ;$470A
46FF- 8D 4B 08 STA $084B
4702- A9 47 LDA #$47
4704- 8D 4C 08 STA $084C
4707- 4C 01 08 JMP $0801 ;PROCEED TO $0801 LOADER NOW
470A- AD FE 08 LDA $08FE ;PAGE BYTE OF LOADED RWTS
470D- 8D 14 47 STA $4714 ;SELF-MODIFY DRIVE BYTE LOCATION
4710- A9 02 LDA #$02 ;DRIVE 2
4712- 8D 07 00 STA $0007 ;STORE IN $XX07
4715- 6C FD 08 JMP ($08FD) ;JUMP TO RWTS LOADER
The stub above will modify the $0801 loader to jump back within the stub, then execute the $0801 loader. After loading RWTS, the stub will self-modify where to place the drive byte depending on the page byte of the loaded RWTS in $08FE. Once that info is filled in, the indirect jump to the RWTS loader fakes any normal DOS 3.3 into booting completeely and correctly from drive 2.
Assuming you booted DOS from drive 1 and typed this all in, you can save your work:
*BSAVE BOOTD2.DOS33,A$4600,L$118
This code can be BRUN safely because it never RTS's to anything.
Booting from drive 2 using ProDOS
As the source shows, booting from drive 2 using ProDOS is possible, but a tad trickier. For ProDOS, the boot block is actually 2 sectors long. We need a convenient place to jump to our stub and modify the UNIT byte at $43 before anything happens. There's a JSR at $0879 that will let us do our magic. We modify this to jump to our "stub":
0879- 20 12 09 JSR $0912 ;READ A BLOCK
For ProDOS, indicating drive 2 is easier than for DOS 3.3 in that no code in the PRODOS image needs to be hacked. All we need to do is flip the high bit of the ProDOS temporary Unit number (stored at $43) on to indicate drive 2, and the boot loader and PRODOS take care of the rest:
PENT PHP ;save proc status jic
LDA UNIT ;get slot/drive
ORA #%10000000 ;turn on drive 2
STA UNIT ;make it so
PLP ;get original proc status
JMP BLKRDFE ;carry on with block read
This, combined with the common task of making a fake "PROM" and hacking it, enables ProDOS to boot from drive 2.
The Source
The source takes care of booting either DOS 3.3 or ProDOS from a single binary. It's designed to assemble in the ProDOS version of Merlin, though you could conceivably assemble it in DOS 3.3 if you hack the TYP op out. Porting it to other assemblers could be tricky (it's not too hard to port to EDASM, though the "relocation" trick I (ab)use in Merlin may gum the works.).
Happy Hacking.