qboot/QBOOT.S

423 lines
9.2 KiB
ArmAsm

;fast seek/multi-read
;copyright (c) Peter Ferrie 2015-16
;assemble using ACME
!cpu 6502
!to "qboot",plain
*=$800
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
zpread = 0 ;set to 1 to allow reading into zero page
;relies on memory wraparound, not supported on IIGS
;also precludes reading to page $FF
stkread = 0 ;set to 1 to allow reading into stack page
;but remember about the 6 bytes of stack
seekback = 0 ;set to 1 to enable seek backwards
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
!byte 1 ;we'll read the other two ourselves
lsr ;check sector number
;the following TAY is a workaround for a CFFA bug
;the bug is that Y isn't zero on entry
;the workaround sets it to two instead
;it's not zero, but it's better than #$10
tay
adc #$bd
sta $27 ;set or update address as needed
asl
bmi + ;branch if not 3
inc $3d ;increment sector (faster to find)
txa
lsr
lsr
lsr
lsr
ora #$c0 ;slot to PROM base
pha
lda #$5b ;read-1
pha
rts
+ txa
ora #$8c ;slot to Q6L
- iny
ldx patchtbl-3, y
sta code_begin, x ;replace placeholders with Q6L
bne -
and #$f8 ;MOTOROFF
sta slotpatch7+1
eor #8 ;PHASEOFF
sta slotpatch8+1
ldx #$3f
stx zmask
inx
ldy #$7f
bne + ;branch always
*=$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
+
-- sty znibble
tya
asl
bit znibble
beq +
ora znibble
eor #$ff
and #$7e
- bcs +
lsr
bne -
dex
txa
asl
asl
sta preshift-$16, y
+ dey
bne --
;construct 2-bit group table
sty zvalue
-- lsr zmask
lsr zmask
- lda indextbl, x
sta grouped, y
inc zvalue
lda zvalue
and zmask
bne +
inx
txa
and #3
tax
+ iny
iny
iny
iny
cpy #3
bcs -
iny
cpy #3
bcc --
lda #>(entry-1)
pha
lda #<(entry-1)
pha
jsr preread
!if seekback { ;no room to do this in the routine
sty startsec+1
sta tmpadr+1
stx total+1
}
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
*=$8fe
!byte $be, 1
;the following lives on sectors $0E and $0D
!pseudopc $be00 {
code_begin
!byte version
readnib
slotpatch1
- lda $c0d1
bpl -
rts
;fill address array for one track
seekread
!if seekback=0 {
sty startsec+1
sta tmpadr+1
stx total+1
}
inittrk
sec
lda #$10
sbc startsec+1
cmp total+1
bcs +
tax
+ stx partial1
stx partial2
jsr seek
startsec
ldy #$d1
!if zpread {
inc tmpadr+1
}
tmpadr
- lda #$d1
sta addrtbl, y
!if !zpread {
inc tmpadr+1
}
iny
dec partial1
bne -
read
-- jsr readnib
- cmp #$d5
bne --
jsr readnib
cmp #$aa
bne -
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
- jsr readnib
rol ;set carry
sta sector+1
jsr readnib
and sector+1
dey
bpl -
tay
ldx addrtbl, y ;fetch corresponding address
beq read
sta sector+1 ;store index for later
!if zpread {
stx adrpatch9+2
dex
}
stx adrpatch1+2
stx adrpatch8+2
stx adrpatch2+2
stx adrpatch3+2
stx adrpatch5+2
stx adrpatch7+2
!if !zpread {
inx
stx adrpatch9+2
dex
}
dex
stx adrpatch4+2
stx adrpatch6+2
!if stkread {
inx
!if zpread {
inx
}
}
ldy #$fe
adrpatch1
- lda $d102, y
pha
iny
bne -
branch_read
bcs read ;branch always
check_mode
cpx #0
beq read ;loop if not expecting #$AD
-- sta tmpval+1 ;zero rolling checksum
slotpatch2
- ldx $c0d1
bpl -
lda preshift-$96, x
adrpatch2
sta $d102, y ;store 2-bit array
tmpval
eor #$d1
iny
bne --
ldy #$aa
slotpatch3
- ldx $c0d1
bpl -
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 -
and #$fc
ldy #$aa
slotpatch4
- ldx $c0d1
bpl -
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 -
and #$fc
ldx #$ac
slotpatch5
- ldy $c0d1
bpl -
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 -
and #$fc
slotpatch6
- ldy $c0d1
bpl -
eor preshift-$96, y
cmp #1 ;carry = !zero
ldy #1
- pla
adrpatch9
sta $d100, y
dey
bpl -
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
!if seekback {
bcs +
}
eor #$ff
inc curtrk+1
!if seekback {
bcc ++
+ adc #$fe
dec curtrk+1
++
}
cmp step+1
bcc +
step
lda #$d1
+ cmp #8
bcs +
tay
sec
+ lda curtrk+1
ldx step1, y
bne +
--- clc
lda tmpval+1
ldx step2, y
+ stx sector+1
and #3
rol
tax
slotpatch8
sta $c0d1, x
-- ldx #$13
- dex
bne -
dec sector+1
bne --
lsr
bcs ---
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 !fill 16
partial1 = *
partial2 = partial1+1
code_end=partial2+1
}