; ; DOS DIRECTORY ROUTINES ; ; OPEN A DIRECTORY (FOR USER) ; LSTDIR LDY #$80-11 SAVFNB LDA FNAME-$80+11,Y STA (FMSBPT),Y INY BPL SAVFNB JSR SFDIR ;FIND A MATCH IN THE DIRECTORY BCS ENDDIR ;IF NO MORE MATCHES, REPORT FREE SPACE NXTDIR JSR FMTDIR ;ENTRY FOUND, FORMAT INTO A TEXT STRING LDA CURFNO STA FCBFNO,X ;SAVE THE FILE NUMBER OF THE ENTRY FOUND GODONE JMP DONE ;AND RETURN ; GOTEOD DEC DATBYT ;CONVERT EOL TO $9B (REAL EOL) STA CURLEN,X ;AND FINISH UP BNE GODONE ; DIRRD LDY #$80-11 RSTFNB LDA (FMSBPT),Y ;FETCH BYTES OF PREVIOUSLY PARSED DIRECTORY ENT STA FNAME-$80+11,Y INY BPL RSTFNB LDA CURLEN,X BMI DIREOF ;EOF IF WE ALREADY REPORTED FREE SPACE TAY LDA (FMSBPT),Y STA DATBYT INC CURLEN,X CMP #$9C BEQ GOTEOD CMP #$9B ;IS THIS END OF LINE? BNE GODONE ;IF NOT, CONTINUE FETCHING OLD BYTES LDA FCBFNO,X CMP CURFNO BNE DMSTRD CPX DIUNIT BEQ DRDNRQ DMSTRD JSR RRDIR ;IF SO, INSURE DIRECTORY BLOCK IS IN MEMORY DRDNRQ JSR CSFDIR ;AND FIND THE NEXT ENTRY BCC NXTDIR ;IF FOUND, LOOP BACK AND FORMAT IT ; ; NO MORE ENTRIES, REPORT FREE SECTORS LAST ; ENDDIR JSR RBITMP ;READ THE VTOC DATA LDY #0 STY CURMAP ;FORCE A REREAD NEXT TIME LDA MAPBUF+3 LDX MAPBUF+4 ;AND STUFF THE BUFFER WITH NO. OF FREE SECTORS JSR CVTDEC LDX #-14 FSECL LDA FSECM+14-256,X ;FOLLOWED BY THE "FREE SECTORS" TEXT STA (FMSBPT),Y INY INX BNE FSECL BEQ GODONE ; DIREOF JMP RETEOF ;NO MORE LINES, RETURN EOF INDICATION ; FSECM DB ' FREE SECTORS',$9C ; ; FORMAT A DIRECTORY ENTRY FOR BASIC, ETC. ; FMTDIR LDY #' ' LDX DIRDSP LDA DIRBUF,X PHA AND #$20 BEQ D0E35 LDY #'*' ;IF SO, MARK AS LOCKED D0E35 TYA LDY #0 STA (FMSBPT),Y PLA LDY #' ' AND #$10 BEQ NOTDIR LDY #':' NOTDIR TYA LDY #1 STA (FMSBPT),Y CPYNAML INY LDA DIRBUF+5,X STA (FMSBPT),Y INX CPY #13 BCC CPYNAML ; LDA #' ' STA (FMSBPT),Y LDY DIRDSP LDA DIRBUF+1,Y LDX DIRBUF+2,Y LDY #14 ;SECTOR COUNT STARTS HERE ; ; CONVERT A 16-BIT INTEGER TO A 4 OR 5 DIGIT NUMBER ; CVTDEC STX TMP2 STA TMP1 LDX #HIGH[10000] LDA #LOW[10000] JSR MKDGT2 CMP #'0' BNE SKIP5 DEY SKIP5 LDX #HIGH[1000] LDA #LOW[1000] JSR MKDGT2 LDA #100 ;FOR THE SHORT STUFF JSR MAKDGT LDA #10 JSR MAKDGT TXA ADC #'0'+10 STA (FMSBPT),Y INY LDA #$9B ;TERMINATE LINE STA DATBYT STA (FMSBPT),Y LDA #0 LDX CURFCB STA CURLEN,X RTS ; ; CREATE A DIGIT AND STORE IT INTO THE DIRECTORY BUFFER ; MAKDGT LDX #0 ;IF SUBTRAHEND < 256, ZERO UPPER BYTE MKDGT2 STX DIRDSP STA DIRSEC STY DATBYT LDY #'0' SEC DGTLP2 LDA TMP1 SBC DIRSEC TAX LDA TMP2 SBC DIRDSP BCC DGTXIT STA TMP2 STX TMP1 INY BCS DGTLP2 ; DGTXIT TYA LDY DATBYT STA (FMSBPT),Y INY RTS ; ; PARSE A FILE NAME WITH WILD CARD CHARACTERS ('*' AND '?') ; GETNM2 iny ;look for ">" in lda (ICBALZ),y ;the start of cmp #'>' ;the filename beq GETNAM ;(for SpartaDOS compatibility) dey ;[Bob Puff] bne GETNAM ;branch always ; GETFNM LDX CURFCB LDY #HIGH[361] LDA #LOW[361] JSR SETDIR INY LDA (ICBALZ),Y INY CMP #':' ;DEFAULT DIRECTORY? BNE GETNM2 ;IF NOT, CHECK FOR SPARTA ">" DEY STY TMP1 LDY DEFAULT STY ICDNOZ TYA STA ICDNO,X JSR SETUPD LDA CDIREC LDY CDIREC+1 JSR SETDIR LDY TMP1 ; GETNAM LDX #-11 INY AFTSTR LDA (ICBALZ),Y CMP #'*' BNE TSTPER LDA #'?' INY QLOOP STA FNAME+11-256,X INX BPL TOXITC ;END OF EXTENSION? PERFND CPX #-3 ;END OF FILE NAME? BNE QLOOP ;NO MORE -?-S BEQ AFTSTR ; TSTPER CMP #'.' ;A PERIOD? BNE TSTCHR ;IF NOT, CHECK FOR INDIVIDUAL CHARACTERS LDA #' ' ;IF SO, FILL WITH SPACES INY BNE PERFND ; TSTCHR CMP #'?' BCC ENDCHR ;IF < '?', CHECK FOR DIGIT CMP #'Z'+1 ;ELSE, UPPER CASE LETTER, '?', OR '@'? BCC GOTCHR CMP #'_' BCC ENDCHR ;IF CARET, BACKSL. OR BRACKETS CMP #'z'+1 ;LOWER CASE, ACCENT OR UNDERSCORE? BCC GOTCHR ENDCHR CPX #-11 ;IF FIRST CHAR, ERROR BEQ ERRCHR ;NO BYTES IN FILE NAME CMP #'0' ;ELSE, A DIGIT? BCC FILLNM ;IF NOT, THIS IS END OF NAME CMP #':' BCS FILLNM ; GOTCHR STA FNAME+11-256,X INY INX BMI AFTSTR ; TOXITC LDA (ICBALZ),Y TSTDIR CMP #':' ;LOOK FOR SUBDIRECTORY BEQ MYDIR ;IF MYDOS SYNTAX CMP #'>' ;OR SPARTA SYNTAX BNE XITCHR ;IF FINISHED, RESTORE FCB PTR TO X AND EXIT MYDIR STY TMP2 JSR SFDIR ;ELSE, FIND FILE BCS FNER1 ;NO SUCH FILE JSR TONXDR BEQ FNER1 LDY TMP2 BNE GETNAM FNER1 LDA #174 ;IF NOT, RETURN ERROR 174 DB $2C ;BIT ABS (SKIP 2 BYTES) ; ERRCHR LDA #165 JMP AEXIT ; FILLNM PHA LDA #' ' FILLLP STA FNAME+11-256,X INX BMI FILLLP PLA JMP TSTDIR ; ; RETURN WITH NON-ZERO FLAG IF FILE IS A DIRECTORY ; TONXDR LDA #$10 ;FILE FOUND, A DIRECTORY? JSR GETFLAG BEQ TONXIT ;IF NOT, SET ZERO FLAG LDA DIRBUF+3,Y ;IF SO, MOVE POINTERS TO THE NEW LEVEL STA DIRBAS,X LDA DIRBUF+4,Y STA DIRBAS+1,X LDA #$10 ;AND CLEAR THE ZERO FLAG TONXIT RTS ; ; ENTER A NAME INTO THE DIRECTORY AT DIRBUF[DIRDSP] ; ENTNAME PHP LDX #-11 LDY DIRDSP NAMELP LDA FNAME+11-256,X ;LOAD THE MASK CHARACTER CMP #'?' BNE STORIT ;IF NOT '?', SAVE IT AS IT APPEARS PLP PHP BCC NOSTOR ;IF CY CLEAR, LEAVE THE CHARACTERS UNCHANGED LDA #' ' ;IF CY SET, CONVERT '?'S TO SPACES STORIT STA DIRBUF+5,Y NOSTOR INY INX BMI NAMELP PLP LDY DIRDSP XITCHR LDX CURFCB RTS ; SFDIR JSR WBITMP ;INSURE BIT MAP IS SAFE LDX #255 STX HOLFN STX CURFNO INX STX DAUX2 INX STX DAUX1 LDX #READ STX DCOMND JSR SYSSET ;SET UP POINTERS FOR SYSTEM BUFFER I/O ; LDA ICDNOZ CMP RAMDKU BEQ CSFDIR ;IF RAMDISK, FORGET DENSITY CHECK ldx CURFCB ;IF A ROOT DIRECTORY ACCESS, READ BOOT SECTOR lda DIRBAS,X ;IF IN A SUBDIRECTORY, ASSUME DENSITY IS OK cmp #LOW[361] ;[Bob Puff] bne CSFDIR ;;; lda DIRBAS+1,X ;Only occasionally will we get an extra read! ;;; cmp #HIGH[361] ;;; bne CSFDIR ; JSR DSKINV ;ELSE, READ THE FIRST BOOT SECTOR BMI ERRX JSR INVUNIT ;UPDATE DRIVE CONFIGURATION ; CSFDIR INC CURFNO ;READ NEXT 16-BYTE DIR. BLOCK LDA CURFNO JSR BSECDS ;CONVERT TO SECTOR AND DISPLACEMENT XITCH1 BCS XITCHR BNE NOREAD ;IF DISP>0, PROCESS BLOCK JSR RDIRBK ;IF DISP=0, READ SECTOR ; NOREAD LDY DIRDSP LDA DIRBUF,Y BEQ FNDOLD ;ZERO IS END OF DIRECTORY (NO MORE ENTRIES) BMI FNDOLD ;NEGATIVE IS EMPTY SLOT (MAY HAVE MORE ENTRIES) ; ; HANDLE DOS 2.5 FILES ; and #$DF ;preserve lock flag cmp #3 ;is this DOS 2.5 + file? bne NOD25 ;nope lda #$41 ;otherwise, kludge the eor DIRBUF,Y ;flag to make $42 sta DIRBUF,Y ;and save lock. ; NOD25 AND #$01 ;IGNORE ANY FILE THAT IS MARKED "OPEN" BNE CSFDIR LDX #-11 CPNXCH LDA FNAME+11-256,X CMP #'?' BEQ WCMTCH ;EVERYTHING MATCHES "?" CMP DIRBUF+5,Y BNE CSFDIR ;NO MATCH, LOOK AT THE NEXT DIRECTORY ENT WCMTCH INY INX BMI CPNXCH CLC BCC XITCHR ;ENTRY FOUND, RETURN WITH CY=0 ; FNDOLD LDX HOLFN BPL KPOLD ;IF AN EMPTY SLOT IS ALREADY FOUND, DO NOTHING LDX CURFNO STX HOLFN ;ELSE SAVE THIS ONE, ITS THE FIRST! KPOLD TAX BMI CSFDIR ;IF NOT END OF THE DIRECTORY, KEEP LOOKING ERRX SEC BCS XITCH1 ;ELSE, ENTRY NOT FOUND, RETURN WITH CY=1 ; ; DOS I/O ROUTINES ; ; DISK SECTOR I/O ROUTINES ; WRDISK SEC ;FMS DISK WRITE ENTRY RWDISK LDY FMSBPT ;DATA SECTOR READ/WRITE ENTRY LDA FMSBPT+1 JSR BUFSET LDA CURSEC+1,X LDY CURSEC,X FMDKIO PHP LDX DUNIT CPX RAMDKU BEQ RDKIO1 PLP pha ;ALLOW FOR DENSITY CHANGE IN FORMAT, ETC. lda SECSIZ-1,X ;[Bob Puff] tax pla JMP DKIO ; RDKIO1 JMP RDKIO ;ABSOLUTE DISK I/O ROUTINE WAS MOVED TO LOW RAM ; EXTEND JSR ALLOC LDA FCBOTC,X LSR A BCC REWRIT DEC FCBOTC,X JSR WTRICK JMP WRTTST ; REWRIT LDY LNKSEC+1,X LDA LNKSEC,X JSR SAVLNK WRTTST BMI RTBADF INC SECCNT,X BNE TONXT INC SECCNT+1,X ; TONXT LDA LNKSEC,X ;MAKE NEXT SECTOR STA CURSEC,X ;NEW CURRENT SEC. LDA LNKSEC+1,X STA CURSEC+1,X LDA #0 STA LNKSEC,X ;ZERO LINK STA LNKSEC+1,X LENSET STA CURLEN,X ;ZERO CURRENT OFFSET LDA DLINK ;GET THE LINK LOC. STA MAXLEN,X ;MAKE IT MAX. LEN. CLC ;CLEAR CY FOR LATER READ RTS ; RDNXTS LDA FCBFLG,X BEQ CHASE ; WRNXTS LDA FCBFLG,X BMI EXTEND ASL A BPL RDNXTS ASL A STA FCBFLG,X JSR WRDISK BPL RDNXTS ; RTBADF JMP HWERR ;RETURN HARDWARE ERROR CODE IF PRESENT ; SAVLNK PHA TYA LDY DLINK STA (FMSBPT),Y PLA INY STA (FMSBPT),Y INY LDA CURLEN,X NOBIT STA (FMSBPT),Y LDY FCBOTC,X BMI LEN16 ;16-BIT LENGTH? LDA FCBFNO,X ASL A ASL A LDY DLINK ORA (FMSBPT),Y STA (FMSBPT),Y LEN16 JMP WRDISK ; WTRICK LDA LNKSEC,X STA SAVSEC,X LDA LNKSEC+1,X STA SAVSEC+1,X STX LSTIOCB LDA CURSEC,X STA LSTSEC LDA CURSEC+1,X STA LSTSEC+1 JMP WRDISK ; INSTRT JSR INITYP ; CHASE LDA LNKSEC,X ORA LNKSEC+1,X BEQ NOLINK JSR TONXT ;SET CY=0, FUNC=READ JSR RWDISK BMI RTBADF ;CANNOT READ SO BAD FILE NUMBER(ERR=164) LDY DLINK LDA FCBOTC,X ;16-BIT LINK? ORA #$7F BMI LNGLNK LDA (FMSBPT),Y LSR A LSR A CMP FCBFNO,X BNE XLINKED LDA #$03 LNGLNK AND (FMSBPT),Y STA LNKSEC+1,X INY LDA (FMSBPT),Y STA LNKSEC,X INY LDA (FMSBPT),Y STA MAXLEN,X DRDXIT CLC RTS ; XLINKED LDA ICCOM,X CMP #FMTCMD ;IS THIS A FORMAT? BNE FNOERR NOLINK SEC RTS ; ; READ OR WRITE A DIRECTORY BLOCK ; RRDIR LDA FCBFNO,X ; SDIRBK STA CURFNO RDCFNO LDA CURFNO JSR BSECDS ; RDIRBK JSR WBITMP ;TAKE CONTROL OF SYSTEM BUFFER CLC DB $A9 ;LDA # (SKIPS 1 BYTE) WDIRBK SEC RWDBK PHP LDX CURFCB ;PUT FCB NO. IN X STX DIUNIT ;SAVE THE DIR. BUFFER IOCB JSR SYSSET CLC LDA DIRSEC ADC DIRBAS,X TAY LDA DIRBAS+1,X ADC #0 ;MULTIPLE DIRS. REQ. THIS [ChasM] PLP SYSRW JSR FMDKIO BPL DRDXIT LDA #163 ;BIT MAP R/W ERROR, RETURN SYSTEM ERR. CODE DB $AE ;SKIP 2 BYTES ; FNOERR lda #164 sta DSTATS jmp HWERR ;FILE NUMBER MISMATCH ; ; READ OR WRITE THE DISK VTOC (BIT MAP) ; RBITMP LDA CURMAP CMP ICDNOZ BEQ MAPXIT ;SKIP READ IF WHAT WE WANT IS ALREADY THERE JSR WBITMP ;ELSE, REAL I/O, SAVE CURRENT BUFFER CONTENTS ; LDA #0 TAY ZMAP STA MAPBUF,Y ;ZERO ENTIRE 512 STA MAPBUF+256,Y ;BYTES OF MAP BUF. DEY BNE ZMAP CLC JSR RWBMAP ;THEN READ 128 OR 256 BYTES OF VTOC DATA ; LDY #$FF STY DIUNIT ;INDICATE MAP (NOT DIR) IS LOADED STY MAP2 ;INDICATE SECOND PAGE OF MAP IS UNLOADED INY STY CHGMAP ;INDICATE MAP IS UNCHANGED INY STY MAP2MOD STY CURMP ; MAPCLR STA CURMAP ;AND SAVE DRIVE NUMBER MAP APPLIES TO MAPXIT RTS ; WBITMP LDA CHGMAP BEQ MAPCLR ;IF MAP NOT CHANGED, SKIP WRITING IT STA DUNIT FMTMAP LDA #0 STA CHGMAP ;ELSE MARK IT UNUSED STA CURMAP lda DUNIT ;save drive # [Bob Puff] pha SEC JSR RWBMAP pla ;then restore it [Bob Puff] sta DUNIT ; WRNXTM LDA MAP2MOD BNE NOMPI2 ;IF THE PAGE BUFFER IS CLEAN, JUST EXIT LDA #$FF ;ELSE, WRITE IT TO DISK PHA LDA MAP2 INC MAP2MOD SEC BCS MUSTWM ; RDNXTM CMP MAP2 ;READ A PAGE INTO THE SECOND PAGE BUFFER BEQ NOMAPI ;IF IT IS ALREADY THERE, JUST EXIT PHA JSR WRNXTM ;ELSE, WRITE THE CURRENT PAGE (IF NECESSARY) PLA ;AND READ THE NEW ONE PHA CLC ;BY FALLING INTO MUSTWM WITH CY=0 ; MUSTWM PHA LDA #HIGH[MAPBUF+256] LDY #LOW[MAPBUF+256] JSR BUFSET ;SET UP THE BUFFER POINTER FOR 2ND PAGE PLA ; OF THE VTOC BUFFER JSR MAPIOC ;ISSUE I/O REQUESTS PLA STA MAP2 ;UPDATE SECOND BUFFER ID BYTE NOMAPI RTS ; RWBMAP JSR SYSSET ;SET UP BUFFER POINTERS FOR SYSTEM BUF I/O LDA #0 MAPIOC PHP pha ldx DUNIT ;NOTE: THE CURRENT I/O MAY NOT BE TO THE lda SECSIZ-1,X ;FCB BEING ACCESSED! tax ;[Bob Puff] pla cpx #2 ;256 BYTE SECS? beq MAPDDS ASL A ;128, CHANGE PAGE NUMBER TO PAIR NUMBER MAPDDS EOR #$FF SEC ADC #LOW[360] TAY cpx #2 ;128 OR 256 BYTE SECTORS? beq DDMAPX ;IF 128, READ 2 SECTORS TO FILL BUFFER LDA #HIGH[360] PLP PHP JSR SYSRW ;READ OR WRITE THE FIRST SECTOR LDA MAPBUF CMP #3 ;IF DOS 2.0 DISK, READ ONE SECTOR BCC XITMBF ;EVEN IN SINGLE DENSITY JSR STEPBP DEY DDMAPX LDA #HIGH[360] PLP PHP JSR SYSRW ;READ OR WRITE THE SECOND (OR ONLY) SECTOR XITMBF PLP NOMPI2 LDA ICDNOZ STA DUNIT ;RESTORE THE USER DRIVE NUMBER TO DUNIT, RTS ;SINCE I/O MAY HAVE BEEN TO ANOTHER DRIVE ; SYSSET LDA #HIGH[MAPBUF] LDY #LOW[MAPBUF] JMP BUFSET ; ; ROUTINE TO STEP TO THE NEXT DIRECTORY ENTRY (UNTIL WE RUN OUT) ; BSECDS LDY #0 STY DIRDSP LSR A ROR DIRDSP LSR A ROR DIRDSP LSR A ROR DIRDSP ;(FILE NUMBER MOD 8) * 16 IS OFFSET IN SECTOR STA DIRSEC ;FILE NUMBER/8 IS SECTOR OFFSET ; CMP #8 ;END OF DIRECTORY? DEY BCS BSECXT ROR DIRDSP BSECXT RTS