mirror of
https://github.com/A2osX/A2osX.git
synced 2024-08-28 14:29:20 +00:00
577 lines
13 KiB
Plaintext
577 lines
13 KiB
Plaintext
NEW
|
||
AUTO 3,1
|
||
.LIST OFF
|
||
*--------------------------------------
|
||
* prodos universal boot loader. this is the second stage boot
|
||
* for all apple manufactured apple ii disk drives.
|
||
* it is located at block zero (0) of a prodos or sos formatted
|
||
* disk(ette). if booted in apple /// native mode, the regular
|
||
* sos boot will be attempted.
|
||
*--------------------------------------
|
||
dcmd .EQ $42 disk command (=1 for read)
|
||
unit .EQ $43 (16*slot)+(128*(drive-1))
|
||
buff .EQ $44 ram address
|
||
blok .EQ $46 disk address
|
||
dent .EQ $48 device call entry address
|
||
idxl .EQ $4a pointer to low page of index block
|
||
idxh .EQ $4c pointer to high page of index block
|
||
idxp .EQ $4e index byte pointer
|
||
|
||
iobuff .EQ $60
|
||
* the following are for disk ii only
|
||
dbuf .EQ $26
|
||
slotz .EQ $2b
|
||
oddbits .EQ $3c
|
||
sector .EQ $3d
|
||
|
||
BB.RetryCnt .EQ $40
|
||
BB.TargetTrk .EQ $41
|
||
|
||
BB.CurrentQTrack .EQ $50
|
||
BB.TargetQTrack .EQ $51
|
||
|
||
BB.HdrPtr .EQ $52
|
||
|
||
BB.Hdr .EQ $54
|
||
BB.HdrTrk .EQ $55
|
||
BB.HdrVol .EQ $56
|
||
BB.Hdr96 .EQ $57
|
||
|
||
nbuf1 .EQ $300
|
||
dnib .EQ $2d6
|
||
|
||
clrscrn .EQ $fc58
|
||
scrn .EQ $5b6
|
||
sosid .EQ $c00
|
||
entlen .EQ sosid+$23
|
||
kernel .EQ $2000
|
||
*--------------------------------------
|
||
.PH $800
|
||
xboot .DA #1
|
||
sec apple iii enters xboot 'ora $38'
|
||
* bcs BB.AppleII branch if not apple iii native mode
|
||
bcc *
|
||
*--------------------------------------
|
||
*BB.AppleIII lda #$9f make apple iii boot using block 1
|
||
* pha the return address is $a000
|
||
* lda #$ff
|
||
* pha
|
||
|
||
* inc
|
||
* tax ldx #0
|
||
|
||
* inc lda #1 (read block 1)
|
||
|
||
* jmp $f479
|
||
*--------------------------------------
|
||
BB.AppleII stx unit save unit number
|
||
cmp #$03 for disk ii
|
||
php save result, it may be irrelevant
|
||
txa find out if disk ii
|
||
and #$70 strip drive # if any
|
||
lsr
|
||
lsr get slot address
|
||
lsr
|
||
lsr
|
||
ora #$c0
|
||
sta dent+1
|
||
ldy #$ff look at last byte
|
||
sty dent
|
||
|
||
plp restore carry (if disk ii & sect 0&2 read)
|
||
|
||
iny make y=0
|
||
lda (dent),y get device entry addr
|
||
bne ndsk2 branch if not disk ii (16 sector)
|
||
|
||
bcs isdsk2 branch if it is disk ii, but block 0 read
|
||
|
||
lda #3 make rom read only sector 2
|
||
sta xboot to complete block 0
|
||
inc sector was = 1
|
||
|
||
lda dent+1 do rts to re-enter rom
|
||
pha
|
||
lda #$5b
|
||
pha
|
||
rts go read sector 2 into $900
|
||
*--------------------------------------
|
||
isdsk2 sta BB.HdrTrk A=0, make sure previous track =0
|
||
sta dent and dent points at beginning of slot
|
||
|
||
ldy #$63 move code from card to ram
|
||
|
||
mvboot lda (dent),y
|
||
sta zzstart-$5e,y
|
||
iny
|
||
cpy #$eb have we moved enough?
|
||
bne mvboot
|
||
|
||
ldx #mods.cnt-1 now modify code to handle errors.
|
||
|
||
modboot ldy mods,x
|
||
lda chgs,x
|
||
sta zzstart,y
|
||
dex
|
||
bpl modboot
|
||
|
||
ldx #7
|
||
|
||
modboot2 lda endcode-1,x
|
||
sta zzzend-1,x
|
||
dex
|
||
bne modboot2
|
||
|
||
lda #BB.Hdr
|
||
sta BB.HdrPtr
|
||
stx BB.HdrPtr+1 X=0
|
||
|
||
lda /d2io reset device entry
|
||
sta dent+1 to point at disk ii routines.
|
||
lda #d2io get low addr (must be <$80)
|
||
*--------------------------------------
|
||
ndsk2 ldy #0 make sure y=0 again.
|
||
cmp #$f9
|
||
bcs bterr1 branch if not bootable device.
|
||
|
||
sta dent save low adr of device call entry.
|
||
sty iobuff
|
||
sty idxl
|
||
sty idxh y=0
|
||
sty idxp
|
||
sty blok+1
|
||
iny
|
||
sty dcmd set read command.
|
||
iny
|
||
sty blok to read directory blocks
|
||
lda #$c 2-5 at $c00
|
||
sta iobuff+1
|
||
sta idxl+1
|
||
|
||
rddir jsr goread call read block routine.
|
||
bcs bterr2 give up on error.
|
||
|
||
inc iobuff+1
|
||
inc iobuff+1
|
||
inc blok
|
||
lda blok have all directory blocks been read?
|
||
cmp #6
|
||
bcc rddir loop if not.
|
||
|
||
lda sosid is it a prodos (sos) directory?
|
||
ora sosid+1
|
||
bterr1 bne booterr branch if not.
|
||
*--------------------------------------
|
||
lda #4 begin look-up with first entry past header.
|
||
* bne nxdent1 branch always
|
||
.HS 2C BIT ABS
|
||
nxdent lda idxl
|
||
|
||
nxdent1 clc
|
||
adc entlen bump to next directory entry.
|
||
tay save in y for now.
|
||
bcc nxdent2 branch if not a page cross.
|
||
|
||
inc idxl+1
|
||
lda idxl+1 check for new block.
|
||
lsr if even then new block.
|
||
bcs nxdent2
|
||
|
||
cmp #$a have all file names been compared?
|
||
beq booterr branch if no pro.kernel.
|
||
|
||
ldy #4 else, begin at block beginning.
|
||
|
||
nxdent2 sty idxl
|
||
|
||
ldy #0
|
||
|
||
lookpro lda (idxl),y look for matching name.
|
||
cmp BB.ProDOS,y
|
||
bne nxdent branch if no match.
|
||
|
||
iny
|
||
cpy #7
|
||
bne lookpro
|
||
|
||
ldy #$10 get file type & index block addr.
|
||
* lda (idxl),y
|
||
* cmp #S.FI.T.SYS is it a system file?
|
||
* bne booterr
|
||
|
||
iny
|
||
lda (idxl),y
|
||
sta blok
|
||
iny
|
||
lda (idxl),y
|
||
sta blok+1
|
||
|
||
lda #0 now set up to read kernel.
|
||
sta idxl
|
||
|
||
ldy #$1e read index block at $1e00 and
|
||
sty idxl+1 kernel at $2000
|
||
sty iobuff+1
|
||
iny
|
||
sty idxh+1
|
||
|
||
rdkernl jsr goread read index block.
|
||
bterr2 bcs booterr
|
||
|
||
inc iobuff+1
|
||
inc iobuff+1
|
||
|
||
ldy idxp get index pointer
|
||
inc idxp bump for next time.
|
||
lda (idxl),y
|
||
sta blok
|
||
lda (idxh),y high disk addr.
|
||
sta blok+1
|
||
ora (idxl),y if both=0 then done.
|
||
bne rdkernl branch if more to read.
|
||
|
||
jmp kernel go execute kernel code.
|
||
*--------------------------------------
|
||
booterr
|
||
* jsr clrscrn clear video
|
||
* ldy #BB.MSG.ERR.Len-1
|
||
|
||
*.1 lda BB.MSG.ERR,y
|
||
* sta scrn,y
|
||
* dey
|
||
* bpl .1
|
||
|
||
jmp $ff69
|
||
*--------------------------------------
|
||
goread lda iobuff
|
||
sta buff
|
||
lda iobuff+1
|
||
sta buff+1
|
||
jmp (dent)
|
||
*--------------------------------------
|
||
mods .DA #mod1,#mod2,#mod3,#mod4,#mod5,#mod6,#mod7,#mod8,#mod8+1,#mod9
|
||
mods.cnt .EQ *-mods
|
||
chgs .DA #chg1,#chg2,#chg3,#chg4,#chg5,#chg6,#chg7,#$91,#BB.HdrPtr,#BB.HdrTrk
|
||
|
||
endcode ldx slotz
|
||
clc
|
||
rts
|
||
|
||
jmp BB.Seek
|
||
*--------------------------------------
|
||
*BB.MSG.ERR .AS -"ERR"
|
||
*BB.MSG.ERR.Len .EQ *-BB.MSG.ERR
|
||
BB.ProDOS .DA #$26 $20 = storage type + 6 = "PRODOS" len
|
||
.AS "PRODOS"
|
||
*--------------------------------------
|
||
d2io lda blok figure out track & sector.
|
||
and #7 strip track for now.
|
||
cmp #4
|
||
and #3
|
||
php
|
||
asl
|
||
plp
|
||
rol now we have the first sector of block.
|
||
sta sector
|
||
|
||
lda blok+1 get high block #
|
||
lsr shift hi addr to carry.
|
||
lda blok now figure track #
|
||
ror
|
||
lsr
|
||
lsr
|
||
sta BB.TargetTrk
|
||
|
||
lda buff+1
|
||
sta dbuf+1
|
||
|
||
ldx slotz
|
||
lda IO.D2.DrvOn,x
|
||
|
||
jsr BB.Seek go read sector.
|
||
|
||
inc dbuf+1 bump address
|
||
inc sector
|
||
inc sector and sector #
|
||
bcs quitrd branch if error.
|
||
|
||
jsr BB.Seek
|
||
|
||
quitrd ldy IO.D2.DrvOff,x
|
||
rts return error status in carry.
|
||
*--------------------------------------
|
||
BB.Seek lda BB.HdrTrk get track we're on
|
||
jsr BB.Trk2Qtrk
|
||
sta BB.CurrentQTrack
|
||
|
||
lda BB.TargetTrk
|
||
jsr BB.Trk2Qtrk
|
||
sta BB.TargetQTrack
|
||
|
||
ldy #0
|
||
|
||
.1 lda BB.TargetQTrack
|
||
sec
|
||
sbc BB.CurrentQTrack
|
||
beq .8
|
||
|
||
bcc .2
|
||
|
||
* Current < Target, must move in
|
||
|
||
cmp #2
|
||
bcc .6 one QT remaining
|
||
|
||
lda BB.CurrentQTrack
|
||
and #$FE from QT1 or QT3
|
||
inc
|
||
inc
|
||
bra .4
|
||
|
||
* Current > Target, must move out
|
||
|
||
.2 cmp #$FF
|
||
beq .6 one QT remaining
|
||
|
||
lda BB.CurrentQTrack
|
||
bit #1 from QT1 or QT3
|
||
bne .3
|
||
|
||
dec
|
||
.3 dec
|
||
|
||
.4 sta BB.CurrentQTrack
|
||
|
||
and #6
|
||
ora slotz
|
||
tax
|
||
pha
|
||
tya
|
||
beq .5
|
||
|
||
lda IO.D2.Ph0Off,y
|
||
|
||
.5 lda IO.D2.Ph0On,x
|
||
ply
|
||
|
||
lda #164
|
||
jsr BB.Wait100usecA
|
||
bra .1
|
||
|
||
* Last QTrack
|
||
|
||
.6 lda BB.TargetQTrack
|
||
and #6
|
||
ora slotz
|
||
tax
|
||
inc
|
||
inc
|
||
and #$F7
|
||
tay
|
||
lda IO.D2.Ph0On,x
|
||
lda IO.D2.Ph0On,y
|
||
|
||
.7 phx
|
||
jsr BB.Wait25600usec
|
||
plx
|
||
|
||
lda IO.D2.Ph0Off,x
|
||
lda IO.D2.Ph0Off,y
|
||
bra BB.Read
|
||
|
||
.8 tya
|
||
beq BB.Read
|
||
|
||
tax
|
||
bra .7
|
||
*--------------------------------------
|
||
BB.Wait25600usec
|
||
lda #0
|
||
BB.Wait100usecA sec (6) JSR (2)
|
||
|
||
.1 ldx #18 (2)
|
||
|
||
.2 dex (2) delay 86 usec.
|
||
bne .2 (2+) 2 + 5x16 + 2 + 2
|
||
|
||
* ldx slotz (3)
|
||
* bit IO.D2.RData,x (4) Slow down ACC boards
|
||
|
||
sbc #1 (2)
|
||
bne .1 (2+)
|
||
|
||
rts (6)
|
||
*--------------------------------------
|
||
BB.Trk2Qtrk asl x2
|
||
sta .1+1
|
||
|
||
bit BB.HdrVol
|
||
bpl .1 x4
|
||
|
||
lsr x3
|
||
|
||
.1 adc #$ff SELF MODIFIED
|
||
BB.Trk2Qtrk.RTS rts
|
||
*--------------------------------------
|
||
BB.Read ldx slotz
|
||
|
||
ldy #$7f allow 127 mistakes.
|
||
sty BB.RetryCnt
|
||
php
|
||
|
||
tryread plp fix stack.
|
||
|
||
rdhead sec anticipate error.
|
||
dec BB.RetryCnt if = 0 then give up!
|
||
beq BB.Trk2Qtrk.RTS branch if can't fine/read sector.
|
||
clc indicate reading header.
|
||
rddata php carry set if reading sector.
|
||
|
||
rd0 dey every time y=0 decrement find count.
|
||
beq tryread
|
||
*--------------------------------------
|
||
* from zzstart to zzend code is moved from rom and modified to match this code...
|
||
*--------------------------------------
|
||
zzstart .EQ *
|
||
|
||
rd1 lda IO.D2.RData,x read a byte from the state machine.
|
||
bpl rd1 loop until ready.
|
||
|
||
.DUMMY
|
||
|
||
rd1a eor #$d5 mark 1?
|
||
mod1 .EQ *-zzstart+1
|
||
bne rd0 branch if not.
|
||
|
||
chg1 .EQ rd0-*
|
||
rd2 lda IO.D2.RData,x
|
||
bpl rd2
|
||
|
||
cmp #$aa mark 2?
|
||
bne rd1a
|
||
nop waste a little time.
|
||
|
||
rd3 lda IO.D2.RData,x
|
||
bpl rd3
|
||
|
||
cmp #$96 header mark 3?
|
||
beq rdhd1 branch if it is.
|
||
|
||
plp were we looking for data mark 3?
|
||
mod2 .EQ *-zzstart+1
|
||
bcc rdhead branch if not.
|
||
|
||
chg2 .EQ rdhead-*
|
||
eor #$ad data mark 3?
|
||
beq rddt1 go read data field if true...
|
||
|
||
mod3 .EQ *-zzstart+1
|
||
rdhd0 bne rdhead otherwise, start over.
|
||
|
||
chg3 .EQ rdhead-*
|
||
|
||
rdhd1 ldy #3 read in trk,sect,&volume #.
|
||
|
||
mod8 .EQ *-zzstart
|
||
rdhd2 sta (BB.HdrPtr),y save last result in .. , BB.HdrTrk , BB.HdrVol , ..
|
||
|
||
rdhd3 lda IO.D2.RData,x
|
||
bpl rdhd3
|
||
|
||
rol
|
||
sta oddbits save odd bits (7,5,3,1)
|
||
|
||
rdhd4 lda IO.D2.RData,x
|
||
bpl rdhd4
|
||
|
||
and oddbits combine even and odd to form value.
|
||
dey
|
||
bne rdhd2 read in next pair.
|
||
|
||
plp
|
||
cmp sector last byte formed is sector#
|
||
|
||
mod4 .EQ *-zzstart+1
|
||
bne rdhead branch if target sector not found.
|
||
|
||
chg4 .EQ rdhead-*
|
||
|
||
mod9 .EQ *-zzstart+1
|
||
lda BB.HdrTrk previous result is track #
|
||
cmp BB.TargetTrk is desired track found?
|
||
|
||
mod5 .EQ *-zzstart+1
|
||
bne goseek re-seek if mismatch.
|
||
|
||
chg5a .EQ *
|
||
mod6 .EQ *-zzstart+1
|
||
bcs rddata branch if proper track always.
|
||
chg6 .EQ rddata-*
|
||
*--------------------------------------
|
||
rddt1 ldy #$56 read 2 bit groupings first.
|
||
rddt1a sty oddbits
|
||
|
||
rddt2 ldy IO.D2.RData,x
|
||
bpl rddt2
|
||
|
||
eor dnib,y denibblize using table left from boot rom.
|
||
ldy oddbits save in nbuf1
|
||
dey
|
||
sta nbuf1,y
|
||
bne rddt1a loop until all 86 groups are read.
|
||
|
||
rddt3 sty oddbits now count up for 6-bit groups.
|
||
|
||
rddt4 ldy IO.D2.RData,x
|
||
bpl rddt4
|
||
|
||
eor dnib,y
|
||
ldy oddbits save result to specified buffer.
|
||
sta (dbuf),y
|
||
iny
|
||
bne rddt3 loop for 256 bytes.
|
||
|
||
rdchk ldy IO.D2.RData,x now verify checksum...
|
||
bpl rdchk
|
||
|
||
eor dnib,y must be equal...
|
||
mod7 .EQ *-zzstart+1
|
||
bne rdhd0 branch if error.
|
||
|
||
chg7 .EQ rdhd0-*
|
||
ldy #0 make y=0
|
||
|
||
nxttwo ldx #$56 now combine 2-bit group with 6 bit group
|
||
|
||
twobit dex all done with this group?
|
||
bmi nxttwo branch if so.
|
||
|
||
lda (dbuf),y
|
||
lsr nbuf1,x
|
||
rol
|
||
lsr nbuf1,x
|
||
rol
|
||
sta (dbuf),y
|
||
iny
|
||
bne twobit
|
||
*--------------------------------------
|
||
zzzend ldx slotz
|
||
clc indicate good read.
|
||
rts
|
||
|
||
chg5 .EQ *-chg5a
|
||
goseek jmp BB.Seek
|
||
.ED
|
||
*--------------------------------------
|
||
.LIST ON
|
||
BB.End .EQ *
|
||
BB.Free .EQ $a00-*
|
||
.BS BB.Free
|
||
.LIST OFF
|
||
.EP
|
||
*--------------------------------------
|
||
MAN
|
||
SAVE usr/src/lib/libblkdev.s.bb
|
||
LOAD usr/src/lib/libblkdev.s
|
||
ASM
|