A2osX/ProDOS.203/ProDOS.S.XDOS.A.txt

648 lines
20 KiB
Plaintext
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

NEW
AUTO 3,1
* object code = mli_2
* xdos mli system call processor
xdosmli cld no decimal.
pla get processor status
sta spare1 save it temporarily
sty mliy save x and y
stx mlix
pla find out the address of the caller
sta A3L
clc preserve the address of the call spec.
adc #$04
sta mliretn last MLI call return address
pla
sta A3L+1
adc #$00
sta mliretn+1
lda spare1
pha pull processor status
plp to re-enable interrupts.
cld still no decimal
ldy #$00
sty p8error clear any previous errors.
iny find out if command is valid.
lda (A3L),y get command #
lsr and hash it to a range of 0-$1F
lsr
lsr
lsr
clc
adc (A3L),y
and #$1F
tax
lda (A3L),y check result to see if valid command #
cmp scnums,x
bne scnerr
iny index to call spec parm list.
lda (A3L),y make A3L point to parameter count byte
pha in parameter block.
iny
lda (A3L),y
sta A3L+1
pla
sta A3L
ldy #$00 make sure parameter list has the
lda pcntbl,x correct # of parameters.
beq goclock clock has 0 parameters.
cmp (A3L),y
bne scperr error if wrong count.
lda scnums,x get call # again
cmp #$65 is it quit?
beq special if so, then call quit dispatcher
asl carry set if bfm or dev mgr
bpl godevmgr
bcs gobfmgr
lsr shift back down for interrupt manager
and #$03 valid calls are 0 and 1
jsr intmgr
bra exitmli
special jmp jspare P8 system death vector
goclock jsr clockv go read clock.
bra exitmli no errors possible
godevmgr lsr shift back down for device manager.
adc #$01 valid commands are 1 and 2.
sta A4L save command #.
jsr devmgr execute read or write request.
bra exitmli
gobfmgr lsr shift back down for block file manager.
and #$1F valid commands are 0-$13
tax
jsr bfmgr
exitmli stz bubit clear backup bit
ldy p8error P8 error code
cpy #$01 if > 0 then set carry
tya and set z flag.
php disable interrupts until exit complete.
sei
lsr mliact indicate MLI done.
plx save status register until return.
lda mliretn+1 place last MLI call return address
pha on stack. return is done via 'rti'
lda mliretn so the status register is restored
pha at the same time, so
phx place status back on stack
tya return error, if any.
ldx mlix MLI X register savearea
ldy mliy MLI Y register savearea
pha
lda bnkbyt1 restore language card status
jmp HBFA0 and return.
nodevice lda #$28 no device connected.
jsr p8errv P8 error vector.
scnerr lda #$01 no such command.
bne H30B0
scperr lda #$04 parameter count is invalid
H30B0 jsr gosyserr
bcs exitmli always taken
* ProDOS Device Manager
devmgr ldy #$05
php do not allow interrupts.
sei the call spec for devices must
H30B9 lda (A3L),y be passed to drivers in page zero:
sta >$0042,y
dey
bne H30B9
ldx buf+1 buffer page
stx usrbuf+1 to user buffer
inx
inx
lda buf is buffer page aligned (nn00) ?
beq H30CC branch if it is
inx else account for 3-page straddle
H30CC jsr vldbuf1 make sure user buffer is not
bcs dvmgrerr conflicting with protected ram.
jsr dmgr call internal entry for device dispatch
bcs dvmgrerr branch if error
plp
clc no error
rts
dvmgrerr plp restore interrupt status
gosyserr jsr p8errv P8 error vector
dmgr lda unitnum get device # and
and #$F0 strip misc lower nibble
sta unitnum then save it.
lsr use as index to device table
lsr
lsr
tax
lda drivertbl1,x fetch driver address
sta goadr
lda drivertbl1+1,x
sta goadr+1
gocmd jmp (goadr) goto driver (or error if no driver)
* ProDOS interrupt manager
intmgr sta A4L interrupt command
lsr allocate interrupt or deallocate?
bcs dealcint branch if deallocate.
ldx #$03 test for a free interrupt space in tbl.
alcint lda inttbl-2,x test high address for 0.
bne H3118 branch if spot occupied.
ldy #$03 get address of routine.
lda (A3L),y must not be zero page.
beq badint error if it is.
sta inttbl-2,x save high address
dey
lda (A3L),y
sta inttbl-3,x and low address.
txa return interrupt # in range 1-4
lsr
dey
sta (A3L),y pass back to user.
clc no errors.
rts
H3118 inx
inx next lower priority spot
cpx #$0B are all 4 already allocated?
bne alcint branch if not.
lda #$25 interrupt table full
bne H3124
badint lda #$53 invalid parameter.
H3124 jsr p8errv P8 error vector.
dealcint ldy #$01 zero out interrupt vector
lda (A3L),y but make sure it is a valid #.
beq badint error if < 1
cmp #$05 or > 4
bcs badint
asl
tax
lda #$00 now clear it
sta inttbl-2,x
sta inttbl-1,x
clc
rts
irqrecev lda accsav get acc from where old ROM put it.
sta p8areg
stx p8xreg entry point on ram card interrupt
sty p8yreg
tsx
stx p8sreg
lda irqflag irq flag = 0 if old roms
bne H315D and 1 if new roms.
pla restore return address and p-reg.
sta p8preg
pla
sta intadr interrupt return address
pla
sta intadr+1
H315D txs
lda mslot set up to re-enable $Cn00 rom
sta irqdev+2
tsx make sure stack has room for 16 bytes.
bmi H3170 branch if stack ok
ldy #$0F otherwise, make room and save it.
H3169 pla
sta svstack,y
dey
bpl H3169
H3170 ldx #$FA save 6 bytes of page 0
H3172 lda $00,x
sta svzerop-$FA,x
inx
bne H3172
* poll interrupt routines for a claimer
lda inttbl+1 test for a valid routine.
beq intr2 branch if no routine.
jsr goint1 execute
bcc irqdone
intr2 lda inttbl+3 repeat 3 more times
beq intr3
jsr goint2
bcc irqdone
intr3 lda inttbl+5
beq intr4
jsr goint3
bcc irqdone
intr4 lda inttbl+7
beq H31A2
jsr goint4
bcc irqdone
H31A2 inc irqcount allow 255 unclaimed interrupts
bne irqdone before system death.
lda #$01 bad irq so
jsr sysdeath kill the system.
irqdone ldx #$FA
H31AE lda svzerop-$FA,x restore the zero page
sta $00,x
inx
bne H31AE
ldx p8sreg test if stack needs restoring.
bmi H31C6 branch if not.
ldy #$00
H31BD lda svstack,y restore stack
pha
iny
cpy #$10
bne H31BD
H31C6 lda irqflag check for old roms.
bne H31DD branch if new roms.
ldy p8yreg restore registers.
ldx p8xreg
lda CLRC8ROM re-enable i/o card.
irqdev lda $C100 Cn is self modifying.
lda irqdev+2 restore device id.
sta mslot slot being accessed.
H31DD jmp irqexit do necessary bank switches and return.
irqflag .HS 00 0 = old roms. 1 = new roms.
irqcount .HS 00 # of unclaimed interrupts.
svstack .HS 0000000000000000
.HS 0000000000000000
svzerop .HS 000000000000
goint1 jmp (inttbl) interrupt routine 1
goint2 jmp (inttbl+2) interrupt routine 2
goint3 jmp (inttbl+4) interrupt routine 3
goint4 jmp (inttbl+6) interrupt routine 4
syserr1 sta p8error P8 error code
plx
plx pop 1 level of return
sec
rts
sysdeath1 tax death error code.
sta CLR80DISP disable 80 col hardware.
lda SETTEXT switch in text.
lda cortflag is this a Cortland?
beq H321A if not, don't use super hires switch.
stz newvideo force off super hires.
H321A lda CLRPAGE2 switch in text page 1.
ldy #$13
H321F lda #$20 inverse space border
sta vline11+10,y
sta vline13+10,y
lda deathmsg,y
sta vline12+10,y 'RESTART SYSTEM-$0x'
dey
bpl H321F
txa x = death error code
and #$0F convert to ascii
ora #$B0
cmp #$BA
bcc H323B branch if not > 9.
adc #$06 inc to alpha a-f
H323B sta vline12+28 death error code 1 to F
H323E bra H323E end of xdos mli
* ProDOS Block File Manager
bfmgr lda disptch,x translate into command address.
asl bit 7 indicates pathname to process
sta cmdtemp
and #$3F bit 6 is refnum, 5 is time to process
tax
lda cmdtable,x move address to indirect jump
sta goadr
lda cmdtable+1,x high byte
sta goadr+1
lda #$20 init backup bit flag
sta bkbitflg to say 'file modified'
bcc nopath
jsr setpath process pathname before calling command
bcs errorsys branch if bad name.
nopath asl cmdtemp test for refnum processing
bcc nopreref
jsr findfcb set pointers to fcb and vcb of file
bcs errorsys
nopreref asl cmdtemp check for necessity of time stamp
bcc H3274
jsr clockv date/time
H3274 jsr gocmd execute command
bcc goodop
errorsys jsr p8errv P8 error vector
goodop rts
setpath ldy #$01 index to pathname pointer
lda (A3L),y low pointer address
sta zpt
iny
lda (A3L),y hi pointer address
sta zpt+1
* entry used by rename for 2nd pathname.
synpath ldx #$00 x = index to pathbuf
ldy #$00 y = index to input pathname.
stx prfxflg assume prefix is in use.
stx pathbuf mark pathbuf = nothing processed.
lda (zpt),y validate pathname length > 0 and < 65
beq errsyn
cmp #$41
bcs errsyn
sta pathcnt this is used to compare for
inc pathcnt end of pathname processing.
iny now check for full pathname...
lda (zpt),y (full name if starts with '/')
ora #$80
cmp #$AF
bne H32AD branch if prefix appended.
sta prfxflg set prefix flag = prefix not used.
iny index to 1st character of pathname.
H32AD lda #$FF set current position of pathbuf
sta pathbuf,x to indicate end of pathname.
sta namcnt $FF = no chars processed in local name.
stx namptr pointer to local name length byte.
H32B8 cpy pathcnt done with pathname processing?
bcs endpath
lda (zpt),y get character
and #$7F
inx prepare for next char
iny
cmp #$2F is it delimiter '/' ?
beq endname yes
cmp #$61 lowercase?
bcc H32CD no
and #$5F shift to uppercase
H32CD sta pathbuf,x store char
inc namcnt is it the 1st char of a local name?
bne H32DA no
inc namcnt increment to 1
bne H32E6 1st char must be alpha (always taken)
H32DA cmp #$2E is it '.' ?
beq H32B8 ok, then do next char
cmp #$30 at least a '0' ?
bcc errsyn error if not
cmp #$3A is it numeric?
bcc H32B8 yes, get next char
H32E6 cmp #$41 at least an 'a' ?
bcc errsyn error if not
cmp #$5B is it > 'z' ?
bcc H32B8 branch if valid alpha to get next char
errsyn sec bad pathname
lda #$40
rts
endpath lda #$00 end pathname with a 0
bit namcnt also make sure count is positive
bpl H32FD
sta namcnt
dex
H32FD inx
sta pathbuf,x
beq errsyn error if '/' only.
stx pathcnt save length of pathname
tax
endname lda namcnt validate local name < 16
cmp #$10
bcs errsyn
phx save pointer
ldx namptr get index to beginning of local name
sta pathbuf,x save local name's length
plx restore pointer
bne H32AD branch if more names to process
clc probably no error, but
lda prfxflg make sure all pathnames are prefixed
bne H3323 or begin with a '/'.
lda newpfxptr must be non-zero
beq errsyn
H3323 rts
* set prefix command
setprefx jsr setpath call is made to detect if a null path.
bcc H3333 path ok.
ldy pathbuf is it a null pathname?
bne pfxerr error if not
jsr stypfx indicate null prefix
clc no error
rts
H3333 jsr findfile go find specified prefix directory.
bcc H333C if no error.
cmp #$40 bad pathname.
bne pfxerr branch if error is not root directory.
H333C lda d_stor make sure last local name is dir type
and #$D0 (either root or sub).
eor #$D0 directory?
bne ptyperr wrong type
ldy prfxflg new or appended prefix?
bne H334D
lda newpfxptr append new prefix to old
H334D tay
sec find new beginning of prefix
sbc pathcnt
cmp #$C0 too long?
bcc errsyn then error
tax
jsr stapfx
lda d_dev save device #
sta p_dev
lda d_frst and address of 1st block
sta p_blok
lda d_frst+1
sta p_blok+1
movprfx lda pathbuf,y
sta pathbuf,x
iny
inx
bne movprfx
clc good prefix
rts
ptyperr lda #$4B filetype error (not a directory)
pfxerr sec
rts
* get prefix command
getprefx clc calc how big a buffer is needed.
ldy #$01 get index to users pathname buffer
lda (A3L),y
sta usrbuf user buffer ptr
iny
lda (A3L),y
sta usrbuf+1
stz cbytes+1 set buffer length at 64 char max
lda #$40
sta cbytes
jsr valdbuf go validate prefix buffer address
bcs pfxerr
ldy #$00 y = indirect index to user buffer.
lda newpfxptr get address of beginning of prefix
tax
beq nulprfx if null prefix.
eor #$FF get total length of prefix
adc #$02 add 2 for leading and trailing slashes.
nulprfx sta (usrbuf),y store length in user's buffer.
beq gotprfx branch if null prefix.
sendprfx iny inc to next user buffer location.
lda pathbuf,x get next char of prefix.
sndlimit sta (usrbuf),y give char to user.
and #$F0 check for length descriptor.
bne H33B3 branch if regular character
lda #$2F otherwise, substitute a slash.
bne sndlimit branch always
H33B3 inx
bne sendprfx branch if more to send.
iny
lda #$2F end with '/'
sta (usrbuf),y
gotprfx clc no error
rts
findfcb ldy #$01 index to ref#
lda (A3L),y is it a valid file# ?
beq badref must not be 0.
cmp #$09 must be 1 to 8 only.
bcs badref
pha
dec
lsr
ror
ror
ror multiply by 32.
sta fcbptr used as an index to fcb
tay
pla restore ref# in acc
cmp fcbbuf,y
bne errnoref
fndfcbuf lda fcbbuf+11,y get page address of file buffer.
jsr getbufadr get file's address into bufaddrl,h
ldx bufaddrh (y=fcbptr preserved)
beq fcbdead fcb corrupted
stx datptr+1 save ptr to data area of buffer
inx
inx index block always 2 pages after data
stx zpt+1
lda fcbbuf+1,y also set up device #
sta devnum
lda bufaddrl
sta datptr index and data buffers always on
sta zpt page boundaries.
fndfvol tax search for associated vcb
lda vcbbuf+16,x
cmp fcbbuf+1,y is this vcb the same device?
beq tstvopen if it is, make sure volume is active.
nxtfvol txa adjust index to next vcb.
clc
adc #$20
bcc fndfvol loop until volume found.
lda #$0A open file has no volume so
jsr sysdeath kill the system.
fcbdead lda #$0B fcb error so
jsr sysdeath kill the system.
tstvopen lda vcbbuf,x make sure this vcb is open.
beq nxtfvol branch if it is not active.
stx vcbptr save ptr to good vcb.
clc no error
rts
errnoref lda #$00 put a zero into this fcb to
sta fcbbuf,y show free fcb.
badref lda #$43 requested refnum is
sec illegal (out of range)
rts
* online command
online jsr mvdbufr figure out how big buffer has to be.
stz cbytes set this for valdbuf routine.
stz cbytes+1
ldy #$01
lda (A3L),y if 0 then cbytes=$100 else $010 for one
and #$F0 device. mask out unused nibble.
sta devnum last device used.
beq H343C branch if all devices.
lda #$10 cbytes = $010
sta cbytes
bne H343F always taken
H343C inc cbytes+1 cbytes = $100
H343F jsr valdbuf go validate buffer range against
bcs onlinerr allocated memory.
lda #$00 zero out user buffer space
ldy cbytes
H3449 dey
sta (usrbuf),y
bne H3449
sta namptr used as pointer to user buffer.
lda devnum get device # again.
bne online1 branch if only 1 device to process.
jsr mvdevnums get list of currently recognized dev's.
H3459 phx save index to last item on list
lda loklst,x
sta devnum save desired device to look at.
jsr online1 log this volume and return it's name.
lda namptr inc pointer for next device
clc
adc #$10
sta namptr
plx get index to device list.
dex next device.
bpl H3459 branch if there is another device.
lda #$00 no errors for multiple on-line
clc
onlinerr rts
online1 jsr fnddvcb see if it has already been logged in.
bcs olinerr1 branch if vcb is full.
ldx #$00 read in root (volume) directory
lda #$02
jsr rdblk read it into general purpose buffer.
ldx vcbptr index to the vcb entry.
bcc volfound branch if read was ok.
tay error value.
lda vcbbuf+17,x don't take the vcb offline if
bne rtrnerr there are active files present.
sta vcbbuf,x now take the volume offline
sta vcbbuf+16,x
rtrnerr tya error value.
bcs olinerr1 branch if unable to read.
volfound lda vcbbuf,x has it been logged in before?
beq H349E if not.
lda vcbbuf+17,x it has, are there active files?
bmi H34AA branch if volume is currently busy.
H349E jsr logvcb1 go log it in.
bcs olinerr1 branch if there is a problem.
lda #$57 anticipate a duplicate active volume
bit duplflag exits.
bmi olinerr1 branch if so.
H34AA ldx vcbptr
jsr cmpvcb does vol read compare with logged vol?
lda #$2E anticipate wrong volume mounted.
bcc H34D0 branch if ok.
olinerr1 pha save error code.
jsr svdevn report what device has problem.
pla error code.
iny tell what error was encountered.
sta (usrbuf),y
cmp #$57 duplicate volume error?
bne H34CE no.
iny report which other device has same name
ldx vcbentry
lda vcbbuf+16,x
sta (usrbuf),y
stz duplflag clear duplicate flag.
lda #$57 duplicate volume error code.
H34CE sec flag error
rts
H34D0 lda vcbbuf,x get volume name count
sta namcnt
ldy namptr index to user's buffer.
H34D9 lda vcbbuf,x move name to user's buffer
sta (usrbuf),y
inx
iny
dec namcnt
bpl H34D9
svdevn ldy namptr index to 1st byte of this entry.
lda devnum upper nibble = device# and
ora (usrbuf),y lower nibble = name length.
sta (usrbuf),y
clc no errors
rts end of block file manager
MAN
SAVE usr/src/prodos.203/prodos.s.xdos.a
LOAD usr/src/prodos.203/prodos.s
ASM