A2osX/ProDOS.FX/ProDOS.S.XDOS.C.txt
2020-05-25 15:58:59 +02:00

831 lines
24 KiB
Plaintext
Raw 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
*--------------------------------------
dealloc stx bmcnt high address of block.
pha save low address.
ldx vcbptr check that bitmap block address is
lda VCBs+VCB.TBLK+1,x valid given the total # of blocks
cmp bmcnt on the volume.
pla
bcc L3C8C branch if invalid
tax
and #$07 bit to be or'd in
tay
lda whichbit,y (shifting takes 7 bytes, but is slower)
sta nofree save bit pattern.
txa low block address.
lsr bmcnt
ror get pointer to byte in block that
lsr bmcnt represents the block address.
ror
lsr bmcnt
ror
sta bmptr save pointer.
lsr bmcnt transfer bit which is page of bitmap
rol half
jsr fndbmap make sure device is correct one.
bcs L3C8B error.
lda bmacmap current map.
cmp bmcnt is in-core bitmap the correct one ?
beq L3C64 branch if yes.
jsr upbmap put current map away.
bcs L3C8B error.
lda bmcnt get map #
ldx vcbptr
sta VCBs+VCB.BMAPIDX,x and make it current.
lda bmadev
jsr gtbmap read it into buffer
bcs L3C8B
L3C64 ldy bmptr index to byte
lsr half
lda nofree (get indiviual bit)
bcc bmbufhi branch if on page 1 of bitmap
ora bmbuf+$100,y
sta bmbuf+$100,y
bcs L3C7D always.
bmbufhi ora bmbuf,y this address + 2 is used as an absolute reference to bmbuf high byte.
sta bmbuf,y
L3C7D lda #$80 mark bitmap as modified
tsb bmastat
inc deblock inc count of blocks deallocated
bne L3C8A
inc deblock+1
L3C8A clc
L3C8B rts
L3C8C lda #MLI.E.BADFS bitmap block # impossible.
sec bitmap disk address wrong
rts (maybe data masquerading as indx block)
*--------------------------------------
alc1blk jsr fndbmap get address of bitmap.
bcs L3CB8 error.
L3C95 ldy #$00 begin search at start of bitmap block.
sty half which half (page) to search
L3C9A lda bmbuf,y
bne L3CB9 free blocks indicated by 'on' bits
iny
bne L3C9A check all in 1st page.
inc half now search page 2.
inc basval base value = base address / 2048.
L3CA8 lda bmbuf+$100,y search 2nd half for free block
bne L3CB9
iny
bne L3CA8
inc basval add 2048 offset for next page.
jsr nxtbmap get next bitmap (if exists) and
bcc L3C95 update vcb. branch if no error.
L3CB8 rts return error.
L3CB9 sty bmptr save index pointer to valid bit group.
lda basval prep for block address calculation
sta scrtch+1
tya address of bit pattern.
asl multiply this and basval by 8
rol scrtch+1
asl
rol scrtch+1
asl
rol scrtch+1
tax low address within 7 of actual address
sec
lda half
beq L3CDB branch if allocating from 1st half.
lda bmbuf+$100,y get pattern from 2nd page.
bcs L3CDE always.
L3CDB lda bmbuf,y get bit pattern from 1st page.
L3CDE rol find left most 'on' bit
bcs L3CE4 if found.
inx adjust low address.
bne L3CDE always.
L3CE4 lsr restore pos'n of all but left most bit.
bcc L3CE4 loop until mark moves into carry.
stx scrtch save low address.
ldx half which half of bitmap ?
bne L3CF4 if page 2.
sta bmbuf,y
beq L3CF7 always.
L3CF4 sta bmbuf+$100,y update to show allocated block in use.
L3CF7 lda #$80 indicate map is modified.
tsb bmastat
ldx vcbptr subtract 1 from total free vcb blocks
lda VCBs+VCB.FBLK,x to account for newly allocated block.
bne .7
dec VCBs+VCB.FBLK+1,x
.7 dec VCBs+VCB.FBLK,x
lda scrtch return address in y,a of newly
ldy scrtch+1 allocated block.
clc no errors.
rts
*--------------------------------------
nxtbmap ldx vcbptr inc to next bitmap, but 1st make sure there is another one.
lda VCBs+VCB.TBLK+1,x
lsr
lsr
lsr
lsr
cmp VCBs+VCB.BMAPIDX,x are there more maps ?
beq L3D60 if no more to look at.
inc VCBs+VCB.BMAPIDX,x add 1 to current map
jsr upbmap
fndbmap ldy vcbptr
lda VCBs+VCB.DEV,y get device #.
cmp bmadev does this map match this device ?
beq L3D4A yes.
jsr upbmap otherwise, save other volume's bitmap
bcs L3D5F
ldy vcbptr
lda VCBs+VCB.DEV,y
sta bmadev and read in fresh bitmap for this dev.
L3D4A ldy bmastat is it already modified ?
bmi L3D54 yes, return pointer
jsr gtbmap otherwise read in fresh bitmap.
bcs L3D5F if error.
L3D54 ldy vcbptr get relative block # of bitmap.
lda VCBs+VCB.BMAPIDX,y
asl 2 pages per block
sta basval
clc no errors.
L3D5F rts
L3D60 lda #MLI.E.VOLFULL request can't be filled
sec error
rts
*--------------------------------------
upbmap clc
lda bmastat is current map modified ?
bpl L3D5F no.
jsr wrtbmap update device.
bcs L3D5F if error on writing.
stz bmastat mark bitmap buffer as free
lda #0 MUST EXIT WITH A=0
rts
*--------------------------------------
gtbmap sta bmadev read bitmap specified by dev and vcb.
ldy vcbptr get lowest map # with free blocks in it
lda VCBs+VCB.BMAPIDX,y
sta bmacmap associate offset with bitmap ctrl block.
clc add this # to the base address of
adc VCBs+VCB.BMAP,y 1st bitmap and save in bmadadr which
sta bmadadr is address of bitmap to be used.
lda VCBs+VCB.BMAP+1,y
adc #$00
sta bmadadr+1
lda #$01 read device command
.HS 2C BIT ABS
wrtbmap lda #$02 write command.
sta A4L
lda devnum save current dev #
pha
lda bmadev get bitmap's dev #
sta devnum
lda bmadadr and disk address
sta bloknml
lda bmadadr+1
sta bloknml+1
lda /bmbuf
* lda bmbufhi+2 address of the buffer (low = 0)
jsr XDOS.RWBlock
tax error code (if any).
pla restore current dev #
sta devnum
bcc L3DB6 and return it if no error.
txa error code
L3DB6 rts
*--------------------------------------
rdblk
XDOS.ReadGBufAX sta bloknml
stx bloknml+1
rdgbuf
XDOS.ReadGBuf lda #$01 read command.
.HS 2C BIT ABS
wrtgbuf
XDOS.WriteGBuf lda #$02 write command
sta A4L pass to device handler.
lda /gbuf general buffer.
dobitmap
XDOS.RWBlock php no interrupts
sei
sta buf+1 buffer high.
stz buf buffer low (always on page boundary)
stz p8error clear global error code.
lda #$FF indicates reg call made to dev handler
sta ioaccess
lda devnum transfer dev # for dispatcher to
sta unitnum convert to unit #.
jsr dmgr call the driver.
bcs .9 if error.
plp restore interrupts.
clc
rts
.9 plp file i/o error. restore interrupts.
sec
rts
*--------------------------------------
XDOS.GetMark ldx fcbptr index to open fcb.
ldy #$02 index to user's mark parmeter.
.1 lda fcbbuf+18,x transfer current position
sta (A3L),y to user's parameter list
inx
iny
cpy #$05 transfer 3 bytes
bne .1
clc
rts
L3DFD lda #MLI.E.BEYEOF invalid position
sec
rts
*--------------------------------------
XDOS.SetMark ldy #$04 index to user's desired position.
ldx fcbptr file's control block index.
inx inc by 2 for index to hi eof
inx
sec indicate comparisons are necessary.
.1 lda (A3L),y move it to 'tpos'
sta tposll-2,y
bcc .2 branch if mark < eof
cmp fcbbuf+21,x
bcc .2 branch if mark qualifies.
bne L3DFD branch if mark > eof (invalid position)
dex
.2 dey move/compare next lower byte of mark.
tya test for all bytes moved/tested.
eor #$01 preserves carry status.
bne .1 branch if more.
rdposn ldy fcbptr test to see if new position is
lda fcbbuf+19,y within the same (current) data block.
and #$FE
sta scrtch
lda tposlh middle byte of new position
sec
sbc scrtch
sta scrtch
bcc L3E44 branch if < current position.
cmp #$02 must be within 512 bytes of beginning
bcs L3E44 of current position.
lda tposhi make sure within the same 64k.
cmp fcbbuf+20,y
bne L3E44 branch if not.
jmp svmark if so, adj fcb, position ptr and return.
L3E44 lda fcbbuf+7,y determine file type for positioning.
beq L3E50 0 = invalid file type.
cmp #$04 tree class file?
bcc L3E59 yes, go position.
jmp dirmark no, test for dir type.
L3E50 ldy #$A4 clear illegal filetype entry in fcb
sta fcbbuf,y
lda #$43 and report error
sec
rts
L3E59 lda fcbbuf+7,y use storage type as # of index levels
sta levels since 1=seed, 2=sapling, 3=tree.
lda fcbbuf+8,y
and #$40 if previous data was modified then
beq L3E6B disk must be updated.
jsr wfcbdat
bcs L3ED4 if error.
L3E6B ldy fcbptr test to see if current index block
lda fcbbuf+20,y is usable by checking if new
and #$FE position is within 128k of the
sta scrtch beginning of current sapling level
lda tposhi chunk.
sec
sbc scrtch
bcc L3E9D branch if a new index block is needed.
cmp #$02 is new position within 128k of old ?
bcs L3E9D branch if not.
ldx levels is it a seed file ?
dex
bne datlevel no, use current indexes.
L3E89 lda tposlh is new position < 512 ?
lsr
ora tposhi
bne L3EEF no, mark both data and index block as
lda fcbbuf+12,y unallocated. 1st block is only block
sta bloknml and it's data.
lda fcbbuf+13,y high block address.
jmp rnewpos go read in block and set statuses.
L3E9D lda fcbbuf+8,y check to see if previous index block
and #$80 was modified.
beq L3EA9 read in over it if current up to date.
jsr wfcbidx go update index on disk (fcb block addr)
bcs L3ED4
L3EA9 ldx levels be sure there is a top index
cpx #$03 before reading it...
beq posindex branch if file is a tree.
lda tposhi is new position within range of a
lsr sapling file (less than 128k) ?
php save results
lda #$07 (no level is allocated for new pos'n)
plp restore z-flag.
bne L3F18 go mark all as dummy.
jsr clrstats clr status bits 0,1,2 (index/data/alloc)
dex check for seed
beq L3E89 if seed, check for position < 512.
jsr rfcbfst go get only index block.
bcs L3ED4 if error.
ldy fcbptr save newly loaded index block's address.
lda bloknml
sta fcbbuf+14,y
lda bloknml+1
sta fcbbuf+15,y
bcc datlevel branch always
L3ED4 rts
posindex jsr clrstats clr all alloc requirements for previous
jsr rfcbfst position. get highest level index block
bcs L3ED4
lda tposhi then test for a sap level index block
lsr
tay
lda (zpt),y
inc zpt+1
cmp (zpt),y (both high and low = 0 if no index exists)
bne saplevel
tax are both bytes 0 ?
bne saplevel
dec zpt+1
L3EEF lda #$03 show neither index or data block alloc'd
bra L3F18
saplevel sta bloknml read in next lower index block.
lda (zpt),y (high address)
sta bloknml+1
dec zpt+1
jsr rfcbidx read in sapling level
bcs L3ED4
datlevel lda tposhi get block address of data block
lsr
lda tposlh ( if there is one )
ror
tay
lda (zpt),y data block address low
inc zpt+1
cmp (zpt),y
bne L3F51
tax
bne L3F51
lda #$01 show data block as never been allocated
dec zpt+1
L3F18 ldy fcbptr set status to show what's missing
ora fcbbuf+8,y
sta fcbbuf+8,y
lsr discard bit that says data block
lsr unallocated because carry indicates if
jsr zipdata index block is invalid and needs to be
bcc svmark zeroed. branch if it doesn't need zeroed
jsr zeroindex zero index block in user's i/o buffer
bra svmark
zeroindex lda #$00
tay
L3F30 sta (zpt),y zero out the index half of the user's
iny i/o buffer
bne L3F30
inc zpt+1
L3F37 sta (zpt),y
iny
bne L3F37
dec zpt+1 restore proper address
rts
zipdata lda #$00
tay
L3F42 sta (datptr),y zero out data area
iny
bne L3F42
inc datptr+1
L3F49 sta (datptr),y
iny
bne L3F49
dec datptr+1
rts
L3F51 sta bloknml get data block of new position
lda (zpt),y (high address)
dec zpt+1
rnewpos sta bloknml+1
jsr rfcbdat
bcs L3F86 if error.
jsr clrstats show whole chain is allocated.
svmark ldy fcbptr update position in fcb
iny
iny
ldx #$02
L3F68 lda fcbbuf+18,y save old mark in case calling routine
sta oldmark,x fails later.
lda tposll,x
sta fcbbuf+18,y
dey
dex move 3 byte position marker
bpl L3F68
clc set up indirect address to buffer
lda datptr page pointed to by the current
sta sos position marker.
lda tposlh
and #$01
adc datptr+1
sta sos+1
L3F86 rts carry set if error
clrstats ldy fcbptr clear allocation states for data block
lda fcbbuf+8,y and both levels of indexes/
and #$F8
sta fcbbuf+8,y indicates that either they exist now
rts or unnecessary for current position.
dirmark cmp #$0D is it a directory ?
beq L3F9C yes...
lda #MLI.E.INCFF no, so compatability problem.
jsr GP.P8errv should not have been opened !!!
L3F9C lda scrtch recover results of previous subtraction.
lsr use difference as counter for how many
sta cntent blocks must be read to get to new pos'n.
lda fcbbuf+19,y test for positive direction
cmp tposlh indicated by carry.
bcc L3FB9 if set, position forward. otherwise,
L3FAB ldy #$00 read directory file in reverse order.
jsr dirpos1 read previous block.
bcs L3FD6 if error.
inc cntent count up to 128.
bpl L3FAB loop if more blocks to pass over.
bmi svmark always.
L3FB9 ldy #$02 position is forward from current.
jsr dirpos1 read next directory block
bcs L3FD6 if error.
dec cntent
bne L3FB9 loop if position not found in this block
beq svmark branch always.
dirpos1 lda (datptr),y get link address of previous or next
sta bloknml directory block.
cmp #$01 test for null byte into carry
iny but first be sure there is a link.
lda (datptr),y get the rest of the link.
bne L3FD8 branch if certain link exists.
bcs L3FD8 was the low part null as well ?
lda #MLI.E.EOF something is wrong with directory file!
L3FD6 sec error.
rts
L3FD8 sta bloknml+1
* read file's data block
rfcbdat lda #$01 read command
sta A4L
ldx #datptr points at address of data buffer.
jsr fileio1 go do file input.
bcs L3FF2 error.
ldy fcbptr
lda bloknml
sta fcbbuf+16,y save block # just read in fcb.
lda bloknml+1
sta fcbbuf+17,y
L3FF2 rts
rfcbidx lda #$01 prepare to read index block : read command
sta A4L
ldx #$48 address of current index buffer.
jsr fileio1 go read index block.
bcs L400C error
ldy fcbptr
lda bloknml
sta fcbbuf+14,y save block address of this index in fcb
lda bloknml+1
sta fcbbuf+15,y
clc
L400C rts
wfcbfst jsr upbmap update the bitmap and write file's 1st block.
lda #$02 write command
.HS 2C skip next instruction
rfcbfst lda #$01 read command.
pha save the command
lda #$0C
ora fcbptr add offset to fcbptr
tay
pla
ldx #$48 rd block into index portion of file buf
dofileio sta A4L command
lda fcbbuf,y get disk block address from fcb.
sta bloknml block 0 not legal
cmp fcbbuf+1,y
bne L4031
cmp #$00 are both bytes 0 ?
bne L4031 no, continue request
lda #$0C otherwise, allocation error.
jsr sysdeath doesn't return...
L4031 lda fcbbuf+1,y high address of disk block
sta bloknml+1
fileio1 php no interrupts
sei
lda $00,x get memory address of buffer from
sta buf page zero pointed to by x register
lda $01,x
sta buf+1 and pass address to device handler
ldy fcbptr
lda fcbbuf+1,y
sta devnum along with device #.
lda #$FF also, set to indicate reg call made to
sta ioaccess device handler.
lda devnum transfer device # for dispatcher
sta unitnum to convert to unit #.
stz p8error clear global error code.
jsr dmgr call the driver.
bcs L405E if error.
plp restore interrupts
clc
rts
L405E plp restore interrupts
sec
rts
wfcbdat ldx #datptr point at memory address with x and
lda #$10 disk address with y.
ora fcbptr add offset to fcbptr
tay and put in y.
lda #$02 write data block.
jsr dofileio
bcs L4096 if errors.
lda #$BF mark data status as current.
bra L408D
wfcbidx jsr upbmap update bitmap.
ldx #$48 point to address of index buffer
lda #$0E and block address of that index block.
ora fcbptr
tay
lda #$02
jsr dofileio go write out index block.
bcs L4096 if errors.
lda #$7F mark index status as current.
L408D ldy fcbptr change status byte to reflect
and fcbbuf+8,y successful disk file update.
sta fcbbuf+8,y (carry is unaffected)
L4096 rts
*--------------------------------------
XDOS.Open jsr findfile look up the file.
bcc L40A0 if ok.
cmp #MLI.E.INVPATH is this opening a root directory ?
bne L40AE if not, then error.
L40A0 jsr tstopen are any other files writing to this
bcc L40AD same file ? branch if not.
L40A5 lda #MLI.E.OPEN file is busy, shared access not allowed.
.HS 2C
L40A9 lda #MLI.E.UNSUPST file is wrong storage type.
.HS 2C
L40AB lda #MLI.E.FCBFULL fcb full error.
L40AE sec
rts
L40AD ldy fcbptr get address of 1st free fcb found.
lda fcbflg if this byte <> 0 then free fcb found
beq L40AB and available for use.
L40B9 ldx #$1F assign fcb,
lda #0
L40BD sta fcbbuf,y but clean it first.
iny
dex
bpl L40BD
lda #$06 start claiming it by moving in file info
tax using x as source index
ora fcbptr and y as destination (fcb).
tay
L40CB lda d_dev-1,x move ownership info.
sta fcbbuf,y note: this code depends upon the defined
dey order of both the fcb and directory
dex entry buffer.
bne L40CB
lda d_stor get storage type and
lsr strip off file name length
lsr by dividing by 16.
lsr
lsr
tax save in x for later comparison
sta fcbbuf+7,y and in fcb for future access.
lda d_attr get file's attributes and use it
and #$03 as a default access request.
cpx #$0D if directory, don't allow write enable.
bne L40EB
and #$01 read enabled bit
L40EB sta fcbbuf+9,y
and #$02 check for write enabled request.
beq L40F7 branch for open as read-only
lda totent otherwise, be sure no one else is
bne L40A5 reading the same file. branch if busy.
L40F7 cpx #$04 is it a tree file type ?
bcc L40FF yes.
cpx #$0D is it a directory type ?
bne L40A9 if not, wrong storage type.
L40FF ldx #$06 move address of 1st block of file, end
L4101 sta bloknml+1 of file and current usage count.
lda fcbptr
ora ofcbtbl,x this is done via a translation table
tay between directory info and fcb.
lda d_frst,x
sta fcbbuf,y
dex
bpl L4101 last loop stores hi address of 1st block
sta bloknml and this is the low one.
ldy fcbptr
lda cntent this was set up by 'tstopen'.
sta fcbbuf,y claim fcb for this file.
jsr alcbuffr go allocate buffer in memory tables.
bcs L4147 if errors.
jsr fndfcbuf rtn addr of bufs in data & index ptrs.
lda flevel mark level at which
sta fcbbuf+27,y file was opened.
lda fcbbuf+7,y file must be positioned at beginning.
cmp #$04 is it a tree file ?
bcs L415E no, assume a directory.
lda #$FF fool the position routine into giving
sta fcbbuf+20,y a valid position with preloaded data,
ldy #$02 etc. set desired position to 0.
lda #$00
L413C sta tposll,y
dey
bpl L413C
jsr rdposn let tree position routine do the rest.
bcc L4163 if successful.
L4147 pha save error code.
ldy fcbptr free buffer space.
lda fcbbuf+11,y
beq L4156 if no bufnum, ok because never alloc'd.
jsr relbuffr go release buffer.
ldy fcbptr since error was before file was
L4156 lda #$00 successfully opened, then it is
sta fcbbuf,y necessary to release fcb also.
pla error code.
sec
rts
L415E jsr rfcbdat read in 1st block of directory file.
bcs L4147 return error after freeing buffer & fcb.
L4163 ldx vcbptr index to vcb.
inc VCBs+VCB.OFCNT,x add 1 to # of files currently open
* sec and indicate that this volume has at
* ror VCBs+VCB.OF,x least 1 file active.
ldy fcbptr index to fcb.
lda fcbbuf,y return ref # to user.
ldy #$05
sta (A3L),y
clc open is successful
rts
*--------------------------------------
tstopen lda #$00
sta cntent returns the ref # of a free fcb.
sta totent flag to indicate file already open.
sta fcbflg flag indicates a free fcb is available.
L4188 tay index to next fcb.
ldx fcbflg test for free fcb found.
bne L4191 if already found.
inc cntent
L4191 lda fcbbuf,y is this fcb in use ?
bne L41A3 yes.
txa if not, should we claim it ?
bne L41C1 branch if free fcb already found.
sty fcbptr save index to new free fcb.
lda #$FF set fcb flag to indicate
sta fcbflg free fcb found.
bne L41C1 branch always to test next fcb.
L41A3 tya add offset to index to ownership info
ora #$06
tay and put it back in y.
ldx #$06 index to directory entry owner info.
L41A9 lda fcbbuf,y all bytes must match to say that it's
cmp d_dev-1,x the same file again.
bne L41C1 if not, then next fcb.
dey index to next lower bytes.
dex
bne L41A9 loop to check all owner info.
inc totent file is already open, now see
lda fcbbuf+9,y if it's already opened for write. and #$02 if so report file busy (with carry set).
and #$02 if so report file busy (with carry set).
beq L41C1 branch if this file is read access only.
sec
rts
L41C1 tya calc position of next fcb.
and #$E0 first strip any possible index offsets.
clc
adc #$20 inc to next fcb.
bne L4188 branch if more to compare.
clc report no conflicts.
rts
*--------------------------------------
MAN
SAVE usr/src/prodos.fx/prodos.s.xdos.c
LOAD usr/src/prodos.fx/prodos.s
ASM