NOTE: It took years for me to get (or emulate) hardware other than a disk][ Apple ][e, so it took years for me to realize that the following code works ONLY on ][ series that have a real disk][ controller (or equivalent). The //c and IIgs seem to have code that's much different in the $C600 slotspace.
Oh well, this ups the ante for me to make a version that works with ANY Apple or compatible!
Not that anyone else would care, but I've rewritten the evil "getting my Merlin-fu back" code so it makes more sense. I've also corrected some symbols, as I've disassembled and documented the ProDOS boot block since this stupid trick.
Furthermore, I apologize for the use of <pre>, but using nonbreaking spaces would suck more.
eslingc 20040803
******************************** *DISK][ STUPID TRICKS * *ESLINGC 20040803 * *Merlin8 v2.57 * ******************************** EXP OFF TR TYP $FF ;TSYS *------------------------------- BOOT = $801 ;location of boot sector PPATCH = $87A ;ProDOS patch addr DPATCH = $84A ;DOS patch addr BLKRDFE = $912 ;ProDOS block reader frontend UNIT = $43 ;Unit (%DSSS0000) for ProDOS RWTSLOAD = $8FE ;page byte of RWTS loader DRV2PROM = $8636 ;modify fake PROM drive byte (depends on controller!) PROMBASE = $8600 ;base for the PROM C6PROM = $C600 ;most everyone has slot 6 REALSLT = $C006 ;enable real slots A1L = $3C ;from address for move A2L = $3E ;length for MOVE A4L = $42 ;to address for MOVE MOVE = $FE2C ;Monitor MOVE subr *------------------------------- * LDAD macro to reduce tedium for fixing adrs bytes *------------------------------- LDAD MAC ;load 16bit number in 2 locns LDA #<]1 ;lob STA ]2 ;little-endian LDA #>]1 ;hob STA ]2+1 <<< ;not >>> *------------------------------- ORG $2000 ;TSYS requirement *=============================== * relo program and setup *=============================== STA REALSLT ;ensure we're on real slots LDAD C6PROM;A1L ;from slot ROM LDAD PROMBASE;A4L ;to RAM "PROM" LDAD C6PROM+255;A2L ;len=$100 LDY #0 JSR MOVE ;go move it LDAD STUB;A1L ;move the stub LDAD PROMBASE+$F8;A4L ;to PROM base LDAD SEND-1;A2L ;amount of code to move LDY #0 JSR MOVE ;getem INC DRV2PROM ;make PROM boot from drive 2 JMP PROMBASE ;boot from drive2 *=============================== * end of relo program * the new end of the disk][ PROM follows *=============================== STUB ;let edasm do the relo work ORG PROMBASE+$F8 ;the stub assembles at $86f8, this is also controller-dependent PHA ;save A register in case of ProDOS LDA BOOT CMP #$38 ;ProDOS/SOS? BEQ :PRODOS ;yes LDA #$4C ;else, assume DOS and pray STA DPATCH LDAD DOS33ENT;DPATCH+1 ;jump to DOS 3.3 stub PLA ;restore A register JMP BOOT ;proceed to "boot" :PRODOS LDAD PENT;PPATCH ;program loader to JSR to our stub PLA ;restore A reg JMP BOOT ;(re)enter into $0801 loader 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 to block reader DOS33ENT LDA RWTSLOAD ;get RWTS loader page STA :DOSP+2 ;self-modify to get relocating DOSes LDA #2 ;drive 2 :DOSP STA $C607 ;into $x707 (make sure this is a 3byte) JMP (RWTSLOAD-1) ;jump to RWTS loader ORG ;apparently will return to $20xx this way SEND ;EOF(relo code)
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.
When I first saw a computer, it was an Apple][(+?) ... Also, the first computer I'd ever programmed for was an Apple][(+/e). Those reasons alone aren't why I stuck with it, however. Set your watch to October of 1986.
I'd been in my first computer class in HS which I was truly interested in. This evening, we went to the public library to get an orientation on their computers, which happened to be a ][e and a ][+. To prove that I was green about computers in general, I'd brought my TRSDOS-formatted floppies in and asked the caretaker to try booting one. Naturally, it failed.
I took the simple test and got my orange dot on my library card anyway. This was the beginning of loads of tube time on these two machines.
I started out by running a few of the BASIC programs off the System Master, then LISTing them to see how they worked. I had no clue (back then) how a "CALL 2080" made the Apple do all that nifty shit (in this case, it did a CATALOG, then let you select what actions to perform on the file). I had no clue about anything Apple. What I DID have, however, was access to loads of documentation on these machines!
Thanks to having the docs, I taught myself FPBASIC, a bit of INTBASIC, and most importantly, 6502 assembly language. I'd also gotten proficient in doing things with the disk -- sector editing, CopyII+ parm file hacks, hacking DOS with nothing more than a well-worn copy of _Beneath Apple DOS_, getting into ProDOS, etc... There wasn't as much documentation as I needed, but I got good results with what I had and what I reverse-engineered on my own, so that made me stick with it.
Contrast this to the TRS-80 Model III I'd been working on that first year. Sure, I had a GWBASIC-like reference available, and used it... but by the end of the year, I'd had a taste of assembly language, and there was no TRS-80 memory map, no Z80 instruction set (hell, I didn't even KNOW what CPU was used in the TRS-80 back then), no docs of which locations were special for TRSDOS or the TRS-80 in general... none of that! All of this was available to me for the Apple, or I could find out if I really needed it.
Many years later -- and despite the fact that I'd thrown most of my best docs in the rubbish bin right after I'd drank an excess of Stupid -- I can still find out what I need to know about the Apples I have. Yes, I still use the Apple today.
I'm currently working on some ROM enhancements to the Apple][e... it's going pretty good, but I find that enhancing one piece breake another...
Did I mention that, even though I'd been using an Apple in some way since 1984, I still learn new things about it today?
In an act of simplification, I've decommissioned the old content manager that drove the mumble, and with that, the old posts in the Apple II section disappeared. They will appear here momentarily.