From 1cf35fd0f8d86e298982ca42f4f5ef942aa7d633 Mon Sep 17 00:00:00 2001 From: mgcaret Date: Tue, 3 Jan 2017 18:43:31 -0800 Subject: [PATCH] Initial code commit --- .gitignore | 6 + rom4x/B0_C763_switcher.s | 12 ++ rom4x/B0_FAB4_patch_pwrup.s | 7 ++ rom4x/B0_FAC8_patch_reset.s | 7 ++ rom4x/B1_C763_switcher.s | 13 ++ rom4x/B1_E000_rom4x.s | 228 ++++++++++++++++++++++++++++++++++++ rom4x/Rakefile | 49 ++++++++ rom4x/iic.defs | 53 +++++++++ 8 files changed, 375 insertions(+) create mode 100644 .gitignore create mode 100644 rom4x/B0_C763_switcher.s create mode 100644 rom4x/B0_FAB4_patch_pwrup.s create mode 100644 rom4x/B0_FAC8_patch_reset.s create mode 100644 rom4x/B1_C763_switcher.s create mode 100644 rom4x/B1_E000_rom4x.s create mode 100644 rom4x/Rakefile create mode 100644 rom4x/iic.defs diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..dadb520 --- /dev/null +++ b/.gitignore @@ -0,0 +1,6 @@ +*.o65 +*.lbl +*.bin +*.swp +copyrom.sh + diff --git a/rom4x/B0_C763_switcher.s b/rom4x/B0_C763_switcher.s new file mode 100644 index 0000000..fc61f20 --- /dev/null +++ b/rom4x/B0_C763_switcher.s @@ -0,0 +1,12 @@ +#include "iic.defs" +.text +* = gorst4x + sta rombank ; gorst4x + jmp rst4xrtn ; in other bank jmp reset4x + sta rombank ; gobt4x + jmp bt4xrtn ; in other bank jmp boot4x + sta rombank ; gobanner + jsr banner ; in other bank jmp $c784 for now + sta rombank ; return to other bank + rts ; should never get here + diff --git a/rom4x/B0_FAB4_patch_pwrup.s b/rom4x/B0_FAB4_patch_pwrup.s new file mode 100644 index 0000000..3b76299 --- /dev/null +++ b/rom4x/B0_FAB4_patch_pwrup.s @@ -0,0 +1,7 @@ +; patch PWRUP to call boot4x + +#include "iic.defs" +.text +* = $fab4 + nop + jmp gobt4x diff --git a/rom4x/B0_FAC8_patch_reset.s b/rom4x/B0_FAC8_patch_reset.s new file mode 100644 index 0000000..3bfd4cf --- /dev/null +++ b/rom4x/B0_FAC8_patch_reset.s @@ -0,0 +1,7 @@ +; patch RESET.X to call reset4x + +#include "iic.defs" +.text +* = $fac8 + jmp gorst4x + diff --git a/rom4x/B1_C763_switcher.s b/rom4x/B1_C763_switcher.s new file mode 100644 index 0000000..149ecee --- /dev/null +++ b/rom4x/B1_C763_switcher.s @@ -0,0 +1,13 @@ +#include "iic.defs" +.text +* = gorst4x + sta rombank ; gorst4x + jmp reset4x ; in other bank jmp rstxrtn + sta rombank ; gobt4x + jmp boot4x + sta rombank ; gobanner + jmp $c784 ; in other bank jsr appleii + sta rombank + rts ; not in other bank + + diff --git a/rom4x/B1_E000_rom4x.s b/rom4x/B1_E000_rom4x.s new file mode 100644 index 0000000..b604029 --- /dev/null +++ b/rom4x/B1_E000_rom4x.s @@ -0,0 +1,228 @@ +#include "iic.defs" +.text +* = 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 +; 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 ons tack + 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 #$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 +; msg format +; high bit set indicates high byte of address +; this bit is inverted before use. Next byte must be +; low byte of address. Anything else are characters to +; display and will have their upper bit set before +; being written to the screen. +msg1 = * + .db $05,$06,"0 Monitor" + .db $05,$86,"1 Reboot" + .db $06,$06,"2 Zero RAM Card and Reboot" + .db $06,$86,"3 Diagnostics" + .db $07,$06,"4 RAM Card Diagnostics" + .db $07,$86,"5 Boot SmartPort" + .db $04,$2e,"6 Boot Int. 5.25" + .db $04,$ae,"7 Boot Ext. 5.25" + .db $07,$5f,"By M.G." +msg2 .db $07,$db,"ROM 4X 01/01/17" + .db $05,$ae,$00 ; cursor pos in menu +msg3 .db $05,$b0,"SURE? ",$00 + .dsb boot4x - *, 0 +* = boot4x + jsr gobanner ; "Apple //c" + 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 + jsr rdrecov ; try to recover ramdisk + 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 + ldy #rx_mslot ; diag routine needs + ldx #rx_devno ; ditto + 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 $300 to boot + ; external 5.25 + ldy #(bt4xend-bootext+1) +btc7lp lda bootext,y + sta $300,y + dey + bpl btc7lp + lda #$03 ; copy done + ldx #$00 + bra bootadr +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 ldy #rx_mslot ; attempt to recover ramdisk + ldx #rx_devno + lda pwrup,y ; get power up flag + cmp #pwrbyte ; already initialized? + bne checkrd ; continue if not initialized + rts ; exit if initialized +checkrd jsr testsize ; does not wreck x or y + lda numbanks,y ; get discovered # banks + bne ckrd1 ; continue if size > 0 + rts ; exit if no mem +ckrd1 stz addrl,x ; set slinky address 0 + stz addrm,x + stz addrh,x + lda data,x ; start compare to ProDOS boot block + cmp #$01 + beq ckrd2 + rts ; not ProDOS +ckrd2 lda data,x + cmp #$38 + beq ckrd3 + rts ; not ProDOS +ckrd3 lda data,x + cmp #$b0 + beq dorecov + rts ; not ProDOS +dorecov lda #pwrbyte + sta pwrup,y ; set power byte + lda "R" ; tell user + sta $7d0 ; on screen + rts +; zero ram card space +rdclear ldy #rx_mslot + ldx #rx_devno + jsr testsize ; get size + lda #$c0 ; 'A' - 1 + sta $400 ; upper left corner + lda #$00 ; we are going to write this everywhere + sta addrl,x ; slinky address 0 + sta addrm,x + sta addrh,x + ldx numbanks,y ; # of 64Ks to write + beq clrdone ; no memory +clbnklp phx ; wish the 65xx had more registers + inc $400 ; poor mans progress meter + ldy #$00 +cl64klp ldx #$00 ; loop for all pages in bank +cl256lp phx ; loop for all bytes in page + ldx #rx_devno ; more registers, please! + sta data,x ; write a zero to card + plx + dex + bne cl256lp + dey + bne cl64klp + plx + dex + beq clrdone + bra clbnklp +clrdone ldy #rx_mslot + sta pwrup,y ; zero screen holes + sta numbanks,y + lda #$a0 ; ' ' + sta $400 ; clear progress + rts +; next is snippet of code to boot external 5.25 +bootext sei + lda #$e0 + ldy #$01 + ldx #$60 + jmp $c60b +bt4xend = * + + diff --git a/rom4x/Rakefile b/rom4x/Rakefile new file mode 100644 index 0000000..ecb1d4e --- /dev/null +++ b/rom4x/Rakefile @@ -0,0 +1,49 @@ +source_rom = "iic_rom4.bin" +dest_rom = "iic_rom4x.bin" +rom_base = 0xc000 + +source_files = Rake::FileList.new('*.s') + +desc "Default: clean and build it" +task :default => [:clean, :assemble, :build_rom] do + sh "ls -l #{dest_rom}" +end + +desc "Clean object files" +task :clean do + sh "rm -f #{dest_rom}" + sh "rm -f *.o65" + sh "rm -f *.o65.lbl" +end + +desc "Assemble all source files" +task :assemble => source_files.ext('.o65') + +rule ".o65" => ".s" do |t| + sh "xa -c -o #{t.name} -l #{t.name}.lbl #{t.source}" +end + +desc "Build ROM" +task :build_rom => [:assemble] do + puts "Building ROM image..." + obj_files = Rake::FileList.new('*.o65') + rom = File.read(source_rom) + obj_files.each do |t| + if t =~ /B(\h)_(\h{4})/ + bnum = $1.to_i(16) + badd = $2.to_i(16) + addr = bnum * 16384 + badd - rom_base + puts "Loading #{t} into bank #{bnum} @ #{badd.to_s(16)}, file addr #{addr.to_s(16)}" + fc = File.read(t) + fc.each_byte do |b| + rom.setbyte(addr, b) + addr += 1 + end + else + puts "I dont know where to load #{t}" + end + end + File.write(dest_rom, rom) + puts "ROM image done: #{dest_rom}" +end + diff --git a/rom4x/iic.defs b/rom4x/iic.defs new file mode 100644 index 0000000..e2f4c54 --- /dev/null +++ b/rom4x/iic.defs @@ -0,0 +1,53 @@ +; hardware +rombank = $c028 +butn0 = $c061 +butn1 = $c062 +kbd = $c000 +kbdstrb = $c010 +addrl = $bff8 +addrm = $bff9 +addrh = $bffa +data = $bffb + +; screen holes +; same as //c firmware listing, need to add $c4 for mem card in slot 4 +sl_scrn1 = $478 - $c0 +sl_scrn2 = $4f8 - $c0 +sl_scrn3 = $578 - $c0 +sl_scrn4 = $5f8 - $c0 +sl_scrn5 = $678 - $c0 +sl_scrn6 = $6f8 - $c0 +sl_scrn7 = $778 - $c0 +sl_scrn8 = $7f8 - $c0 +numbanks = sl_scrn1 +pwrup = sl_scrn7 +; next loc is commented in firmware listing, but apple engineers +; planned on a more sophisticated power-up check that they didn't do +; we will repurpose this to store selected closed-apple menu item +power2 = sl_scrn8 +sl_devno = $778 + +; locations +softev = $3f2 +pwerdup = $3f4 + +; values +pwrbyte = $a5 +rx_slot = $4 +rx_mslot = rx_slot + $c0 +rx_devno = rx_slot * $10 + $88 + +; entry points +gorst4x = $c763 ; switch to/from reset4x +gobt4x = gorst4x + 6 ; switch to/from boot4x +gobanner = gobt4x + 6 ; banner from bank 1 +rst4xrtn = $facb ; where to return from reset4x +;bt4xrtn = $fb12 ; where to return from boot4x +bt4xrtn = $fb19 ; where to return from boot4x +reset4x = $e000 ; reset routine +boot4x = $e180 ; boot routine +banner = $fb60 ; 'Apple //c' +testsize = $d99f ; test ramdisk size (rom 3 = $d995) +monitor = $ff59 ; monitor +swrts2 = $c784 ; switch firmware and rts +