ROM5X preliminary code

This commit is contained in:
mgcaret 2017-02-12 11:53:47 -08:00
parent cda85678ee
commit adeb5e6b04
15 changed files with 394 additions and 63 deletions

25
notes/mig_notes.txt Normal file
View File

@ -0,0 +1,25 @@
MIG space references in ROM:
CE00-CE1F - MIG RAM window
CE20 - Increment page
CE3D-CE3E - ?
CE40 - write in E4D9,E503,E612,EF02
read in 8E9C,E9A3,E9EB,EA15,EA2D,EA40,EE87,
always around slot 6 I/O accesses.
CE60 - read in routine at E4C7,E8C5,E974,EA6B,EE95
write in routine at E4F2,E612,E652,EF02,EFC6,F54C
always around slot 6 I/O accesses.
CEA0 - Reset page 0
CECD - ? from data
CED5 - ? from data
CF9A - ? from bank switch @C746 prob calling main bannk
CFCF - ? from data
CFFF - leftover from non //c ROM
MIG page usage:
Page 0 - 3.5 ROM - routines at CA12, E51D
CE11 - slot I/O offset of ? (ldy CE11, lda C000,y in routine at CA12)
Page 1 - used by routines at CA71,E54F,E534
Page 2 - Appears used only by accelerator code
Page 3 - used by routines at CA4B, CA71, E1E1, EB8B, ECCF
Page 4+ - used all over the place

27
notes/rom5_zeros.txt Normal file
View File

@ -0,0 +1,27 @@
Inventory of zeros of 5 bytes or more in the IIc Plus ROM
Main Bank
C1FB - 5 bytes
C4EE - 12 bytes
C5F3 - 5 bytes
C6FB - 5 bytes
C9A1 - 9 bytes
CFF9 - 7 bytes
Alt Bank
C572 - 8 bytes
C7FB - 8 bytes
C7FC - 7 bytes
CE00 - 512 bytes not usable (MIG space)
D134 - 76 bytes
D516 - 234 bytes
D6CE - 306 bytes
DB63 - 157 bytes
DE00 - 512 bytes maybe not usable (second mig space?), none of the firmware
touches it.
F72D - 16 bytes not usable (some kind of data table)
F7ED - 19 bytes
FB3C - 196 bytes
FC3C - 12 bytes
FCC9 - 55 bytes
FE96 - 352 bytes, but reserve 65816 vectors

View File

@ -0,0 +1,8 @@
#include "iic+.defs"
.text
* = $cff9 ; 7 bytes available here
lda #$a9 ; lda opcode
nop ; jmp/jsr $cffa does lda #$ea
jmp $fbdf ; jump to bell1 hijack
; total 6 bytes.

View File

@ -0,0 +1,7 @@
; patch PWRUP to call boot5x
#include "iic+.defs"
.text
* = $fab4
nop
jmp gobt5x

View File

@ -0,0 +1,7 @@
; patch RESET.X to call reset5x
#include "iic+.defs"
.text
* = $fac8
jmp gorst5x

View File

@ -0,0 +1,4 @@
.text
* = $fbdf
sta $c028

View File

@ -1,5 +0,0 @@
#include "iic+.defs"
.text
* = $fcde
sta rombank

View File

@ -1,39 +0,0 @@
#include "iic+.defs"
.text
* = rom5x
asl butn1 ; check option key
bcc rd5x ; not pressed, see if RD recoverable
lda #"O" ; flashing "O"
sta $7d0 ; tell user
exit5x lda #>(r5xrtn-1)
pha
lda #<(r5xrtn-1)
pha
ldy #$00 ; in case someone assumes this later
jmp swrts2
rd5x jsr rdinit ; init ram card and registers
lda pwrup,y ; get power up flag
cmp #pwrbyte ; already initialized?
beq exit5x ; exit if so
jsr testsize ; does not wreck x or y
lda numbanks,y ; get discovered # banks
beq exit5x ; no memory
stz addrl,x ; set slinky address 0
stz addrm,x
stz addrh,x
lda data,x ; get first byte
cmp #$01 ; boot block?
bne exit5x ; nope
lda data,x ; next byte
beq exit5x ; not bootable if 0
cmp #$ff ; other likely byte for fresh RAM
beq exit5x ; not bootable if $ff
lda #pwrbyte ; sta pwrup,y
lda #"R" ; tell user
sta $7d0 ; on screen
bra exit5x
rdinit bit rx_mslot*$100 ; activate registers
ldy #rx_mslot ; slot offset
ldy #rx_devno ; register offset
rts

112
rom5x/B1_D516_boot5x.s Normal file
View File

@ -0,0 +1,112 @@
#include "iic+.defs"
.text
* = boot5x ; 234 bytes available, code assembles to 231 when
; next line uncommented
; jsr ntitle ; TODO "Apple IIc +"
jsr rdrecov ; try to recover ramdisk
lda power2 + rx_mslot ; get action saved by reset5x
beq boot4 ; if zero, continue boot
jsr bann5x ; display ROM 5X footer
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
btc5 cmp #$05 ; boot smartport
beq boot5
; fall through if none of the above
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 lda #>(bt5xrtn-1)
pha
lda #<(bt5xrtn-1)
pha
lda $1
jmp swrts2
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
; next is snippet of code to boot external 5.25
bootext lda #$e0
ldy #$01
ldx #$60
jmp $c60b
bt4xend = *

View File

@ -0,0 +1,90 @@
#include "iic+.defs"
.text
* = misc5x ; max 306 bytes
bra domenu
bra dobann
bra gtkey
bra confirm
dobann jsr ntitle
ldx #(msg2-msg1) ; msg display entry point
jmp disp
domenu jsr ntitle ; "Apple ||c +"
ldx #$00 ; menu start
jsr disp ; show it
rts
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 #$40
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
; display "Apple IIc +" in a convoluted manner
; ultimately, the rts instruction here "rts" to swrts2
; which switches banks and "rts" to the title/banner firmware call
; which then "rts" to swrts (same addr as swrts2, but main bank)
; which then actually rts to our caller
ntitle lda #>(swrts2-1) ; put return addr of swrts2 on stack
pha
lda #<(swrts2-1)
pha
lda #>(banner-1)
pha
lda #<(banner-1)
pha
lda #>(swrts2-1)
pha
lda #<(swrts2-1)
pha
rts ; jump to swrts2
; 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 = *
.db $05,$06,"0 Monitor"
.db $05,$86,"1 Reboot"
.db $06,$06,"2 Zero RAM Card"
.db $06,$86,"3 Sys Diags"
.db $07,$06,"4 RAM Card Diags"
.db $07,$86,"5 Boot 3.5/SmartPort"
.db $04,$2e,"6 Boot 5.25"
; .db $04,$ae,"7 Accelerator"
.db $07,$5f,"By M.G."
msg2 .db $07,$db,"ROM 5X 02/08/17"
.db $05,$ae,$00 ; cursor pos in menu
msg3 .db $05,$b0,"SURE? ",$00

42
rom5x/B1_DB63_reset5x.s Normal file
View File

@ -0,0 +1,42 @@
#include "iic+.defs"
.text
* = reset5x ; max 157 bytes
stz power2 + rx_mslot ; action = normal reset
lda #>(rst5xrtn-1) ; common case
pha
lda #<(rst5xrtn-1)
pha ; note that this stays on stack
asl butn1 ; closed apple
bcs ckdiag
exitrst jmp swrts2
; check to see if both apples are down
ckdiag bit butn0 ; open apple
bmi exitrst ; return to RESET.X
; present menu because only closed apple is down
menu jsr menu5x ; display menu
jsr gkey5x
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 conf5x
bne menu ; go back to menu4x
ckkey2 sec
sbc #$b0 ; ascii->number
bmi menu ; < 0 not valid
cmp #$08 ; we will use 7 for accelerator later
bpl menu ; > 7 not valid
sta power2 + rx_mslot ; for boot5x
stz softev + 1 ; deinit coldstart
stz pwerdup ; ditto
bra exitrst

View File

@ -0,0 +1,17 @@
#include "iic+.defs"
.text
* = $fbe2 ; ~29 bytes free here
cmp #$a9 ; reset patch
bne chk2
jmp reset5x
chk2: cmp #$ea ; boot patch
bne dowait
jmp boot5x
dowait: jsr $fcb5 ; do delay if anything else
lda #>($fbe2-1)
pha
lda #<($fbe2-1)
pha
lda #$00 ; in case someone assumes this
jmp swrts2
; 28 bytes, will have to move if we get bigger

View File

@ -1,6 +0,0 @@
#include "iic+.defs"
.text
* = $fce1
sta set80col ; instruction we patched over
jmp rom5x

View File

@ -1,18 +1,26 @@
# ROM 5X by MG
## DO NOT EVEN TRY THIS YET :-)
## PRELIMINARY, DO NOT EVEN TRY THIS YET :-)
**Warning:** This has not been tested on an emulator or a real Apple IIc Plus.
This is a patch for the Apple IIc Plus firmware that tries to recover a battery-backed
RAM disk upon cold start. Because of the limited space in the Apple IIc ROM. it does not
have the complete feature set of ROM 4X for the (non-Plus) //c.
This is ROM4X revised to the Apple IIc Plus ROM version 5.
Upon cold start, the patch checks for a potentially bootable RAM disk and restores the
appropriate screen holes to prevent it from being destroyed and to enable boot. If a
RAMdisk is recovered, a flashing "R" will appear in the lower left corner of the screen.
There are almost no free bytes in the main bank of the IIc Plus firmware, so
I had to get creative to get into the alternate bank, where I then had to split
the code up across multiple smaller free spaces. Ironically this makes the
code larger as well.
For those interested, I hijack the monitor BEEP1 routine. The beep routine has
an LDA #$40 and then calls WAIT with this value for a .1 second delay,
presumably so that multiple beeps are distinct from each other.
I patch the JSR WAIT to be STA $C028, which switches to the other bank.
The code in the other bank checks the accumulator and for two values calls
either reset5x or boot5x, and for any other value executes the WAIT (assuming
that we got there from BEEP1).
Then, in only 6 bytes I can create two entry points that load the value into
A that we need for the reset or boot routines, and then jump to the above patch.
To prevent the check and recovery, power on the machine with the Option key held down.
A flashing "O" will appear in the lower left corner of the screen and the system will
boot without checking for or recovering any RAM disk.

View File

@ -1,8 +1,10 @@
; hardware
set80col = $c001
;set80col = $c001
rombank = $c028
butn0 = $c061
butn1 = $c062
kbd = $c000
kbdstrb = $c010
addrl = $bff8
addrm = $bff9
addrh = $bffa
@ -20,8 +22,13 @@ sl_scrn7 = $778 - $c0
sl_scrn8 = $7f8 - $c0
numbanks = sl_scrn1
pwrup = sl_scrn7
power2 = sl_scrn8
sl_devno = $778
; locations
softev = $3f2
pwerdup = $3f4
; values
pwrbyte = $a5
rx_slot = $4
@ -29,8 +36,35 @@ rx_mslot = rx_slot + $c0
rx_devno = rx_slot * $10 + $88
; entry points
r5xrtn = $fce1
rom5x = $cf00
gorst5x = $cff9
gobt5x = $cffa
rst5xrtn = $facb
bt5xrtn = $fb19
reset5x = $db63
boot5x = $d516
testsize = $d99f
swrts2 = $c784
monitor = $ff59
misc5x = $d6ce
menu5x = misc5x
bann5x = menu5x+2
gkey5x = bann5x+2
conf5x = gkey5x+2
banner = $fb60
; macros
#define psa(addr) \
lda #>(addr-1) \
pha \
lda #<(addr-1) \
pha \
jsr swrts2
#define rtj(addr) \
psa(addr) \
rts
#define rtl(addr) \
psa(addr) \
jmp swrts2