diff --git a/qboot/Makefile b/qboot/Makefile new file mode 100644 index 00000000..6203d799 --- /dev/null +++ b/qboot/Makefile @@ -0,0 +1,19 @@ +include ../Makefile.inc + +DOS33_RAW = ../dos33fs-utils/dos33_raw + +all: boot.dsk + +boot.dsk: BOOT + cp empty.dsk boot.dsk + $(DOS33_RAW) boot.dsk 0 0 BOOT + +BOOT: boot_sector.o + ld65 -o BOOT boot_sector.o -C ../linker_scripts/apple2_800.inc + +boot_sector.o: boot_sector.s stage2.s + ca65 -o boot_sector.o boot_sector.s -l boot_sector.lst + +clean: + rm -f *~ *.o *.lst BOOT + diff --git a/qboot/boot_sector.s b/qboot/boot_sector.s new file mode 100644 index 00000000..eab17dd1 --- /dev/null +++ b/qboot/boot_sector.s @@ -0,0 +1,204 @@ +; fast seek/multi-read +; copyright (c) Peter Ferrie 2015-16 + + sectors = $d1 ; user-defined + firsttrk = $d1 ; user-defined, first track to read + firstsec = $d1 ; user-defined, first sector to read + address = $d1 ; user-defined + entry = $d1d1 ; user-defined + version = 1 + + ;memory usage: + ;256 bytes ($bd00-bdff) static table + grouped = $bd00 + ;106 bytes ($xx00-xx69) static table + preshift = code_end + zvalue = $fd ;only during init + znibble = $fe ;only during init + zmask = $ff ;only during init + + +; $26/$27 sector read location (ROM), scratch space (RWTS) +; $3D sector number + + +; at entry (at least on AppleWin) A=1, X=60, Y=0 +; qkumba says cffa cards leave Y at $10 +; 26/27 = 00/09 +; 3D = 1 + + ; For Disk II booting, the firmware loads track0/sector0 + ; to $800 and then jumps to $801 + +.org $800 + .byte 1 ; number of sectors for ROM to load + +boot_entry: + ; this code loads two sectors up to $BE/$BF + + lsr ; check sector number + tay + adc #$bd + sta $27 ; set or update address as needed + asl + ; be, bf, c0 (1011 1011 1100) + ; so if hit $c000 we are done + + bmi not_three ; branch if not 3 + + inc $3d ; increment sector (faster to find) + + ; call to the read routine in proper slot + ; using rts to jump indirect to + ; $CX5C + + ; this routine reads sector in $3D on track $41 + ; to address in $26/$27 + ; when it's done it jumps back to $801 + + txa ; x is slot# << 4 + lsr + lsr + lsr + lsr + ora #$c0 ; slot to PROM base + pha + lda #$5b ;read-1 + pha + rts + +not_three: + txa + ora #$8c ; slot to Q6L + ; Q6L? + ; 1000 1100 +patch_loop: + iny + ldx patchtbl-3, y + sta code_begin, x ;replace placeholders with Q6L + bne patch_loop + and #$f8 ;MOTOROFF + sta slotpatch7+1 + eor #8 ;PHASEOFF + sta slotpatch8+1 + ldx #$3f + stx zmask + inx + ldy #$7f + + bne skip_ahead ; branch always + + ; pad with zeros until $839 +.res $839-* +;*=$839 + lda #>(entry-1) + pha + lda #<(entry-1) + pha + jsr preread + jmp $bf00 ;DOS 3.3 launcher entrypoint + +patchtbl: + .byte <(slotpatch1+1), <(slotpatch2+1), <(slotpatch3+1), <(slotpatch4+1), <(slotpatch5+1), <(slotpatch6+1) +indextbl: ;the 0 also terminates the patchtbl list! + .byte 0, 2, 1, 3 + + + ;construct denibbilisation table + ;pre-shifted for interleave read + +skip_ahead: +loopaa: + sty znibble + tya + asl + bit znibble + beq loopz + ora znibble + eor #$ff + and #$7e +loopa: + bcs loopz + lsr + bne loopa + dex + txa + asl + asl + sta preshift-$16, Y +loopz: + dey + bne loopaa + + ;construct 2-bit group table + + sty zvalue +loopbb: + lsr zmask + lsr zmask +loopb: + lda indextbl, X + sta grouped, Y + inc zvalue + lda zvalue + and zmask + bne loopy + inx + txa + and #3 + tax +loopy: + iny + iny + iny + iny + cpy #3 + bcs loopb + iny + cpy #3 + bcc loopbb + lda #>(entry-1) + pha + lda #<(entry-1) + pha + jsr preread + + jmp seekread + +preread: + +;copy post-read if necessary +;push post-read address here +; pla +; tax +; pla +; tay +; lda #>(postread-1) +; pha +; lda #<(postread-1) +; pha +; tya +; pha +; txa +; pha + + lda #<(firsttrk*2) + sta phase+1 + ldx #sectors + lda #address + ldy #firstsec + rts + + + +end_code: + +.res $8fe-* + +; traditionally, entry point to jump to at end of loading +; $be01 in this case +;*=$8fe + .byte $be, 1 + + +.include "stage2.s" diff --git a/qboot/empty.dsk b/qboot/empty.dsk new file mode 100644 index 00000000..b34eb519 Binary files /dev/null and b/qboot/empty.dsk differ diff --git a/qboot/stage2.s b/qboot/stage2.s new file mode 100644 index 00000000..3f0ce047 --- /dev/null +++ b/qboot/stage2.s @@ -0,0 +1,257 @@ +;the following lives on sectors $0E and $0D +; ???? + +.org $be00 + +code_begin: + + .byte version + +readnib: +slotpatch1: + lda $c0d1 ; ??? + bpl readnib + rts + + ;fill address array for one track +seekread: + sty startsec+1 + sta tmpadr+1 + stx total+1 + +inittrk: + sec + lda #$10 + sbc startsec+1 + cmp total+1 + bcs it_skip + + tax + +it_skip: + stx partial1 + stx partial2 + jsr seek + +startsec: + ldy #$d1 + +tmpadr: +tmpadr_loop: + lda #$d1 + sta addrtbl, y + inc tmpadr+1 + iny + dec partial1 + bne tmpadr_loop + +read: + +outer_read: + jsr readnib +inner_read: + cmp #$d5 + bne outer_read + jsr readnib + cmp #$aa + bne inner_read + tay ; we need Y=#$AA later + jsr readnib + eor #$ad ; zero A if match + beq check_mode + + ;if not #$AD, then #$96 is assumed + + ldy #2 ; volume, track, sector +another: + jsr readnib + rol ; set carry + sta sector+1 + jsr readnib + and sector+1 + dey + bpl another + tay + ldx addrtbl, Y ; fetch corresponding address + beq read + sta sector+1 ; store index for later + + stx adrpatch1+2 + stx adrpatch8+2 + stx adrpatch2+2 + stx adrpatch3+2 + stx adrpatch5+2 + stx adrpatch7+2 + + inx + stx adrpatch9+2 + dex + + dex + stx adrpatch4+2 + stx adrpatch6+2 + + ldy #$fe +adrpatch1: +loop2: + lda $d102, Y + pha + iny + bne loop2 + +branch_read: + bcs read ; branch always +check_mode: + cpx #0 + beq read ; loop if not expecting #$AD + +loop33: + sta tmpval+1 ; zero rolling checksum +slotpatch2: +loop4: + ldx $c0d1 + bpl loop4 + lda preshift-$96, X +adrpatch2: + sta $d102, Y ; store 2-bit array + +tmpval: + eor #$d1 + iny + bne loop33 + ldy #$aa +slotpatch3: +loop5: + ldx $c0d1 + bpl loop5 + eor preshift-$96, X +adrpatch3: + ldx $d102, Y ; bit2tbl + eor grouped+2, X ; first 86 nibbles use group bits 0-1 +adrpatch4: + sta $d156, y + iny + bne loop5 + and #$fc + ldy #$aa +slotpatch4: +loop6: + ldx $c0d1 + bpl loop6 + eor preshift-$96, X +adrpatch5: + ldx $d102, Y ; bit2tbl + eor grouped+1, X ; second 86 nibbles use group bits 2-3 +adrpatch6: + sta $d1ac, Y + iny + bne loop6 + and #$fc + ldx #$ac +slotpatch5: +loop7: + ldy $c0d1 + bpl loop7 + eor preshift-$96, Y +adrpatch7: + ldy $d100, X ; bit2tbl + eor grouped, Y ; last 84 nibbles use group bits 4-5 +adrpatch8: + sta $d100, x + inx + bne loop7 + and #$fc +slotpatch6: +loop8: + ldy $c0d1 + bpl loop8 + eor preshift-$96, Y + cmp #1 ; carry = !zero + ldy #1 +loop9: + pla +adrpatch9: + sta $d100, Y + dey + bpl loop9 +branch_read2: + bcs branch_read ; branch if checksum failure +sector: + ldy #$d1 + txa + sta addrtbl, Y ; zero corresponding address + dec total+1 + dec partial2 ; adjust remaining count (faster than looping over array) + sec + bne branch_read2 ; read all requested sectors in one track +total: + ldx #$d1 + beq driveoff + inc phase+1 + inc phase+1 ; update current track + jmp inittrk + +driveoff: +slotpatch7: + lda $c0d1 + +seekret: + rts + +seek: + lda #0 + sta step+1 +copy_cur: +curtrk: + lda #0 + sta tmpval+1 + sec +phase: + sbc #$d1 + beq seekret + + eor #$ff + inc curtrk+1 + + cmp step+1 + bcc loop10 +step: + lda #$d1 +loop10: + cmp #8 + bcs loop11 + tay + sec +loop11: + lda curtrk+1 + ldx step1, Y + bne loop12 +loopmmm: + clc + lda tmpval+1 + ldx step2, Y +loop12: + stx sector+1 + and #3 + rol + tax +slotpatch8: + sta $c0d1, X +loopmm: + ldx #$13 +loopm: + dex + bne loopm + dec sector+1 + bne loopmm + lsr + bcs loopmmm + inc step+1 + bne copy_cur + +step1: .byte 1, $30, $28, $24, $20, $1e, $1d, $1c +step2: .byte $70, $2c, $26, $22, $1f, $1e, $1d, $1c +addrtbl: .res 16 +partial1 = * +partial2 = partial1+1 +code_end=partial2+1