cc65/libsrc/cbm/filename.s

203 lines
4.9 KiB
ArmAsm

;
; Ullrich von Bassewitz, 16.11.2002
;
; File name handling for CBM file I/O
;
.export fnparse, fnparsename, fnset
.export fnadd, fnaddmode, fncomplete, fndefunit
.export fnunit, fnlen, fnisfile, fncmd, fnbuf
.import curunit, __filetype
.importzp ptr1, tmp1
.include "ctype.inc"
.include "cbm.inc"
;------------------------------------------------------------------------------
; 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 will always use the default unit
jsr fndefunit
; Check the name for a drive spec
ldy #0
lda (ptr1),y
cmp #'0'
beq digit
cmp #'1'
bne nodrive
digit: sta fnbuf+0
iny
lda (ptr1),y
cmp #':'
bne nodrive
; We found a drive spec, copy it to the buffer
sta fnbuf+1
iny ; Skip colon
bne drivedone ; Branch always
; We did not find a drive spec, always use drive zero
nodrive:
lda #'0'
sta fnbuf+0
lda #':'
sta fnbuf+1
ldy #$00 ; Reposition to start of name
; Drive spec done. We do now have a drive spec in the buffer.
drivedone:
lda #2 ; Length of drive spec
sta fnlen
; Assume this is a standard file on disk
sta fnisfile
; 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 '$'.
lda (ptr1),y ; Get first character
cmp #'$' ;
bne fnparsename
; Juggle stuff
ldx fnbuf+0 ; unit
stx fnbuf+1
sta fnbuf+0
; Add the file mask
lda #':'
sta fnbuf+2
lda #'*'
sta fnbuf+3
lda #4
sta fnlen
; 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
.proc fnset
lda fnlen
ldx #<fnbuf
ldy #>fnbuf
jmp SETNAM
.endproc
;--------------------------------------------------------------------------
; 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
;
; 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
fnisfile: .res 1 ; Flags standard file (as opposed to "$")
.data
fncmd: .byte 's' ; Use as scratch command
fnbuf: .res 35 ; Either 0:0123456789012345,t,m
; Or 0:0123456789012345=0123456789012345