; File name handling for CBM file I/O
;
- .export fnparse, fnset, fncomplete
- .export fnunit, fnlen, fncmd, fnbuf
+ .export fnparse, fnparsename, fnset
+ .export fnadd, fnaddmode, fncomplete, fndefunit
+ .export fnunit, fnlen, fnisfile, fncmd, fnbuf
.import SETNAM
- .import __curunit, __filetype
- .importzp ptr1
+ .import curunit, __filetype
+ .importzp ptr1, tmp1
.include "ctype.inc"
-;--------------------------------------------------------------------------
-; fnparse: Parse a filename passed in in a/x. Will set the following
+;------------------------------------------------------------------------------
+; fnparsename: Parse a filename (without drive spec) passed in in ptr1 and y.
+
+.proc fnparsename
+
+ lda #0
+ sta tmp1 ; Remember length of name
+
+nameloop:
+ lda (ptr1),y ; Get next char from filename
+ beq namedone ; Jump if end of name reached
+
+; Check the maximum length, store the character
+
+ ldx tmp1
+ cpx #16 ; Maximum length reached?
+ bcs invalidname
+ lda (ptr1),y ; Reload char
+ jsr fnadd ; Add character to name
+ iny ; Next char from name
+ inc tmp1 ; Increment length of name
+ bne nameloop ; Branch always
+
+; Invalid file name
+
+invalidname:
+ lda #33 ; Invalid file name
+
+; Done, we've successfully parsed the name.
+
+namedone:
+ rts
+
+.endproc
+
+
+;------------------------------------------------------------------------------
+; fnparse: Parse a full filename passed in in a/x. Will set the following
; variables:
;
; fnlen -> length of filename
; fnbuf -> filename including drive spec
; fnunit -> unit from spec or default unit
-
+;
+; Returns an error code in A or zero if all is ok.
.proc fnparse
sta ptr1
stx ptr1+1 ; Save pointer to name
-; For now we're always using the default unit
+; For now we will always use the default unit
- lda __curunit
- sta fnunit
+ jsr fndefunit
; Check the name for a drive spec
ldy #0
lda (ptr1),y
- sta fnbuf+0
cmp #'0'
beq digit
cmp #'1'
bne nodrive
-digit: iny
+digit: sta fnbuf+0
+ iny
lda (ptr1),y
cmp #':'
bne nodrive
sta fnbuf+1
ldy #$00 ; Reposition to start of name
-; Drive spec done. Copy the name into the file name buffer. Check that all
-; file name characters are valid and that the maximum length is not exceeded.
+; Drive spec done. We do now have a drive spec in the buffer.
drivedone:
lda #2 ; Length of drive spec
sta fnlen
-nameloop:
- lda (ptr1),y ; Get next char from filename
- beq namedone ; Jump if end of name reached
+; Assume this is a standard file on disk
-; Check for valid chars in the file name. We allow letters, digits, plus some
-; additional chars from a table.
+ sta fnisfile
- ldx #fncharcount-1
-namecheck:
- cmp fnchars,x
- beq nameok
- dex
- bpl namecheck
- tax
- lda __ctype,x
- and #CT_ALNUM
- beq invalidname
+; Special treatment for directory. If the file name is "$", things are
+; actually different: $ is directory for unit 0, $0 dito, $1 is directory
+; for unit 1. For simplicity, we won't check anything else if the first
+; character of the file name is '$'.
-; Check the maximum length, store the character
+ lda (ptr1),y ; Get first character
+ cmp #'$' ;
+ bne fnparsename
-nameok: ldx fnlen
- cpx #16 ; Maximum length reached?
- bcs invalidname
- lda (ptr1),y ; Reload char
- sta fnbuf,x ; Store into buffer
- inc fnlen ; Count characters
- iny ; Next char from name
- bne nameloop ; Branch always
+; Juggle stuff
-; Invalid file name
+ ldx fnbuf+0 ; unit
+ stx fnbuf+1
+ sta fnbuf+0
-invalidname:
- lda #33 ; Invalid file name
+; Add the file mask
-; Done, we've successfully parsed the name.
+ lda #':'
+ sta fnbuf+2
+ lda #'*'
+ sta fnbuf+3
+ lda #4
+ sta fnlen
-namedone:
+; No need to check the name. Length is already 2
+
+ lda #0 ; ok flag
+ sta fnisfile ; This is not a real file
rts
.endproc
+;--------------------------------------------------------------------------
+; fndefunit: Use the default unit
+
+.proc fndefunit
+
+ lda curunit
+ sta fnunit
+ rts
+
+.endproc
;--------------------------------------------------------------------------
; fnset: Tell the kernal about the file name
;--------------------------------------------------------------------------
; fncomplete: Complete a filename by adding ",t,m" where t is the file type
; and m is the access mode passed in in the A register
-
-.proc fncomplete
-
- pha ; Save mode
- ldx fnlen
- lda #','
- sta fnbuf,x
- inx
- lda __filetype
- sta fnbuf,x
- inx
- lda #','
- sta fnbuf,x
- inx
- pla
- sta fnbuf,x
- inx
- stx fnlen
- rts
-
-.endproc
+;
+; fnaddmode: Add ",m" to a filename, where "m" is passed in A
+
+fncomplete:
+ pha ; Save mode
+ lda __filetype
+ jsr fnaddmode ; Add the type
+ pla
+fnaddmode:
+ pha
+ lda #','
+ jsr fnadd
+ pla
+
+fnadd: ldx fnlen
+ inc fnlen
+ sta fnbuf,x
+ rts
;--------------------------------------------------------------------------
; Data
.bss
-fnunit: .res 1
-fnlen: .res 1
+fnunit: .res 1
+fnlen: .res 1
+fnisfile: .res 1 ; Flags standard file (as opposed to "$")
.data
-fncmd: .byte 's' ; Use as scratch command
-fnbuf: .res 22 ; 0:0123456789012345,t,m
-
-.rodata
-; Characters that are ok in filenames besides digits and letters
-fnchars:.byte ".,-_+()"
-fncharcount = *-fnchars
-
-
+fncmd: .byte 's' ; Use as scratch command
+fnbuf: .res 35 ; Either 0:0123456789012345,t,m
+ ; Or 0:0123456789012345=0123456789012345