; C02 filesys.h02 assembly language subroutines
; for all Commodore 8 bit machines
; Requires external functions ADDDST, FOPENA, FREAD, FSKIP, 
; FSBCMD, FSCBFR, FSCDRA, FSGBFR, FSOPTS, and SETSRC
; external zero page locations BFRHI, BFRLO, DSTHI, DSTLO, 
; SRCHI, and SRCLO
; and external locations FSCNTR, FSDVNO, FSLFNO, and TEMP0

;String Constants
FSDIRP  DC "$0:",0  ;Disk Directory Prefix

;opndir() - Open Directory for Reading
;Args: A = Drive/Options 
;      Y,X = Pointer to Directory Name
;Uses: BFRHI,BFRLO = Pointer to Work Buffer
;Sets: SRCHI,SRCLO = Pointer to Directory Name
;Returns: A = File Pointer
;             0 - Error
OPNDIR: JSR SETSRC      ;Save Directory Pointer
        STY FSCNTR      ;Set File Count to 0
        JSR FSOPTS      ;Parse Options Byte
        JSR FSCDRV      ;If Device is Not Disk Drive
        BEQ CLSDIX      ;  Return Error
        LDA #36         ;Set Command to "$"
        JSR FSBCMD      ;and Build Command String
        SEC             ;Set Flag to Concatenate
        JSR FSCBFR      ;Concatenate Directory Name to Buffer
        JSR FSGBFR      ;Get String Buffer Address
        JMP FOPENA      ;Execute File Open (Alternate Entry Point)

;clsdir() - Close Directory File
;Args: A = Directory File Pointer
;Returns: A = Error Code
;             0 - Success
CLSDIR: ORA #0          ;Check File Pointer
        BEQ CLSDIX      ;If Not Zero
        JMP FCLOSE      ;Close File Channel
CLSDIX: RTS

;rdhdr() - Read Directory Header
;Note: Call once before first rddir()
;Args: A = Directory File Pointer
;      Y,X = Pointer to HDRENT buffer
;Sets: DSTHI,DSTLO = Pointer to HDRENT buffer
;Returns: A = Disk Type
;         Y = Error Code (0=None)
RDHDR:  JSR SETDST      ;Set Destination Address
        LDY #2          ;Set Record Length
        JSR FREAD       ;and Read Record
        BCS RDHDRZ      ;If Error, Exit
        STY TEMP0       ;Set Skipped Bytes to 0
        LDA (DSTLO),Y   ;Get Disk Version
        PHA             ;and Save It
        CMP #$43        ;If 8050/8250
        LDY #2          ;Skip Unused bytes
        BNE RDHDRC
        CMP #$41        ;If 4040/1541/1571
        BNE RDHDRD      ;  Skip BAM
        LDA FSLFNO      ;  Get Channel
        LDY #140        ;  Set Record Length
RDHDRC: STY TEMP0       ;  Save Number of Skipped Bytes
        JSR FSKIP       ;  and Skip Bytes
        BCS RDHDRX      ;  If Error, Exit
RDHDRD: LDA #2          ;Add 2 Bytes
        JSR ADDDST      ;to Destination Address
        LDA FSLFNO      ;Get Channel
        LDY #24         ;Set Record Length
        JSR FREAD       ;and Read Record
        BCS RDHDRX      ;If Error, Exit
        LDA #228        ;Set Padding Bytes
        SEC
        SBC TEMP0       ;Subtract Bytes Skipped
        TAY             ;Set as Record Length
        LDA FSLFNO      ;Get Channel
        JSR FSKIP       ;and Skip Bytes
        LDY #23         ;Set Index to 24
RDHDRN: LDA (DSTLO),Y   ;Load Byte
        CMP #$A0        ;If Shifted Space
        BNE RDHDRS
        LDA #0          ;Change to 0
        STA (DSTLO),Y
RDHDRS: DEY             ;Decrement Index
        BPL RDHDRN      ;and Loop if Not Negative
        INY             ;Set Error Code to 0
RDHDRX: PLA             ;Retrieve Disk Type
RDHDRZ: RTS

;rddir() - Read Directory Entry
;Args: A = Directory File Pointer
;      Y,X = Pointer to DIRENT buffer
;Uses: BFRHI,BFRLO = Pointer to Work Buffer
;Sets: DSTHI,DSTLO = Pointer to DIRENT buffer
;Returns: A = File Type (0=Null Entry)
;         Y = Error Code (0=None)
RDDIR:  JSR SETDST      ;Set Destination Address
        TAX             ;Save LFN
        LDY #32         ;Set Record Length
        INC FSCNTR      ;Increment File Count
        LDA FSCNTR      ;Load It
        AND #$07        ;Modulo 8
        BNE RDDIRB      ;If 0
        LDY #30         ;  Change Record Length
RDDIRB: TXA             ;Restore LFN
        JSR FREAD       ;and Read Record
RDDIRC: LDA #0          ;Initialize Return Value
        BCS RDDIRX      ;If Error, Exit
        LDA (DSTLO),Y   ;Get File Type
        PHA             ;and Save it
        LDA #3          ;Add 3 Bytes
        JSR ADDDST      ;to Destination Address
        LDY #15         ;Set Index to 15
RDDIRN: LDA (DSTLO),Y   ;Load Byte
        CMP #$A0        ;If Shifted Space
        BNE RDDIRS
        LDA #0          ;Change to 0
        STA (DSTLO),Y
RDDIRS: DEY             ;Decrement Index
        BPL RDDIRN      ;and Loop if Not Negative
        INY             ;Set Error Code to 0
        PLA             ;Restore File Type
RDDIRX: RTS

;setdrv() - Set Current Drive
;Args: A = Drive Identifier
;Returns: A = Drive Identifier
;             0 - None/Error
SETDRV: JSR FSCDRA      ;Check Device Number
        BCS SETDRX      ;If Disk Drive
        STA FSDVNO      ;  Write to Device#
SETDRX: RTS

;getdrv() - Get Current Drive
;Returns: A = Drive Identifier
;             0 - None/Error
GETDRV: LDA FSDVNO      ;Load Current Device#
        JMP FSCDRA      ;Check if Disk Drive

;setdir() - Set Current Directory
;Args: A = Drive Identifier
;      Y,X = Pointer to Directory Name
;Uses: BFRHI,BFRLO = Pointer to Work Buffer
;Sets: SRCHI,SRCLO = Pointer to Directory Name
;Returns: A = Error Code
;             $00 - Successful
;             $FF - Inapplicable
SETDIR: JSR SETSRC      ;Save Pointer
        JSR FSOPTS      ;Parse Drive Argument
        JSR FSGBFR      ;Get String Buffer Address
        ;command is "/0:Directory"
        ;assuming 0 is disk number
        ;of course this is switched from normal command syntax
        RTS

;getdir() - Get Current Directory
;Args: A = Drive Identifier
;      Y,X = Pointer to String
;Uses: BFRHI,BFRLO = Pointer to Work Buffer
;Sets: DSTHI,DSTLO = Pointer to String
;Returns: A - Length of Directory Name
;             $00 - Root
;             $FF - Inapplicable
GETDIR: ;Return Inapplicable (fall through)

;mkdir() - Create Directory
;Args: A = Drive Identifier
;      Y,X = Pointer to Directory Name
;Uses: BFRHI,BFRLO = Pointer to Work Buffer
;Sets: SRCHI,SRCLO = Pointer to Directory Name
;Returns: A = Error Code
;             $00 - Successful
;             $FF - Inapplicable
MKDIR:  ;Return Inapplicable (fall through)

;rmdir() - Remove Directory
;Args: A = Drive Identifier
;      Y,X = Pointer to Directory Name
;Uses: BFRHI,BFRLO = Pointer to Work Buffer
;Sets: SRCHI,SRCLO = Pointer to Directory Name
;Returns: A = Error Code
;             $00 - Successful
;             $FF - Inapplicable
RMDIR:  ;Return Inapplicable (fall through)

;remove() - Delete File
;Args: A = Drive Identifier
;      Y,X = Pointer to File Name
;Uses: BFRHI,BFRLO = Pointer to Work Buffer
;Sets: SRCHI,SRCLO = Pointer to File Name
;Returns: A = Error Code
;             $00 - Successful
;             $FF - Inapplicable
REMOVE: ;Return Inapplicable (fall through)

;rename() - Rename File
;Args: A = Drive Identifier
;      Y,X = Pointer to Destination File Name
;Uses: SRCHI,SRCLO = Pointer to Source File Name 
;      BFRHI,BFRLO = Pointer to Work Buffer
;Sets: DSTHI,DSTLO = Pointer to Destination File Name
;Returns: A = Error Code
;             $00 - Successful
;             $FF - Inapplicable
RENAME: LDA #$FF    ;Return Inapplicable
        RTS

