1;
2; Ullrich von Bassewitz, 16.11.2002
3;
4; File name handling for CBM file I/O
5;
6
7        .export         fnparse, fnparsename, fnset
8        .export         fnadd, fnaddmode, fncomplete, fndefunit
9        .export         fnunit, fnlen, fnisfile, fncmd, fnbuf
10
11        .import         curunit, __filetype
12        .importzp       ptr1, tmp1
13
14        .include        "ctype.inc"
15        .include        "cbm.inc"
16
17
18;------------------------------------------------------------------------------
19; fnparsename: Parse a filename (without drive spec) passed in in ptr1 and y.
20
21.proc   fnparsename
22
23        lda     #0
24        sta     tmp1            ; Remember length of name
25
26nameloop:
27        lda     (ptr1),y        ; Get next char from filename
28        beq     namedone        ; Jump if end of name reached
29
30; Check the maximum length, store the character
31
32        ldx     tmp1
33        cpx     #16             ; Maximum length reached?
34        bcs     invalidname
35        lda     (ptr1),y        ; Reload char
36        jsr     fnadd           ; Add character to name
37        iny                     ; Next char from name
38        inc     tmp1            ; Increment length of name
39        bne     nameloop        ; Branch always
40
41; Invalid file name
42
43invalidname:
44        lda     #33             ; Invalid file name
45
46; Done, we've successfully parsed the name.
47
48namedone:
49        rts
50
51.endproc
52
53
54;------------------------------------------------------------------------------
55; fnparse: Parse a full filename passed in in a/x. Will set the following
56; variables:
57;
58;       fnlen   -> length of filename
59;       fnbuf   -> filename including drive spec
60;       fnunit  -> unit from spec or default unit
61;
62; Returns an error code in A or zero if all is ok.
63
64.proc   fnparse
65
66        sta     ptr1
67        stx     ptr1+1          ; Save pointer to name
68
69; For now we will always use the default unit
70
71        jsr     fndefunit
72
73; Check the name for a drive spec
74
75        ldy     #0
76        lda     (ptr1),y
77        cmp     #'0'
78        beq     digit
79        cmp     #'1'
80        bne     nodrive
81
82digit:  sta     fnbuf+0
83        iny
84        lda     (ptr1),y
85        cmp     #':'
86        bne     nodrive
87
88; We found a drive spec, copy it to the buffer
89
90        sta     fnbuf+1
91        iny                     ; Skip colon
92        bne     drivedone       ; Branch always
93
94; We did not find a drive spec, always use drive zero
95
96nodrive:
97        lda     #'0'
98        sta     fnbuf+0
99        lda     #':'
100        sta     fnbuf+1
101        ldy     #$00            ; Reposition to start of name
102
103; Drive spec done. We do now have a drive spec in the buffer.
104
105drivedone:
106        lda     #2              ; Length of drive spec
107        sta     fnlen
108
109; Assume this is a standard file on disk
110
111        sta     fnisfile
112
113; Special treatment for directory. If the file name is "$", things are
114; actually different: $ is directory for unit 0, $0 dito, $1 is directory
115; for unit 1. For simplicity, we won't check anything else if the first
116; character of the file name is '$'.
117
118        lda     (ptr1),y        ; Get first character
119        cmp     #'$'            ;
120        bne     fnparsename
121
122; Juggle stuff
123
124        ldx     fnbuf+0         ; unit
125        stx     fnbuf+1
126        sta     fnbuf+0
127
128; Add the file mask
129
130        lda     #':'
131        sta     fnbuf+2
132        lda     #'*'
133        sta     fnbuf+3
134        lda     #4
135        sta     fnlen
136
137; No need to check the name. Length is already 2
138
139        lda     #0              ; ok flag
140        sta     fnisfile        ; This is not a real file
141        rts
142
143.endproc
144
145;--------------------------------------------------------------------------
146; fndefunit: Use the default unit
147
148.proc   fndefunit
149
150        lda     curunit
151        sta     fnunit
152        rts
153
154.endproc
155
156;--------------------------------------------------------------------------
157; fnset: Tell the kernal about the file name
158
159.proc   fnset
160
161        lda     fnlen
162        ldx     #<fnbuf
163        ldy     #>fnbuf
164        jmp     SETNAM
165
166.endproc
167
168;--------------------------------------------------------------------------
169; fncomplete: Complete a filename by adding ",t,m" where t is the file type
170; and m is the access mode passed in in the A register
171;
172; fnaddmode: Add ",m" to a filename, where "m" is passed in A
173
174fncomplete:
175        pha                     ; Save mode
176        lda     __filetype
177        jsr     fnaddmode       ; Add the type
178        pla
179fnaddmode:
180        pha
181        lda     #','
182        jsr     fnadd
183        pla
184
185fnadd:  ldx     fnlen
186        inc     fnlen
187        sta     fnbuf,x
188        rts
189
190;--------------------------------------------------------------------------
191; Data
192
193.bss
194
195fnunit:         .res    1
196fnlen:          .res    1
197fnisfile:       .res    1       ; Flags standard file (as opposed to "$")
198
199.data
200fncmd:          .byte   's'     ; Use as scratch command
201fnbuf:          .res    35      ; Either 0:0123456789012345,t,m
202                                ; Or     0:0123456789012345=0123456789012345
203