]> git.sur5r.net Git - cc65/blob - libsrc/atari/fdtable.s
Remove the ",r" spec
[cc65] / libsrc / atari / fdtable.s
1 ;
2 ; Christian Groessler, May-2000
3 ;
4 ; fd indirection table & helper functions
5 ;
6
7         .include "atari.inc"
8         .include "fd.inc"
9         .importzp tmp1,tmp2,tmp3,ptr4,sp
10         .import fd_table,fd_index
11         .import fdt_to_fdi
12         .export clriocb
13         .export fdtoiocb
14         .export fdtoiocb_down
15         .export findfreeiocb
16         .export fddecusage
17         .export newfd
18
19         .code
20
21 ; gets fd in ax, decrements usage counter
22 ; return iocb index in X
23 ; return N bit set for invalid fd
24 ; return Z bit set if last user
25 ; all registers destroyed
26 .proc   fdtoiocb_down
27
28         cpx     #0
29         bne     inval
30         cmp     #MAX_FD_INDEX
31         bcs     inval
32         tax
33         lda     fd_index,x              ; get index
34         tay
35         lda     #$ff
36         sta     fd_index,x              ; clear entry
37         tya
38         asl     a                       ; create index into fd table
39         asl     a
40         tax
41         lda     #$ff
42         cmp     fd_table+ft_iocb,x      ; entry in use?
43         beq     inval                   ; no, return error
44         lda     fd_table+ft_usa,x       ; get usage counter
45         beq     ok_notlast              ; 0?
46         sec
47         sbc     #1                      ; decr usage counter
48         sta     fd_table+ft_usa,x
49 retiocb:php
50         txa
51         tay
52         lda     fd_table+ft_iocb,x      ; get iocb
53         tax
54         plp
55         bne     cont
56         php
57         lda     #$ff
58         sta     fd_table+ft_iocb,y      ; clear table entry
59         plp
60 cont:   rts
61
62 ok_notlast:
63         lda     #1                      ; clears Z
64         jmp     retiocb
65
66 .endproc        ; fdtoiocb_down
67
68 inval:  ldx     #$ff                    ; sets N
69         rts
70
71
72 ; clear iocb except for ICHID field
73 ; expects X to be index to IOCB (0,$10,$20,etc.)
74 ; all registers destroyed
75
76 .proc   clriocb
77
78         inx                     ; don't clear ICHID
79         ldy     #15
80         lda     #0
81 loop:   sta     ICHID,x
82         inx
83         dey
84         bne     loop
85         rts
86
87 .endproc
88
89
90 ; gets fd in ax
91 ; return iocb index in A, fd_table index in X
92 ; return N bit set for invalid fd
93 ; all registers destroyed
94 .proc   fdtoiocb
95
96         cpx     #0
97         bne     inval
98         cmp     #MAX_FD_INDEX
99         bcs     inval
100         tax
101         lda     fd_index,x
102         asl     a                       ; create index into fd table
103         asl     a
104         tax
105         lda     #$ff
106         cmp     fd_table+ft_iocb,x      ; entry in use?
107         beq     inval                   ; no, return error
108         lda     fd_table+ft_usa,x       ; get usage counter
109         beq     inval                   ; 0? should not happen
110         lda     fd_table+ft_iocb,x      ; get iocb
111         rts
112
113 .endproc        ; fdtoiocb
114
115 ; find a free iocb
116 ; no entry parameters
117 ; return ZF = 0/1 for not found/found
118 ;        index in X if found
119 ; all registers destroyed
120
121 .proc   findfreeiocb
122
123         ldx     #0
124         ldy     #$FF
125 loop:   tya
126         cmp     ICHID,x
127         beq     found
128         txa
129         clc
130         adc     #$10
131         tax
132         cmp     #$80
133         bcc     loop
134         inx                     ; return ZF cleared
135 found:  rts
136
137 .endproc        ; findfreeiocb
138
139 ; decrements usage counter for fd
140 ; if 0 reached, it's marked as unused
141 ; get fd index in tmp2
142 ; Y register preserved
143 .proc   fddecusage
144
145         lda     tmp2                    ; get fd
146         cmp     #MAX_FD_INDEX
147         bcs     ret                     ; invalid index, do nothing
148         tax
149         lda     fd_index,x
150         pha
151         lda     #$ff
152         sta     fd_index,x
153         pla
154         asl     a                       ; create index into fd table
155         asl     a
156         tax
157         lda     #$ff
158         cmp     fd_table+ft_iocb,x      ; entry in use?
159         beq     ret                     ; no, do nothing
160         lda     fd_table+ft_usa,x       ; get usage counter
161         beq     ret                     ; 0? should not happen
162         sec
163         sbc     #1                      ; decrement by one
164         sta     fd_table+ft_usa,x
165         bne     ret                     ; not 0
166         lda     #$ff                    ; 0, table entry unused now
167         sta     fd_table+ft_iocb,x      ; clear table entry
168 ret:    rts
169
170 .endproc        ; fddecusage
171
172 ; newfd
173 ;
174 ; called from open() function
175 ; finds a fd to use for an open request
176 ; checks whether it's a device or file (file: characters follow the ':')
177 ; files always get an exclusive slot
178 ; for devices it is checked whether the device is already open, and if yes,
179 ; a link to this open device is returned
180 ;
181 ; Calling parameters:
182 ;       tmp3 - length of filename + 1
183 ;       AX   - points to filename
184 ;       Y    - iocb to use (if we need a new open)
185 ; Return parameters:
186 ;       tmp2 - fd num ($ff and C=0 in case of error - no free slot)
187 ;       C    - 0/1 for no open needed/open should be performed
188 ; all registers preserved!
189
190 ; local variables:
191 ;   AX     - 0 (A-0,X-1)
192 ;   Y      - 2
193 ;   ptr4   - 3,4  (backup)
194 ;   devnum - 5
195
196         .bss
197 loc_Y:          .res    1
198 loc_ptr4_l:     .res    1
199 loc_ptr4_h:     .res    1
200 loc_tmp1:       .res    1
201 loc_devnum:     .res    1
202 loc_size:       .res    1
203
204         .code
205
206 .proc   newfd
207
208         pha
209         txa
210         pha
211         tya
212         pha
213
214         ldx     #0
215         stx     loc_devnum
216         lda     tmp1
217         sta     loc_tmp1
218         stx     tmp1            ; init tmp1
219         stx     tmp2            ; init tmp2
220         lda     ptr4+1
221         sta     loc_ptr4_h
222         lda     ptr4
223         sta     loc_ptr4_l
224         pla
225         sta     loc_Y
226         pla
227         sta     ptr4+1
228         pla
229         sta     ptr4
230
231         ; ptr4 points to filename
232
233         ldy     #1
234         lda     #':'
235         cmp     (ptr4),y        ; "X:"
236         beq     colon1
237         iny
238         cmp     (ptr4),y        ; "Xn:"
239         beq     colon2
240
241         ; no colon there!? OK, then we use a fresh iocb....
242         ; return error here? no, the subsequent open call should fail
243
244 do_open_nd:     ; do open and don't remember device
245         lda     #2
246         sta     tmp1
247 do_open:lda     tmp1
248         ora     #1
249         sta     tmp1            ; set flag to return 'open needed' : C = 1
250         ldx     #ft_iocb
251         ldy     #$ff
252 srchfree:
253         tya
254         cmp     fd_table,x
255         beq     freefnd         ; found a free slot
256         txa
257         clc
258         adc     #ft_entrylen
259         tax
260         cmp     #(MAX_FD_VAL*4)+ft_iocb ; end of table reached?
261         bcc     srchfree
262
263 ; error: no free slot found
264 noslot: ldx     #0
265         stx     tmp1            ; return with C = 0
266         dex
267         stx     tmp2            ; iocb: $ff marks error
268         jmp     finish
269
270 ; found a free slot
271 freefnd:txa
272         sec
273         sbc     #ft_iocb        ; normalize
274         tax
275         lsr     a
276         lsr     a
277         sta     tmp2            ; return fd
278         lda     #2
279         bit     tmp1            ; remember device?
280         beq     l1              ; yes
281         lda     #0              ; no, put 0 in field
282         beq     l2
283
284 l1:     ldy     #0
285         lda     (sp),y                  ; get device
286 l2:     sta     fd_table+ft_dev,x       ; set device
287         lda     #1
288         sta     fd_table+ft_usa,x       ; set usage counter
289         lda     loc_Y
290         sta     fd_table+ft_iocb,x      ; set iocb index
291         lda     loc_devnum
292         and     #7                      ; only 3 bits
293         sta     fd_table+ft_flag,x
294         lda     tmp2
295         jsr     fdt_to_fdi              ; get new index
296         bcs     noslot                  ; no one available
297         ;cmp    #$ff                    ; no one available
298         ;beq    noslot  ;@@@ cleanup needed
299         sta     tmp2                    ; return index
300         jmp     finish
301
302 ; string in "Xn:xxx" format
303 colon2: dey
304         lda     (ptr4),y        ; get device number
305         sec
306         sbc     #'0'
307         and     #7
308         sta     loc_devnum
309         sta     tmp2            ; save it for speed later here also
310         lda     #4              ; max. length if only  device + number ("Xn:")
311         cmp     tmp3
312         bcc     do_open_nd      ; string is longer -> contains filename
313         bcs     check_dev       ; handle device only string
314
315 ; string in "X:xxx" format
316 colon1: lda     #3              ; max. length if device only ("X:")
317         cmp     tmp3
318         bcc     do_open_nd      ; string is longer -> contains filename
319
320 ; get device and search it in fd table
321 check_dev:
322         ldy     #0
323         lda     (ptr4),y        ; get device id
324         tay
325         ldx     #(MAX_FD_VAL*4) - ft_entrylen
326 srchdev:lda     #$ff
327         cmp     fd_table+ft_iocb,x      ; is entry valid?
328         beq     srch2                   ; no, skip this entry
329         tya
330         cmp     fd_table+ft_dev,x
331         beq     fnddev
332 srch2:  txa
333         sec
334         sbc     #ft_entrylen+1
335         tax
336         bpl     srchdev
337
338 ; not found, open new iocb
339         jmp     do_open
340
341 ; helper for branch out of range
342 noslot1:jmp     noslot
343
344 ; found device in table, check device number (e.g R0 - R3)
345 fnddev: lda     fd_table+ft_flag,x
346         and     #7
347         cmp     tmp2                    ; contains devnum
348         bne     srch2                   ; different device numbers
349
350 ; found existing open iocb with same device
351         txa
352         lsr     a
353         lsr     a
354         sta     tmp2
355         inc     fd_table+ft_usa,x       ; increment usage counter
356         jsr     fdt_to_fdi              ; get new index
357         bcs     noslot1                 ; no one available
358         sta     tmp2                    ; return index
359
360 ; clean up and go home
361 finish: lda     ptr4
362         pha
363         lda     ptr4+1
364         pha
365         lda     loc_Y
366         pha
367         lda     tmp1
368         pha
369         lda     loc_tmp1
370         sta     tmp1
371         pla
372         lsr     a                       ; set C as needed
373
374         pla
375         tay
376         pla
377         tax
378         pla
379         rts
380
381 .endproc        ; newfd
382