From fdbb458ec697b007e2e98c8acff245932d3be4cd Mon Sep 17 00:00:00 2001 From: mgcaret Date: Tue, 25 Apr 2017 20:10:02 -0700 Subject: [PATCH] 4X: create README.md specifically for 4X, add experimental config file support --- rom4x/B1_E000_rom4x.s | 524 +++++++++++------- ..._new_bootfail.s => B1_E400_new_bootfail.s} | 0 rom4x/README.md | 233 ++++++++ rom4x/iic.defs | 2 +- rom5x/B1_D516_boot5x.s | 2 +- 5 files changed, 560 insertions(+), 201 deletions(-) rename rom4x/{B1_E300_new_bootfail.s => B1_E400_new_bootfail.s} (100%) create mode 100644 rom4x/README.md diff --git a/rom4x/B1_E000_rom4x.s b/rom4x/B1_E000_rom4x.s index 72eb8f9..87e4635 100644 --- a/rom4x/B1_E000_rom4x.s +++ b/rom4x/B1_E000_rom4x.s @@ -1,216 +1,342 @@ .psc02 .code .include "iic.defs" - .org reset4x - stz power2 + rx_mslot ; action = normal boot - asl butn1 ; closed apple - bcs ckdiag -exitrst: jmp gorst4x ; return to RESET.X + .org reset4x + stz power2 + rx_mslot ; action = normal boot + asl butn1 ; closed apple + bcs ckdiag +exitrst: jmp gorst4x ; return to RESET.X ; check to see if both apples are down -ckdiag: bit butn0 ; open apple - bmi exitrst ; return to RESET.X +ckdiag: bit butn0 ; open apple + bmi exitrst ; return to RESET.X ; present menu because only closed apple is down -menu4x: jsr gobanner ; "Apple //c" - ldx #$00 ; menu start - jsr disp ; show it - jsr gtkey - cmp #$b0 ; "0" - bne ckkey1 - ldx #$ff ; reset stack - txs - lda #>(monitor-1) ; monitor entry on stack - pha - lda #<(monitor-1) - pha - jmp swrts2 ; rts to enter monitor -ckkey1: cmp #$b2 ; "2" - beq doconf - cmp #$b4 ; "4" - bne ckkey2 -doconf: jsr confirm - bne menu4x ; go back to menu4x -ckkey2: sec - sbc #$b0 ; ascii->number - bmi menu4x ; < 0 not valid - cmp #$08 - bpl menu4x ; > 7 not valid - sta power2 + rx_mslot ; for boot4x - stz softev + 1 ; deinit coldstart - stz pwerdup ; ditto - bra exitrst -gtkey: lda #$60 - sta ($0),y ; cursor - sta kbdstrb ; clr keyboard -kbdin: lda kbd ; get key - bpl kbdin - sta kbdstrb ; clear keyboard - sta ($0),y ; put it on screen - rts +menu4x: jsr gobanner ; "Apple //c" + ldx #$00 ; menu start + jsr disp ; show it + jsr gtkey + cmp #$b0 ; "0" + bne ckkey1 + ldx #$ff ; reset stack + txs + lda #>(monitor-1) ; monitor entry on stack + pha + lda #<(monitor-1) + pha + jmp swrts2 ; rts to enter monitor +ckkey1: cmp #$b2 ; "2" + beq doconf + cmp #$b4 ; "4" + bne ckkey2 +doconf: jsr confirm + bne menu4x ; go back to menu4x +ckkey2: sec + sbc #$b0 ; ascii->number + bmi menu4x ; < 0 not valid + cmp #$08 + bpl menu4x ; > 7 not valid + sta power2 + rx_mslot ; for boot4x + stz softev + 1 ; deinit coldstart + stz pwerdup ; ditto + bra exitrst +gtkey: lda #$60 + sta ($0),y ; cursor + sta kbdstrb ; clr keyboard +kbdin: lda kbd ; get key + bpl kbdin + sta kbdstrb ; clear keyboard + sta ($0),y ; put it on screen + rts ; display message, input x = message start relative to msg1 -disp: stz $0 ; load some safe defaults - lda #$04 - sta $1 - ldy #$0 ; needs to be zero -disp0: lda msg1,x ; get message byte - bne disp1 ; proceed if nonzero - rts ; exit if 0 -disp1: inx ; next byte either way - cmp #$20 ; ' ' - bcc disp2 ; start of ptr if < 20 - eor #$80 ; invert high bit - sta ($0),y ; write to mem - inc $0 ; inc address low byte - bra disp0 ; back to the beginning -disp2: sta $1 ; write address high - lda msg1,x ; get it - sta $0 ; write address low - inx ; set next msg byte - bra disp0 ; back to the beginning -confirm: pha - ldx #(msg3-msg1) ; ask confirm - jsr disp - jsr gtkey - plx - ora #$20 ; to lower - cmp #$f9 ; "y" - php - txa - plp - rts +disp: stz $0 ; load some safe defaults + lda #$04 + sta $1 + ldy #$0 ; needs to be zero +disp0: lda msg1,x ; get message byte + bne disp1 ; proceed if nonzero + rts ; exit if 0 +disp1: inx ; next byte either way + cmp #$20 ; ' ' + bcc disp2 ; start of ptr if < 20 + eor #$80 ; invert high bit + sta ($0),y ; write to mem + inc $0 ; inc address low byte + bra disp0 ; back to the beginning +disp2: sta $1 ; write address high + lda msg1,x ; get it + sta $0 ; write address low + inx ; set next msg byte + bra disp0 ; back to the beginning +confirm: pha + ldx #(msg3-msg1) ; ask confirm + jsr disp + jsr gtkey + plx + ora #$20 ; to lower + cmp #$f9 ; "y" + php + txa + plp + rts ; msg format ; A byte < $20 indicates high byte of address. ; Next byte must be low byte of address. Anything ; else are characters to display and will have their ; upper bit inverted before being written to the screen. msg1 = * - .byte $05,$06,"0 Monitor" - .byte $05,$86,"1 Reboot" - .byte $06,$06,"2 Zero RAM Card and Reboot" - .byte $06,$86,"3 Diagnostics" - .byte $07,$06,"4 RAM Card Diagnostics" - .byte $07,$86,"5 Boot SmartPort" - .byte $04,$2e,"6 Boot Int. 5.25" - .byte $04,$ae,"7 Boot Ext. 5.25" - .byte $07,$5f,"By M.G." -msg2: .byte $07,$db,"ROM 4X 04/08/17" - .byte $05,$ae,$00 ; cursor pos in menu -msg3: .byte $05,$b0,"SURE? ",$00 - .res boot4x - *, 0 - .org boot4x - jsr gobanner ; "Apple //c" - jsr rdrecov ; try to recover ramdisk - lda power2 + rx_mslot ; get action saved by reset4x - beq boot4 ; if zero, continue boot - ldx #(msg2-msg1) ; short banner offset - jsr disp ; display it - lda power2 + rx_mslot ; boot selection -btc2: cmp #$02 ; clear ramcard - bne btc3 - jsr rdclear ; do clear - bra boot4 -btc3: cmp #$03 ; Diags - bne btc4 - jmp $c7c4 -btc4: cmp #$04 ; RX diags - bne btc5 - ldx #$ff - txs ; reset stack - jsr rdinit ; get x and y loaded - stx sl_devno ; diags need this - jsr testsize ; compute card size - lda #>(monitor-1) ; load "return" address - pha ; into stack so that we - lda #<(monitor-1) ; exit card test into - pha ; the monitor - lda numbanks,y ; get the card size in banks - bne dordiag ; do diag if memory present - jmp swrts2 ; otherwise jump to monitor -dordiag: jmp $db3a ; diags - ;bra boot4 -btc5: cmp #$05 ; boot smartport - beq boot5 -btc6: cmp #$06 ; boot int drive - beq boot6 -btc7: cmp #$07 ; boot ext drive - bne boot4 ; none of the above - ; copy small routine to $800 to boot - ; external 5.25 - ldy #(bt4xend-bootext+1) -btc7lp: lda bootext,y - sta $800,y - dey - bpl btc7lp - lda #$08 ; copy done - bra bootsl -boot4: lda #rx_mslot ; boot slot 4 - bra bootsl -boot5: lda #$c5 ; boot slot 5 - bra bootsl -boot6: lda #$c6 ; boot slot 6 -bootsl: ldx #$00 ; low byte of slot -bootadr: stx $0 ; store address - sta $1 ; return to bank 0 does jmp (0) -endbt4x: jmp gobt4x ; continue boot -rdrecov: jsr rdinit ; init ramcard - lda pwrup,y ; get power up flag - cmp #pwrbyte ; already initialized? - beq recovdn ; exit if initialized - jsr testsize ; does not wreck x or y - lda numbanks,y ; get discovered # banks - beq recovdn ; no mem - stz addrl,x ; set slinky address 0 - stz addrm,x - stz addrh,x - lda data,x ; start check for bootable ramdisk - cmp #$01 - bne recovdn ; not bootable - lda data,x ; next byte should be nonzero and not $ff - beq recovdn ; not bootable - cmp #$ff - beq recovdn ; not bootable - lda #pwrbyte - sta pwrup,y ; set power byte - lda #'R' ; tell user - sta $7d0 ; on screen -recovdn: rts + .byte $05,$06,"0 Monitor" + .byte $05,$86,"1 Reboot" + .byte $06,$06,"2 Zero RAM Card and Reboot" + .byte $06,$86,"3 Diagnostics" + .byte $07,$06,"4 RAM Card Diagnostics" + .byte $07,$86,"5 Boot SmartPort" + .byte $04,$2e,"6 Boot Int. 5.25" + .byte $04,$ae,"7 Boot Ext. 5.25" + .byte $07,$5f,"By M.G." +msg2: .byte $07,$db,"ROM 4X 04/08/17" + .byte $05,$ae,$00 ; cursor pos in menu +msg3: .byte $05,$b0,"SURE? ",$00 + .res boot4x - *, 0 + .org boot4x + jsr gobanner ; "Apple //c" + jsr rdrecov ; try to recover ramdisk + lda power2 + rx_mslot ; get action saved by reset4x + beq :+ + pha ; save it + bra selboot ; set, go do it +: lda numbanks,y ; (y should be OK here) ram card present? + beq boot6 ; nope, boot slot 6 + jsr getcfg ; try to get config + bcs boot4 ; no config, normal boot + ;stx $7d2 + ;sty $7d3 + phx ; config present, move on + lda #'C' ; tell user + sta $7d1 ; on screen +selboot: ldx #(msg2-msg1) ; short banner offset + jsr disp ; display it + pla ; boot selection + sta $7d2 +btc2: cmp #$02 ; clear ramcard + bne btc3 + jsr rdclear ; do clear + bra boot4 +btc3: cmp #$03 ; Diags + bne btc4 + jmp $c7c4 +btc4: cmp #$04 ; RX diags + bne btc5 + ldx #$ff + txs ; reset stack + jsr rdinit ; get x and y loaded + stx sl_devno ; diags need this + jsr testsize ; compute card size + lda #>(monitor-1) ; load "return" address + pha ; into stack so that we + lda #<(monitor-1) ; exit card test into + pha ; the monitor + lda numbanks,y ; get the card size in banks + bne dordiag ; do diag if memory present + jmp swrts2 ; otherwise jump to monitor +dordiag: jmp $db3a ; diags + ;bra boot4 +btc5: cmp #$05 ; boot smartport + beq boot5 +btc6: cmp #$06 ; boot int drive + beq boot6 +btc7: cmp #$07 ; boot ext drive + bne boot4 ; none of the above + ; copy small routine to $800 to boot + ; external 5.25 + ldy #(bt4xend-bootext+1) +btc7lp: lda bootext,y + sta $800,y + dey + bpl btc7lp + lda #$08 ; copy done + bra bootsl +boot4: lda #rx_mslot ; boot slot 4 + bra bootsl +boot5: lda #$c5 ; boot slot 5 + bra bootsl +boot6: lda #$c6 ; boot slot 6 +bootsl: ldx #$00 ; low byte of slot +bootadr: stx $0 ; store address + sta $1 ; return to bank 0 does jmp (0) +endbt4x: jmp gobt4x ; continue boot +rdrecov: jsr rdinit ; init ramcard + lda pwrup,y ; get power up flag + cmp #pwrbyte ; already initialized? + beq recovdn ; exit if initialized + jsr testsize ; does not wreck x or y + lda numbanks,y ; get discovered # banks + beq recovdn ; no mem + stz addrl,x ; set slinky address 0 + stz addrm,x + stz addrh,x + lda data,x ; start check for bootable ramdisk + cmp #$01 + bne recovdn ; not bootable + lda data,x ; next byte should be nonzero and not $ff + beq recovdn ; not bootable + cmp #$ff + beq recovdn ; not bootable + lda #pwrbyte + sta pwrup,y ; set power byte + lda #'R' ; tell user + sta $7d0 ; on screen +recovdn: rts ; zero ram card space -rdclear: jsr rdinit ; init ramcard - jsr testsize ; get size - lda numbanks,y ; # of 64Ks to write - beq clrdone ; no memory - lda #$c0 ; 'A' - 1 - sta $400 ; upper left corner - stz addrl,x ; slinky address 0 - stz addrm,x - stz addrh,x -clbnklp: inc $400 ; poor mans progress meter - ldy #$00 -cl64klp: ldx #$00 ; loop for all pages in bank -cl256lp: txa ; loop for all bytes in page - ldx #rx_devno - stz data,x ; write a zero to card - tax - dex - bne cl256lp ; 256 byte loop - dey - bne cl64klp ; 64K loop - ldx #rx_mslot - dec numbanks,x - bne clbnklp ; if more banks -clrdone: ldx #rx_mslot - stz pwrup,x ; zero powerup byte - lda #$a0 ; ' ' - sta $400 ; clear progress - rts -rdinit: bit rx_mslot*$100 ; activate registers - ldy #rx_mslot ; slot offset - ldx #rx_devno ; register offset - rts +rdclear: jsr rdinit ; init ramcard + jsr testsize ; get size + lda numbanks,y ; # of 64Ks to write + beq clrdone ; no memory + lda #$c0 ; 'A' - 1 + sta $400 ; upper left corner + stz addrl,x ; slinky address 0 + stz addrm,x + stz addrh,x +clbnklp: inc $400 ; poor mans progress meter + ldy #$00 +cl64klp: ldx #$00 ; loop for all pages in bank +cl256lp: txa ; loop for all bytes in page + ldx #rx_devno + stz data,x ; write a zero to card + tax + dex + bne cl256lp ; 256 byte loop + dey + bne cl64klp ; 64K loop + ldx #rx_mslot + dec numbanks,x + bne clbnklp ; if more banks +clrdone: ldx #rx_mslot + stz pwrup,x ; zero powerup byte + lda #$a0 ; ' ' + sta $400 ; clear progress + rts +rdinit: bit rx_mslot*$100 ; activate registers + ldy #rx_mslot ; slot offset + ldx #rx_devno ; register offset + rts ; next is snippet of code to boot external 5.25 -bootext: lda #$e0 - ldy #$01 - ldx #$60 - jmp $c60b +bootext: lda #$e0 + ldy #$01 ; unit # + ldx #$60 ; slot # + jmp $c60b ; jump into Disk II code bt4xend = * +; -------------------------------------------------- +; config getter +; values and locs + ;chktype = $5a ; 'CFG' + chktype = $06 ; 'BIN' - easy to set auxtype with bsave + entbuf = $0280 +; zp locs, safe to use under our circumstances + blkptrl = $06 + blkptrh = blkptrl + 1 + entryl = $08 + nentries = $09 +.proc getcfg + jsr rdinit + lda #$02 ; first block of volume directory + sta blkptrl + stz blkptrh + jsr setblk + lda #$03 ; want this to EOR out to $00 + ldy #$04 ; check 4 bytes +: eor data,x ; check previous blk ptr for zero + dey + bne :- + cmp #$00 ; see if A is 0 + bne nocfg ; not vol dir key block, end of mission + lda #$04 ; where we expect to find volume dir header + sta addrl,x ; set data ptr + lda data,x ; volume directory header first byte + and #$f0 ; mask off length + cmp #$f0 ; storage type is $f? + bne nocfg ; nope, eom + lda #$23 ; offset of directory entry length in block + sta addrl,x + lda data,x ; grab entry length + sta entryl ; save it + ldy data,x ; entries per block + sty nentries ; save it for later + bra nxtbl1 ; skip setting slinky block and nentries, already there +nxtblk: jsr setblk + beq nocfg ; just set block 0, eom + ldy nentries ; restore # entries per block+1 into y +nxtbl1: jsr gnxtblk ; set next block pointer, leave data ptr at offset $04 +nxtent: dey ; next entry, assumes y has # of entries remaining to check + bmi nxtblk ; next block if we dont have any more (hope we don't have more than $7F of them) + jsr rentry ; read directory entry + ; now check storage type and name length + lda entbuf + and #$f0 + beq nxtent ; if storage type = $0 + and #$c0 ; mask out values $1-$3 (normal files) + bne nxtent ; if any other bits set + lda entbuf+$10 ; get type + cmp #chktype ; and check + bne nxtent ; no match, try next entry + lda entbuf ; get storage type and length + and #$0f ; mask in length + cmp #(fname_-fname) ; check length + bne nxtent + phy ; save num entries + tay ; a still has length +mtchlp: lda entbuf,y ; get file name char + cmp fname-1,y ; compare to what we are looking for + bne nomtch ; if no match + dey + bne mtchlp ; check next char + ; we have a match + ply ; discard saved num entries + ldx entbuf+$1f ; low byte of aux type + ldy entbuf+$20 ; high byte of aux type + clc + rts +nomtch: ply ; restore saved num entries + bra nxtent + ; no config found +nocfg: sec + rts +fname: .byte "BOOTX" +fname_ = * +.endproc +; get next block pointer into blkptrl and blkptrh +.proc gnxtblk + lda #$02 ; assumes we are in first half of block + sta addrl,x ; set byte offset + lda data,x ; next block low byte + sta blkptrl + lda data,x ; next block high byte + sta blkptrh + rts +.endproc +; set slinky address to block pointer, address = blk num * 2 * $100 +.proc setblk + stz addrl,x ; zero low byte of slinky address + lda blkptrl ; low byte of block pointer + ; sta $7e0 + asl ; shift left, high bit to c + sta addrm,x ; put into middle byte of slinky address + lda blkptrh ; get high byte of block pointer + ; sta $7e1 + rol ; rotate left, c into bit 0 + sta addrh,x ; set high byte of slinky address + ora addrm,x ; set z flag if we just set block 0 + rts +.endproc +; read a ProDOS directory entry from slinky +.proc rentry + phy ; preserve y + ldy #$00 +: lda data,x + sta entbuf,y + iny + cpy entryl + bne :- + ply + rts +.endproc diff --git a/rom4x/B1_E300_new_bootfail.s b/rom4x/B1_E400_new_bootfail.s similarity index 100% rename from rom4x/B1_E300_new_bootfail.s rename to rom4x/B1_E400_new_bootfail.s diff --git a/rom4x/README.md b/rom4x/README.md new file mode 100644 index 0000000..d444939 --- /dev/null +++ b/rom4x/README.md @@ -0,0 +1,233 @@ +# ROM 4X by MG + +ROM 4X is a collection of enhancements to the Apple //c version 4. See the top level [README.md](../README.md) for more general information on ROM 4X and ROM 5X. + +It adds the following features to the Apple //c and IIc Plus firmware: + + - Identifies and reinstates a *bootable* (it must have something that looks like a boot block!) RAM disk from battery-backed expansion memory (see below), such as the [RAM Express II+](http://a2heaven.com/webshop/index.php?rt=product/product&product_id=144) from A2Heaven. + - Provides a menu of various tools upon pressing Ctrl+Closed-Apple+Reset (or holding Closed-Apple when powering up), that let you: + - Enter the monitor unconditionally. + - Reboot the machine (enter standard boot sequence). + - Zero the RAM card, in case it is corrupted. + - Execute the machine and RAM card diagnostics. + - Tell the machine to boot the SmartPort, the internal floppy drive, or an external floppy drive. + - *New as of 04/25/2017*: By saving a file on the RAM card, control the way the system boots by default. + - The system drops to BASIC if no bootable device is found (this is the default behavior in the IIc Plus). + +# User Guide + +## Installation + +### Real System + +Assuming you already have it burned onto a chip (I use SST27SF512s flash chips which hold 64K and Atmel 27C256, which hold 32K, and program with a TL866), generally the instructions [here](http://mirrors.apple2.org.za/Apple%20II%20Documentation%20Project/Computers/Apple%20II/Apple%20IIc/Manuals/Apple%20IIc%20v4%20ROM%20Upgrade%20Installation.pdf) are relevant. You won't need to cut any traces or solder a jumper unless, you are installing this ROM in an original //c. I don't recommend installing it on a non-memory expansion //c unless you have expansion memory that looks like the 'slinky' memory of the later models. ROM 4X/5X doesn't know about RAMWorks-style expansions. + +Cards known to work with ROM 4X include the Apple Memory Expansion Card (but no battery!), and the A2Heaven [RAM Express II](http://a2heaven.com/webshop/index.php?rt=product/product&product_id=146) for the original //c, and the [RAM Express II+](http://a2heaven.com/webshop/index.php?rt=product/product&product_id=144) for the memory-expandable //c and IIc Plus. + +### Emulator + +#### //c + +Copy the ROM into the appropriate location for your emulator. At the time of writing the only emulator I am aware of that can emulate the //c with memory expansion is [Catakig](http://catakig.sourceforge.net/) for MacOS. It's a bit older of an emulator but it runs fine on newer MacOSes. + +MAME's Apple //c emulation may work, but I have not tried it. + +## Operation + +### Menu + +Power on your machine. Everything should look and work *almost* like it did before. If there is a bootable device somewhere, the machine will boot it. If there is not (and this is one of the noticable changes), you will get dropped to BASIC without the need to press ctrl+reset. If things don't go well, revisit your installation. + +If you don't have an initialized RAM disk, format the card RAM disk with something like Copy II Plus. Put ProDOS and BASIC.SYSTEM on it. Power off the machine, and power it on after a few minutes. You should boot off of the RAM disk. You might notice an "R" flash on the screen for an instant before ProDOS loads. + +Now, press Control+Closed-Apple+Reset, holding down Closed-Apple after releasing reset. You should see the following menu appear (on a //c, IIc Plus menu is more compact to save firmware space): + +``` +0 Monitor +1 Reboot +2 Zero RAM Card and Reboot +3 Diagnostics +4 RAM Card Diagnostics +5 Boot SmartPort +6 Boot Int. 5.25 +7 Boot Ext. 5.25 +``` + +Picking any of the menu options besides 0 results in the menu being cleared, but the bottom line 'ROM 4X mm/dd/yy' immediately reappears to confirm that the new code is taking action. + +What each option does is detailed below. Note that the various device boot options will try that device and any remaining devices in the boot order, which for the Apple //c is RAM card, 5.25 drive, and finally SmartPort. + +#### 0 Monitor + +This drops you unconditionally into the monitor. + +#### 1 Reboot + +This carries out the normal boot sequence, which is to try the RAM disk first, then the internal 5.25 floppy drive, then the first connected smartport device. Some of the other options let you skip over one or more of this ordering. + +#### 2 Zero RAM Card and Reboot + +This zeros out the RAM card memory and the screen holes. This is a nuclear option if the RAM disk is corrupt and the system fails to boot. After selecting 2 the word "SURE?" appears on the screen. At this point you must type `Y` or `y` to continue with the zeroing, or any other key to cancel. + +If there is no card RAM, you are immediately rebooted. Otherwise an 'A' will appear in the upper left corner of the screen and will follow the alphabet as each 64K of the card is cleared. After it completes the letter will disappear and the machine will try booting. + +#### 3 Diagnostics + +This jumps to the //c internal diagnostics that are also run when you press control+both-apples+reset. + +#### 4 RAM Card Diagnostics + +This runs the RAM card diagnostics. When the diagnostics are finished either by user cancel or error, you are dropped into the monitor. + +Since the test may damage data on the card, you are asked to confirm as per option 2 above. + +#### 5 Boot SmartPort + +This attempts to boot the first smartport device, such as a UniDisk 3.5. + +#### 6 Boot Internal 5.25 + +This skips the RAM disk and starts booting with the internal 5.25 drive. + +#### 7 Boot External 5.25 + +This is like option 6, but using an external 5.25 drive. The only OS I am aware of that supports booting this way is ProDOS. + +This destructively copies a short routine to $800, which under most circumstances is also immediately overwritten by the boot sector, so should not be a problem.. + +### Configuration File + +**EXPERIMENTAL** + +If the RAM card is ProDOS-formatted, you can save a binary file in the volume directory called `BOOTX`. ROM 4X will find this file and use the Aux Type field (the load address) to set a default of the menu options above when no option has been selected using the menu. For example, `BSAVE /RAM4/BOOTX,A6,L0` will cause ROM 4X to skip booting the RAM card and go straight to booting the internal floppy drive (menu item 6). The contents of `BOOTX` are irrelevant, only the Aux Type is used. You cannot set it to jump into the monitor because that action happens before the boot code takes over. + +You will know the configuration file is being used because the ROM 4X line will appear on the bottom of the screen and a flashing 'C' will appear in the lower-left corner. + +**WARNING**: You *can* set the `BOOTX` file to clear the RAM card or run the RAM card diagnostics. This will happen exactly once and your RAM disk will be gone. *Caveat emptor*. + +# Build/Develop Guide + +## Build + +To build the new firmware, you must start with a copy of the repository, and obtain a copy of the Apple //c version 4 ROM. The patches to the firmware work with the ROM dump that has sha256sum: + + +``` +8ad5e6c4ed15d09b62183965b6c04762610d4b26510afc1896bdb4ecc55da883 +``` + +It may work with other ROM dumps, it will *not* work with any other ROM versions, including ROM 3 and earlier. You must build ROM 4X using a ROM 4 dump. + +Place the ROM dump in the directory with the other files and name it `iic_rom4.bin`. + +Now you will need a 65C02 cross assembler. The current codebase is developed using ca65 from the [cc65](http://www.cc65.org/) project. (Note: The code was developed originally using [xa](http://www.floodgap.com/retrotech/xa/)). + +Finally you will need [Ruby](https://www.ruby-lang.org/en/) and [Rake](https://github.com/ruby/rake). + +Once you have it all together change to the directory with the source files and original ROM image and type `rake`. + +If all goes well, you will have a shiny new `iic_rom4x.bin` or `iic+_rom5x.bin`. + +If you intend to build an image for a 512-kbit chip such as the SST27SF512, do `rake sf512`. + +## Develop + +### First Thing's First + +First and foremost, it is most helpful to have an emulator. The only one that I have found that can be used for (almost) thorough testing is [Catakig](http://catakig.sourceforge.net/) for MacOS. It can emulate the //c and the Expansion Card (though not battery-backed). + +If you plan to test on a real machine, be aware that the ROM socket is not rated for a large number of insertions and you *will* break something after a while. You may consider putting a machine-pin DIP socket or a ZIF socket into the CPU socket position. This can be done by desoldering the original socket if you have the skills, or by plugging the new socket into the existing CPU socket. If you do do the latter you should consider the new socket permanent as the socket pins are thicker than a ROM chip's and removing it may leave the socket in such a state as to not be able to make good contact with a subsequent chip. + +As for me, I just use the emulator and then I am very careful with changing the ROM when I want to test on the real hardware. For heavy development/testing I insert a low-profile solder-tail ZIF socket into the existing chip socket.. + +### Apple //c Technical Reference and other Documentation + +You need this. + +The Apple //c Technical Reference Manual that is available on the internet has the firmware listing for ROM 3. ROM 4 fixes a few bugs that were in ROM 3, including with the memory card driver. The changes are minor and affect some of the offsets of routines in the RAM card support, but it is easy to figure them out. + +[This](http://www.1000bit.it/support/manuali/apple/technotes/memx/tn.memx.1.html) tech note is also helpful as it documents the screen holes and some of the card behavior including under what conditions it reformats. Though the power2 byte is *not* used by the Apple //c code -- it is commented out in the firmware listings in the Technical Reference. ROM 4X uses it for the menu function. + +[This](http://www.1000bit.it/support/manuali/apple/technotes/aiic/tn.aiic.5.html) technical note is a little less helpful for this project. + +### Magic File Names + +The main source files are named after a pattern, `B#_####_something.s` where the first # represents the bank number (0 = main, 1 = aux), and #### is the location in the bank to patch the code into. E.G. the `B1_E000_rom4.bin`'s object code is loaded into bank 1 at E000. Generally the origin address of the code in the file matches the #### portion of the file name. + +The Rakefile uses this information to patch the original ROM 4 and produce the ROM 4X version. + +### Defs + +One file, `iic.defs` is included by all of the other source files. This has entry points, origins, and various RAM locations defined in it for use by the other source code. + +### Test Scenarios + +#### Basic Functional Tests + + 1. Boot ProDOS from power off. Run SlotScan 1.62 and confirm that the slots are identified as expected, see below. + 2. With no bootable ProDOS RAMdisk, boot the system from power off or ctrl-oa-reset. + 1. With the drop-to-basic patch: + - Expected: The system says "No bootable device" and drops to BASIC. + 2. Without to drop-to-basic patch: + - Expected: The system boots the same as an unmodified ROM 4. + 3. With a bootable ProDOS RAMdisk containing ProDOS, boot the system from power off or ctrl-oa-reset. + - Expected: The system boots from RAM disk, an inverse or flashing R may appear on the left of line 24 of the display. + 4. Power on the system with the ca key pressed or use ctrl-ca-reset. + - Expected: The menu is displayed. + 5. RAM disk recovery: + 1. Battery-backed RAM present with bootable RAM disk: Power off the machine and leave it for 1 hr. Power on. + - Expected: The system boots from RAM disk. + 2. Non-battery-backed RAM present with bootable RAM disk: Erase main RAM from 0300 up (e.g. in monitor: `300:00` then `301<300.BFFEM`) and press ctrl-reset. + - Expected: The system boots from RAM disk. + +Expected SlotScan output: +``` +SlotScan Version 1.62 Copyright 1989-1994 by Robert S. Claney +-------------------------------------------------------------------------------- +Apple Computer Type: //c, ROM Ver 4 (Newer Mem. Exp.) +Processor type: 65c02 +Total RAM: 128K + +-----Scanning for peripherals----- +Port 1: Serial Port (#1) +Port 2: Serial Port (#1) +Port 3: 80-Column Port (#8) +Port 4: RamCard SmartPort: 1 device found + Manufacturer #0 (Unknown) + Device 1: "RAMCARD", Size: 2048 Blocks (1024K, 1 Meg) + Type: Mem. expansion Version: 0.102 + Addl. info: (None) +Port 5: SmartPort: 0 devices found +Port 6: Disk ][ Port + Device Size: 280 Blocks (140K) +Port 7: Mouse Port (#0) + +Done. Press any key to continue, or Control-P to get a printout +``` + + +#### Menu Item Functional Tests + +All cases: When any menu option is selected, the "ROM 4X MM/DD/YY" message is displayed on the bottom of the screen. + + 0. Monitor + - Expected: We are dropped into the monitor immediately. + 1. Reboot + - Expected: System boots as normal. + 2. Zero RAM Card and Reboot + - Expected: Reboot if no card RAM present. Otherwise, counter appears in upper left corner and card RAM is cleared. + 3. Diagnostics + - Expected: System enters built-in diagnostics as if ctrl-oa-ca-reset was pressed. + 4. RAM Card Diagnostics + - Expected: System enters RAM card diagnostics if card RAM present, then/or (no mem) drops to monitor when exited by failure or user escape key. + 5. Boot SmartPort + - Expected: The system boots from a SmartPort device, skipping the RAM card and 5.25 floppy drives. + 6. Boot Internal 5.25 + - Expected: The system boots from the internal 5.25 drive, skipping the RAM card. The system may proceed to the SmartPort if no disk is found. + 7. Boot External 5.25 + - Expected: The system boots from the external 5.25 drive, skipping the RAM card. The system may proceed to the SmartPort if no disk is found. + +### Ideas for Future + + - Replace Apple Slinky code with RamFactor code. (Difficulty: Hard) + diff --git a/rom4x/iic.defs b/rom4x/iic.defs index cb1ac88..c0f7af0 100644 --- a/rom4x/iic.defs +++ b/rom4x/iic.defs @@ -47,7 +47,7 @@ rst4xrtn = $facb ; where to return from reset4x bt4xrtn = $fb19 ; where to return from boot4x reset4x = $e000 ; reset routine boot4x = $e180 ; boot routine -nbtfail = $e300 ; new boot fail +nbtfail = $e400 ; new boot fail banner = $fb60 ; 'Apple //c' testsize = $d99f ; test ramdisk size (rom 3 = $d995) monitor = $ff59 ; monitor diff --git a/rom5x/B1_D516_boot5x.s b/rom5x/B1_D516_boot5x.s index e81236a..4595693 100644 --- a/rom5x/B1_D516_boot5x.s +++ b/rom5x/B1_D516_boot5x.s @@ -1,7 +1,7 @@ .code .psc02 .include "iic+.defs" - .org boot5x ; 234 bytes available, code assembles to 222 + .org boot5x ; 234 bytes available, code assembles to 220 jsr titl5x ; "Apple IIc +" jsr rdrecov ; try to recover ramdisk lda power2 + rx_mslot ; get action saved by reset5x