4X: create README.md specifically for 4X, add experimental config file support

This commit is contained in:
mgcaret 2017-04-25 20:10:02 -07:00
parent ce5f476f64
commit fdbb458ec6
5 changed files with 560 additions and 201 deletions

View File

@ -1,216 +1,342 @@
.psc02 .psc02
.code .code
.include "iic.defs" .include "iic.defs"
.org reset4x .org reset4x
stz power2 + rx_mslot ; action = normal boot stz power2 + rx_mslot ; action = normal boot
asl butn1 ; closed apple asl butn1 ; closed apple
bcs ckdiag bcs ckdiag
exitrst: jmp gorst4x ; return to RESET.X exitrst: jmp gorst4x ; return to RESET.X
; check to see if both apples are down ; check to see if both apples are down
ckdiag: bit butn0 ; open apple ckdiag: bit butn0 ; open apple
bmi exitrst ; return to RESET.X bmi exitrst ; return to RESET.X
; present menu because only closed apple is down ; present menu because only closed apple is down
menu4x: jsr gobanner ; "Apple //c" menu4x: jsr gobanner ; "Apple //c"
ldx #$00 ; menu start ldx #$00 ; menu start
jsr disp ; show it jsr disp ; show it
jsr gtkey jsr gtkey
cmp #$b0 ; "0" cmp #$b0 ; "0"
bne ckkey1 bne ckkey1
ldx #$ff ; reset stack ldx #$ff ; reset stack
txs txs
lda #>(monitor-1) ; monitor entry on stack lda #>(monitor-1) ; monitor entry on stack
pha pha
lda #<(monitor-1) lda #<(monitor-1)
pha pha
jmp swrts2 ; rts to enter monitor jmp swrts2 ; rts to enter monitor
ckkey1: cmp #$b2 ; "2" ckkey1: cmp #$b2 ; "2"
beq doconf beq doconf
cmp #$b4 ; "4" cmp #$b4 ; "4"
bne ckkey2 bne ckkey2
doconf: jsr confirm doconf: jsr confirm
bne menu4x ; go back to menu4x bne menu4x ; go back to menu4x
ckkey2: sec ckkey2: sec
sbc #$b0 ; ascii->number sbc #$b0 ; ascii->number
bmi menu4x ; < 0 not valid bmi menu4x ; < 0 not valid
cmp #$08 cmp #$08
bpl menu4x ; > 7 not valid bpl menu4x ; > 7 not valid
sta power2 + rx_mslot ; for boot4x sta power2 + rx_mslot ; for boot4x
stz softev + 1 ; deinit coldstart stz softev + 1 ; deinit coldstart
stz pwerdup ; ditto stz pwerdup ; ditto
bra exitrst bra exitrst
gtkey: lda #$60 gtkey: lda #$60
sta ($0),y ; cursor sta ($0),y ; cursor
sta kbdstrb ; clr keyboard sta kbdstrb ; clr keyboard
kbdin: lda kbd ; get key kbdin: lda kbd ; get key
bpl kbdin bpl kbdin
sta kbdstrb ; clear keyboard sta kbdstrb ; clear keyboard
sta ($0),y ; put it on screen sta ($0),y ; put it on screen
rts rts
; display message, input x = message start relative to msg1 ; display message, input x = message start relative to msg1
disp: stz $0 ; load some safe defaults disp: stz $0 ; load some safe defaults
lda #$04 lda #$04
sta $1 sta $1
ldy #$0 ; needs to be zero ldy #$0 ; needs to be zero
disp0: lda msg1,x ; get message byte disp0: lda msg1,x ; get message byte
bne disp1 ; proceed if nonzero bne disp1 ; proceed if nonzero
rts ; exit if 0 rts ; exit if 0
disp1: inx ; next byte either way disp1: inx ; next byte either way
cmp #$20 ; ' ' cmp #$20 ; ' '
bcc disp2 ; start of ptr if < 20 bcc disp2 ; start of ptr if < 20
eor #$80 ; invert high bit eor #$80 ; invert high bit
sta ($0),y ; write to mem sta ($0),y ; write to mem
inc $0 ; inc address low byte inc $0 ; inc address low byte
bra disp0 ; back to the beginning bra disp0 ; back to the beginning
disp2: sta $1 ; write address high disp2: sta $1 ; write address high
lda msg1,x ; get it lda msg1,x ; get it
sta $0 ; write address low sta $0 ; write address low
inx ; set next msg byte inx ; set next msg byte
bra disp0 ; back to the beginning bra disp0 ; back to the beginning
confirm: pha confirm: pha
ldx #(msg3-msg1) ; ask confirm ldx #(msg3-msg1) ; ask confirm
jsr disp jsr disp
jsr gtkey jsr gtkey
plx plx
ora #$20 ; to lower ora #$20 ; to lower
cmp #$f9 ; "y" cmp #$f9 ; "y"
php php
txa txa
plp plp
rts rts
; msg format ; msg format
; A byte < $20 indicates high byte of address. ; A byte < $20 indicates high byte of address.
; Next byte must be low byte of address. Anything ; Next byte must be low byte of address. Anything
; else are characters to display and will have their ; else are characters to display and will have their
; upper bit inverted before being written to the screen. ; upper bit inverted before being written to the screen.
msg1 = * msg1 = *
.byte $05,$06,"0 Monitor" .byte $05,$06,"0 Monitor"
.byte $05,$86,"1 Reboot" .byte $05,$86,"1 Reboot"
.byte $06,$06,"2 Zero RAM Card and Reboot" .byte $06,$06,"2 Zero RAM Card and Reboot"
.byte $06,$86,"3 Diagnostics" .byte $06,$86,"3 Diagnostics"
.byte $07,$06,"4 RAM Card Diagnostics" .byte $07,$06,"4 RAM Card Diagnostics"
.byte $07,$86,"5 Boot SmartPort" .byte $07,$86,"5 Boot SmartPort"
.byte $04,$2e,"6 Boot Int. 5.25" .byte $04,$2e,"6 Boot Int. 5.25"
.byte $04,$ae,"7 Boot Ext. 5.25" .byte $04,$ae,"7 Boot Ext. 5.25"
.byte $07,$5f,"By M.G." .byte $07,$5f,"By M.G."
msg2: .byte $07,$db,"ROM 4X 04/08/17" msg2: .byte $07,$db,"ROM 4X 04/08/17"
.byte $05,$ae,$00 ; cursor pos in menu .byte $05,$ae,$00 ; cursor pos in menu
msg3: .byte $05,$b0,"SURE? ",$00 msg3: .byte $05,$b0,"SURE? ",$00
.res boot4x - *, 0 .res boot4x - *, 0
.org boot4x .org boot4x
jsr gobanner ; "Apple //c" jsr gobanner ; "Apple //c"
jsr rdrecov ; try to recover ramdisk jsr rdrecov ; try to recover ramdisk
lda power2 + rx_mslot ; get action saved by reset4x lda power2 + rx_mslot ; get action saved by reset4x
beq boot4 ; if zero, continue boot beq :+
ldx #(msg2-msg1) ; short banner offset pha ; save it
jsr disp ; display it bra selboot ; set, go do it
lda power2 + rx_mslot ; boot selection : lda numbanks,y ; (y should be OK here) ram card present?
btc2: cmp #$02 ; clear ramcard beq boot6 ; nope, boot slot 6
bne btc3 jsr getcfg ; try to get config
jsr rdclear ; do clear bcs boot4 ; no config, normal boot
bra boot4 ;stx $7d2
btc3: cmp #$03 ; Diags ;sty $7d3
bne btc4 phx ; config present, move on
jmp $c7c4 lda #'C' ; tell user
btc4: cmp #$04 ; RX diags sta $7d1 ; on screen
bne btc5 selboot: ldx #(msg2-msg1) ; short banner offset
ldx #$ff jsr disp ; display it
txs ; reset stack pla ; boot selection
jsr rdinit ; get x and y loaded sta $7d2
stx sl_devno ; diags need this btc2: cmp #$02 ; clear ramcard
jsr testsize ; compute card size bne btc3
lda #>(monitor-1) ; load "return" address jsr rdclear ; do clear
pha ; into stack so that we bra boot4
lda #<(monitor-1) ; exit card test into btc3: cmp #$03 ; Diags
pha ; the monitor bne btc4
lda numbanks,y ; get the card size in banks jmp $c7c4
bne dordiag ; do diag if memory present btc4: cmp #$04 ; RX diags
jmp swrts2 ; otherwise jump to monitor bne btc5
dordiag: jmp $db3a ; diags ldx #$ff
;bra boot4 txs ; reset stack
btc5: cmp #$05 ; boot smartport jsr rdinit ; get x and y loaded
beq boot5 stx sl_devno ; diags need this
btc6: cmp #$06 ; boot int drive jsr testsize ; compute card size
beq boot6 lda #>(monitor-1) ; load "return" address
btc7: cmp #$07 ; boot ext drive pha ; into stack so that we
bne boot4 ; none of the above lda #<(monitor-1) ; exit card test into
; copy small routine to $800 to boot pha ; the monitor
; external 5.25 lda numbanks,y ; get the card size in banks
ldy #(bt4xend-bootext+1) bne dordiag ; do diag if memory present
btc7lp: lda bootext,y jmp swrts2 ; otherwise jump to monitor
sta $800,y dordiag: jmp $db3a ; diags
dey ;bra boot4
bpl btc7lp btc5: cmp #$05 ; boot smartport
lda #$08 ; copy done beq boot5
bra bootsl btc6: cmp #$06 ; boot int drive
boot4: lda #rx_mslot ; boot slot 4 beq boot6
bra bootsl btc7: cmp #$07 ; boot ext drive
boot5: lda #$c5 ; boot slot 5 bne boot4 ; none of the above
bra bootsl ; copy small routine to $800 to boot
boot6: lda #$c6 ; boot slot 6 ; external 5.25
bootsl: ldx #$00 ; low byte of slot ldy #(bt4xend-bootext+1)
bootadr: stx $0 ; store address btc7lp: lda bootext,y
sta $1 ; return to bank 0 does jmp (0) sta $800,y
endbt4x: jmp gobt4x ; continue boot dey
rdrecov: jsr rdinit ; init ramcard bpl btc7lp
lda pwrup,y ; get power up flag lda #$08 ; copy done
cmp #pwrbyte ; already initialized? bra bootsl
beq recovdn ; exit if initialized boot4: lda #rx_mslot ; boot slot 4
jsr testsize ; does not wreck x or y bra bootsl
lda numbanks,y ; get discovered # banks boot5: lda #$c5 ; boot slot 5
beq recovdn ; no mem bra bootsl
stz addrl,x ; set slinky address 0 boot6: lda #$c6 ; boot slot 6
stz addrm,x bootsl: ldx #$00 ; low byte of slot
stz addrh,x bootadr: stx $0 ; store address
lda data,x ; start check for bootable ramdisk sta $1 ; return to bank 0 does jmp (0)
cmp #$01 endbt4x: jmp gobt4x ; continue boot
bne recovdn ; not bootable rdrecov: jsr rdinit ; init ramcard
lda data,x ; next byte should be nonzero and not $ff lda pwrup,y ; get power up flag
beq recovdn ; not bootable cmp #pwrbyte ; already initialized?
cmp #$ff beq recovdn ; exit if initialized
beq recovdn ; not bootable jsr testsize ; does not wreck x or y
lda #pwrbyte lda numbanks,y ; get discovered # banks
sta pwrup,y ; set power byte beq recovdn ; no mem
lda #'R' ; tell user stz addrl,x ; set slinky address 0
sta $7d0 ; on screen stz addrm,x
recovdn: rts 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 ; zero ram card space
rdclear: jsr rdinit ; init ramcard rdclear: jsr rdinit ; init ramcard
jsr testsize ; get size jsr testsize ; get size
lda numbanks,y ; # of 64Ks to write lda numbanks,y ; # of 64Ks to write
beq clrdone ; no memory beq clrdone ; no memory
lda #$c0 ; 'A' - 1 lda #$c0 ; 'A' - 1
sta $400 ; upper left corner sta $400 ; upper left corner
stz addrl,x ; slinky address 0 stz addrl,x ; slinky address 0
stz addrm,x stz addrm,x
stz addrh,x stz addrh,x
clbnklp: inc $400 ; poor mans progress meter clbnklp: inc $400 ; poor mans progress meter
ldy #$00 ldy #$00
cl64klp: ldx #$00 ; loop for all pages in bank cl64klp: ldx #$00 ; loop for all pages in bank
cl256lp: txa ; loop for all bytes in page cl256lp: txa ; loop for all bytes in page
ldx #rx_devno ldx #rx_devno
stz data,x ; write a zero to card stz data,x ; write a zero to card
tax tax
dex dex
bne cl256lp ; 256 byte loop bne cl256lp ; 256 byte loop
dey dey
bne cl64klp ; 64K loop bne cl64klp ; 64K loop
ldx #rx_mslot ldx #rx_mslot
dec numbanks,x dec numbanks,x
bne clbnklp ; if more banks bne clbnklp ; if more banks
clrdone: ldx #rx_mslot clrdone: ldx #rx_mslot
stz pwrup,x ; zero powerup byte stz pwrup,x ; zero powerup byte
lda #$a0 ; ' ' lda #$a0 ; ' '
sta $400 ; clear progress sta $400 ; clear progress
rts rts
rdinit: bit rx_mslot*$100 ; activate registers rdinit: bit rx_mslot*$100 ; activate registers
ldy #rx_mslot ; slot offset ldy #rx_mslot ; slot offset
ldx #rx_devno ; register offset ldx #rx_devno ; register offset
rts rts
; next is snippet of code to boot external 5.25 ; next is snippet of code to boot external 5.25
bootext: lda #$e0 bootext: lda #$e0
ldy #$01 ldy #$01 ; unit #
ldx #$60 ldx #$60 ; slot #
jmp $c60b jmp $c60b ; jump into Disk II code
bt4xend = * 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

233
rom4x/README.md Normal file
View File

@ -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)

View File

@ -47,7 +47,7 @@ rst4xrtn = $facb ; where to return from reset4x
bt4xrtn = $fb19 ; where to return from boot4x bt4xrtn = $fb19 ; where to return from boot4x
reset4x = $e000 ; reset routine reset4x = $e000 ; reset routine
boot4x = $e180 ; boot routine boot4x = $e180 ; boot routine
nbtfail = $e300 ; new boot fail nbtfail = $e400 ; new boot fail
banner = $fb60 ; 'Apple //c' banner = $fb60 ; 'Apple //c'
testsize = $d99f ; test ramdisk size (rom 3 = $d995) testsize = $d99f ; test ramdisk size (rom 3 = $d995)
monitor = $ff59 ; monitor monitor = $ff59 ; monitor

View File

@ -1,7 +1,7 @@
.code .code
.psc02 .psc02
.include "iic+.defs" .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 titl5x ; "Apple IIc +"
jsr rdrecov ; try to recover ramdisk jsr rdrecov ; try to recover ramdisk
lda power2 + rx_mslot ; get action saved by reset5x lda power2 + rx_mslot ; get action saved by reset5x