lawless-legends/Platform/Apple/tools/ProRWTS/proboot.s
2017-01-11 07:14:16 -08:00

343 lines
8.5 KiB
ArmAsm
Executable File

;license:BSD-3-Clause
;minimal open/read binary file in ProDOS filesystem
;copyright (c) Peter Ferrie 2016-2017
!cpu 6502
*=$800
;zpage usage, arbitrary selection except for the "PROM constant" ones
tmpsec = $3c
reqsec = $3d ;PROM constant
A1L = $3c
A1H = $3d
curtrk = $40 ;PROM constant
adrlo = $44
adrhi = $45
sizehi = $53
entries = $f8 ;(internal) total number of entries in directory
step = $fd ;(internal) state for stepper motor
tmptrk = $fe ;(internal) temporary copy of current track
phase = $ff ;(internal) current phase for seek
;constants
scrn2p2 = $f87b
dirbuf = $e00 ;for size-optimisation
PHASEOFF = $c080
Q6L = $c08c
!byte 1
lsr
bne init
inc reqsec
txa
jsr scrn2p2
ora #$c0
pha
lda #$5b
pha
rts
fakeMLI pla
tax
inx
inx
inx
txa
pha
rts
filename !byte filename_e - filename_b
filename_b !text "LEGENDOS.SYSTEM" ;your start-up file, file is min 513 bytes, max 64kb
filename_e
init txa
tay
ora #$80
sta unrseek+1
ora #$0c
sta unrread1+1
sta unrread2+1
sta unrread3+1
sta unrread4+1
- lda fakeMLI-1, x
sta $beff, x
lda #$ff
sta $bf0f, x
dex
bne -
sty $bf30
sta $200
opendir ;read volume directory key block
txa
ldx #2
jsr readdirsel
;include volume directory header in count
firstent lda #<(dirbuf+4)
sta A1L
lda #>(dirbuf+4)
sta A1H
nextent ldy #0
lda (A1L), y
;match name lengths before attempting to match names
lda (A1L), y
and #$0f
tax
inx
!byte $2c
- lda (A1L), y
cmp filename, y
beq foundname
;move to next directory in this block
+ clc
lda A1L
adc #$27
sta A1L
bcc +
;there can be only one page crossed, so we can increment instead of adc
inc A1H
+ cmp #<(dirbuf+$1ff) ;4+($27*$0d)
lda A1H
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 -
;cache EOF (file size)
ldy #$15
lda (A1L), y
cmp #1
iny
lda (A1L), y
adc #1
lsr
sta sizehi
;cache KEY_POINTER
ldy #$11
lda (A1L), y
tax
iny
lda (A1L), y
;read index block in case of sapling
jsr readdirsec
;restore load offset
asl adrhi
readfile
;fetch data block and read it
ldy $41 ;zeroed by boot PROM
inc $41
ldx dirbuf, y
lda dirbuf+256, y
jsr seekread
;loop while size-$200 is non-zero
dec sizehi
bne readfile
readdone jmp $2000
;no tricks here, just the regular stuff
seek sty step
asl phase
txa
asl
copy_cur tax
sta tmptrk
sec
sbc phase
beq +++
bcs +
eor #$ff
inx
bcc ++
+ sbc #1
dex
++ cmp step
bcc +
lda step
+ cmp #8
bcs +
tay
sec
+ txa
pha
ldx step1, y
+++ php
bne +
--- clc
lda tmptrk
ldx step2, y
+ stx tmpsec
and #3
rol
tax
lsr
unrseek
lda PHASEOFF, x
-- ldx #$13
- dex
bne -
dec tmpsec
bne --
bcs ---
plp
beq seekret
pla
inc step
bne copy_cur
step1 !byte 1, $30, $28, $24, $20, $1e, $1d, $1c
step2 !byte $70, $2c, $26, $22, $1f, $1e, $1d, $1c
readadr
- jsr readd5aa
cmp #$96
bne -
ldy #3
- sta curtrk
jsr readnib
rol
sta tmpsec
jsr readnib
and tmpsec
dey
bne -
seekret rts
readd5aa
-- jsr readnib
- cmp #$d5
bne --
jsr readnib
cmp #$aa
bne -
tay ;we need Y=#$AA later
readnib
unrread1
- lda Q6L
bpl -
rts
readdirsel sta adrlo
readdirsec
ldy #>dirbuf
sty adrhi
;convert block number to track/sector
seekread lsr
txa
ror
lsr
lsr
sta phase
txa
and #3
php
asl
plp
rol
sta reqsec
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 sector
checksec jsr cmpsec
inc reqsec
inc reqsec
;force sector mismatch
cmpsecrd lda #$ff
cmpsec cmp reqsec
beq readdata
jsr readadr
beq cmpsec
;read sector data
readdata jsr readd5aa
eor #$ad ;zero A if match
;; bne * ;lock if read failure
unrread2
- ldx Q6L
bpl -
eor nibtbl - $96, x
sta bit2tbl - $aa, y
iny
bne -
unrread3
- ldx Q6L
bpl -
eor nibtbl-$96, x
sta (adrlo), y ;the real address
iny
bne -
unrread4
- ldx Q6L
bpl -
eor nibtbl-$96, x
bne cmpsecrd
-- ldx #$a9
- inx
beq --
lda (adrlo), y
lsr bit2tbl - $aa, x
rol
lsr bit2tbl - $aa, x
rol
sta (adrlo), y
iny
bne -
readret inc adrhi
rts
bit2tbl = $300 ;PROM constant
nibtbl = bit2tbl + 108 ;PROM constant
dataend = nibtbl + 106 ;PROM constant
readbuff
!byte $D3,$C1,$CE,$A0,$C9,$CE,$C3,$AE