613 lines
26 KiB
ArmAsm
613 lines
26 KiB
ArmAsm
**************************************************
|
|
* GETMARK Call
|
|
|
|
GetMark LDX fcbPtr ;Get index to open file control block
|
|
LDY #c_mark ; & index to user's mark parameter
|
|
:loop LDA fcb+fcbMark,X
|
|
STA (parm),Y ;Transfer current position
|
|
INX ; to user's parameter list
|
|
INY
|
|
CPY #c_mark+3 ;Have all three bytes been transferred?
|
|
BNE :loop ;Branch if not...
|
|
CLC ;No errors
|
|
RTS
|
|
|
|
ErrMrkEOF LDA #outOfRange ;Report invalid position.
|
|
SEC
|
|
RTS
|
|
|
|
**************************************************
|
|
* SETMARK Call
|
|
|
|
SetMark LDY #c_mark+2 ;Get index to user's desired position
|
|
LDX fcbPtr ; & file's control block index
|
|
INX ;(bump by 2 for index to hi EOF)
|
|
INX
|
|
SEC ;Indicate comparisons are necessary
|
|
:loop LDA (parm),Y ;Move it to 'tPos'
|
|
STA tPosll-c_mark,Y
|
|
BCC :1 ;Branch if we already know mark<EOF
|
|
CMP fcb+fcbEOF,X ;Carry or Z flag must be clear to qualify
|
|
BCC :1 ;Branch if mark qualifies for sure
|
|
BNE ErrMrkEOF ;Branch if mark>EOF
|
|
DEX
|
|
|
|
:1 DEY dey ;Prepare to move/compare next lower byte of mark
|
|
TYA ;Test for all bytes moved/tested
|
|
EOR #c_mark-1 ;To preserve carry status
|
|
BNE :loop ;Branch if more
|
|
|
|
* Still in same data block
|
|
|
|
RdPosn LDY fcbPtr ;First test to see if new position is
|
|
LDA fcb+fcbMark+1,Y ; within the same (current) data block
|
|
AND #%11111110
|
|
STA scrtch ;(At a block boundary)
|
|
LDA tPoslh ;Get middle byte of new position
|
|
SEC
|
|
SBC scrtch
|
|
STA scrtch
|
|
BCC TypMark ;Branch if possibly l.t. current position
|
|
CMP #$02 ;Must be within 512 bytes of beginning of current
|
|
BCS TypMark ;No
|
|
LDA tPosHi ;Now make sure we're talking
|
|
CMP fcb+fcbMark+2,Y ; about the same 64K chunk!
|
|
BNE TypMark ;Branch if we aren't
|
|
JMP SavMark ;If we are, adjust FCB, posPtr and return
|
|
|
|
TypMark EQU * ;Now find out which type
|
|
LDA fcb+fcbStorTyp,Y; of file we're positioning on
|
|
BEQ :11 ;There is no such type as zero, branch never!
|
|
CMP #tree+1 ;Is it a tree class file?
|
|
BCC TreePos ;Yes, go position
|
|
JMP DirMark ;No, test for directory type
|
|
|
|
:11 LDY #fcbPtr ;Clear illegally typed FCB entry
|
|
STA fcb+fcbRefNum,Y
|
|
LDA #invalidRefNum ;Tell 'em there is no such file
|
|
SEC
|
|
RTS
|
|
|
|
* Need different data blk
|
|
|
|
TreePos EQU * ;Use storage type as number of index levels
|
|
LDA fcb+fcbStorTyp,Y; (since 1=seed, 2=sapling, and 3=tree)
|
|
STA levels
|
|
LDA fcb+fcbStatus,Y ;Must not forget previous data
|
|
AND #dataMod ;Therefore, see if previous data was modified
|
|
BEQ :21 ; then disk must be updated
|
|
JSR WrFCBData ;Yes, so go write current data block
|
|
BCS PosErr ;Return any error encountered
|
|
|
|
:21 LDY fcbPtr ;Test to see if current
|
|
LDA fcb+fcbMark+2,Y ; index block is going to be usable...
|
|
AND #%11111110 ; or in other words - is new position
|
|
STA scrtch ; within 128K of the beginning
|
|
LDA tPosHi ; of current sapling level chunk?
|
|
SEC
|
|
SBC scrtch
|
|
BCC PosNew2 ;Branch if a new index block is also needed
|
|
CMP #$02 ;New position is > begining of old. Is it within 128K?
|
|
BCS PosNew2 ;Branch if not
|
|
LDX levels ;Is the file we're dealing with a seed?
|
|
DEX
|
|
BNE DataLevel ;No, use current indexes
|
|
|
|
TestTiny LDA tPoslh ;Is new position under 512?
|
|
LSR
|
|
ORA tPosHi
|
|
BNE NoIdxData ;No, mark both data and index block as un-allocated
|
|
LDA fcb+fcbFirst,Y ;First block is only block and it's data!
|
|
STA blockNum
|
|
LDA fcb+fcbFirst+1,Y;(high block address)
|
|
JMP RdNewPos
|
|
|
|
PosNew2 EQU * ;Gota check to see if previous
|
|
LDA fcb+fcbStatus,Y ; index block was modified
|
|
AND #idxMod
|
|
BEQ PosnIdx ;Read in over it if current is up to date
|
|
JSR WrFCBIdx ;Go update index on disk (block addr in fcb)
|
|
BCS PosErr
|
|
|
|
PosnIdx LDX levels ;Before reading in top index, check
|
|
CPX #tree ; to be sure that there is a top index...
|
|
BEQ PosIndex ;Branch if file is full blown tree
|
|
|
|
LDA tPosHi ;Is new position within range
|
|
LSR ; of a sapling file (l.t. 128k)?
|
|
PHP ;Anticipate no good
|
|
LDA #topAloc+idxAloc+dataAloc;(to indicate no level is allocated for new posn)
|
|
PLP ;Z flag tells all...
|
|
BNE NoData ;Go mark 'em all dummy
|
|
|
|
JSR ClrStats ;Go clear status bits 0,1,2 (index/data alloc status)
|
|
DEX ;(unaffected since loaded above) Check for seed
|
|
BEQ TestTiny ;If seed, check for position l.t. 512...
|
|
|
|
JSR RdFCBFst ;Go get only index block
|
|
BCS PosErr ;Branch if error
|
|
|
|
LDY fcbPtr ;Save newly loaded index block's address
|
|
LDA blockNum
|
|
STA fcb+fcbIdxBlk,Y
|
|
LDA blockNum+1
|
|
STA fcb+fcbIdxBlk+1,Y
|
|
BCC DataLevel ;Branch always...
|
|
PosErr RTS ;Carry always set when branched to
|
|
|
|
PosIndex JSR ClrStats ;Clear all allocation requirements for prev posn
|
|
JSR RdFCBFst ;Get highest level index block
|
|
BCS PosErr
|
|
|
|
LDA tPosHi ;Then test for a sap level index block
|
|
LSR
|
|
TAY
|
|
LDA (tIndex),Y
|
|
INC tIndex+1
|
|
CMP (tIndex),Y ;(both hi and lo will be zero if no index exists)
|
|
BNE SapLevel
|
|
TAX ;Are both bytes zero?
|
|
BNE SapLevel ;No
|
|
DEC tIndex+1 ;Don't leave wrong pointers laying around!
|
|
NoIdxData LDA #idxAloc+dataAloc
|
|
BRA NoData
|
|
|
|
SapLevel STA blockNum ;Read in next lower index block
|
|
LDA (tIndex),Y ;(hi address)
|
|
STA blockNum+1
|
|
DEC tIndex+1
|
|
JSR RdFCBIdx ;Read in sapling level
|
|
BCS PosErr
|
|
|
|
DataLevel LDA tPosHi ;Now get block address of data block
|
|
LSR
|
|
LDA tPoslh ;( if there is one )
|
|
ROR
|
|
TAY
|
|
LDA (tIndex),Y ;Data block address low
|
|
INC tIndex+1
|
|
CMP (tIndex),Y
|
|
BNE PosNew3
|
|
TAX ;Are both bytes zero?
|
|
BNE PosNew3 ;No
|
|
LDA #dataAloc ;Show data block has never been allocated
|
|
DEC tIndex+1
|
|
|
|
NoData LDY fcbPtr ;Set status to show what's missing
|
|
ORA fcb+fcbStatus,Y
|
|
STA fcb+fcbStatus,Y
|
|
LSR ;Throw away bit that says data block un-allocated
|
|
LSR ; cuz we know that. Carry now indicates if index block
|
|
JSR ZipData ; also is invalid and needs to be zeroed (Carry undisturbed)
|
|
BCC SavMark ;Branch if index block doesn't need zipping
|
|
|
|
JSR ZeroIndex ;Go zero index block in user's i/o buffer
|
|
BRA SavMark
|
|
|
|
ZeroIndex LDA #$00
|
|
TAY
|
|
:loop1 STA (tIndex),Y ;Zero out the index half
|
|
INY
|
|
BNE :loop1 ; of the user's i/o buffer
|
|
INC tIndex+1
|
|
:loop2 STA (tIndex),Y
|
|
INY
|
|
BNE :loop2 ;Restore proper address
|
|
DEC tIndex+1
|
|
RTS ;That's all
|
|
|
|
ZipData LDA #$00 ;Also is invalid and needs to be zeroed
|
|
TAY
|
|
:loop1 STA (dataPtr),Y ;Zero out data area
|
|
INY
|
|
BNE :loop1
|
|
INC dataPtr+1
|
|
:loop2 STA (dataPtr),Y
|
|
INY
|
|
BNE :loop2
|
|
DEC dataPtr+1
|
|
RTS
|
|
|
|
* Read file data blk
|
|
|
|
PosNew3 STA blockNum ;Get data block of new position
|
|
LDA (tIndex),Y ;(hi address)
|
|
DEC tIndex+1
|
|
RdNewPos STA blockNum+1
|
|
JSR RdFCBData
|
|
BCS pritz ;Return any error
|
|
JSR ClrStats ;Show whole chain is allocated
|
|
|
|
* Got data blk wanted
|
|
|
|
SavMark LDY fcbPtr ;Update position in file control block
|
|
INY
|
|
INY
|
|
LDX #$02
|
|
:loop LDA fcb+fcbMark,Y ;Remember oldmark in case
|
|
STA oldMark,X ; calling routine fails later
|
|
LDA tPosll,X ;Set new mark
|
|
STA fcb+fcbMark,Y ; in FCB
|
|
DEY
|
|
DEX ;Move 3-byte position marker
|
|
BPL :loop
|
|
|
|
CLC ;Last, but not least, set up
|
|
LDA dataPtr ; indirect address to buffer page pointed
|
|
STA posPtr ; to by the current position marker
|
|
LDA tPoslh
|
|
AND #$01 ;(A)=0/1
|
|
ADC dataPtr+1 ;(posPtr) = start of pg in
|
|
STA posPtr+1 ; data blk which contains the mark
|
|
pritz RTS ;Carry set indicates error!
|
|
|
|
*-------------------------------------------------
|
|
* Reset block allocate flags
|
|
|
|
ClrStats LDY fcbPtr ;Clear allocation states for data block
|
|
LDA fcb+fcbStatus,Y ; and both levels of indexes
|
|
AND #$FF-topAloc-idxAloc-dataAloc
|
|
STA fcb+fcbStatus,Y ;This says that either they exist currently
|
|
RTS ; or that they're unnecessary for current position.
|
|
|
|
*-------------------------------------------------
|
|
* Set dir file position
|
|
|
|
DirMark CMP #directoryFile ;Is it a directory?
|
|
BEQ DirPos ;Yes...
|
|
LDA #badFileFormat ;No, there is a compatiblity problem -
|
|
JSR SysErr ; the damn thing should never been opened!
|
|
|
|
DirPos LDA scrtch ;Recover results of previous subtraction
|
|
LSR ;Use difference as counter as to how many
|
|
STA cntEnt ; blocks must be read to get to new position
|
|
LDA fcb+fcbMark+1,Y ;Test for position direction
|
|
CMP tPoslh ;Carry indicates direction...
|
|
BCC DirFwrd ;If set, position forward
|
|
|
|
DirReverse LDY #$00 ;Otherwise, read directory file in reverse order
|
|
JSR DirPos1 ;Read previous block
|
|
BCS DirPosErr ;Branch if anything goes wrong
|
|
INC cntEnt ;Count up to 128
|
|
BPL DirReverse ;Loop if there is more blocks to pass over
|
|
BMI SavMark ;Branch always
|
|
|
|
DirFwrd LDY #$02 ;Position is forward from current position
|
|
JSR DirPos1 ;Read next directory block
|
|
BCS DirPosErr
|
|
DEC cntEnt
|
|
BNE DirFwrd ;Loop if position not found in this bloc
|
|
BEQ SavMark ;Branch always
|
|
|
|
DirPos1 LDA (dataPtr),Y ;Get link address of previous
|
|
STA blockNum ; or next directory block
|
|
CMP #$01 ; but first be sure there is a link
|
|
INY
|
|
LDA (dataPtr),Y
|
|
BNE DirPos2
|
|
BCS DirPos2 ;Branch if certain link exists
|
|
LDA #eofEncountered ;Something is wrong with this directory file!
|
|
DirPosErr SEC ;Indicate error
|
|
RTS
|
|
|
|
DirPos2 STA blockNum+1 ;(high order block address)
|
|
*
|
|
* Drop into rfcbdat (Read file's data block)
|
|
*
|
|
*
|
|
* Note: for directory positioning, no optimization has been done since
|
|
* since directory files will almost always be less than 6 blocks.
|
|
* If more speed is required or directory type files are to be used
|
|
* for other purposes requiring more blocks, then the recommended
|
|
* method is to call RdFCBData for the first block and go directly to
|
|
* device (via jmp (iounitl)) handler for subsequent accesses.
|
|
* Also note that no checking is done for read/write enable since a
|
|
* directory file can only be opened for read access.
|
|
*
|
|
RdFCBData LDA #rdCmd ;Set read command
|
|
STA dhpCmd
|
|
LDX #dataPtr ;Use X to point at address of data buffer
|
|
JSR FileIOZ ;Go do file input
|
|
BCS :Ret ;Return any error
|
|
|
|
LDY fcbPtr
|
|
LDA blockNum
|
|
STA fcb+fcbDataBlk,Y;Save block number just read in FCB
|
|
LDA blockNum+1
|
|
STA fcb+fcbDataBlk+1,Y
|
|
:Ret RTS ;Carry set indicates error
|
|
|
|
*-------------------------------------------------
|
|
* Read sub index blk
|
|
|
|
RdFCBIdx LDA #rdCmd ;Prepare to read in index bloc
|
|
STA dhpCmd
|
|
LDX #tIndex ;Point at address of current index buffer
|
|
JSR FileIOZ ;Go read index block
|
|
BCS :Ret ;Report error
|
|
LDY fcbPtr
|
|
LDA blockNum
|
|
STA fcb+fcbIdxBlk,Y ;Save block address of this index in fcb
|
|
LDA blockNum+1
|
|
STA fcb+fcbIdxBlk+1,Y
|
|
CLC
|
|
:Ret RTS
|
|
|
|
*-------------------------------------------------
|
|
* Write key index blk
|
|
|
|
WrFCBFst1 LDA #wrtCmd ;Set write mode for device
|
|
DB $2C ;Skip next 2 bytes for pseudo-branch always to RWFst
|
|
|
|
* Read key index blk
|
|
|
|
RdFCBFst LDA #rdCmd ;Set read mode for device
|
|
RWFst PHA ;Save command
|
|
LDA #fcbFirst
|
|
ORA fcbPtr ;Add offset to fcbPtr
|
|
TAY
|
|
PLA
|
|
LDX #tIndex ;Read block into index portion of file buffer
|
|
*
|
|
* Drop into DoFileIO
|
|
*
|
|
DoFileIO STA dhpCmd ;Save command
|
|
LDA fcb,Y ;Get disk block address from FCB
|
|
STA blockNum ;Block zero not legal
|
|
CMP fcb+1,Y
|
|
BNE FileIO
|
|
CMP #$00 ;Are both bytes zero?
|
|
BNE FileIO ;No, continue with request
|
|
LDA #badBlockErr ;Otherwise report allocation error
|
|
JSR SysDeath ;Never returns...
|
|
|
|
FileIO LDA fcb+1,Y ;Get high address of disk block
|
|
STA blockNum+1
|
|
|
|
*-------------------------------------------------
|
|
* Set up and do file block I/O
|
|
* Entry
|
|
* (X) = buf ptr in page zero
|
|
|
|
FileIOZ PHP ;No interupts from here on out
|
|
SEI
|
|
LDA $00,X ;Get memory address of buffer from
|
|
STA bufPtr ; zero page pointed to by
|
|
LDA $01,X ; the X-register
|
|
STA bufPtr+1 ; & pass address to device handler
|
|
|
|
LDY fcbPtr
|
|
LDA fcb+fcbDevNum,Y ;Of course having the device number
|
|
STA DevNum ; would make the whole operation more meaningful...
|
|
LDA #$FF ;Also, set to
|
|
STA ioAccess ; indicate reg call made to dev handler
|
|
LDA DevNum ;xfer the device # for dispatcher to convert to unit #
|
|
STA unitNum
|
|
STZ SErr ;Clear global error value
|
|
JSR DMgr ;Call the driver
|
|
BCS :1 ;Branch if error
|
|
PLP ;Restore interupts
|
|
CLC
|
|
RTS
|
|
|
|
:1 PLP ;Restore interupts
|
|
SEC
|
|
RTS
|
|
|
|
*-------------------------------------------------
|
|
* Check point bit map & write key blk
|
|
|
|
WrFCBFirst JSR UpdateBitMap ;First update the bitmap
|
|
BRA WrFCBFst1 ; and go write file's first block!
|
|
|
|
*-------------------------------------------------
|
|
* Check point data blk buffer
|
|
|
|
WrFCBData LDX #dataPtr
|
|
LDA #fcbDataBlk ;Point at mem addr with X and disk addr with Y
|
|
ORA fcbPtr ;Add offset to fcbptr
|
|
TAY ; and put it in Y-reg
|
|
LDA #wrtCmd ;Write data block
|
|
JSR DoFileIO
|
|
BCS FileIOerr ;Report any errors
|
|
LDA #$FF-dataMod ;Mark data status as current
|
|
BRA FCBUpdate
|
|
|
|
*-------------------------------------------------
|
|
* Check point index blk buffer
|
|
|
|
WrFCBIdx JSR UpdateBitMap ;Go update bitmap
|
|
LDX #tIndex ;Point at address of index buffer
|
|
LDA #fcbIdxBlk ; & block address of that index block
|
|
ORA fcbPtr
|
|
TAY
|
|
LDA #wrtCmd
|
|
JSR DoFileIO ;Go write out index block
|
|
BCS FileIOerr ;Report any errors
|
|
LDA #$FF-idxMod ;Mark index status as current
|
|
FCBUpdate LDY fcbPtr ;Change status byte to
|
|
AND fcb+fcbStatus,Y ; reflect successful disk file update
|
|
STA fcb+fcbStatus,Y ;(carry is unaffected)
|
|
FileIOerr RTS
|
|
|
|
**************************************************
|
|
* ProDOS8 OPEN Call
|
|
|
|
Open JSR FindFile ;First of all look up the file...
|
|
BCC :1
|
|
CMP #badPathSyntax ;Is an attempt to open a root directory?
|
|
BNE ErrOpen ;No, pass back error
|
|
:1 JSR TestOpen ;Find out if any other files are writing
|
|
BCC Open1 ; to this same file. (branch if not)
|
|
ErrBusy LDA #fileBusy
|
|
ErrOpen SEC
|
|
RTS
|
|
|
|
WrgStorTyp LDA #badStoreType ;Report file is of wrong storage type!
|
|
SEC
|
|
RTS
|
|
|
|
Open1 LDY fcbPtr ;Get address of first free FCB found
|
|
LDA fcbFlg ;This byte indicates that a free FCB found
|
|
BNE AssignFCB ; if non-zero is available for use
|
|
LDA #fcbFullErr ;Report FCB full error
|
|
SEC
|
|
RTS
|
|
|
|
AssignFCB LDX #fcbSize-1 ;Assign fcb, but first
|
|
LDA #$00 ; clean out any old
|
|
ClrFCB STA fcb,Y ; rubbish left around...
|
|
INY
|
|
DEX
|
|
BPL ClrFCB
|
|
|
|
LDA #fcbEntNum ;Now begin claim by moving in file info
|
|
TAX ;Use X as source index
|
|
ORA fcbPtr
|
|
TAY ; and Y as destination (FCB)
|
|
FCBOwner LDA d_dev-1,X ;Move ownership information
|
|
STA fcb,Y ;Note: this code depends upon the defined
|
|
DEY ; order of both the FCB and directory entry
|
|
DEX
|
|
BNE FCBOwner ; buffer (d.). beware of changes!!! *************
|
|
|
|
LDA d_file+d_stor ;Get storage type
|
|
LSR ;Strip off file name length
|
|
LSR
|
|
LSR
|
|
LSR ;(by dividing by 16)
|
|
TAX ;Save in X for later type comparison
|
|
STA fcb+fcbStorTyp,Y; and in FCB for future access
|
|
|
|
LDA d_file+d_attr ;Get files attributes & use
|
|
AND #readEnable+writeEnable; it as a default access request
|
|
CPX #directoryFile ;If directory, don't allow write enable
|
|
BNE SavAttr1
|
|
AND #readEnable ;(Read-only)
|
|
SavAttr1 STA fcb+fcbAttr,Y
|
|
AND #writeEnable ;Check for write enabled requested
|
|
BEQ :1 ;Branch if read only open
|
|
LDA totEnt ;Otherwise, be sure no one else is reading
|
|
BNE ErrBusy ; same file (set up by TestOpen)
|
|
|
|
:1 CPX #tree+1 ;Is it a tree type file?
|
|
BCC :2 ;Test for further compatiblity. It must
|
|
CPX #directoryFile ; be either a tree or a directory
|
|
BNE WrgStorTyp ;Report file is of wrong storage type
|
|
|
|
:2 LDX #$06 ;Move address of first block of file,
|
|
:loop1 STA blockNum+1 ; end of file, and current usage count
|
|
LDA fcbPtr
|
|
ORA oFCBTbl,X ;This is done via a translation
|
|
TAY ; table between directory info and FCB
|
|
LDA d_file+d_first,X
|
|
STA fcb,Y
|
|
DEX ;Has all info been moved?
|
|
BPL :loop1
|
|
|
|
STA blockNum ;Last loop stored hi addr of first block
|
|
LDY fcbPtr
|
|
LDA cntEnt ;This was set up by 'TestOpen'...
|
|
STA fcb+fcbRefNum,Y ;Claim fcb for this file
|
|
JSR AllocBuf ;Go allocate buffer in memtables
|
|
BCS ErrOpen2 ;Give up if any errors occurred
|
|
|
|
JSR FndFCBuf ;Returns addrs of bufs in data & index pointers
|
|
LDA Level ;Mark level at which
|
|
STA fcb+fcbLevel,Y ; file was opened
|
|
LDA fcb+fcbStorTyp,Y;File must be positioned to beginning
|
|
CMP #tree+1 ;Is it a tree file?
|
|
BCS OpenDir ;No, assume it's a directory
|
|
LDA #$FF ;Fool the position routine into giving a
|
|
STA fcb+fcbMark+2,Y ; valid position with preloaded data, etc
|
|
LDY #$02 ;Set desired position to zero
|
|
LDA #$00
|
|
:loop2 STA tPosll,Y
|
|
DEY
|
|
BPL :loop2
|
|
|
|
JSR RdPosn ;Let tree position routine do the rest
|
|
BCC OpenDone ;Branch if successful
|
|
|
|
ErrOpen2 PHA ;Save error code
|
|
LDY fcbPtr ;Return buffer to free space
|
|
LDA fcb+fcbFileBuf,Y
|
|
BEQ :1 ;Branch if no buf #
|
|
|
|
JSR ReleaseBuf ;Doesn't matter if it was never allocated
|
|
LDY fcbPtr ; since error was encountered before file
|
|
:1 LDA #$00 ; was successfully opened, then
|
|
STA fcb+fcbRefNum,Y ; it's necessary to release FCB
|
|
PLA
|
|
SEC
|
|
RTS
|
|
|
|
OpenDir JSR RdFCBData ;Read in first block of directory file
|
|
BCS ErrOpen2 ;Return any error after freeing buffer & FCB
|
|
OpenDone LDX vcbPtr ;Index to volume control block
|
|
INC vcb+vcbOpenCnt,X;Add 1 to the number of files currently open
|
|
LDA vcb+vcbStatus,X ; & indicate that this volume has
|
|
ORA #$80 ; at least 1 file active
|
|
STA vcb+vcbStatus,X
|
|
|
|
LDY fcbPtr ;Index to file control block
|
|
LDA fcb+fcbRefNum,Y ;Return reference number to user
|
|
LDY #c_outRef
|
|
STA (parm),Y
|
|
CLC ;Indicate successful open!
|
|
RTS ;All done...
|
|
|
|
*-------------------------------------------------
|
|
* Test if file can be opened
|
|
* C=1
|
|
* Already opened with write access
|
|
* NB. Multiple write access is not allowed
|
|
* C=0
|
|
* File may be opened/already opened
|
|
* If fcbFlag <> 0, got a free FCB &
|
|
* (fcbPtr) = index into FCB table
|
|
* NB. Multiple read access is allowed
|
|
|
|
TestOpen LDA #$00
|
|
STA cntEnt ;This temp returns the refnum of a free FCB
|
|
STA totEnt ;This is used as a flag to indicate file is already open
|
|
STA fcbFlg ;This is a flag to indicate a free FCB is available
|
|
|
|
TestOpen1 TAY ;Index to next FCB
|
|
LDX fcbFlg ;Test for free FCB found
|
|
BNE :1 ;Branch if already found
|
|
INC cntEnt
|
|
:1 LDA fcb+fcbRefNum,Y ;Is this FCB in use?
|
|
BNE ChkActive ;Branch if it is
|
|
TXA ;If not, should we claim it?
|
|
BNE TestNxtFCB ;Branch if free FCB already found
|
|
STY fcbPtr ;Save index to free FCB
|
|
LDA #-1 ;Set fcb flag to indicate free FCB found
|
|
STA fcbFlg
|
|
BNE TestNxtFCB ;Branch always to test next FCB
|
|
|
|
ChkActive TYA ;Add offset to index to ownership info
|
|
ORA #fcbEntNum
|
|
TAY ;Put it back in Y-reg
|
|
LDX #fcbEntNum ;Index to directory entry owner info
|
|
WhoOwns LDA fcb,Y
|
|
CMP d_dev-1,X ;All bytes must match to say that its
|
|
BNE TestNxtFCB ; the same file again
|
|
DEY ;Index to next lower bytes
|
|
DEX
|
|
BNE WhoOwns ;Loop to check all owner info
|
|
|
|
INC totEnt ;File is already open,
|
|
LDA fcb+fcbAttr,Y ;Now see if it's already opened for write
|
|
AND #writeEnable
|
|
BEQ TestNxtFCB ;Branch if this file is read access only
|
|
SEC ;Multiple write access not allowed
|
|
RTS
|
|
|
|
TestNxtFCB TYA ;Calc position of next FCB
|
|
AND #%11100000 ;First strip any possible index offsets
|
|
CLC
|
|
ADC #fcbSize ;Bump to next FCB
|
|
BNE TestOpen1 ;Branch if more to compare
|
|
CLC ;Report no conflicts
|
|
RTS |