From 82e952bdfbab5fb38a27b5c7c6a2f5312f35177b Mon Sep 17 00:00:00 2001 From: Vince Weaver Date: Mon, 15 Jul 2024 12:32:37 -0400 Subject: [PATCH 1/2] prorwts: see if I can get this working --- disk/prorwts/Makefile | 43 + disk/prorwts/README | 10 + disk/prorwts/proboothd.s | 189 +++++ disk/prorwts/prorwts_ca65.s | 1553 +++++++++++++++++++++++++++++++++++ 4 files changed, 1795 insertions(+) create mode 100644 disk/prorwts/Makefile create mode 100644 disk/prorwts/README create mode 100644 disk/prorwts/proboothd.s create mode 100644 disk/prorwts/prorwts_ca65.s diff --git a/disk/prorwts/Makefile b/disk/prorwts/Makefile new file mode 100644 index 00000000..246ff1a5 --- /dev/null +++ b/disk/prorwts/Makefile @@ -0,0 +1,43 @@ +include ../../Makefile.inc + +EMPTY_DISK = ../../empty_disk/ +LINKER_SCRIPTS = ../../linker_scripts/ +CADIUS = ~/research/apple2/cadius/bin/release/cadius +PRODOSDIR = ../../utils/prodos-utils/ +PRODOS = ../../utils/prodos-utils/prodos + +all: prorwts_test.2mg + +# Note: cadius, put #XXYYYY after filename for type/value + +#prorwts_test.po: disk01_files/LEVEL_ARRIVAL prorwts_ca65.o +# $(PRODOSDIR)/mkprodosfs prorwts_test.po -n Test + +prorwts_ca65.o: prorwts_ca65.s + ca65 -o prorwts_ca65.o prorwts_ca65.s -l prorwts_ca65.lst + +### + +prorwts_test.2mg: \ + PROBOOTHD + $(CADIUS) CREATEVOLUME prorwts_test.2mg Test 32MB + dd conv=notrunc if=PROBOOTHD of=prorwts_test.2mg bs=512 count=1 +# $(CADIUS) CREATEFOLDER prorwts_test.2mg /Test/DISK01 +# $(CADIUS) CREATEFOLDER prorwts_test.2mg /Test/DISK39 +# $(CADIUS) CREATEFOLDER prorwts_test.2mg /Test/DISK40 +# $(CADIUS) CREATEFOLDER prorwts_test.2mg /Test/DISK41 +# $(CADIUS) CREATEFOLDER prorwts_test.2mg /Test/DISK43 +# $(CADIUS) ADDFILE prorwts_test.2mg /Test/DISK01/ disk01_files/LEVEL_ARRIVAL + + +### +PROBOOTHD: proboothd.o + ld65 -o PROBOOTHD proboothd.o -C $(LINKER_SCRIPTS)/apple2_800.inc + +proboothd.o: proboothd.s + ca65 -o proboothd.o proboothd.s -l proboothd.lst + +#### + +clean: + rm -f *~ *.o *.lst diff --git a/disk/prorwts/README b/disk/prorwts/README new file mode 100644 index 00000000..55bd5cd4 --- /dev/null +++ b/disk/prorwts/README @@ -0,0 +1,10 @@ + +some test code for using large 32MB prodos hard-drive images + +this is based on the prorwts code by qkumba, and also the + 4cade/total-replay code by 4am and qkumba + +currently code here only work on hd image, and unlike 4cade +won't work as double-clicking a disk image on a IIgs as that's not +really a use case I would ever do + diff --git a/disk/prorwts/proboothd.s b/disk/prorwts/proboothd.s new file mode 100644 index 00000000..c4139def --- /dev/null +++ b/disk/prorwts/proboothd.s @@ -0,0 +1,189 @@ +;license:BSD-3-Clause + +; based on minimal open/read binary file in ProDOS filesystem +; from 4cade +; +;copyright (c) Peter Ferrie 2016-2019 + +; zpage usage, arbitrary selection except for the "ProDOS constant" ones + command = $42 ;ProDOS constant + unit = $43 ;ProDOS constant + adrlo = $44 ;ProDOS constant + adrhi = $45 ;ProDOS constant + bloklo = $46 ;ProDOS constant + blokhi = $47 ;ProDOS constant + + A2L = $3e + A2H = $3f + sizehi = $53 + +;constants + scrn2p2 = $f87b + dirbuf = $1e00 ;for size-optimisation + +; start of boot sector, how many sectors to load +.byte 1 + +proboot_start: + txa + pha + + lda #'A'+$80 + sta $400 ; write A to upper-left of screen + +forever: + jmp forever + + +;src "src/4cade.init.machine.a" + +; src "src/4cade.init.screen.a" + + +; pla + ; sta unit + ; tax + ; ; X = boot slot x16 + ; ; Y = 0 + + ; set up ProDOS shim + +;- txa +; jsr scrn2p2 +; and #7 +; ora #$c0 +; sta $be30, y +; sta slot+2 +; sta entry+2 +;slot lda $cfff +; sta entry+1 +; lda fakeMLI_e-$100, y +; sta $be00+fakeMLI_e-fakeMLI, y +; iny +; bne - +; sty adrlo +; stx $bf30 +; sty $200 + +opendir: + ; read volume directory key block + ldx #2 + + ; include volume directory header in count + +firstent: + lda #>dirbuf + sta adrhi + sta A2H + jsr seekread + lda #4 + sta A2L +nextent: + ldy #0 + + ; match name lengths before attempting to match names + +; lda (A2L), y +; and #$0f +; tax +; inx +;- cmp filename, y +; beq foundname + + ;move to next directory in this block + +; clc + ; lda A2L + ; adc #$27 + ; sta A2L + ; bcc + + + ;there can be only one page crossed, so we can increment instead of adc + +; inc A2H +;+ cmp #$ff ;4+($27*$0d) +; bne nextent + + ;read next directory block when we reach the end of this block + +; ldx dirbuf+2 +; ldy dirbuf+3 +; bcs firstent + +foundname: +; iny +; lda (A2L), y +; dex +; bne - +; stx $ff + + ;cache KEY_POINTER + +; ldy #$11 +; lda (A2L), y +; tax +; iny +; lda (A2L), y +; tay + +readfile: +; jsr seekread +; inc adrhi +; inc adrhi + + ;fetch data block and read it + +blockind: +; ldy $ff +; inc $ff +; ldx dirbuf, y +; lda dirbuf+256, y +; tay +; bne readfile +; txa +; bne readfile + +readdone: +; jmp ProBootEntry + +seekread: +; stx bloklo +; sty blokhi +; lda #1 +; sta command +; lda adrhi +; pha +;entry jsr $d1d1 +; pla +; sta adrhi +; rts + +;fakeMLI bne retcall +;readblk dey +; dey +; sty adrhi +; tay +; jsr $bf00+seekread-fakeMLI +;retcall pla +; tax +; inx +; inx +; inx +; txa +; pha +;- rts +;fakeMLI_e + + +;filename +PSTRING "LAUNCHER.SYSTEM" + +; !src "src/4cade.branding.a" + +;!if (* > $9f7) { +; !serious "Bootloader is too large" +;} + +;*=$9f8 +;!byte $D3,$C1,$CE,$A0,$C9,$CE,$C3,$AE +; S A N I N C . +; diff --git a/disk/prorwts/prorwts_ca65.s b/disk/prorwts/prorwts_ca65.s new file mode 100644 index 00000000..fe48f05c --- /dev/null +++ b/disk/prorwts/prorwts_ca65.s @@ -0,0 +1,1553 @@ +;open/read/write binary file in ProDOS filesystem +;copyright (c) Peter Ferrie 2013-16 + +; modified to assemble with ca65 (vmw) 2024 + + +;!cpu 6502 +;!to "prorwts",plain +;*=$800 + + ;constants + cmdread = 1 ;requires enable_write=1 + cmdwrite = 2 ;requires enable_write=1 + SETKBD = $fe89 + SETVID = $fe93 + DEVNUM = $bf30 + PHASEOFF = $c080 + MOTOROFF = $c088 + MOTORON = $c089 + Q6L = $c08c + Q6H = $c08d + Q7L = $c08e + Q7H = $c08f + MLI = $bf00 + KEY_POINTER = $11 ;ProDOS constant + EOF = $15 ;ProDOS constant + AUX_TYPE = $1f ;ProDOS constant + ROMIN = $c081 + LCBANK2 = $c089 + CLRAUXRD = $c002 + CLRAUXWR = $c004 + + ;options + enable_floppy = 0 ;set to 1 to enable floppy drive support + poll_drive = 0 ;set to 1 to check if disk is in drive + override_adr = 0 ;set to 1 to require an explicit load address + aligned_read = 0 ;set to 1 if all reads can be a multiple of block size + enable_write = 0 ;set to 1 to enable write support + ;file must exist already and its size cannot be altered + ;writes occur in multiples of block size (256 bytes for floppy, 512 bytes for HDD) + allow_multi = 0 ;set to 1 to allow multiple floppies + check_checksum=0 ;set to 1 to enforce checksum verification for floppies + allow_subdir = 0 ;set to 1 to allow opening subdirectories to access files + might_exist = 0 ;set to 1 if file is not known to always exist already + ;makes use of status to indicate success or failure + allow_aux = 0 ;set to 1 to allow read/write directly to/from aux memory + ;requires load_high to be set for arbitrary memory access + ;else driver must be running from same memory target + ;i.e. running from main if accessing main, running from aux if accessing aux + load_high = 0 ;load into banked RAM instead of main RAM + lc_bank = 1 ;load into specified bank (1 or 2) if load_high=1 + + ;zpage usage +.if enable_floppy=1 + tmpsec = $3c + reqsec = $3d +.endif ; enable_floppy + +.if enable_floppy=1 + curtrk = $40 +.endif ;enable_floppy + + command = $42 ;ProDOS constant + unit = $43 ;ProDOS constant + adrlo = $44 ;ProDOS constant + adrhi = $45 ;ProDOS constant + bloklo = $46 ;ProDOS constant + blokhi = $47 ;ProDOS constant + +.if aligned_read=0 + secsize = $46 + secsize1 = $47 + secsize2 = $48 +.endif ;aligned_read + +.if might_exist=1 + status = $f3 ;returns non-zero on error +.endif ;might_exist + +.if allow_aux=1 + auxreq = $f4 ;set to 1 to read/write aux memory, else main memory is used +.endif ;allow_aux + sizelo = $f5 ;set if enable_write=1 and writing + sizehi = $f6 ;set if enable_write=1 and writing + entries = $f7 ;(internal) total number of entries + reqcmd = $f8 ;set (read/write) if enable_write=1 + ;if allow_multi=1, bit 7 selects floppy drive in current slot (clear=drive 1, set=drive 2) + ldrlo = $f9 ;set to load address if override_adr=1 + ldrhi = $fa ;set to load address if override_adr=1 + namlo = $fb ;name of file to access + namhi = $fc ;name of file to access +.if enable_floppy=1 + step = $fd ;(internal) state for stepper motor + tmptrk = $fe ;(internal) temporary copy of current track + phase = $ff ;(internal) current phase for seek + .if enable_write=1 + .if load_high=1 + reloc = $d000 ;$300 bytes code, $100 bytes data + dirbuf = reloc+$400 + encbuf = dirbuf+$200 + .else ;load_high + reloc = $bc00 ;$300 bytes code, $100 bytes data + dirbuf = reloc-$200 + encbuf = dirbuf-$100 + .endif ;load_high + .else ;enable_write + .if load_high=1 + reloc = $d000 ;$200 bytes code, $100 bytes data + dirbuf = reloc+$300 + .else ;load_high + reloc = $bd00 ;$200 bytes code, $100 bytes data + dirbuf = reloc-$200 + .endif ;load_high + .endif ;enable_write +.else ;enable_floppy + .if load_high=1 + reloc = $d000 ;$200 bytes code + .if aligned_read=0 + dirbuf = reloc+$200 + .else ;aligned_read + dirbuf = reloc+$100 + .endif ;aligned_read + .else ;load_high + reloc = $be00 ;$200 bytes code + .if aligned_read=0 + dirbuf = reloc-$200 + .else ;aligned_read + dirbuf = reloc-$100 + .endif ;aligned_read + .endif ;load_high +.endif ;enable_floppy + +init: + jsr SETVID ; intialize text output pointers? + jsr SETKBD ; initalize keyboard? + lda DEVNUM + sta x80_parms+1 + sta unrunit+1 + and #$70 +.if (enable_floppy+enable_write)=2 + sta unrslot1+1 + sta unrslot2+1 + sta unrslot3+1 + sta unrslot4+1 +.endif ;enable_floppy and enable_write + pha +.if enable_floppy=1 + ora #(readbuff+4) + sta blokhi +inextent: + ldy #0 + lda (bloklo), Y + pha + and #$d0 + + ; watch for subdirectory entries + + cmp #$d0 + bne readblock_plus_one ; + + + lda (bloklo), Y + and #$0f + tax + iny +readblock_minus_two: ; -- + lda (bloklo), Y + cmp (namlo), Y + beq ifoundname + + ; match failed, move to next directory in this block, if possible + +readblock_minus_one: ; - +readblock_plus_one: ; + + pla + clc + lda bloklo + adc #$27 + sta bloklo + bcc readblock_plus_two ; + + + ; there can be only one page crossed, so we can increment instead of adc + + inc blokhi +readblock_plus_two: ; + + cmp #<(readbuff+$1ff) ;4+($27*$0d) + lda blokhi + sbc #>(readbuff+$1ff) + bcc inextent + + ; read next directory block when we reach the end of this block + + lda readbuff+2 + ldx readbuff+3 + bcs readblock_plus_four ; + + +ifoundname: + iny + dex + bne readblock_minus_two ; -- + lda (namlo), Y + cmp #'/' + bne readblock_minus_one ; - + tya + eor #$ff + adc sizelo + sta sizelo + clc + tya + adc namlo + sta namlo + pla + and #$20 + bne readblock_plus_five ; ++ + ldy #KEY_POINTER+1 + lda (bloklo), Y + tax + dey + lda (bloklo), Y +.if enable_floppy=1 + sta unrblocklo+1 + stx unrblockhi+1 +.endif ;enable_floppy + sta unrhddblocklo+1 + stx unrhddblockhi+1 +readblock_plus_four: ; + + sta x80_parms+4 + stx x80_parms+5 +readblock_plus_five: ; ++ + lda sizelo + bne readblock + +readblock_plus_three: ; +++ + pla + lsr + lsr + lsr + tax + lsr + ora #$c0 + ldy $bf11, x + cpy #$c8 ; max slot+1 + bcs set_slot + tya +set_slot: + sta slot+2 + sta unrentry+2 +.if enable_floppy=1 + ldx #>unrelocdsk + ldy #unrelochdd + ldy #((bit2tbl-opendir)+$ff) + ldy #0 +copydrv_minus_one: ; - + lda (bloklo), Y +reladr: + sta reloc, Y + iny + bne copydrv_minus_one ; - + inc blokhi + inc reladr+2 + dex + bne copydrv_minus_one ; - + plp + bne ++ + ldx #$16 +copydrv_minus_two: ; -- + stx bloklo + txa + asl + bit bloklo + beq + + ora bloklo + eor #$ff + and #$7e +- bcs + + lsr + bne - + tya + sta nibtbl-$16, x + .if enable_write=1 + txa + ora #$80 + sta xlattbl, y + .endif ;enable_write + iny ++ inx + bpl copydriv_minus_two ; -- +++ rts +.else ; enable_floppy +slot: + lda $cfff + sta unrentry+1 + .if load_high=1 + .if lc_bank=1 + lda LCBANK2 + lda LCBANK2 + .else ; ;lc_bank + lda ROMIN + lda ROMIN + .endif ;lc_bank + .endif ;load_high + ldy #0 +slot_minus_one: ; - + lda unrelochdd, Y + sta reloc, y + lda unrelochdd+$100, Y + sta reloc+$100, Y + iny + bne slot_minus_one + rts +.endif ;enable_floppy + + +c7_parms: + .byte 1 + .word $200 + +x80_parms: + .byte 3, $d1 + .word readbuff, 2 + +.if enable_floppy=1 +unrelocdsk: + +;!pseudopc reloc +.org reloc + +opendir: + ; read volume directory key block +unrblocklo=unrelocdsk+(*-reloc) + ldx #2 +unrblockhi=unrelocdsk+(*-reloc) + lda #0 + jsr readdirsel + + ;include volume directory header in count + +readdir: + .if might_exist=1 + ldx dirbuf+37 + inx + stx entries + .endif ;might_exist +firstent: + lda #<(dirbuf+4) + sta bloklo + lda #>(dirbuf+4) + sta blokhi +nextent: + ldy #0 + .if might_exist=1 + sty status + .endif ;might_exist + lda (bloklo), Y + .if (might_exist+allow_subdir)>0 + and #$f0 + + .if might_exist=1 + ; skip deleted entries without counting + + beq ++ + .endif ; might_exist + .endif ; might_exist or allow_subdir + + .if allow_subdir=1 + ;subdirectory entries are seedlings + ;but we need to distinguish between them later + + cmp #$d0 + beq savetype + .endif ;allow_subdir + + ; watch for seedling and saplings only + + cmp #$30 + bcs + + + ; remember type + +savetype: + .if allow_subdir=1 + asl + asl + .else ;allow_subdir + cmp #$20 + .endif ;allow_subdir + php + + ;match name lengths before attempting to match names + + lda (bloklo), y + and #$0f + tax + inx + .byte $2c +- lda (bloklo), y + cmp (namlo), y + beq foundname + + ;match failed, check if any directory entries remain + + plp ++ + .if might_exist=1 + dec entries + bne ++ +nodisk: +unrdrvoff1=unrelocdsk+(*-reloc) + lda MOTOROFF + inc status + rts + .endif ;might_exist + + ;move to next directory in this block, if possible + +++ clc + lda bloklo + adc #$27 + sta bloklo + bcc + + + ;there can be only one page crossed, so we can increment instead of adc + + inc blokhi ++ cmp #<(dirbuf+$1ff) ;4+($27*$0d) + lda blokhi + sbc #>(dirbuf+$1ff) + bcc nextent + + ;read next directory block when we reach the end of this block + + ldx dirbuf+2 + lda dirbuf+3 + jsr readdirsec + bne firstent + +foundname: + iny + dex + bne - + stx entries + + .if enable_write=1 + ldy reqcmd + cpy #cmdwrite ;control carry instead of zero + bne + + + ;round requested size up to nearest sector if writing + ;or nearest block if using aligned reads + + lda sizelo + .if aligned_read=0 + beq + + inc sizehi + .else ;aligned_read + ldx sizehi + jsr round + sta sizehi + .endif ;aligned_read ++ + .endif ;enable_write + + ;cache EOF (file size, loaded backwards) + + ldy #EOF+1 + lda (bloklo), y + .if (enable_write+aligned_read)>0 + tax + .else ;enable_write or aligned_read + sta sizehi + .endif ;enable_write or aligned_read + dey + lda (bloklo), y + .if (enable_write+aligned_read)>0 + + ;round file size up to nearest sector if writing without aligned reads + ;or nearest block if using aligned reads + + .if aligned_read=0 + bcc ++ + beq + + inx + lda #0 + .else ;aligned_read + .if enable_write=1 + jsr round + tax + .else ;enable_write + adc #$fe + txa + adc #1 + and #$fe + .endif ;enable_write + .endif ;aligned_read + + ;set requested size to min(length, requested size) + + .if enable_write=1 ++ cpx sizehi + bcs + +++ stx sizehi ++ + .else ;enable_write + sta sizehi + .endif ;enable_write + .endif ;enable_write or aligned_read + .if aligned_read=0 + sta sizelo + .endif ;aligned_read + + ;cache AUX_TYPE (load offset for binary files) + + .if override_adr=0 + .if allow_subdir=1 + pla + tax + .else ;allow_subdir + plp + .endif ;allow_subdir + ldy #AUX_TYPE + lda (bloklo), y + pha + iny + lda (bloklo), y + pha + .if allow_subdir=1 + txa + pha + .endif ;allow_subdir + .endif ;override_adr + + ;cache KEY_POINTER + + ldy #KEY_POINTER + lda (bloklo), y + tax + sta dirbuf + iny + lda (bloklo), y + sta dirbuf+256 + + ;read index block in case of sapling + + .if allow_subdir=1 + plp + bpl rdwrfile + php + jsr readdirsec + plp + .else ;allow_subdir + .if override_adr=1 + plp + .endif ;override_adr + bcc rdwrfile + jsr readdirsec + .endif ;allow_subdir + + ;restore load offset + +rdwrfile + .if override_adr=1 + ldx ldrhi + lda ldrlo + .else ;override_adr + pla + tax + pla + .endif ;override_adr + + .if allow_subdir=1 + ;check file type and fake size and load address for subdirectories + + bcc + + ldy #2 + sty sizehi + ldx #>dirbuf + lda #dirbuf + sty adrhi + .if aligned_read=0 + ldy #2 + sty secsize2 + .endif ;aligned_read + ldy #cmdread + sty command + + ;convert block number to track/sector + +seekrdwr +unrdrvon2=unrelocdsk+(*-reloc) + ldy MOTORON + lsr + txa + ror + lsr + lsr + sta phase + txa + and #3 + php + asl + plp + rol + sta reqsec + + .if aligned_read=0 + ;set read size to min(first size, $100) and then read address + + ldy #0 + lda secsize2 + bne + + ldy secsize1 ++ sty secsize + dec secsize2 + .endif ;aligned_read + jsr readadr + + ;if track does not match, then seek + + ldx curtrk + cpx phase + beq checksec + jsr seek + + ;force sector mismatch + + lda #$ff + + ;match or read/write sector + +checksec jsr cmpsec + + .if aligned_read=0 + ;return if less than one sector requested + + tya + bne readret + + ;return if only one sector requested + + lda secsize1 + cmp secsize2 + beq readret + sta secsize + .endif ;aligned_read + inc reqsec + inc reqsec + + ;force sector mismatch + +cmpsecrd: + lda #$ff + +cmpsec: + .if enable_write=1 + ldy command + cpy #cmdwrite ;we need Y=2 below + beq encsec + .endif ; enable_write +cmpsec2: + cmp reqsec + beq readdata + jsr readadr + beq cmpsec2 + + ; read sector data + +readdata: + jsr readd5aa + eor #$ad ;zero A if match +;; bne * ;lock if read failure +unrread4=unrelocdsk+(*-reloc) + +readdata_minus_one: ; - + ldx Q6L + bpl readdata_minus_one ; - + eor nibtbl-$96, X + sta bit2tbl-$aa, Y + iny + bne readdata_minus_one ; - +unrread5=unrelocdsk+(*-reloc) + +readdata_minus_two: ; -- + ldx Q6L + bpl readdata_minus_two ; -- + eor nibtbl-$96, X + sta (adrlo), Y ; the real address + iny + .if check_checksum=1 + .if aligned_read=0 + bne check_end + .else ;aligned_read + bne readdata_minus_two ; -- + .endif ;aligned_read + +unrread6=unrelocdsk+(*-reloc) + +readdata_minus_three: ; - + ldx Q6L + bpl readdata_minus_three ; - + eor nibtbl-$96, X + bne cmpsecrd + .endif ;check_checksum + + .if aligned_read=0 +check_end: + cpy secsize + bne readdata_minus_two ; -- + ldy #0 + .endif ;aligned_read +-- ldx #$a9 +- inx + beq -- + lda (adrlo), y + lsr bit2tbl-$aa, x + rol + lsr bit2tbl-$aa, x + rol + sta (adrlo), y + iny + .if aligned_read=0 + cpy secsize + .endif ;aligned_read + bne - +readret inc adrhi + rts + + .if enable_write=1 +encsec: +-- ldx #$aa +- dey + lda (adrlo), y + lsr + rol bit2tbl-$aa, x + lsr + rol bit2tbl-$aa, x + sta encbuf, y + lda bit2tbl-$aa, x + and #$3f + sta bit2tbl-$aa, x + inx + bne - + tya + bne -- + +cmpsecwr: + jsr readadr + cmp reqsec + bne cmpsecwr + + ;skip tail #$DE #$AA #$EB some #$FFs ... + + ldy #$24 +- dey + bpl - + + ;write sector data + +unrslot1=unrelocdsk+(*-reloc) + ldx #$d1 + lda Q6H, x ;prime drive + lda Q7L, x ;required by Unidisk + tya + sta Q7H, x + ora Q6L, x + + ;40 cycles + + ldy #4 ;2 cycles + cmp $ea ;3 cycles + cmp ($ea,x) ;6 cycles +- jsr writenib1 ;(29 cycles) + + ;+6 cycles + dey ;2 cycles + bne - ;3 cycles if taken, 2 if not + + ;36 cycles + ;+10 cycles + ldy #(prolog_e-prolog) ;2 cycles + cmp $ea ;3 cycles +- lda prolog-1, y ;4 cycles + jsr writenib3 ;(17 cycles) + + ;32 cycles if branch taken + ;+6 cycles + dey ;2 cycles + bne - ;3 cycles if taken, 2 if not + + ;36 cycles on first pass + ;+10 cycles + tya ;2 cycles + ldy #$56 ;2 cycles +- eor bit2tbl-1, y ;5 cycles + tax ;2 cycles + lda xlattbl, x ;4 cycles +unrslot2=unrelocdsk+(*-reloc) + ldx #$d1 ;2 cycles + sta Q6H, x ;5 cycles + lda Q6L, x ;4 cycles + + ;32 cycles if branch taken + + lda bit2tbl-1, y ;5 cycles + dey ;2 cycles + bne - ;3 cycles if taken, 2 if not + + ;32 cycles + ;+9 cycles + clc ;2 cycles +-- eor encbuf, y ;4 cycles +- tax ;2 cycles + lda xlattbl, x ;4 cycles +unrslot3=unrelocdsk+(*-reloc) + ldx #$d1 ;2 cycles + sta Q6H, x ;5 cycles + lda Q6L, x ;4 cycles + bcs + ;3 cycles if taken, 2 if not + + ;32 cycles if branch taken + + lda encbuf, y ;4 cycles + iny ;2 cycles + bne -- ;3 cycles if taken, 2 if not + + ;32 cycles + ;+10 cycles + sec ;2 cycles + bcs - ;3 cycles + + ;32 cycles + ;+3 cycles ++ ldy #(epilog_e-epilog) ;2 cycles + cmp ($ea,x) ;6 cycles +- lda epilog-1, y ;4 cycles + jsr writenib3 ;(17 cycles) + + ;32 cycles if branch taken + ;+6 cycles + dey ;2 cycles + bne - ;3 cycles if branch taken, 2 if not + + lda Q7L, x + lda Q6L, x ;flush final value + inc adrhi + rts + +writenib1: + cmp ($ea,X) ; 6 cycles +writenib2: + cmp ($ea,X) ; 6 cycles +writenib3: +unrslot4=unrelocdsk+(*-reloc) + ldx #$d1 ; 2 cycles +writenib4: + sta Q6H, X ; 5 cycles + ora Q6L, X ; 4 cycles + rts ; 6 cycles + +prolog: + .byte $ad, $aa, $d5 +prolog_e: +epilog: + .byte $ff, $eb, $aa, $de +epilog_e: +.endif ;enable_write +bit2tbl = (*+255) & -256 +nibtbl = bit2tbl+86 + .if enable_write=1 +xlattbl = nibtbl+106 +dataend = xlattbl+64 + .else ;enable_write +dataend = nibtbl+106 + .endif ;enable_write +;hack to error out when code is too large for current address + .if reloc<$c000 + .if dataend>$c000 + .error "code is too large" + .endif + .else + .if relocdirbuf + .error "code is too large" + .endif + .endif + .endif +.endif ;enable_floppy +;.endif ;reloc + + +unrelochdd: + .org reloc ; !pseudopc reloc + +hddopendir: ;read volume directory key block + +unrhddblocklo=unrelochdd+(*-reloc) + ldx #2 +unrhddblockhi=unrelochdd+(*-reloc) + lda #0 + jsr hddreaddirsel + +.if enable_floppy=1 + .if (*-hddopendir) < (readdir-opendir) + ;essential padding to match offset with floppy version + .res (readdir-opendir)-(*-hddopendir), $ea ; .fill + .endif +.endif ;enable_floppy + + ;include volume directory header in count + +hddreaddir: + .if might_exist=1 + ldx dirbuf+37 + inx + stx entries + .endif ;might_exist +hddfirstent: + lda #<(dirbuf+4) + sta bloklo + lda #>(dirbuf+4) + sta blokhi +hddnextent: + ldy #0 + .if might_exist=1 + sty status + .endif ;might_exist + lda (bloklo), Y + .if (might_exist+allow_subdir)>0 + and #$f0 + + .if might_exist=1 + ;skip deleted entries without counting + + beq hddst_plus_two ; ++ + .endif ;might_exist + .endif ;might_exist or allow_subdir + + .if allow_subdir=1 + ;subdirectory entries are seedlings + ;but we need to distinguish between them later + + cmp #$d0 + beq hddsavetype + .endif ;allow_subdir + + ;watch for seedling and saplings only + + cmp #$30 + bcs hddst_plus_one ; + + + ;remember type + +hddsavetype: + .if allow_subdir=1 + asl + asl + .else ;allow_subdir + cmp #$20 + .endif ;allow_subdir + php + + ;match name lengths before attempting to match names + + lda (bloklo), Y + and #$0f + tax + inx + .byte $2c +hddst_minus_one: ; - + lda (bloklo), Y + cmp (namlo), y + beq hddfoundname + + ;match failed, check if any directory entries remain + + plp +hddst_plus_one: ; + + .if might_exist=1 + dec entries + bne hddst_plus_two ; ++ + inc status + rts + .endif ;might_exist + + ;move to next directory in this block, if possible + +hddst_plus_two: ; __ ++ + clc + lda bloklo + adc #$27 + sta bloklo + bcc hddst_plus_three ; + + + ;there can be only one page crossed, so we can increment instead of adc + + inc blokhi +hddst_plus_three: ; + + cmp #<(dirbuf+$1ff) ;4+($27*$0d) + lda blokhi + sbc #>(dirbuf+$1ff) + bcc hddnextent + + ;read next directory block when we reach the end of this block + + ldx dirbuf+2 + lda dirbuf+3 + jsr hddreaddirsec + bcc hddfirstent + +hddfoundname: + iny + dex + bne hddst_minus_one ; - + stx entries + + .if enable_write=1 + ldy reqcmd + cpy #cmdwrite ;control carry instead of zero + bne hddst_plus_four + + ;round requested size up to nearest block if writing + + lda sizelo + ldx sizehi + jsr hddround + sta sizehi + .if aligned_read=0 + sec + .endif ;aligned_read +hddst_plus_four: ; + + .endif ;enable_write + + ;cache EOF (file size, loaded backwards) + + ldy #EOF+1 + lda (bloklo), Y + .if (enable_write+aligned_read)>0 + tax + .else ;enable_write or aligned_read + sta sizehi + .endif ;enable_write or aligned_read + dey + lda (bloklo), Y + .if (enable_write+aligned_read)>0 + .if aligned_read=0 + bcc hddst_plus_five ; ++ + .endif ;aligned_read + + ;round file size up to nearest block if writing or using aligned reads + + .if enable_write=1 + jsr hddround + tax + .if aligned_read=0 + lda #0 + .endif ;aligned_read + + ;set requested size to min(length, requested size) + + cpx sizehi + bcs hddst_plus_six +hddst_plus_five: ; ++ + stx sizehi +hddst_plus_six: ; + + .else ;enable_write + adc #$fe + txa + adc #1 + and #$fe + sta sizehi + .endif ;enable_write + .endif ;enable_write or aligned_read + .if aligned_read=0 + sta sizelo + .endif ;aligned_read + + ;cache AUX_TYPE (load offset for binary files) + + .if override_adr=0 + .if allow_subdir=1 + pla + tax + .else ;allow_subdir + plp + .endif ;allow_subdir + ldy #AUX_TYPE + lda (bloklo), Y + pha + iny + lda (bloklo), Y + pha + .if allow_subdir=1 + txa + pha + .endif ;allow_subdir + .endif ;override_adr + + ;cache KEY_POINTER + + ldy #KEY_POINTER + lda (bloklo), Y + tax + sta dirbuf + iny + lda (bloklo), Y + sta dirbuf+256 + + ; read index block in case of sapling + + .if allow_subdir=1 + plp + bpl hddrdwrfile + php + jsr hddreaddirsec + plp + .else ;allow_subdir + .if override_adr=1 + plp + .endif ;override_adr + bcc hddrdwrfile + jsr hddreaddirsec + .endif ;allow_subdir + + ;restore load offset + +hddrdwrfile: + .if override_adr=1 + ldx ldrhi + lda ldrlo + .else ;override_adr + pla + tax + pla + .endif ;override_adr + + .if allow_subdir=1 + ;check file type and fake size and load address for subdirectories + + bcc hdd_rdwr_plus_one ; + + ldy #2 + sty sizehi + ldx #>dirbuf + lda #dirbuf + sta adrhi + lda #0 + sta adrlo +hdd_rdwr_plus_two: ; + + php + .endif ;aligned_read + + ;fetch data block and read/write it + + ldy entries + inc entries + ldx dirbuf, Y + lda dirbuf+256, Y + .if enable_write=1 + ldy reqcmd + .endif ;enable_write + jsr hddseekrdwr + + .if aligned_read=0 + plp + bcc hdd_rdwr_plus_three ; + + .endif ;aligned_read + inc adrhi + inc adrhi + dec sizehi + dec sizehi + bne hddrdwrloop + .if aligned_read=0 + lda sizelo + bne hddrdwrloop + .endif ;aligned_read + .if allow_aux=1 +hddrdwrdone: + ldx #0 +hddsetaux: + sta CLRAUXRD, x + sta CLRAUXWR, x + .endif ;allow_aux + rts + + .if aligned_read=0 +hdd_rdwr_plus_three: ; + + pla + sta bloklo + pla + sta blokhi + pla + tay + beq hdd_rdwr_plus_four ; + + dey +hdd_rdwr_minus_one: ; - + lda (adrlo), Y + sta (bloklo), Y + iny + bne hdd_rdwr_minus_one + inc blokhi + inc adrhi + bne hdd_rdwr_plus_four ; + +hdd_rdwr_minus_two: ; - + lda (adrlo), Y + sta (bloklo), Y + iny +hdd_rdwr_plus_four: ; + + cpy sizelo + bne hdd_rdwr_minus_two ; - + .if allow_aux=1 + beq hddrdwrdone + .else ;allow_aux + rts + .endif ;allow_aux + .endif ;aligned_read + + .if enable_write=1 +hddround: + clc + adc #$ff + txa + adc #1 + and #$fe + rts + .endif ;enable_write + +hddreaddirsel: + ldy #0 + sty adrlo + .if might_exist=1 + sty status + .endif ;might_exist + + .if allow_multi=1 + asl reqcmd + lsr reqcmd + .endif ;allow_multi + +hddreaddirsec: + ldy #>dirbuf + sty adrhi + ldy #cmdread + .if enable_write=1 +hddseekrdwr: + .endif ;enable_write + sty command + .if enable_write=0 +hddseekrdwr: + .endif ;enable_write + stx bloklo + sta blokhi + +unrunit=unrelochdd+(*-reloc) + lda #$d1 + sta unit + +unrentry=unrelochdd+(*-reloc) + jmp $d1d1 + +;} end reloc + +readbuff: +.byte $D3,$C1,$CE,$A0,$C9,$CE,$C3,$AE From 491eb4ca4eac0154fc57d7ee0f2a9b75c46d5dc7 Mon Sep 17 00:00:00 2001 From: Vince Weaver Date: Mon, 15 Jul 2024 16:31:49 -0400 Subject: [PATCH 2/2] prorwts: sort of figured out what proboothd is doing --- disk/prorwts/Makefile | 17 +- disk/prorwts/hardware.inc | 99 ++++++++++++ disk/prorwts/proboothd.s | 318 ++++++++++++++++++++++++-------------- disk/prorwts/seasons.s | 269 ++++++++++++++++++++++++++++++++ 4 files changed, 579 insertions(+), 124 deletions(-) create mode 100644 disk/prorwts/hardware.inc create mode 100644 disk/prorwts/seasons.s diff --git a/disk/prorwts/Makefile b/disk/prorwts/Makefile index 246ff1a5..526a5076 100644 --- a/disk/prorwts/Makefile +++ b/disk/prorwts/Makefile @@ -19,15 +19,15 @@ prorwts_ca65.o: prorwts_ca65.s ### prorwts_test.2mg: \ - PROBOOTHD + PROBOOTHD SEASONS $(CADIUS) CREATEVOLUME prorwts_test.2mg Test 32MB - dd conv=notrunc if=PROBOOTHD of=prorwts_test.2mg bs=512 count=1 + dd conv=notrunc if=PROBOOTHD of=prorwts_test.2mg bs=1 count=512 oseek=64 # $(CADIUS) CREATEFOLDER prorwts_test.2mg /Test/DISK01 # $(CADIUS) CREATEFOLDER prorwts_test.2mg /Test/DISK39 # $(CADIUS) CREATEFOLDER prorwts_test.2mg /Test/DISK40 # $(CADIUS) CREATEFOLDER prorwts_test.2mg /Test/DISK41 # $(CADIUS) CREATEFOLDER prorwts_test.2mg /Test/DISK43 -# $(CADIUS) ADDFILE prorwts_test.2mg /Test/DISK01/ disk01_files/LEVEL_ARRIVAL + $(CADIUS) ADDFILE prorwts_test.2mg /Test/ SEASONS#061000 ### @@ -39,5 +39,14 @@ proboothd.o: proboothd.s #### +SEASONS: seasons.o + ld65 -o SEASONS seasons.o -C ../../linker_scripts/apple2_1000.inc + +seasons.o: seasons.s + ca65 -o seasons.o seasons.s -l seasons.lst + + +#### + clean: - rm -f *~ *.o *.lst + rm -f *~ *.o *.lst PROBOOTHD SEASONS diff --git a/disk/prorwts/hardware.inc b/disk/prorwts/hardware.inc new file mode 100644 index 00000000..3c85fd67 --- /dev/null +++ b/disk/prorwts/hardware.inc @@ -0,0 +1,99 @@ +;; HARDWARE LOCATIONS + +KEYPRESS = $C000 +KEYRESET = $C010 + +;; SOFT SWITCHES +CLR80COL = $C000 ; (w) PAGE1/PAGE2 normal +SET80COL = $C001 ; (w) PAGE1/PAGE2 switches PAGE1 in Aux instead +READMAINMEM = $C002 ; (w) to read from main mem ($0200..$BFFF) +READAUXMEM = $C003 ; (w) to read from aux mem ($0200..$BFFF) +WRITEMAINMEM = $C004 ; (w) to write to main mem ($0200..$BFFF) +WRITEAUXMEM = $C005 ; (w)to write to aux mem ($0200..$BFFF) +SETSTDZP = $C008 ; (w) to use main mem stack/zp ($00FF-$01FF) +EIGHTYCOLOFF = $C00C ; (w) use 40 cols / exit DHGR +EIGHTYCOLON = $C00D +PRIMARYCHARSET = $C00E ; (w) to disable mousetext +TBCOLOR = $C022 ; IIgs text foreground / background colors +NEWVIDEO = $C029 ; IIgs graphics modes +SPEAKER = $C030 +CLOCKCTL = $C034 ; bits 0-3 are IIgs border color +CYAREG = $C036 ; iigs motor detect and clock speed +SET_GR = $C050 +SET_TEXT = $C051 +FULLGR = $C052 +TEXTGR = $C053 +PAGE1 = $C054 +PAGE2 = $C055 +LORES = $C056 ; Enable LORES graphics +HIRES = $C057 ; Enable HIRES graphics +AN3 = $C05E ; Annunciator 3 + +PADDLE_BUTTON0 = $C061 +PADDL0 = $C064 +PTRIG = $C070 + +; $C081 for setting language card +; $C082 for setting READ_ROM_NOWRITE + + + + +;; MONITOR ROUTINES + +HLINE = $F819 ; HLINE Y,$2C at A +VLINE = $F828 ; VLINE A,$2D at Y +CLRSCR = $F832 ; Clear low-res screen +CLRTOP = $F836 ; clear only top of low-res screen +SETCOL = $F864 ; COLOR=A +ROM_TEXT2COPY = $F962 ; iigs +INIT_TEXT = $FB2F ; set lo-res/page1 and call text +TEXT = $FB36 +GR = $FB40 +TABV = $FB5B ; VTAB to A +ROM_MACHINEID = $FBB3 ; iigs +BELL = $FBDD ; ring the bell +BASCALC = $FBC1 ; +VTAB = $FC22 ; VTAB to CV +HOME = $FC58 ; Clear the text screen +WAIT = $FCA8 ; delay 1/2(26+27A+5A^2) us +CROUT1 = $FD8B +SETINV = $FE80 ; INVERSE +SETNORM = $FE84 ; NORMAL +COUT = $FDED ; output A to screen +COUT1 = $FDF0 ; output A to screen +SETKBD = $FE89 ; set input to keyboard +SETVID = $FE93 ; set output to video screen + +COLOR_BLACK = 0 +COLOR_RED = 1 +COLOR_DARKBLUE = 2 +COLOR_PURPLE = 3 +COLOR_DARKGREEN = 4 +COLOR_GREY = 5 +COLOR_MEDIUMBLUE = 6 +COLOR_LIGHTBLUE = 7 +COLOR_BROWN = 8 +COLOR_ORANGE = 9 +COLOR_GREY2 = 10 +COLOR_PINK = 11 +COLOR_LIGHTGREEN = 12 +COLOR_YELLOW = 13 +COLOR_AQUA = 14 +COLOR_WHITE = 15 + +COLOR_BOTH_BLACK = $00 +COLOR_BOTH_RED = $11 +COLOR_BOTH_DARKBLUE = $22 +COLOR_BOTH_DARKGREEN = $44 +COLOR_BOTH_GREY = $55 +COLOR_BOTH_MEDIUMBLUE = $66 +COLOR_BOTH_LIGHTBLUE = $77 +COLOR_BOTH_BROWN = $88 +COLOR_BOTH_ORANGE = $99 +COLOR_BOTH_PINK = $BB +COLOR_BOTH_LIGHTGREEN = $CC +COLOR_BOTH_YELLOW = $DD +COLOR_BOTH_AQUA = $EE +COLOR_BOTH_WHITE = $FF + diff --git a/disk/prorwts/proboothd.s b/disk/prorwts/proboothd.s index c4139def..beea7fc0 100644 --- a/disk/prorwts/proboothd.s +++ b/disk/prorwts/proboothd.s @@ -5,65 +5,104 @@ ; ;copyright (c) Peter Ferrie 2016-2019 +.include "hardware.inc" + +PROBOOTENTRY = $2000 + ; zpage usage, arbitrary selection except for the "ProDOS constant" ones - command = $42 ;ProDOS constant - unit = $43 ;ProDOS constant - adrlo = $44 ;ProDOS constant - adrhi = $45 ;ProDOS constant - bloklo = $46 ;ProDOS constant - blokhi = $47 ;ProDOS constant + command = $42 ; ProDOS constant + UNIT = $43 ; ProDOS constant + ADRLO = $44 ; ProDOS constant + ADRHI = $45 ; ProDOS constant + BLOKLO = $46 ; ProDOS constant + BLOKHI = $47 ; ProDOS constant A2L = $3e A2H = $3f sizehi = $53 -;constants - scrn2p2 = $f87b + + SCRN2P2 = $f87b ; shifts top nibble to bottom + dirbuf = $1e00 ;for size-optimisation -; start of boot sector, how many sectors to load +; start of boot sector, presumably how many sectors to load +; 512 bytes on prodos/hard-disk(???) + .byte 1 proboot_start: txa - pha + pha ; save slot for later - lda #'A'+$80 - sta $400 ; write A to upper-left of screen + ; init. is all this necessary? + ; originally "4cade.init.machine.a" -forever: - jmp forever + cld ; clear direction flag + sta $C082 ; read rom / no write (language card) + sta PRIMARYCHARSET ; turn off mouse text + sta EIGHTYCOLOFF ; disable 80-col mode + sta CLR80COL + sta READMAINMEM ; make sure not using aux mem + sta WRITEMAINMEM + sta SETSTDZP + + ; more init + ; originally "4cade.init.screen.a" + + ; initializes and clears screen using ROM routines + + jsr INIT_TEXT ; setup text mode + jsr HOME ; clear screen + jsr SETNORM ; normal text + jsr SETKBD ; keyboard input + jsr SETVID ; video output + + ; set up disk stuff? + + pla ; restore slot + sta UNIT ; save for later + + tax + ; X = boot slot x16 + + ; Y = 0 + ; 4cade calls a print-title routine here that exits with Y=0 + + ldy #0 + + ; set up ProDOS shim + + ; from IIgs smartport firmware manual + + ; prodos entry point is $CX00+($CXFF) + ; so if slot 7, $C700 + value in $C7ff (say, A) so $C70A + ; smartport entry point is $CX00+(CXFF)+3 -;src "src/4cade.init.machine.a" +setup_loop: + txa + jsr SCRN2P2 ; shift top nibble of A to bottom + and #7 + ora #$c0 + sta $be30, Y ; ???? + sta slot_smc+2 + sta entry_smc+2 ; set up smartport/prodos entry point -; src "src/4cade.init.screen.a" +slot_smc: + lda $cfff + sta entry_smc+1 ; set up rest of smartport/prodos entry + lda fakeMLI_e-$100, Y + sta $be00+fakeMLI_e-fakeMLI, Y + iny + bne setup_loop ; ????? -; pla - ; sta unit - ; tax - ; ; X = boot slot x16 - ; ; Y = 0 - - ; set up ProDOS shim - -;- txa -; jsr scrn2p2 -; and #7 -; ora #$c0 -; sta $be30, y -; sta slot+2 -; sta entry+2 -;slot lda $cfff -; sta entry+1 -; lda fakeMLI_e-$100, y -; sta $be00+fakeMLI_e-fakeMLI, y -; iny -; bne - -; sty adrlo -; stx $bf30 -; sty $200 + ; Y is 0 here +; ldy #0 + sty ADRLO + stx $bf30 ; ????? + sty $200 ; ????? opendir: ; read volume directory key block @@ -72,116 +111,155 @@ opendir: ; include volume directory header in count firstent: - lda #>dirbuf - sta adrhi + lda #>dirbuf ; load volume block to ADDRH/L (dirbuf/$1e00) + sta ADRHI sta A2H jsr seekread - lda #4 + + + lda #4 ; start at filename offset sta A2L nextent: ldy #0 ; match name lengths before attempting to match names + ; first byte, bottom nibble is length -; lda (A2L), y -; and #$0f -; tax -; inx -;- cmp filename, y -; beq foundname + lda (A2L), Y + and #$0f + tax + inx - ;move to next directory in this block +try_again: + cmp filename, Y + beq filename_char_match -; clc - ; lda A2L - ; adc #$27 - ; sta A2L - ; bcc + + ; move to next directory in this block +not_found: + clc + lda A2L + adc #$27 + sta A2L + bcc no_cross_page - ;there can be only one page crossed, so we can increment instead of adc + ; there can be only one page crossed, + ; so we can increment instead of adc -; inc A2H -;+ cmp #$ff ;4+($27*$0d) -; bne nextent + inc A2H +no_cross_page: + cmp #$ff ; 4+($27*$0d) + bne nextent - ;read next directory block when we reach the end of this block + ; read next directory block when we reach the end of this block -; ldx dirbuf+2 -; ldy dirbuf+3 -; bcs firstent + ldx dirbuf+2 + ldy dirbuf+3 + bcs firstent -foundname: -; iny -; lda (A2L), y -; dex -; bne - -; stx $ff +filename_char_match: + iny ; point to next char + lda (A2L), Y ; grab value + dex ; countdown filename length + bne try_again ; if not full match, keep going - ;cache KEY_POINTER -; ldy #$11 -; lda (A2L), y -; tax -; iny -; lda (A2L), y -; tay + stx $ff ; set address $FF in zero page to zero? + + ; bytes $11 and $12 in the file entry are the "key pointer" + + ldy #$11 + lda (A2L), Y + tax + iny + lda (A2L), Y + tay + + + ; seedling files = less than 512 bytes, contents are simply key block + ; storage type is $1 + ; sapling files = 512B - 128k + ; key block has low bytes of addrss in 0..255 and high in 256..512 + ; storage type is $2 + ; tree files = 128k - 16M + + + ; read the 512-byte block at key pointer into memory + ; will only work for a "sapling" file? readfile: -; jsr seekread -; inc adrhi -; inc adrhi + jsr seekread - ;fetch data block and read it + inc ADRHI ; point destination past it (so at $2000) + inc ADRHI + + ; fetch contents of file? + ; just keep reading 512-byte blocks until done? + ; this means file will be at $2000? blockind: -; ldy $ff -; inc $ff -; ldx dirbuf, y -; lda dirbuf+256, y -; tay -; bne readfile -; txa -; bne readfile + ldy $ff ; use $ff as block index? + inc $ff ; + + ldx dirbuf, Y ; low byte of block# + lda dirbuf+256, Y ; high byte of block# + tay + + bne readfile ; if high byte!=0, read another block + + txa ; if high byte=0 and low_byte=0, done + bne readfile readdone: -; jmp ProBootEntry + jmp PROBOOTENTRY ; would be $2000 if sapling + + ;================================ + ; seek read + ;================================ + ; Y:X = block number to load (???) + ; A = page to load to? seekread: -; stx bloklo -; sty blokhi -; lda #1 -; sta command -; lda adrhi -; pha -;entry jsr $d1d1 -; pla -; sta adrhi -; rts + stx BLOKLO + sty BLOKHI + lda #1 + sta command + lda ADRHI + pha +entry_smc: + jsr $d1d1 + pla + sta ADRHI + rts -;fakeMLI bne retcall -;readblk dey -; dey -; sty adrhi -; tay -; jsr $bf00+seekread-fakeMLI -;retcall pla -; tax -; inx -; inx -; inx -; txa -; pha -;- rts -;fakeMLI_e +fakeMLI: + bne retcall +readblk: + dey + dey + sty ADRHI + tay + jsr $bf00+seekread-fakeMLI +retcall: + pla + tax + inx + inx + inx + txa + pha +;-: + rts +fakeMLI_e: -;filename +PSTRING "LAUNCHER.SYSTEM" +filename: + ; expects PASCAL-string filename + ; first byte size (max 15) + .byte 7,"SEASONS" -; !src "src/4cade.branding.a" - -;!if (* > $9f7) { -; !serious "Bootloader is too large" -;} +;.if (* > $9f7) +; .error "Bootloader is too large" +;.endif ;*=$9f8 ;!byte $D3,$C1,$CE,$A0,$C9,$CE,$C3,$AE diff --git a/disk/prorwts/seasons.s b/disk/prorwts/seasons.s new file mode 100644 index 00000000..2e9928fd --- /dev/null +++ b/disk/prorwts/seasons.s @@ -0,0 +1,269 @@ +; Apple II Seasons -=DESiRE=- 128B Demo for Outline 2020 +; based on the code in Hellmood's 64B x86 demo "Autumn" +; by deater (Vince Weaver) + +; DOS version is 64 bytes +; original Apple II 6502 port was 167 bytes +; I got it down to 126 bytes +; qkumba got it down to 116 +; color-cycling brought it back up to 127 bytes + +; To save space, runs from the zero page starting at $50 +; need to avoid $E0-$E5 used by the hgr/hplot routines + +; Zero Page Addresses + +XCOORDL = $F3 +XCOORDH = $F4 +YCOORDL = $F5 +YCOORDH = $F6 +EBP1 = $F7 +EBP2 = $F8 +EBP3 = $F9 +EBP4 = $FA +COLORL = $FB +COLORH = $FC +SOUND = $FD +FRAMEL = $FE +FRAMEH = $FF + +; Soft Switches +KEYPRESS= $C000 +KEYRESET= $C010 +SPEAKER = $C030 + +; ROM routines +; Some of these are in the Applesoft ROMs so need at least an Apple II+ +; or later to run + +TEXT = $FB36 ; Set text mode +HGR2 = $F3D8 ; Set full-screen hi-res mode using page 2 ($4000) + ; 280x192 6-colors +HPLOT0 = $F457 ; Plot point, (Y,X) = Horizontal, (A=Vertical) +HCOLOR = $F6EC ; Set color in X, must be 0..7 + +; use zero-page addressing to save space +;.zeropage + +seasons: + + ;=================== + ; init screen ; Instruction Length + jsr HGR2 ; 3 + + ; init vars to zero. Apple II doesn't clear RAM + ; some of these might be necessary? + ; should we make this a loop? + +; ldx #0 ; 2 +; stx XCOORDL ; 2 +; stx YCOORDL ; 2 +; stx XCOORDH ; 2 +; stx YCOORDH ; 2 +; stx EBP1 ; 2 +; stx EBP2 ; 2 +; stx EBP3 ; 2 +; stx EBP4 ; 2 +; stx COLORH ; 2 + + +seasons_forever: + + ; save old Xcoord value to X/Y for later + ; push/pop is 1 byte each but have to get + ; value into accumulator first + ldx XCOORDL ; 2 + ldy XCOORDH ; 2 + + ; 16-bit subtraction x=x-y + ; need to set carry before subtraction on 6502 + txa ; 1 (xcoordl in X) + sec ; 1 + sbc YCOORDL ; 2 + sta XCOORDL ; 2 + tya ; 1 (xcoordh in Y) + sbc YCOORDH ; 2 + + ; 16-bit arithmatic shift right of X + ; 6502 has no asr instruction + ; cmp #$80 sets carry if high bit set + cmp #$80 ; 2 ; XCOORDH still in A from before + ror ; 1 + sta XCOORDH ; 2 + ror XCOORDL ; 2 + + ; 16-bit add, ycoord=ycoord+oldx + clc ; 1 + txa ; 1 + adc YCOORDL ; 2 + sta YCOORDL ; 2 + tya ; 1 + adc YCOORDH ; 2 + + ; 16-bit arithmatic shift right of y-coord + cmp #$80 ; 2 ; YCOORDH still in A from before + ror ; 1 + sta YCOORDH ; 2 + ror YCOORDL ; 2 + + ; 32 bit rotate of low bit shifted out of Y-coordinate + ror EBP1 ; 2 + ror EBP2 ; 2 + ror EBP3 ; 2 + ror EBP4 ; 2 + + ; branch if carry set + bcs label_11f ; 2 + + ; 16-bit increment of color + inc COLORL ; 2 + bne no_oflo ; 2 + inc COLORH ; 2 +no_oflo: + + ; 16-bit add of X-coord by 0x80 + ; this keeps the drawing roughly to the 280x192 screen + ; carry should still be clear (inc doesn't set it) + lda XCOORDL ; 2 + adc #$80 ; 2 + sta XCOORDL ; 2 + bcc no_oflo2 ; 2 + inc XCOORDH ; 2 +no_oflo2: + + ; 16-bit negate of Y-coord + sec ; 1 + lda #0 ; 2 + sbc YCOORDL ; 2 + sta YCOORDL ; 2 + lda #0 ; 2 + sbc YCOORDH ; 2 + sta YCOORDH ; 2 + +label_11f: + + ; skipping the color manipulation done here by original + + ; mix colors a bit? + + ; 16-bit shift of color + ; 2nd is a rotate as asl doesn't shift in cary + + lda COLORL ; 2 + asl ; 1 ; shl %ax + rol COLORH ; 2 + eor COLORH ; 2 + sta COLORL ; 2 + + ; get color mapping + ; using a color lookup table looks best but too many bytes + ; you can approximate something close to the lookup with + ; two extra instructions + + and #$7 ; 2 +smc: + ora #$2 ; 2 + tax ; 1 + + ; if using color lookup table +; tay ; 1 +; ldx color_lookup,Y ; 3 (could be 2 if we run in zero page) + + ; if ycoord negative, loop + lda YCOORDH ; 2 + bmi seasons_forever ; 2 + + ; if top bits of xcoord, loop + lda XCOORDH ; 2 + and #$f0 ; 2 + bne seasons_forever ; 2 + +put_pixel: + + ; actually set the color + jsr HCOLOR ; 3 ; color is in X + + ; set up paramaters for HPLOT ROM call + ldx XCOORDL ; 2 ; x coord in (y:x) + ldy XCOORDH ; 2 + lda YCOORDL ; 2 ; y coord in A + jsr HPLOT0 ; 3 + + ; flip palettes when color at $4200 (roughly 0,32 on screen) + ; changes. This is sort of arbitrary, but having a 16-bit counter + ; takes too many instructions and Apple II doesn't have a + ; programmable timer + + lda $4200 ; 3 ; check colors at 0,32 + bmi seasons_forever ; 2 + + ; flip between blue/purple and orange/green palettes + ; with self-modifying code. 2 bytes are saved when + ; we execute in the zero page + lda smc+1 ; 2 + eor #$3 ; 2 + sta smc+1 ; 2 + + ; the adc/sbc in HPLOT0 leave the V flag clear + ; so we can save a byte (over jump) by using bvc + bvc seasons_forever ; 2 + + + + + ; Thankfully not necessary for a 128B demo? +; lda KEYPRESS ; 3 ; see if key pressed +; bpl seasons_forever ; 2 ; loop if not +; bit KEYRESET +exit_to_prompt: +; jsr TEXT ; 3 ; return to text mode +; jmp $3D0 ; 3 ; return to Applesoft prompt + + +;======================================================== +;======================================================== +; color lookup tables used when testing +; some of them look better, but make the executable bigger +; than the AND/OR version of setting colors + + +; Apple II Hi-Res Colors +; It's all NTSC artifacting and complex +; There can be color-clash at a 3.5 pixel level +; Adjacent on pixels make white, adjacent off make black +; Simplistic summary, you can have these 8 colors (6 unique) +; 0 = Black0 +; 1 = Green +; 2 = Purple +; 3 = White0 +; 4 = Black1 +; 5 = Orange +; 6 = Blue +; 7 = White2 + +color_lookup: + + ; colorful palette +; .byte $01,$01,$02,$03, $05,$05,$06,$07 + + ; blue and purple palette +; .byte $02,$02,$03,$06, $06,$06,$02,$07 + + ; qkumba ora2 white/blue/purple +; .byte $02,$03,$02,$03, $06,$07,$06,$07 + + ; ora1 white/orange/green +; .byte $01,$01,$03,$03, $05,$05,$07,$07 + + ; better mixed orange/green/white +; .byte $01,$03,$03,$03, $05,$05,$07,$07 + + ; orange and green palette +; .byte $01,$01,$03,$05, $05,$05,$01,$07 + +; .byte $01,$00,$01,$00, $05,$00,$05,$00 + +; "Leaf" Locations +; TOP-LEFT ?? CENTER-TOP TOP-RIGHT LEFT ?? CENTER-BOTTOM ?? + +