NEW AUTO 3,1 *-------------------------------------- XDOS.FindDirOrVol jsr XDOS.FindFileOrVol bcs .99 lda d_stor and #$F0 cmp #$D0 beq moventry.CLCRTS .9 lda #MLI.E.UNSUPST sec .99 rts *-------------------------------------- XDOS.FindFileOrVol jsr XDOS.CheckPath bcc moventry cmp #MLI.E.INVPATH bne fnderr clc rts moventry ldy h_entln Get FileInfo From Directory Block Buffer .1 dey lda (zpt),y move entry into storage sta d_stor,y tya bne .1 moventry.CLCRTS clc rts *-------------------------------------- XDOS.FindFile jsr XDOS.CheckPath see if file exists bcc moventry rts *-------------------------------------- XDOS.CheckPath jsr XDOS.FindVol bcs fnderr.RTS bne lookfil0 branch if more than root jsr XDOS.ZPT.InitGBuf ldy #$1F move in id and date info .1 lda (zpt),y sta d_stor,y dey cpy #$17 bne .1 .2 lda rootstuf-$10,y sta d_stor,y dey cpy #$0F bne .2 lda #$D0 fake directory file sta d_stor lda gbuf+2 check forward link. ora gbuf+3 if non-zero, assume full sized directory bne .3 else assume it's the slot 3 /RAM volume lda #$02 so reset eof and blocks_used fields sta d_eof+1 lda #$01 sta d_usage .3 lda #MLI.E.INVPATH bad path (carry set) rts *-------------------------------------- errdir lda #MLI.E.BADDIR directory error fnderr sec fnderr.RTS rts *-------------------------------------- lookfil0 stz nofree reset free entry indicator. sec dir to be searched has header in this block. L37C9 stz totent reset entry counter. jsr XDOS.LookupNameInDirBlk look for name pointed to by pnptr. bcc namfound if name was found. lda entcntl have we looked at all of the sbc totent entries in this directory? bcc L37E2 maybe, check hi count. bne L37EB no, read next directory block. lda entcnth has the last entry been looked at? beq errfnf yes, give 'file not found' error L37E2 dec entcnth should be at least one L37EB sta entcntl keep a running count. lda /gbuf reset indirect pointer sta zpt+1 lda gbuf+2 get link to next dir block bne L37FC (if there is one). cmp gbuf+3 are both zero, i.e. no link? if so, beq errdir then not all entries were acct'd for. L37FC ldx gbuf+3 acc has value for block# (low). .DO LOWERCASE=1 jsr XDOS.ReadGBufAXDir .ELSE jsr XDOS.ReadGBufAX go read the next linked directory. .FIN bcc L37C9 if no error. rts return error in acc. *-------------------------------------- errfnf lda nofree was any free entry found? bne fnf0 lda gbuf+2 test link bne L3814 cmp gbuf+3 if both are 0 then give up. beq fnf0 report 'not found'. L3814 sta d_entblk lda gbuf+3 sta d_entblk+1 assume 1st entry of next block lda #$01 is free for use. sta d_entnum mark as valid (for create) sta nofree fnf0 jsr nxtpnam1 'file not found' or 'path not found'? errpath1 beq .1 if non-zero then 'path not found' lda #MLI.E.PNOTFND path not found .HS 2C BIT ABS .1 lda #MLI.E.FNOTFND file not found sec lookfil0.RTS rts *-------------------------------------- namfound jsr nxtpname adj index to next name in path. beq filfound branch if that was the last name. ldy #$00 be sure this is a directory entry. lda (zpt),y high nibble will tell. and #$F0 cmp #$D0 is it a subdirectory? bne errpath1 error if not. ldy #$12 get address of 1st subdirectory block lda (zpt),y sta d_head+1 save as file's header block too tax dey lda (zpt),y sta d_head .DO LOWERCASE=1 jsr XDOS.ReadGBufAXDir .ELSE jsr XDOS.ReadGBufAX read subdirectory into gbuf. .FIN bcs lookfil0.RTS if error. lda gbuf+37 get the # of files contained in this sta entcntl directory. lda gbuf+38 sta entcnth *-------------------------------------- * Check if $75 at VOL/DIR entry + $14 * (8 bytes reserved) *-------------------------------------- .DO LOWERCASE=0 lda gbuf+20 make sure password is disabled ldx #$00 sec rol L3869 bcc L386C inx L386C asl bne L3869 cpx #$05 is password disabled? beq movhead lda #MLI.E.INCFF directory is not compatible sec rts .FIN *-------------------------------------- movhead jsr movhed0 move directory info. jmp lookfil0 do next local pathname. movhed0 ldx #9 move this directory info .1 lda gbuf+$1C,x sta h_credt,x dex bpl .1 .DO ACL=1 ldx #7 lda gbuf+$14 cmp #$57 bne .20 lda gbuf+$15 bne .20 .2 lda gbuf+$14,x sta h_acl,x dex bpl .2 bra .21 .20 stz h_acl,x dex bpl .20 .21 .FIN lda gbuf+4 if this is root, then nothing to do and #$F0 eor #$F0 test header type. beq .8 branch if root ldx #$03 otherwise, save owner info about .3 lda gbuf+$27,x this header. sta own_blk,x dex bpl .3 .8 rts *-------------------------------------- filfound lda h_maxent figure out which entry # this is sec sbc cntent max entries - count entries + 1 adc #$00 = entry # (carry was set) sta d_entnum lda bloknml and indicate block # of this directory sta d_entblk lda bloknml+1 sta d_entblk+1 * clc done by ADC #$00 rts *-------------------------------------- XDOS.LookupNameInDirBlk lda h_maxent reset count of files per block sta cntent jsr XDOS.ZPT.InitGBuf reset indirect pointer to gbuf bcs .4 branch if this block contains a header .1 ldy #$00 lda (zpt),y get length of name in directory. bne .2 branch if there is a name. lda nofree test if a free entry has been declared. bne .4 yes, inc to next entry. jsr filfound set address for current entry. inc nofree indicate a free spot has been found. bra .4 .2 and #$0F strip byte (is checked by 'filfound') inc totent inc count of valid files found. sta namcnt save name length as counter. ldx namptr get index to current path. cmp pathbuf,x are both names the same length? bne .4 no, inc to next entry. .3 inx (first) next letter index iny lda (zpt),y compare names letter by letter cmp pathbuf,x bne .4 dec namcnt all letters compared? bne .3 no, continue. clc a match is found. .9 rts .4 dec cntent checked all entries in this block? sec beq .9 yes, no name match. jsr XDOS.ZPT.Next bra .1 *-------------------------------------- XDOS.FindVol jsr XDOS.FindVolInVCBOrDev bcs novolume .DO ACL=1 ldx #$4A .ELSE ldx #$42 zero out directory temps .FIN .1 stz own_blk,x and owner info dex bpl .1 lda DEVNUM setup device # for this directory sta d_dev jsr movhed0 setup other header info from directory ldy #$01 in gbuf and clean up misc info. ldx vcbptr inx .2 lda VCBs+VCB.TBLK,x misc info includes sta h_tblk,y total # of blocks, lda VCBs+VCB.BMAP,x the address of the 1st bitmap, sta h_bmap,y lda bloknml,y directory's disk address, sta d_head,y lda h_fcnt,y and setting up a counter for the # of sta entcntl,y files in this directory. dex dey bpl .2 nxtpname jsr nxtpnam1 get new namptr in y and namlen in acc. sty namptr save new pathname pointer. rts (status reg according to accumulator) nxtpnam1 ldy namptr inc pathname pointer to next name lda pathbuf,y in the path. sec adc namptr if this addition results in zero, tay then prefixed directory has been moved bne L395F to another device. branch if not. lda DEVNUM revise DEVNUM for prefixed directory sta p_dev L395F lda pathbuf,y test for end of name. clc no errors novolume rts *-------------------------------------- XDOS.FindVolInVCBOrDev lda #$00 ldy preflag use prefix volume name to look up vcb. bit prfxflg is this a prefixed path? bpl L396F branch if it is tay set ptr to volume name L396F sty vnptr and save. sta DEVNUM zero out dev# until vcb located. lda #VCB0 L3975 pha acc now used as vcb lookup index. tax index pointer to x. lda VCBs,x get vcb volume name length. bne L3987 branch if claimed vcb to be tested. L397C ldy vnptr restore pointer to requested vol name. pla now adj vcb index to next vcb entry. clc adc #VCB bcc L3975 branch if more vcb's to check bcs L39D4 otherwise go look for unlogged volumes. L3987 sta namcnt save length of vol name to be compared. L398A cmp pathbuf,y is it the same as requested vol name? bne L397C branch if not inx iny next character lda VCBs,x dec namcnt last character? bpl L398A if not. plx restore pointer to matching vcb. stx vcbptr save it for future reference. lda VCBs+VCB.DEV,x get it's device # sta DEVNUM and save it. lda #$02 assume prefix is not used and ldx #$00 that root directory is to be used. pha lda vnptr = 0 if no prefix. L39AC tay if prefix then find ptr to prefixed sta namptr dir name. save path ptr. beq L39C2 branch if no prefix. sec adc pathbuf,y inc to next dir in prefix path. bcc L39AC branch if another dir in prefix. pla lda p_blok volume verification will occur at pha ldx p_blok+1 subdirectory level. * verify volume name L39C2 pla jsr XDOS.ReadGBufAX read in directory (or prefix dir) bcs L39CC if error then look on other devices. .DO LOWERCASE=1 jsr XDOS.CheckAndUnpackGBuf bcs L39CC .FIN jsr XDOS.CheckVolName compare dir name with path name. bcc L39F0 if they match, stop looking. L39CC ldx vcbptr check if current (matched) vcb is active lda VCBs+VCB.OFCNT,x i.e. does it have open files? bne L39ED report not found if active. L39D4 lda vnptr make path ptr same as volume ptr sta namptr jsr mvdevnums copy all device #'s to be examined. lda DEVNUM log current device 1st before searching bne L39F1 others. L39E2 ldx DEVCNT scan look list for devices we need L39E5 lda loklst,x to search for the requested volume. bne L39F4 branch if we've a device to look at. dex bpl L39E5 look at next one. L39ED lda #MLI.E.VNOTFND no mounted volume sec error L39F0 rts L39F1 ldx DEVCNT now remove the device from the list L39F4 cmp loklst,x of prospective devices. beq L39FE branch if match. dex look until found. bpl L39F4 always taken (usually) unless bmi L39ED if dev was removed from devlst (/RAM). L39FE sta DEVNUM preserve device to be checked next. stz loklst,x mark this one as tested. jsr XDOS.FindVCBForDevNum find vcb that claims this dev (if any). bcs L3A29 branch if vcb full. lda VCBs,x did we find it or return free vcb? beq L3A16 if free vcb. lda VCBs+VCB.OFCNT,x is this volume active? bne L39E2 if so, no need to re-log. L3A16 lda #$02 go read root dir into gbuf ldx #$00 .DO LOWERCASE=1 jsr XDOS.ReadGBufAXDir .ELSE jsr XDOS.ReadGBufAX .FIN bcs L39E2 ignore if unable to read. jsr XDOS.VCBMount bcs L39E2 look at next if non-xdos disk mounted. jsr XDOS.CheckVolName is this the volume ? bcs L39E2 if not L3A29 rts *-------------------------------------- mvdevnums ldx DEVCNT copy all dev #'s to be checked. L3A2D lda DEVLST,x active device list. and #$F0 strip device type info. sta loklst,x copy them to a temp workspace dex bpl L3A2D ldx DEVCNT rts *-------------------------------------- XDOS.FindVCBForDevNum lda #VCB0 look for vcb for DEVNUM ldy #$FF .1 tax new index to next vcb lda VCBs+VCB.DEV,x check all devnums cmp DEVNUM is this the vcb? beq .7 lda VCBs,x is this a free vcb? bne .3 if not iny bne .3 already found a free one stx vcbptr save first free VCB .3 txa clc inc index to next vcb adc #VCB bcc .1 ldx vcbptr get found free if any tya any free vcb's available? bpl .8 yes, exit with X = vcbptr lda #VCB0 look for an entry to kick out .4 tax lda VCBs+VCB.OFCNT,x any open files? beq .5 no, kick this one out. txa next vcb clc adc #VCB bcc .4 lda #MLI.E.VCBFULL all vcb entries have open files * sec rts .5 stz VCBs,x free this entry stz VCBs+VCB.DEV,x .7 stx vcbptr save entry index. .8 clc no error. rts *-------------------------------------- XDOS.CheckVolName ldx #$00 index to directory name. ldy namptr index to pathname. lda gbuf+4 get dir name length and type. cmp #$E0 is it a directory? bcc L3A90 if not. and #$0F isolate name length and sta namcnt save as a counter. bne L3A95 branch if valid length. L3A90 sec indicate not found rts L3A92 lda gbuf+4,x next char L3A95 cmp pathbuf,y bne L3A90 if not the same. inx check next char iny dec namcnt bpl L3A92 if more to compare. clc match found XDOS.CheckVolName.RTS rts *-------------------------------------- XDOS.VCBMount ldx vcbptr previously logged in volume? lda VCBs,x (acc = 0?) beq XDOS.VCBMountAtX no, go prepare vcb. jsr XDOS.VCBCmpGBUF does vcb match vol read? bcc XDOS.CheckVolName.RTS yes, do not disturb. XDOS.VCBMountAtX ldy #VCB zero out vcb entry L3AB2 stz VCBs,x inx dey bne L3AB2 lda gbuf pointer to previous dir block ora gbuf+1 must be null bne tsterr lda gbuf+4 test for header and #$E0 cmp #$E0 bne tsterr jsr tstdupvol does a duplicate with open files bcs L3B04 already exist? branch if yes. lda gbuf+4 move volume name to vcb. and #$0F strip root marker tay pha * clc adc vcbptr tax L3ACE lda gbuf+4,y sta VCBs,x dex dey bne L3ACE pla get length again sta VCBs,x and save. lda DEVNUM last device used. sta VCBs+VCB.DEV,x save device # and ldy #0 .1 lda gbuf+39,y sta VCBs+VCB.BMAP,x copy BMAP+TBLK iny inx cpy #4 bne .1 L3B04 clc indicate logged if possible rts tsterr lda #MLI.E.NOTPRODOS not tree or dir, unrecognized type sec rts *-------------------------------------- XDOS.VCBCmpGBUF lda gbuf+4 with name in directory. and #$0F cmp VCBs,x are they the same length? stx xvcbptr (see rev note #23) bne .9 if not the same. tay clc adc xvcbptr tax .1 lda gbuf+4,y cmp VCBs,x bne .9 if not the same. dex dey bne .1 clc indicate match. .HS B0 BCS .9 sec ldx xvcbptr offset to start of vcb (rev note #23) rts *-------------------------------------- tstdupvol lda #VCB0 check for other logged in volumes with the same name. L3B2C tax jsr XDOS.VCBCmpGBUF bcs L3B41 if no match. lda VCBs+VCB.OFCNT,x test for any open files. bne L3B4B cannot look at this volume. stz VCBs,x take duplicate offline if no open files stz VCBs+VCB.DEV,x * clc ok to log in new volume. rts L3B41 txa index to next vcb * sec adc #VCB-1 bcc L3B2C branch if more to check clc rts L3B4B sta duplflag duplicate has been found. stx vcbentry save pointer to conflicting vcb. sec error. rts *-------------------------------------- tstfrblk ldx vcbptr test if enough free blocks available for request. lda VCBs+VCB.FBLK+1,x check if proper count for this volume. ora VCBs+VCB.FBLK,x bne L3BAD branch if count is non-zero. tkfrecnt jsr cntbms get # of bitmaps sta bmcnt and save. stz scrtch start count at 0 stz scrtch+1 lda #$FF mark 'first free' temp as unknown sta nofree jsr upbmap update volume bitmap. bcs L3BC1 if error. ldx vcbptr get address of 1st bitmap lda VCBs+VCB.BMAP,x sta bloknml lda VCBs+VCB.BMAP+1,x sta bloknml+1 L3B81 jsr XDOS.ReadGBuf use general buffer for temp space to bcs L3BC1 count free blocks (bits). jsr count dec bmcnt was that the last bitmap? bmi L3B96 if so, go change fcb so not done again. inc bloknml bne L3B81 inc bloknml+1 bra L3B81 L3B96 ldx vcbptr mark which block had 1st free space lda nofree bmi L3BBE if no free space was found. sta VCBs+VCB.BMAPIDX,x update the free count. lda scrtch+1 sta VCBs+VCB.FBLK+1,x update volume control byte. lda scrtch sta VCBs+VCB.FBLK,x L3BAD lda VCBs+VCB.FBLK,x compare total available free blocks sec on this volume. sbc reql lda VCBs+VCB.FBLK+1,x sbc reqh bcc L3BBE clc rts L3BBE lda #MLI.E.VOLFULL sec L3BC1 rts count ldy #$00 L3BC4 lda gbuf,y bit pattern. beq L3BCC don't count jsr cntfree L3BCC lda gbuf+$100,y do both pages with same loop beq L3BD4 jsr cntfree L3BD4 iny bne L3BC4 loop until all 512 bytes counted. bit nofree has 1st block w/free space been found? bpl L3BEE if yes. lda scrtch test to see if any blocks were counted ora scrtch+1 beq L3BEE branch if none counted. jsr cntbms get total # of maps. sec subtract countdown from total bitmaps sbc bmcnt sta nofree L3BEE rts cntfree asl count the # of bits in this byte bcc L3BFA inc scrtch bne L3BFA inc scrtch+1 L3BFA ora #$00 bne cntfree loop until all bits counted rts cntbms ldx vcbptr ldy VCBs+VCB.TBLK+1,x return the # of bitmaps lda VCBs+VCB.TBLK,x possible with the total count bne L3C0B found in the vcb. dey adj for bitmap block boundary L3C0B tya lsr divide by 16. the result is lsr the # of bitmaps. lsr lsr rts *-------------------------------------- MAN SAVE usr/src/prodos.fx/prodos.s.xdos.b LOAD usr/src/prodos.fx/prodos.s ASM