From 73b2b6f9184d8dbae2f1909341b92891d26e17b6 Mon Sep 17 00:00:00 2001 From: Michael Guidero Date: Thu, 7 Feb 2019 14:26:55 -0800 Subject: [PATCH] initial --- .gitignore | 16 ++++ common/iiee.defs | 70 ++++++++++++++ common/pickboot.s | 50 ++++++++++ common/romx_main.s | 132 +++++++++++++++++++++++++ common/slotscan.s | 109 +++++++++++++++++++++ no_diags/B0_C600_romx_main.s | 39 ++++++++ no_diags/B0_D8F0_patch_vartio.s | 36 +++++++ no_diags/B0_FAB6_patch_pwrup.s | 7 ++ no_diags/B0_FD75_patch_getln1.s | 6 ++ no_diags/Rakefile | 165 ++++++++++++++++++++++++++++++++ no_diags/iiee.defs | 4 + no_tape/B0_C2C0_patch_resetx.s | 6 ++ no_tape/B0_C500_romx_main.s | 7 ++ no_tape/B0_D034_kill_shload.s | 2 + no_tape/B0_D04E_kill_recall.s | 2 + no_tape/B0_D050_kill_store.s | 2 + no_tape/B0_D06C_kill_load.s | 2 + no_tape/B0_D06E_kill_save.s | 2 + no_tape/B0_D8B0_slotscan.s | 5 + no_tape/B0_F39F_pickboot.s | 6 ++ no_tape/B0_F77B_no_shload_jmp.s | 7 ++ no_tape/B0_F7E4_fix_getarypt.s | 2 + no_tape/B0_FAB6_patch_pwrup.s | 7 ++ no_tape/B0_FCCC_no_mon_headr.s | 5 + no_tape/B0_FD75_patch_getln1.s | 6 ++ no_tape/B0_FECD_mon_write.s | 9 ++ no_tape/B0_FEFD_mon_read.s | 12 +++ no_tape/Rakefile | 165 ++++++++++++++++++++++++++++++++ no_tape/iiee.defs | 4 + 29 files changed, 885 insertions(+) create mode 100644 .gitignore create mode 100644 common/iiee.defs create mode 100644 common/pickboot.s create mode 100644 common/romx_main.s create mode 100644 common/slotscan.s create mode 100644 no_diags/B0_C600_romx_main.s create mode 100644 no_diags/B0_D8F0_patch_vartio.s create mode 100644 no_diags/B0_FAB6_patch_pwrup.s create mode 100644 no_diags/B0_FD75_patch_getln1.s create mode 100644 no_diags/Rakefile create mode 100644 no_diags/iiee.defs create mode 100644 no_tape/B0_C2C0_patch_resetx.s create mode 100644 no_tape/B0_C500_romx_main.s create mode 100644 no_tape/B0_D034_kill_shload.s create mode 100644 no_tape/B0_D04E_kill_recall.s create mode 100644 no_tape/B0_D050_kill_store.s create mode 100644 no_tape/B0_D06C_kill_load.s create mode 100644 no_tape/B0_D06E_kill_save.s create mode 100644 no_tape/B0_D8B0_slotscan.s create mode 100644 no_tape/B0_F39F_pickboot.s create mode 100644 no_tape/B0_F77B_no_shload_jmp.s create mode 100644 no_tape/B0_F7E4_fix_getarypt.s create mode 100644 no_tape/B0_FAB6_patch_pwrup.s create mode 100644 no_tape/B0_FCCC_no_mon_headr.s create mode 100644 no_tape/B0_FD75_patch_getln1.s create mode 100644 no_tape/B0_FECD_mon_write.s create mode 100644 no_tape/B0_FEFD_mon_read.s create mode 100644 no_tape/Rakefile create mode 100644 no_tape/iiee.defs diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..b41a3eb --- /dev/null +++ b/.gitignore @@ -0,0 +1,16 @@ +*.o65 +*.lbl +*.bin +*.bin.cd +*.bin.ef +*.swp +*.zip +*.o +*.lst +*.b +*.po +copyrom.sh +make_rom.sh +rom.sha256 +**/.DS_Store +t diff --git a/common/iiee.defs b/common/iiee.defs new file mode 100644 index 0000000..8f90926 --- /dev/null +++ b/common/iiee.defs @@ -0,0 +1,70 @@ +; macros + +; use at beginning of patch, set maxsize=0 for no max size check +.macro rompatch addr,maxsize,desc + patchstart = addr + .org patchstart + patchmsize = maxsize + .define patchdesc desc + .if patchmsize > 0 + .out .sprintf(" ROM patch %s bgn %x, max size %d", patchdesc, patchstart, patchmsize) + .else + .out .sprintf(" ROM patch %s bgn %x, max size unconstrained", patchdesc, patchstart) + .endif +.endmacro + +; use at end of patch, displays info about the patch +; and checks for over-size patch +.macro endpatch + .if patchmsize > 0 + .out .sprintf(" ROM patch %s end %x; size: %d of %d, %d left", patchdesc, *-1, *-patchstart, patchmsize, patchmsize-*+patchstart) + .assert * <= (patchstart+patchmsize), error, .sprintf(" ROM patch %s code too big", patchdesc) + .else + .out .sprintf(" ROM patch %s end %x; size: %d", patchdesc, *-1, *-patchstart) + .endif +.endmacro + +; hardware +;set80col = $c001 +setslotcxrom = $c006 +setintcxrom = $c007 +setaltchar = $c00f +butn0 = $c061 +butn1 = $c062 +kbd = $c000 +kbdstrb = $c010 +romin = $c081 + + +; ZP locations +ch = $24 ; cursor horizontal pos +cv = $25 + +; locations +softev = $3f2 +pwerdup = $3f4 +ampervec = $3f5 + +; values +pwrbyte = $a5 +menucol = 10 ; column for menu entries + +; entries +init = $fb2f ; init text screen +tabv = $fb5b ; vtab to a-reg +vtab = $fc22 ; vtab to cv +sloop = $faba ; slot scan loop +title = $fb60 ; clear screen, display "Apple //e" +bell1 = $fbdd ; beep +wait = $fca8 ; waste time +rdkey = $fd0c ; read keyboard +cout = $fded ; character out +setkbd = $fe89 ; set keyboard as input +setvid = $fe93 ; set text screen as output +rdchar = $fd35 ; rdchar, used for delete key patch +prhex = $fde3 ; x,y preserved +prbyte = $fdda ; x,y preserved +monitor = $ff59 ; monitor +intcxrts = $f8cb ; switch in internal cx ROM and rts +slotcxrts = $fec5 ; switch in slot cx ROM and rts + diff --git a/common/pickboot.s b/common/pickboot.s new file mode 100644 index 0000000..8b243f3 --- /dev/null +++ b/common/pickboot.s @@ -0,0 +1,50 @@ +.pc02 +.if ::no_tape +checkatalk = $d8b7 ; actually checkatalk2... +atwait = $d8b9 + rts ; so STORE returns +.else +; pressoa defined elsewhere +.endif +; we get here from patch at $fab6 (no tape) or $d8f0 (no diags) +.proc pickboot + stx $00 ; is a zero + sta $01 ; is $c8 + lda $02 ; + eor $03 + cmp #pwrbyte + bne goboot +dosel: lda $02 + cmp #$b1 + bcc goboot ; check value right, but illegal value + cmp #$b8 + bcs goboot + eor #$70 ; $b0 -> $c0 + inc a + sta $01 +.if ::no_tape + ; if we are assembling over STORE/RECALL + bit $60 ; assembles an RTS at RECALL +.assert *-1=$f3bc,error,.sprintf("RECALL aligment problem, *=%x",*-1) +.endif + sta $02 ; so that next try has default behavior + jsr checkatalk ; note ::no_tape version calls checkatalk2 here + bcc goboot ; nope, just boot the slot + sta setaltchar ; turn on mousetext + jsr atwait ; Wait for open apple +goboot: +.if !::no_tape + ; set up RTS trick + lda #>(sloop-1) + pha + lda #<(sloop-1) + pha +.endif + ldx $00 + lda $01 +.if ::no_tape + jmp sloop +.else + jmp slotcxrts ; return to slot ROM and execute RTS trick +.endif +.endproc diff --git a/common/romx_main.s b/common/romx_main.s new file mode 100644 index 0000000..361aa89 --- /dev/null +++ b/common/romx_main.s @@ -0,0 +1,132 @@ +.pc02 + +.if no_tape +checkblk = $d8b1 +checkatalk = $d8b3 +getslotbyte = $d8b5 +checkatalk2 = $d8b7 ; not used here +atwait = $d8b9 +.else +; above must be defined by including file +.endif + +.proc pressoa + ldx #msg7-msg0 ; Press open apple + jmp Disp +.endproc +.proc resete0x +.if ::no_tape + ; if we are over tape code, we still have diags so allow access + bit butn0 ; open apple also pressed? + bpl :+ ; nope, just ca/option + jmp $c600 ; do diags +.endif +: jsr title + ldx #msg0-msg0 ; basic parts of menu + jsr Disp + ; display slots now + stz $00 ; zero low byte of slot ptr + ldx #$07 +: phx + jsr dslot + dec cv + jsr vtab ; wrecks y + lda #menucol + sta ch + plx + dex + bne :- + jsr rdkey + cmp #$b0 ; is 0 or less? + bcc :-- ; less than, re-draw + bne :+ ; not zero, skip + jmp monitor ; do not pass go, do not collect $200 +: cmp #$b8 ; 8 or higher + bcs :--- ; yep, re-draw + sta $02 ; put in $02 + eor #pwrbyte ; make check byte + sta $03 ; put in $03 + lda #$80 ; flag to open-apple+reset + jmp $c2c6 ; back to resetx +.endproc +; entered with slot # in x, and scanslots having been called +.proc dslot + txa + jsr prhex + lda #$a0 ; space + jsr cout + txa + ora #$c0 ; to ref + sta $01 ; high nibble of ptr + jsr checkatalk + bcc :+ ; skip if not + ldx #msg2-msg0 + jsr Disp ; print it +: jsr checkblk ; is block device + bcs block + ldy #$0b ; check for Pascal 1.1 FW protocol + jsr getslotbyte ; get byte (cxrom is on!) + dec a + beq pascal +exit: rts +pascal: ldx #msg5-msg0 + jsr Disp + ldy #$0c ; Pascal card ID + jsr getslotbyte + jmp prbyte +block: beq smart + ldy #$ff ; last byte of firmware + jsr getslotbyte + beq disk ; $00 = 16-sector + inc a ; is $FF? + beq disk ; yes 13-sector + ldx #msg3-msg0 ; generic block device + .byte $2c ; BIT Absolute opcode +disk: ldx #msg4-msg0 + .byte $2c +smart: ldx #msg6-msg0 + ; fall-through +.endproc +.proc Disp + lda msg0,x + bne :+ + rts +: inx ; set up for next message byte + cmp #$18 ; last line + 1 + bcc repos + eor #$80 + jsr cout ; not supposed to change any regs + bra Disp +repos: jsr tabv ; destroys a and y, but not x + lda msg0,x ; get horizontal + sta ch ; and write + inx ; next message byte + bra Disp +.endproc +.if no_tape +msg0: .byte 3,menucol,"0 Mon" +.else +msg0: .byte 3,menucol,"0 Monitor" +.endif + .byte 5,menucol,"Slots:" + .byte 22,16,"By M.G." +msg1: .byte 23,13,"ROM eX 02-19A",13,menucol,$00 +.if no_tape +msg2: .byte "ATalk ",$00 +.else +msg2: .byte "AppleTalk ",$00 +.endif +msg3: .byte "Block",$00 +msg4: .byte "Disk II",$00 +.if no_tape +msg5: .byte "Pas $",$00 +.else +msg5: .byte "Pascal $",$00 +.endif +.if no_tape +msg6: .byte "Smart",$00 +.else +msg6: .byte "SmartPort",$00 +.endif +msg7: .byte 3,16,"Press ",$C1,$00 + diff --git a/common/slotscan.s b/common/slotscan.s new file mode 100644 index 0000000..d15f676 --- /dev/null +++ b/common/slotscan.s @@ -0,0 +1,109 @@ +; If building the version that removes the tape code, +; this lands outside of $Cxxx space, so we can directly query the slots +; If we are removing the diags, then this lands in $Cxxx space and must +; call the getslotbyte routine that lives outside of $Cxxx space. +; to facilitate this, a couple of AppleSoft tape I/O routines are relocated +; to $Cxxx space. +.pc02 +.if ::no_tape + rts ; so SAVE returns + bra checkblk ; $d8b1 + bra checkatalk ; $d8b3 + bra getslotbyte ; $d8b5 + bra checkatalk2 ; $d8b7, without cxrom stuff + ; fall-through $d8b9 to atwait +.endif + +; WS card requires open apple to be held to boot appletalk after the +; firmware diagnostics have passed. Display wait msg and +.proc atwait + jsr title +.if ::no_tape + jsr $c502 ; display message +.else + jsr $c606 ; display messsage +.endif +: bit butn0 + bpl :- + rts +.endproc + +.if ::no_tape +; enter assuming cxrom is on ($00) points to card slot ROM +; y contains byte index into card firmware +.proc getslotbyte + sta setslotcxrom + lda ($00),y + bra cxexit +.endproc +.else +getslotbyte = $d8f3 +.endif + +; enter assuming cxrom is on, ($00) points to card slot ROM +; and y is usable +; exits with carry set if block device in slot, and z flag set if smartport +; carry clear otherwise +.proc checkblk +.if ::no_tape + sta setslotcxrom +.endif + ldy #$05 +: +.if ::no_tape + lda ($00),y +.else + jsr getslotbyte +.endif + cmp $fb01,y ; Disk ID bytes + beq :+ + clc + bcc cxexit +: dey ; note carry is set + dey + bpl :-- ; until done or all bytes match + ldy #$07 ; carry still set here +.if ::no_tape + lda ($00),y ; get smartport +.else + jsr getslotbyte +.endif +cxexit: +.if ::no_tape + jmp $f8cb ; has sta setintcxrom then rts +.else + rts +.endif +.endproc +cxexit = checkblk::cxexit + +; enter assuming that cxrom is on, ($00) points to card slot ROM +; and y is usable +.proc checkatalk +.if ::no_tape + sta setslotcxrom + jsr checkatalk2 + bra cxexit +.endproc + +; enter assuming ($00) points to card slot ROM +; and y is usable +.proc checkatalk2 +.endif + ldy #$F9 ; check $CnF9-$CnFC +at_chk: +.if ::no_tape + lda ($00),y +.else + jsr getslotbyte +.endif + cmp atid-$F9,y + clc ; anticipate failure + bne done + iny + cpy #$FD + bcc at_chk +done: rts +atid: .byte "ATLK" +.endproc + diff --git a/no_diags/B0_C600_romx_main.s b/no_diags/B0_C600_romx_main.s new file mode 100644 index 0000000..a3375dc --- /dev/null +++ b/no_diags/B0_C600_romx_main.s @@ -0,0 +1,39 @@ +.include "iiee.defs" + +rompatch $c600,512,"romx_main" +.pc02 +; if we get here, we know that the closed apple/option key was held down +; and CX ROM is already active + bra resete0x ; $C600 + bra tapestuff ; $C602 + bra pickboot ; $C604 + bra pressoa ; $C606 +; Replacement tape routines +.proc tapestuff + bcc progio + ; fall-through +.endproc +.proc vartio + lda #$50 ; LINNUM + ldy #$00 + sta $3C ; A1L + sty $3D ; A1H + lda #$52 ; TMPPT (lock byte) + sty $D6 ; LOCK +seta2: sta $3E ; A2L + sty $3F ; A2H + jmp slotcxrts +.endproc +.proc progio + lda $67 ; TXTTAB + ldy $68 + sta $3C ; A1L + sta $3D ; A1H + lda $69 ; VARTAB + ldy $6A + bra vartio::seta2 +.endproc +.include "../common/pickboot.s" +.include "../common/romx_main.s" +.include "../common/slotscan.s" +endpatch diff --git a/no_diags/B0_D8F0_patch_vartio.s b/no_diags/B0_D8F0_patch_vartio.s new file mode 100644 index 0000000..fe9cc7d --- /dev/null +++ b/no_diags/B0_D8F0_patch_vartio.s @@ -0,0 +1,36 @@ + +.pc02 +.include "iiee.defs" +rompatch $d8f0,34,"patch_vartio" ; patches over Applesoft VARTIO +.proc vartio + sec + bra gocx +.endproc +; enter assuming cxrom is on ($00) points to card slot ROM +; y contains byte index into card firmware +.proc getslotbyte + sta setslotcxrom + lda ($00),y + jmp intcxrts +.endproc +.proc gopickboot + sta setintcxrom + jmp $c604 +.endproc +.assert *=$d901,error,.sprintf("PROGIO aligment problem, *=%x",*) +.proc progio + clc + ; fall-through +.endproc +.proc gocx + sta setintcxrom + jmp $c602 ; go to vartio/progio replacement +.endproc +.proc fixdelkey + jsr rdchar + cmp #$ff + bne :+ + lda #$88 +: rts +.endproc +endpatch \ No newline at end of file diff --git a/no_diags/B0_FAB6_patch_pwrup.s b/no_diags/B0_FAB6_patch_pwrup.s new file mode 100644 index 0000000..0ede9d9 --- /dev/null +++ b/no_diags/B0_FAB6_patch_pwrup.s @@ -0,0 +1,7 @@ +; patch PWRUP to go to romx boot code +.code +.include "iiee.defs" +rompatch $fab6,4,"patch_pwrup" + jmp $d8fb + nop +endpatch diff --git a/no_diags/B0_FD75_patch_getln1.s b/no_diags/B0_FD75_patch_getln1.s new file mode 100644 index 0000000..ec8bca1 --- /dev/null +++ b/no_diags/B0_FD75_patch_getln1.s @@ -0,0 +1,6 @@ +; patch GETLN1 to call delete key handler +.code +.include "iiee.defs" +rompatch $fd75,3,"patch_getln1" + jsr $d908 +endpatch diff --git a/no_diags/Rakefile b/no_diags/Rakefile new file mode 100644 index 0000000..ac6c7b5 --- /dev/null +++ b/no_diags/Rakefile @@ -0,0 +1,165 @@ +rom_url = 'http://mirrors.apple2.org.za/Apple%20II%20Documentation%20Project/Computers/Apple%20II/Apple%20IIe/ROM%20Images/Apple%20IIe%20Enhanced%20ROM%20Pages%20C0-FF%20-%20342-0349-B%20-%201985.bin' +source_rom = '../iiee_rom.bin' +source_rom_sha256 = 'aab38a03ca8deabbb2f868733148c2efd6f655a59cd9c5d058ef3e0b7aa86a1a' +dest_rom = 'iiee_romx_no_diags.bin' +distzip = 'iiee_romx_no_diags.zip' +rom_base = 0xc000 +acmd = 'java -jar ~/bin/AppleCommander-1.3.5-ac.jar' + +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 + +task :zip => [:clean, :assemble, :build_zip] do + sh "ls -l #{dest_rom}" +end + +desc "Clean object files" +task :clean do + sh "rm -f #{dest_rom}" + sh "rm -f #{dest_rom}.cd" + sh "rm -f #{dest_rom}.ef" + sh "rm -f sf512_#{dest_rom}" + sh "rm -f *.o" + sh "rm -f *.lst" + sh "rm -f *.b" + sh "rm -f rom.sha256" + sh "rm -f make_rom.sh" + sh "rm -f #{distzip}" +end + +desc 'Obtain ROM' +rule source_rom do + require 'open-uri' + + puts "Downloading ROM..." + + File.open(source_rom, "wb") do |romfile| + open(rom_url) do |wwwfile| + romfile.write(wwwfile.read) + end + end +end + +desc "Verify ROM Checksum" +task :checksum_rom => source_rom do + require 'digest' + + sha256 = Digest::SHA256.file source_rom + fail "ROM checksum failed" unless sha256.hexdigest == source_rom_sha256 + puts "Source ROM appears correct!" +end + +desc "Assemble all source files" +task :assemble => source_files.ext('.b') + +rule ".o" => ".s" do |t| + sh "ca65 -l #{t.name}.lst #{t.source}" +end + +rule ".b" => ".o" do |t| + sh "ld65 -t none -o #{t.name} #{t.source}" +end + +desc "Build ROM" +task :build_rom => [:assemble, :checksum_rom] do + puts "Building ROM image..." + obj_files = Rake::FileList.new('*.b') + 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 + fc = File.read(t) + fl = fc.bytes.count + puts "Loading #{t} into bank #{bnum} @ $#{badd.to_s(16)}, file addr $#{addr.to_s(16)}, len $#{fl.to_s(16)} (#{fl})" + nzc = 0 + fc.each_byte do |b| + nzc += 1 if rom.getbyte(addr) != 0 && rom.getbyte(addr) != b + rom.setbyte(addr, b) + addr += 1 + end + puts "\tNote: patched over #{nzc} nonzero bytes!" if nzc > 0 + else + puts "I dont know where to load #{t}" + end + end + File.write(dest_rom, rom) + puts "ROM image done: #{dest_rom}" +end + +# IIe version copies 4 times because rom is half size +desc "Build SST27SF512 Image" +task :sf512 => [:build_rom] do + sh "cat #{dest_rom} #{dest_rom} #{dest_rom} #{dest_rom} > sf512_#{dest_rom}" +end + +desc "Split image into two images" +task :split => [:build_rom] do + sh "split -b 8192 #{dest_rom}" + sh "mv -f xaa #{dest_rom}.cd" + sh "mv -f xab #{dest_rom}.ef" +end + +desc "Build disributable ZIP" +task :build_zip => [:build_rom] do + require 'digest' + require 'date' + + sha256 = Digest::SHA256.file dest_rom + shafile = < #{source_rom} +elif [ -e `which wget` ]; then + wget -O #{source_rom} "${ROM_URL}" +else + echo "Can't download source ROM image!" +fi +cp #{source_rom} #{dest_rom} +#{dd_cmds.join("\n")} +if [ -e `which shasum` ]; then + shasum -a 256 -c rom.sha256 +elif [ -e "sha256sum" ]; then + sha256sum -c rom.sha256 +else + echo "Please check the .bin files against rom.sha256" +fi +echo "#{dest_rom} created!" +EOF + + File.write('rom.sha256', shafile) + File.write('make_rom.sh', script) + + sh "zip #{distzip} rom.sha256 make_rom.sh" +end + diff --git a/no_diags/iiee.defs b/no_diags/iiee.defs new file mode 100644 index 0000000..d05fda3 --- /dev/null +++ b/no_diags/iiee.defs @@ -0,0 +1,4 @@ +.include "../common/iiee.defs" + +no_tape = 0 + diff --git a/no_tape/B0_C2C0_patch_resetx.s b/no_tape/B0_C2C0_patch_resetx.s new file mode 100644 index 0000000..b255cd4 --- /dev/null +++ b/no_tape/B0_C2C0_patch_resetx.s @@ -0,0 +1,6 @@ +.pc02 +.include "iiee.defs" +; correlate these with the text patch +rompatch $c2c0,3,"resetx" + jmp $c500 ; intercept diags hook +endpatch diff --git a/no_tape/B0_C500_romx_main.s b/no_tape/B0_C500_romx_main.s new file mode 100644 index 0000000..c812819 --- /dev/null +++ b/no_tape/B0_C500_romx_main.s @@ -0,0 +1,7 @@ +.include "iiee.defs" +.pc02 + +rompatch $c500,256,"romx_main" + bra resete0x +.include "../common/romx_main.s" +endpatch diff --git a/no_tape/B0_D034_kill_shload.s b/no_tape/B0_D034_kill_shload.s new file mode 100644 index 0000000..c0c73e1 --- /dev/null +++ b/no_tape/B0_D034_kill_shload.s @@ -0,0 +1,2 @@ +.include "iiee.defs" + .addr ampervec-1 diff --git a/no_tape/B0_D04E_kill_recall.s b/no_tape/B0_D04E_kill_recall.s new file mode 100644 index 0000000..c0c73e1 --- /dev/null +++ b/no_tape/B0_D04E_kill_recall.s @@ -0,0 +1,2 @@ +.include "iiee.defs" + .addr ampervec-1 diff --git a/no_tape/B0_D050_kill_store.s b/no_tape/B0_D050_kill_store.s new file mode 100644 index 0000000..c0c73e1 --- /dev/null +++ b/no_tape/B0_D050_kill_store.s @@ -0,0 +1,2 @@ +.include "iiee.defs" + .addr ampervec-1 diff --git a/no_tape/B0_D06C_kill_load.s b/no_tape/B0_D06C_kill_load.s new file mode 100644 index 0000000..c0c73e1 --- /dev/null +++ b/no_tape/B0_D06C_kill_load.s @@ -0,0 +1,2 @@ +.include "iiee.defs" + .addr ampervec-1 diff --git a/no_tape/B0_D06E_kill_save.s b/no_tape/B0_D06E_kill_save.s new file mode 100644 index 0000000..c0c73e1 --- /dev/null +++ b/no_tape/B0_D06E_kill_save.s @@ -0,0 +1,2 @@ +.include "iiee.defs" + .addr ampervec-1 diff --git a/no_tape/B0_D8B0_slotscan.s b/no_tape/B0_D8B0_slotscan.s new file mode 100644 index 0000000..663ff0a --- /dev/null +++ b/no_tape/B0_D8B0_slotscan.s @@ -0,0 +1,5 @@ +.pc02 +.include "iiee.defs" +rompatch $d8b0,98,"slotscan" ; patches over Applesoft SAVE, LOAD,and VARTIO +.include "../common/slotscan.s" +endpatch diff --git a/no_tape/B0_F39F_pickboot.s b/no_tape/B0_F39F_pickboot.s new file mode 100644 index 0000000..e21751c --- /dev/null +++ b/no_tape/B0_F39F_pickboot.s @@ -0,0 +1,6 @@ +.pc02 +.include "iiee.defs" +; correlate these with the text patch +rompatch $f39f,57,"pickboot" ; patches over AppleSoft STORE and RECALL +.include "../common/pickboot.s" +endpatch \ No newline at end of file diff --git a/no_tape/B0_F77B_no_shload_jmp.s b/no_tape/B0_F77B_no_shload_jmp.s new file mode 100644 index 0000000..57904a6 --- /dev/null +++ b/no_tape/B0_F77B_no_shload_jmp.s @@ -0,0 +1,7 @@ +; Patch out JSR $C500 in AppleSoft SHLOAD code and +; always return failure +.include "iiee.defs" + nop + nop + sec + diff --git a/no_tape/B0_F7E4_fix_getarypt.s b/no_tape/B0_F7E4_fix_getarypt.s new file mode 100644 index 0000000..937a427 --- /dev/null +++ b/no_tape/B0_F7E4_fix_getarypt.s @@ -0,0 +1,2 @@ +.include "iiee.defs" + rts diff --git a/no_tape/B0_FAB6_patch_pwrup.s b/no_tape/B0_FAB6_patch_pwrup.s new file mode 100644 index 0000000..439f8b9 --- /dev/null +++ b/no_tape/B0_FAB6_patch_pwrup.s @@ -0,0 +1,7 @@ +; patch PWRUP to go to romx boot code +.code +.include "iiee.defs" + .org $fab6 + jmp $f3a0 + nop + diff --git a/no_tape/B0_FCCC_no_mon_headr.s b/no_tape/B0_FCCC_no_mon_headr.s new file mode 100644 index 0000000..9dffce2 --- /dev/null +++ b/no_tape/B0_FCCC_no_mon_headr.s @@ -0,0 +1,5 @@ +; Patch out JSR $C567 in monitor tape HEADR code +.include "iiee.defs" + nop + lda #$00 + diff --git a/no_tape/B0_FD75_patch_getln1.s b/no_tape/B0_FD75_patch_getln1.s new file mode 100644 index 0000000..fc8f4ee --- /dev/null +++ b/no_tape/B0_FD75_patch_getln1.s @@ -0,0 +1,6 @@ +; patch GETLN1 to call delete key handler +.code +.include "iiee.defs" + .org $fd75 + jsr $feff + diff --git a/no_tape/B0_FECD_mon_write.s b/no_tape/B0_FECD_mon_write.s new file mode 100644 index 0000000..759b6d7 --- /dev/null +++ b/no_tape/B0_FECD_mon_write.s @@ -0,0 +1,9 @@ +; Patch monitor WRITE code +.pc02 +.include "iiee.defs" +rompatch $fecd,10,"mon_write" + bra $ff2d ; print ERR + sta romin ; at $fecf + jmp $f3a0 ; to boot selection hanndler +endpatch + diff --git a/no_tape/B0_FEFD_mon_read.s b/no_tape/B0_FEFD_mon_read.s new file mode 100644 index 0000000..34ed9b5 --- /dev/null +++ b/no_tape/B0_FEFD_mon_read.s @@ -0,0 +1,12 @@ +; Patch monitor READ code +.pc02 +.include "iiee.defs" +rompatch $fefd,13,"mon_read" + bra $ff2d ; print ERR + ; delete key patch + jsr $fd35 ; RDCHAR + cmp #$ff + bne :+ + lda #$88 +: rts +endpatch diff --git a/no_tape/Rakefile b/no_tape/Rakefile new file mode 100644 index 0000000..cd4122d --- /dev/null +++ b/no_tape/Rakefile @@ -0,0 +1,165 @@ +rom_url = 'http://mirrors.apple2.org.za/Apple%20II%20Documentation%20Project/Computers/Apple%20II/Apple%20IIe/ROM%20Images/Apple%20IIe%20Enhanced%20ROM%20Pages%20C0-FF%20-%20342-0349-B%20-%201985.bin' +source_rom = '../iiee_rom.bin' +source_rom_sha256 = 'aab38a03ca8deabbb2f868733148c2efd6f655a59cd9c5d058ef3e0b7aa86a1a' +dest_rom = 'iiee_romx_no_tape.bin' +distzip = 'iiee_romx_no_tape.zip' +rom_base = 0xc000 +acmd = 'java -jar ~/bin/AppleCommander-1.3.5-ac.jar' + +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 + +task :zip => [:clean, :assemble, :build_zip] do + sh "ls -l #{dest_rom}" +end + +desc "Clean object files" +task :clean do + sh "rm -f #{dest_rom}" + sh "rm -f #{dest_rom}.cd" + sh "rm -f #{dest_rom}.ef" + sh "rm -f sf512_#{dest_rom}" + sh "rm -f *.o" + sh "rm -f *.lst" + sh "rm -f *.b" + sh "rm -f rom.sha256" + sh "rm -f make_rom.sh" + sh "rm -f #{distzip}" +end + +desc 'Obtain ROM' +rule source_rom do + require 'open-uri' + + puts "Downloading ROM..." + + File.open(source_rom, "wb") do |romfile| + open(rom_url) do |wwwfile| + romfile.write(wwwfile.read) + end + end +end + +desc "Verify ROM Checksum" +task :checksum_rom => source_rom do + require 'digest' + + sha256 = Digest::SHA256.file source_rom + fail "ROM checksum failed" unless sha256.hexdigest == source_rom_sha256 + puts "Source ROM appears correct!" +end + +desc "Assemble all source files" +task :assemble => source_files.ext('.b') + +rule ".o" => ".s" do |t| + sh "ca65 -l #{t.name}.lst #{t.source}" +end + +rule ".b" => ".o" do |t| + sh "ld65 -t none -o #{t.name} #{t.source}" +end + +desc "Build ROM" +task :build_rom => [:assemble, :checksum_rom] do + puts "Building ROM image..." + obj_files = Rake::FileList.new('*.b') + 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 + fc = File.read(t) + fl = fc.bytes.count + puts "Loading #{t} into bank #{bnum} @ $#{badd.to_s(16)}, file addr $#{addr.to_s(16)}, len $#{fl.to_s(16)} (#{fl})" + nzc = 0 + fc.each_byte do |b| + nzc += 1 if rom.getbyte(addr) != 0 && rom.getbyte(addr) != b + rom.setbyte(addr, b) + addr += 1 + end + puts "\tNote: patched over #{nzc} nonzero bytes!" if nzc > 0 + else + puts "I dont know where to load #{t}" + end + end + File.write(dest_rom, rom) + puts "ROM image done: #{dest_rom}" +end + +# IIe version copies 4 times because rom is half size +desc "Build SST27SF512 Image" +task :sf512 => [:build_rom] do + sh "cat #{dest_rom} #{dest_rom} #{dest_rom} #{dest_rom} > sf512_#{dest_rom}" +end + +desc "Split image into two images" +task :split => [:build_rom] do + sh "split -b 8192 #{dest_rom}" + sh "mv -f xaa #{dest_rom}.cd" + sh "mv -f xab #{dest_rom}.ef" +end + +desc "Build disributable ZIP" +task :build_zip => [:build_rom] do + require 'digest' + require 'date' + + sha256 = Digest::SHA256.file dest_rom + shafile = < #{source_rom} +elif [ -e `which wget` ]; then + wget -O #{source_rom} "${ROM_URL}" +else + echo "Can't download source ROM image!" +fi +cp #{source_rom} #{dest_rom} +#{dd_cmds.join("\n")} +if [ -e `which shasum` ]; then + shasum -a 256 -c rom.sha256 +elif [ -e "sha256sum" ]; then + sha256sum -c rom.sha256 +else + echo "Please check the .bin files against rom.sha256" +fi +echo "#{dest_rom} created!" +EOF + + File.write('rom.sha256', shafile) + File.write('make_rom.sh', script) + + sh "zip #{distzip} rom.sha256 make_rom.sh" +end + diff --git a/no_tape/iiee.defs b/no_tape/iiee.defs new file mode 100644 index 0000000..4340be0 --- /dev/null +++ b/no_tape/iiee.defs @@ -0,0 +1,4 @@ +.include "../common/iiee.defs" + +no_tape = 1 +