************************************************** * READ Call Read JSR MovDBuf ;First transfer buffer adr & request count to a JSR MovCBytes ; more accessible location, also get fcbAttr, CLC PHA ;Save attributes for now JSR CalcMark ;Calc mark after read, test mark>eof PLA ;Carry Set indicates end mark>eof AND #readEnable ;Test for read enabled first BNE :1 ;Branch if ok to read LDA #invalidAccess ;Report illegal access BNE GoFix1 ;Branch always taken :1 BCC Read2 ;Branch if result mark is used to set V flag) *------------------------------------------------- * Cleanup after direct I/O FixDataPtr LDA dataPtr ;Put current user buffer STA userBuf ; address back to normal LDA dataPtr+1 STA userBuf+1 ;Bank pair byte should be moved also LDY fcbPtr ;Restore buffer address JMP FndFCBuf *------------------------------------------------- * Read directory file... DirRead JSR RdPosn BCS ErrDirRd ;Pass back any errors JSR PrepRW ;Prepare for transfer JSR ReadPart ;Move data to user's buffer BVC DirRead ;Repeat until request is satisfied JSR RWDone ;Update FCB as to new position BCC :1 ;Branch if all is well CMP #eofEncountered ;Was last read to end of file? SEC ;Anticipate some other problem BNE :Ret ;Branch if not EOF error JSR SavMark JSR ZipData ;Clear out data block LDY #$00 ;Provide dummy back pointer for future re-position LDX fcbPtr ;Get hi byte of last block :loop LDA fcb+fcbDataBlk,X STA (dataPtr),Y LDA #$00 ;Mark current block as imposible STA fcb+fcbDataBlk,X INX INY ;Bump indexes to do both hi & low bytes CPY #$02 BNE :loop :1 CLC ;Indicate no error :Ret RTS ErrDirRd JMP ErrFixZ *------------------------------------------------- * Copy caller's I/O len * Exit * (A)=attributes * (Y)=(fcbptr) MovCBytes LDY #c_reqCnt ;Move request count LDA (parm),Y ; to a more accessible location STA cBytes STA rwReqL INY LDA (parm),Y STA cBytes+1 STA rwReqH LDY fcbPtr ;Also return (Y)=val(fcbptr) LDA fcb+fcbAttr,Y ; & (A)=attributes CLC ; & carry clear... RTS *------------------------------------------------- * Point userBuf ($4E,$4F) to caller's data buffer * Exit * (A) = file's storage type MovDBuf LDY #c_dataBuf ;Move pointer to user's buffer to bfm LDA (parm),Y STA userBuf INY LDA (parm),Y STA userBuf+1 GfcbStorTyp LDY fcbPtr ;Also return storage type LDA fcb+fcbStorTyp,Y;(on fall thru) RTS *------------------------------------------------- * Copy file mark, compute and compare end mark CalcMark LDX #$00 ;This subroutine adds the requested byte LDY fcbPtr CLC :loop LDA fcb+fcbMark,Y ;Count to mark, and returns sum STA tPosll,X ; in scrtch and also returns mark in tPos STA oldMark,X ; and oldMark ADC cBytes,X STA scrtch,X ;On exit: Y, X, A=unknown TXA ;Carry set indicates scrtch>eof EOR #$02 ;(cBytes+2 always = 0) BEQ EOFtest INY INX BNE :loop ;Branch always EOFtest LDA scrtch,X ;New mark in scrtch! CMP fcb+fcbEOF,Y ;Is new position > eof? BCC :Ret ;No, proceed BNE :Ret ;Yes, adjust 'cBytes' request DEY DEX ;Have we compared all three bytes? BPL EOFtest :Ret RTS *------------------------------------------------- * Set new mark & eof WrErrEOF JSR Plus2FCB ;Reset EOF to pre-error position :loop LDA oldEOF,X ;Place oldEOF back into fcb STA fcb+fcbEOF,Y LDA oldMark,X ;Also reset mark to last best write position STA fcb+fcbMark,Y STA scrtch,X ; & copy mark to scrtch for DEY ; test of EOF less than mark DEX BPL :loop JSR Plus2FCB ;Get pointers to test EOFEOF!! * Drop into WrAdjEOF to adjust EOF to mark if necessary. WrAdjEOF JSR Plus2FCB ;Get (Y)=fcbPtr+2, (X)=2,(A)=(Y) :loop1 LDA fcb+fcbEOF,Y ;Copy EOF to oldEOF STA oldEOF,X BCC :1 ; & if carry set... LDA scrtch,X ; copy scrtch to fcb's EOF STA fcb+fcbEOF,Y :1 DEY DEX ;Copy all three bytes BPL :loop1 RTS *------------------------------------------------- * Set 3-byte indices * Exit * (A)=(Y)=(fcbPtr)+2 * (X)=2 Plus2FCB LDA #$02 TAX ORA fcbPtr TAY RTS ************************************************** * WRITE Call Write EQU * ;First determine if requested JSR MovCBytes ; write is legal PHA ;Save attributes temporarily JSR CalcMark ;Save a copy of EOF to oldEOF, set/clr Carry JSR WrAdjEOF ; to determine if new mark > EOF PLA ;Get attributes again AND #writeEnable BNE Write1 ;It's write enabled ErrAccess LDA #invalidAccess ;Report illegal access BNE WrtError ;Always Write1 JSR TestWrProt ;Otherwise, ensure device is not write protected BCS WrtError ;Report write potected and abort operation LDA cBytes ORA cBytes+1 ;Anything to write? BNE :1 ;branch if write request definitely non-zero JMP RWDone ;Do nothing :1 JSR MovDBuf ;Move pointer to user's buffer to bfm CMP #tree+1 ; zpage area, also get storage type BCS ErrAccess ;If not tree, return an access error! TreeWrite JSR RdPosn ;Read block we're in BCS WrtError JSR GetFCBStat ;Get file's status AND #dataAloc+idxAloc+topAloc;Need to allocate? BEQ TreeWrt1 ;No LDY #$00 ;Find out if enough disk space is available :loop INY ; for indexes and data block LSR ;Count # of blks needed BNE :loop STY reqL ;Store # of blks needed STA reqH ;(A)=0 JSR TestFreeBlk BCS WrtError ;Pass back any errors JSR GetFCBStat ;Now get more specific AND #topAloc ;Are we lacking a tree top? BEQ TestSapWr ;No, test for lack of sapling level index JSR MakeTree ;Go allocate tree top and adjust file type BCC AllocDataBlk ;Continue with allocation of data block WrtError PHA ;Save error JSR ErrFixZ JSR WrErrEOF ;Adjust EOF and mark to pre-error state PLA ;Restore error code SEC ;Flag error RTS TestSapWr JSR GetFCBStat ;Get status byte again AND #idxAloc ;Do we need a sapling level index block? BEQ AllocDataBlk ;No, assume it's just a data block needed JSR AddNewIdxBlk ;Go allocate an index block and update tree top BCS WrtError ;Return any errors AllocDataBlk JSR AllocWrBlk ;Go allocate for data block BCS WrtError JSR GetFCBStat ;Clear allocation required bits in status ORA #idxMod ; but first tell 'em index block is dirty AND #$FF-dataAloc-idxAloc-topAloc;Flag these have been allocated STA fcb+fcbStatus,Y LDA tPosHi ;Calculate position within index block LSR LDA tPoslh ROR TAY ;Now put block address into index block INC tIndex+1 ;High byte first LDA scrtch+1 TAX STA (tIndex),Y DEC tIndex+1 ;(Restore pointer to lower page of index block) LDA scrtch ;Get low block address STA (tIndex),Y ;Now store low address LDY fcbPtr ;Also update file control block to indicate STA fcb+fcbDataBlk,Y; that this block is allocated TXA ;Get high address again STA fcb+fcbDataBlk+1,Y TreeWrt1 JSR PrepRW ;Write on JSR WrtPart BVC TreeWrite JMP RWDone ;Update FCB with new position *------------------------------------------------- * Copy write data to I/O blk * Logic is similar to ReadPart rtn * Exit * V = 1 - done * V = 0 - More to write WrtPart TXA BNE WrtPart1 ;Branch if request is not an even page LDA rwReqH ;A call of zero bytes should never get here! BEQ SetWrDone ;Do nothing! DEC rwReqH WrtPart1 DEX LDA (userBuf),Y ;Move data from user's buffer STA (posPtr),Y ; one byte at a time TXA BEQ EndWReqChk WrtPart2 INY ;Page crossed? BNE WrtPart1 ;No, move next byte LDA posPtr+1 ;Test for end of buffer INC userBuf+1 ; but first adjust user buffer INC tPoslh ; pointer and position BNE :1 INC tPosHi * Don't wrap around on file! BNE :1 LDA #outOfRange ; Say out of range if >32 meg BNE WrtError ;Always :1 INC posPtr+1 ; and sos buffer high address EOR dataPtr+1 ;(carry has been cleverly undisturbed.) BEQ WrtPart1 ;Crunch if more to write to buffer CLV ;Indicate not finished BVC WrPartDone ;Branch always EndWReqChk LDA rwReqH BEQ WrtReqDone ;Branch if request satisfied INY ;Are we done with this block of data? BNE :11 ;Branch if not LDA posPtr+1 EOR dataPtr+1 ;While this is redundant, it's necessary for BNE :12 ; proper adjustment of request count :11 DEC rwReqH ;(not finished- ok to adjust hi byte.) :12 DEY ;Reset modified Y-reg BRA WrtPart2 WrtReqDone INY ; and position BNE SetWrDone INC userBuf+1 ;bump pointers INC tPoslh BNE SetWrDone INC tPosHi SetWrDone BIT SetVFlag ;(set V flag) WrPartDone STY tPosll ;Save low position STX rwReqL ; and remainder of request count PHP ;Save statuses JSR GetFCBStat ORA #dataMod+useMod STA fcb+fcbStatus,Y CLC ;Adjust user's low buffer address LDA tPosll ADC userBuf STA userBuf BCC :21 INC userBuf+1 ;Adjust hi address as needed :21 JSR FCBUsed ; Set directory flush bit PLP ;Restore return statuses RTS *------------------------------------------------- * Make a tree file by adding a new master index blk MakeTree JSR SwapDown ;First make curr 1st blk an entry in new top BCS ErrMakeTree ;Return any errors JSR GfcbStorTyp ;Find out if storage type has been changed to 'tree' ;(if not, assume it was originally a seed and CMP #tree ; both levels need to be built BEQ MakeTree1 ; Otherwise, only an index need be allocated) JSR SwapDown ;Make previous swap a sap level index block BCS ErrMakeTree MakeTree1 JSR AllocWrBlk ;Get another block address for the sap level index BCS ErrMakeTree LDA tPosHi ;Calculate position of new index block LSR ; in the top of the tree TAY LDA scrtch ;Get address of newly allocated index block again TAX STA (tIndex),Y INC tIndex+1 LDA scrtch+1 STA (tIndex),Y ;Save hi address DEC tIndex+1 LDY fcbPtr ;Make newly allocated block the current index block STA fcb+fcbIdxBlk+1,Y TXA STA fcb+fcbIdxBlk,Y JSR WrFCBFirst ;Save new top of tree BCS ErrMakeTree JMP ZeroIndex ;Zero index block in user's i/o buffer *------------------------------------------------- * Add new index blk AddNewIdxBlk JSR GfcbStorTyp ;Find out if we're dealing with a tree CMP #seedling ;If seed then an adjustment to file type is necessary BEQ SwapDown ;Branch if seed JSR RdFCBFst ;Otherwise read in top of tree. BCC MakeTree1 ;Branch if no error ErrMakeTree RTS ;Return errors * Add a higher index level to file SwapDown EQU * ;Make current seed into a sapling JSR AllocWrBlk ;Allocate a block before swap BCS SwapErr ;Return errors immediately LDY fcbPtr ;Get previous first block LDA fcb+fcbFirst,Y ; address into index block PHA ;Save temporarly while swapping in new top index LDA scrtch ;Get new block address (low) TAX STA fcb+fcbFirst,Y LDA fcb+fcbFirst+1,Y PHA LDA scrtch+1 ; and high address too STA fcb+fcbFirst+1,Y STA fcb+fcbIdxBlk+1,Y;Make new top also the current index in memory TXA ;Get low address again STA fcb+fcbIdxBlk,Y INC tIndex+1 ;Make previous the first entry in sub index PLA STA (tIndex) DEC tIndex+1 PLA STA (tIndex) JSR WrFCBFirst ;Save new file top BCS SwapErr JSR GfcbStorTyp ;Now adjust storage type by adding 1 ADC #$01 ; (thus seed becomes sapling becomes tree) STA fcb+fcbStorTyp,Y LDA fcb+fcbStatus,Y ;Mark storage type modified ORA #storTypMod STA fcb+fcbStatus,Y CLC ;Return 'no error' status SwapErr RTS *------------------------------------------------- AllocWrBlk JSR Alloc1Blk ;Allocate 1 block BCS AlocErr JSR GetFCBStat ;Mark usage as modified ORA #useMod STA fcb+fcbStatus,Y LDA fcb+fcbBlksUsed,Y;Bump current usage count by 1 CLC ADC #$01 STA fcb+fcbBlksUsed,Y LDA fcb+fcbBlksUsed+1,Y ADC #$00 STA fcb+fcbBlksUsed+1,Y WrOK CLC ;Indicate no error AlocErr RTS ;All done *------------------------------------------------- * Do Status if not I/O yet TestWrProt JSR GetFCBStat ;Check for a 'never been modified' condition AND #useMod+dataMod+idxMod+eofMod BNE WrOK ;Ordinary RTS if known write ok LDA fcb+fcbDevNum,Y ;Get file's device number STA DevNum ;Get current status of block device * Status call TestWrProtZ STA unitNum ;Make the device status call LDA blockNum+1 PHA LDA blockNum ;Save the current block values PHA STZ dhpCmd ;=statCmd STZ blockNum ;Zero the block # STZ blockNum+1 PHP SEI JSR DMgr ;Branch if write protect error BCS :1 LDA #$00 ; Otherwise, assume no errors :1 PLP ;Restore interrupt status CLC TAX ;Save error BEQ :2 ;Branch if no error SEC ; else, set carry to show error :2 PLA STA blockNum ;Restore the block # PLA STA blockNum+1 TXA RTS ;Carry is indeterminate