; ; 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 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