NEW AUTO 3,1 *-------------------------------------- XDOS.Read jsr XDOS.GetUserBuf xfer buffer address and request count jsr mvcbytes to a more accessable location, also pha get fcb attributes and save on stack. jsr XDOS.CalcNewMark calc mark after read, test if mark > eof pla carry set means end mark > eof. and #$01 test for read enabled. beq .9 bcc L4205 branch if result mark < eof. adjust ldy XDOS.FCBPtr request to read until just before eof. lda XDOS.FCBs+FCB.EOF,y result = (eof-1) - position sbc XDOS.TmpPos sta cbytes sta rwreql lda XDOS.FCBs+FCB.EOF+1,y sbc XDOS.TmpPos+1 sta cbytes+1 sta rwreqh ora cbytes if both bytes = 0 then eof error bne L4210 lda #MLI.E.EOF .HS 2C .9 lda #MLI.E.LOCKED L4202 jmp errfix1 L4205 lda cbytes ora cbytes+1 bne L4210 if read request definitely non-zero. L420D jmp rwdone do nothing. L4210 jsr valdbuf validate user's data buffer range. bcs L4202 branch if memory conflict. jsr XDOS.GetFCB.ST get storage type cmp #$04 and find out if it's a tree or other. bcc L421F branch if a tree file jmp XDOS.ReadDir otherwise assume it's a directory. L421F jsr rdposn set up data pointer. bcs L4202 errors. jsr preprw test for newline, setup for partial jsr readpart read. move current data buffer contents bvs L420D to user area. branch if satisfied. bcs L421F indicates newline is set. lda rwreqh how many blocks are to be read ? lsr if < 2 then use the slow way. beq L421F sta cmdtemp save bulk block count. jsr XDOS.GetFCBStatus make sure current data area doesn't and #$40 need writing before resetting ptr to bne L421F read into user's area. branch if data sta ioaccess needs to be written to force 1st call lda ZP.UserBuf thru all dev handler checking. make sta ZP.DataPtr the data buffer the user's space. lda ZP.UserBuf+1 sta ZP.DataPtr+1 L4249 jsr rdposn get next block directly into user space. bcs L42B7 if error. L424E inc ZP.DataPtr+1 incll ptrs by one block (512 bytes) inc ZP.DataPtr+1 dec rwreqh dec rwreqh inc XDOS.TmpPos+1 inc XDOS.TmpPos+1 bne L4269 if pos'n doesn't get to a 64k boundary inc XDOS.TmpPos+2 otherwise, must check for a 128k one. lda XDOS.TmpPos+2 carry set if 128k boundary reached. eor #$01 lsr L4269 dec cmdtemp has all been read fast ? bne L427B branch if more to read. jsr fxdatptr go fix up data pointer to xdos buffer. lda rwreql test for end of read. ora rwreqh are both 0 ? beq rwdone yes, done. bne L421F no, read last partial block L427B bcs L4249 jsr XDOS.Tpos2Y get index to next block address lda (zpt),y get low address sta ZP.BLKNUM inc zpt+1 cmp (zpt),y are hi and low address the same? bne L4299 no, it's a real block address. cmp #$00 are both bytes 0 ? bne L4299 no, must be real data. sta ioaccess don't do repeat io just after sparse. beq L429C branch always (carry set). L4299 lda (zpt),y get high address clc L429C dec zpt+1 bcs L4249 if no block to read. sta ZP.BLKNUM+1 lda ioaccess has 1st call gone to device yet ? beq L4249 no, go thru normal route lda ZP.DataPtr+1 reset hi buffer address for dev handler sta ZP.BUFPTR+1 jsr XDOS.DevCall bcc L424E no errors, branch always. L42B7 pha save error code. jsr fxdatptr go restore data pointers, etc. pla errfix1 pha save error code jsr rwdone pass back # of bytes actually read pla sec error rts *-------------------------------------- rwdone ldy #$06 return total # of bytes actually read sec derived from cbytes-rwreq. lda cbytes sbc rwreql sta (ZP.A3L),y iny lda cbytes+1 sbc rwreqh sta (ZP.A3L),y jmp rdposn leave with valid position in fcb. *-------------------------------------- preprw ldy XDOS.FCBPtr adj pointer to user's buffer to make sec the transfer lda ZP.UserBuf sbc XDOS.TmpPos sta ZP.UserBuf bcs .1 if no adjustment to hi address needed dec ZP.UserBuf+1 .1 lda XDOS.FCBs+FCB.NLMASK,y test for new line enabled. clc beq .2 if new line not enabled. sec carry indicates new line enabled sta nlmask lda XDOS.FCBs+FCB.NLBYTE,y move newline character to more sta nlchar accesible spot. .2 ldy XDOS.TmpPos index to 1st data. lda ZP.DataPtr reset low order of position pointer to sta sos beginning of page. ldx rwreql get low order count of requested bytes. rts return statuses. *-------------------------------------- readpart txa x = low count of bytes to move. bne L430F branch if request is not an even page. lda rwreqh a call of 0 bytes should never get here! beq L435D branch if nothing to do. dec rwreqh L430F dex L4310 lda (sos),y move data to user's buffer sta (ZP.UserBuf),y bcs tstnewl test for newline 1st ! L4316 txa note: x must be unchanged from tstnewl ! beq L4332 go see if read request is satisfied... L4319 dex dec # of bytes left to move. iny page crossed ? bne L4310 no, move next byte. lda sos+1 test for end of buffer, but first inc ZP.UserBuf+1 adjust user buffer pointer inc XDOS.TmpPos+1 and position bne L4329 inc XDOS.TmpPos+2 L4329 inc sos+1 and sos buffer high address. eor ZP.DataPtr+1 (carry is undisturbed) beq L4310 branch if more to read in buffer. clv indicate not finished. bvc L4360 always. L4332 lda rwreqh beq L4350 branch if request is satisfied. iny done with this block of data ? bne L4340 no, adjust high byte of request. lda sos+1 maybe, check for end of block buffer. eor ZP.DataPtr+1 (don't disturb carry). bne L4343 if hi count can be dealt with next time L4340 dec rwreqh L4343 dey restore proper value bra L4319 tstnewl lda (sos),y get last byte transferred again. and nlmask only bits on in mask are significant. eor nlchar does it match newline character? bne L4316 no, read next. L4350 iny adjust position. bne L435D inc ZP.UserBuf+1 inc pointers inc XDOS.TmpPos+1 bne L435D inc XDOS.TmpPos+2 L435D bit setvflg (sets v flag) L4360 sty XDOS.TmpPos save low position bvs L4366 inx leave request as +1 for next call L4366 stx rwreql and remainder of request count. php save statuses clc adjust user's low buffer address tya adc ZP.UserBuf sta ZP.UserBuf bcc L4374 inc ZP.UserBuf+1 adjust hi address as needed. L4374 plp restore return statuses. setvflg rts this byte ($60) is used to set v flag. *-------------------------------------- fxdatptr lda ZP.DataPtr put current user buffer address back to normal sta ZP.UserBuf lda ZP.DataPtr+1 sta ZP.UserBuf+1 bank pair byte should be moved also. ldx XDOS.FCBPtr restore buffer address jmp XDOS.GetFCBBufX *-------------------------------------- XDOS.ReadDir jsr rdposn bcs L43B8 pass back any errors. jsr preprw prepare for transfer. jsr readpart move data to user's buffer. bvc XDOS.ReadDir repeat until request is satisfied. jsr rwdone update fcb as to new position. bcc L43B6 branch if done with no errors. cmp #MLI.E.EOF was last read to end of file ? sec anticipate some other error. bne L43B7 branch if not eof error. jsr svmark jsr XDOS.ZeroData clear out data block. ldy #$00 provide dummy back pointer for future ldx XDOS.FCBPtr re-position. x = hi byte of last block L43A6 lda XDOS.FCBs+FCB.DBLK,x sta (ZP.DataPtr),y stz XDOS.FCBs+FCB.DBLK,x mark current block as impossible inx iny inc indexes to do both hi and low bytes cpy #$02 bne L43A6 L43B6 clc no error L43B7 rts L43B8 jmp errfix1 report how much xfer'd before error. *-------------------------------------- mvcbytes ldy #$04 move request count to a more accessable location lda (ZP.A3L),y sta cbytes sta rwreql iny lda (ZP.A3L),y sta cbytes+1 sta rwreqh ldy XDOS.FCBPtr return y = val(XDOS.FCBPtr), lda XDOS.FCBs+FCB.ACCESS,y a = attributes * clc and carry clear... rts *-------------------------------------- XDOS.GetUserBuf ldy #$02 move the pointer to user's buffer lda (ZP.A3L),y to the block file manager sta ZP.UserBuf z-page area iny lda (ZP.A3L),y sta ZP.UserBuf+1 XDOS.GetFCB.ST ldy XDOS.FCBPtr return storage type lda XDOS.FCBs+FCB.STYPE,y rts *-------------------------------------- * this subroutine adds the requested byte count to mark and returns sum * in scrtch and also returns mark in tpos and oldmark. * * on exit: * y,x,a is unknown * carry set indicates scrtch > eof *-------------------------------------- XDOS.CalcNewMark ldx #$00 ldy XDOS.FCBPtr clc .1 lda XDOS.FCBs+FCB.MARK,y sta XDOS.TmpPos,x sta oldmark,x adc cbytes,x sta scrtch,x txa eor #$02 cbytes+2 always=0 beq eoftest iny inx bne .1 always. *-------------------------------------- eoftest lda scrtch,x new mark in scrtch. cmp XDOS.FCBs+FCB.EOF,y is new position > eof ? bcc .1 no, proceed. bne .1 yes, adjust 'cbytes' request dey dex all tree bytes compared ? bpl eoftest no, test next lowest .1 rts *-------------------------------------- werreof jsr plus2fcb reset eof to pre-error position. L4418 lda oldeof,x place oldeof back into fcb sta XDOS.FCBs+FCB.EOF,y lda oldmark,x also reset mark to last best sta XDOS.FCBs+FCB.MARK,y write position sta scrtch,x and copy mark to scrtch for test of dey eof less than mark. dex bpl L4418 jsr plus2fcb get pointers to test eof < mark. jsr eoftest carry set means mark > eof !! * drop into wadjeof to adjust eof to mark if necessary wadjeof jsr plus2fcb get y=XDOS.FCBPtr+2, x=2, a=y. L4434 lda XDOS.FCBs+FCB.EOF,y copy eof to old eof sta oldeof,x bcc L4442 and if carry set... lda scrtch,x then copy scrtch to fcb's eof. sta XDOS.FCBs+FCB.EOF,y L4442 dey dex copy all 3 bytes bpl L4434 rts plus2fcb lda #$02 on exit both a and y = XDOS.FCBPtr+2. tax x = 2 ora XDOS.FCBPtr tay rts *-------------------------------------- XDOS.Write jsr mvcbytes first determine if requested write is legal. pha jsr XDOS.CalcNewMark save a copy of eof to old eof, set/clr jsr wadjeof carry to determine if new mark > eof. pla get attributes again. and #$02 is write enabled ? bne L4462 yes, continue... L445E lda #MLI.E.LOCKED illegal access error. bne L44A2 L4462 jsr XDOS.TestWP otherwise, make sure device is not bcs L44A2 write protected. if so, branch to abort. lda cbytes ora cbytes+1 anything to write ? bne L4472 branch if so, jmp rwdone else do nothing. L4472 jsr XDOS.GetUserBuf move the user's buffer ptr to bfm zero cmp #$04 page area, also get storage type. bcs L445E if not tree, return an access error. L4479 jsr rdposn bcs L44A2 jsr XDOS.GetFCBStatus and #$07 beq L44E9 ldy #$00 is enough disk space available for L4487 iny indexes and data block ? lsr bne L4487 sty reql sta reqh jsr XDOS.CheckFree bcs L44A2 pass back any errors. jsr XDOS.GetFCBStatus now get more specific. and #$04 are we lacking a tree top ? beq L44AC no, test for lack of sapling level index jsr topdown go allocate tree top and adj file type. bcc L44B8 continue with allocation of data block. L44A2 pha save error. jsr errfix1 error return. jsr werreof adjust eof and mark to pre-error state. pla restore error code. sec rts L44AC jsr XDOS.GetFCBStatus get status byte again. and #$02 do we need a sapling level index block ? beq L44B8 no, assume it's just a data block needed jsr sapdown go alloc an indx blk and update tree top bcs L44A2 if error. L44B8 jsr alcwblk go allocate for data block. bcs L44A2 jsr XDOS.ClrFCBStatus clear allocation required bits in status lda #FCB.F.IBLKMOD indicate index block is dirty. jsr XDOS.SetFCBStatus jsr XDOS.Tpos2Y now put block address into index block. inc zpt+1 high byte first. lda scrtch+1 tax sta (zpt),y dec zpt+1 restore pointer to lower page of index lda scrtch block. get low block address. sta (zpt),y store low address. ldy XDOS.FCBPtr update fcb to indicate that this block sta XDOS.FCBs+FCB.DBLK,y is allocated. txa get high address again. sta XDOS.FCBs+FCB.DBLK+1,y L44E9 jsr preprw jsr wrtpart bvc L4479 jmp rwdone update fcb with new position wrtpart txa bne L44FF branch if request is not even pages lda rwreqh a call of 0 bytes should never get here! beq L4546 do nothing dec rwreqh L44FF dex lda (ZP.UserBuf),y move data from user's buffer sta (sos),y txa beq L4525 L4507 iny page crossed ? bne L44FF no, keep moving. lda sos+1 test for end of buffer inc ZP.UserBuf+1 but first adjust user buffer pointer inc XDOS.TmpPos+1 and position bne L451C inc XDOS.TmpPos+2 bne L451C lda #MLI.E.BEYEOF out of range if > 32MB bne L44A2 L451C inc sos+1 adjust sos buffer high address eor ZP.DataPtr+1 (carry is undisturbed) beq L44FF branch if more to write to buffer. clv indicates not finished. bvc L4549 always. L4525 lda rwreqh beq L4539 branch if request satisfied. iny done with this block of data ? bne L4533 if not. lda sos+1 this is necessary for proper eor ZP.DataPtr+1 adjustment of request count bne L4536 L4533 dec rwreqh L4536 dey reset modified y bra L4507 L4539 iny and position bne L4546 inc ZP.UserBuf+1 inc pointers inc XDOS.TmpPos+1 bne L4546 inc XDOS.TmpPos+2 L4546 bit setvflg set v flag L4549 sty XDOS.TmpPos save low position stx rwreql and remainder of request count. php save statuses lda #$50 jsr XDOS.SetFCBStatus clc adjust user's low buffer address lda XDOS.TmpPos adc ZP.UserBuf sta ZP.UserBuf bcc L4564 inc ZP.UserBuf+1 adjust high address as needed. L4564 jsr XDOS.SetFCB.DIRTY set directory flush bit. plp restore return statuses rts topdown jsr swapdown make current 1st block an entry in new bcs L45B1 top. branch if errors. jsr XDOS.GetFCB.ST get storage type * has storage type been changed to 'tree' ? if not, assume it was originally * a seed and both levels need to be built. otherwise, only an index needs * to be allocated. cmp #$03 tree type beq L457A jsr swapdown make previous swap a sap level index bcs L45B1 block. branch if errors. L457A jsr alcwblk get another block address for the sap bcs L45B1 level index. branch if errors. lda XDOS.TmpPos+2 calculate position of new index block lsr in the top of the tree. tay lda scrtch get address of newly allocated index tax block again. sta (zpt),y inc zpt+1 lda scrtch+1 sta (zpt),y save hi address dec zpt+1 ldy XDOS.FCBPtr make newly allocated block the current sta XDOS.FCBs+FCB.IBLK+1,y index block. txa sta XDOS.FCBs+FCB.IBLK,y jsr wfcbfst save new top of tree bcs L45B1 *-------------------------------------- XDOS.ZeroIndex lda #$00 tay inc zpt+1 jsr .1 dec zpt+1 .1 sta (zpt),y iny bne .1 rts *-------------------------------------- sapdown jsr XDOS.GetFCB.ST find out if dealing with a tree. cmp #$01 if seed then adj to file type is needed. beq swapdown branch if seed jsr rfcbfst otherwise read in top of tree. bcc L457A if no error. L45B1 rts return errors. *-------------------------------------- swapdown jsr alcwblk make current seed into a sapling, allocate a block before swap. bcs .9 return errors. ldy XDOS.FCBPtr get previous first block lda XDOS.FCBs+FCB.1stBLK,y address into index block. pha save temporarily while swapping in new lda scrtch top index. get new block address (low) tax sta XDOS.FCBs+FCB.1stBLK,y lda XDOS.FCBs+FCB.1stBLK+1,y pha lda scrtch+1 and high address too sta XDOS.FCBs+FCB.1stBLK+1,y sta XDOS.FCBs+FCB.IBLK+1,y make new top also the current index in txa memory. get low address again. sta XDOS.FCBs+FCB.IBLK,y inc zpt+1 make previous the 1st entry in sub index pla sta (zpt) dec zpt+1 pla sta (zpt) jsr wfcbfst save new file top. bcs .9 if error. lda #FCB.F.STMOD jsr XDOS.SetFCBStatus inc XDOS.FCBs+FCB.STYPE,x * clc no error .9 rts *-------------------------------------- alcwblk jsr XDOS.GetFreeBlk bcs .9 lda #FCB.F.UMOD jsr XDOS.SetFCBStatus inc XDOS.FCBs+FCB.UBLK,x bne .9 inc XDOS.FCBs+FCB.UBLK+1,x .9 rts *-------------------------------------- XDOS.TestWP jsr XDOS.GetFCBStatus check for 'never been modified' condition and #$F0 clc bne XDOS.Tpos2Y.RTS ordinary rts if known write ok. jsr XDOS.FCBDevIDSelect XDOS.TestWPA sta ZP.UNITNUM make the device status call lda ZP.BLKNUM pha lda ZP.BLKNUM+1 save the current block values pha stz ZP.CMDNUM stz ZP.BLKNUM zero the block # stz ZP.BLKNUM+1 jsr XDOS.DevCall bcs .1 branch if write protect error lda #$00 otherwise, assume no errors. .1 jmp XDOS.PopBlkNumRTS restore the block # *-------------------------------------- XDOS.Tpos2Y lda XDOS.TmpPos+2 get index to next block address lsr lda XDOS.TmpPos+1 ror tay index to address = int(pos/512) XDOS.Tpos2Y.RTS rts *-------------------------------------- MAN SAVE usr/src/prodos.fx/prodos.s.xdos.d LOAD usr/src/prodos.fx/prodos.s ASM