]> git.sur5r.net Git - cc65/blob - libsrc/atari/open.s
ostype.o: new object file
[cc65] / libsrc / atari / open.s
1 ;
2 ; Christian Groessler, May-2000
3 ;
4 ; int open(const char *name,int flags,...);
5 ;
6
7 UCASE_FILENAME  = 1             ; comment it out if filename shouldn't be uppercased
8
9         .include "atari.inc"
10         .include "../common/fmode.inc"
11         .include "../common/errno.inc"
12         .export _open
13         .import fddecusage,newfd
14         .import __do_oserror,__seterrno,incsp4
15         .import ldaxysp,addysp,subysp
16         .import _strupr,__oserror
17         .importzp tmp4,tmp2,sp
18 .ifdef  UCASE_FILENAME
19         .importzp tmp3,ptr4
20 .endif
21
22 .proc   _open
23
24         cpy     #4              ; correct # of arguments (bytes)?
25         beq     parmok          ; parameter count ok
26         tya                     ; parm count < 4 shouldn't be needed to be checked
27         sec                     ;       (it generates a c compiler warning)
28         sbc     #4
29         tay
30         jsr     addysp          ; fix stack, throw away unused parameters
31
32 parmok: jsr     findfreeiocb
33         beq     iocbok          ; we found one
34
35         lda     #<EMFILE        ; "too many open files"
36         ldx     #>EMFILE
37 seterr: jsr     __seterrno
38         jsr     incsp4          ; clean up stack
39         lda     #$FF
40         tax
41         rts                     ; return -1
42
43         ; process the mode argument
44         ; @@@TODO: append not handled yet!
45
46 iocbok: stx     tmp4
47         jsr     clriocb         ; init with zero
48         ldy     #1
49         jsr     ldaxysp         ; get mode
50         ldx     tmp4
51         cmp     #O_RDONLY
52         bne     l1
53         lda     #OPNIN
54 set:    sta     ICAX1,x
55         bne     cont
56
57 l1:     cmp     #O_WRONLY
58         bne     l2
59         lda     #OPNOT
60         bne     set
61
62 l2:     ; O_RDWR
63         lda     #OPNOT|OPNIN
64         bne     set
65
66         ; process the filename argument
67
68 cont:   ldy     #3
69         jsr     ldaxysp
70
71 .ifdef  UCASE_FILENAME
72         ; we make sure that the filename doesn't contain lowercase letters
73         ; we copy the filename we got onto the stack, uppercase it and use this
74         ; one to open the iocb
75         ; we're using tmp3, ptr4
76
77         ; save the original pointer
78         sta     ptr4
79         stx     ptr4+1
80
81         ; now we need the length of the name
82         ldy     #0
83 loop:   lda     (ptr4),y
84         beq     str_end
85         cmp     #ATEOL          ; we also accept Atari EOF char as end of string
86         beq     str_end
87         iny
88         bne     loop            ; not longer than 255 chars (127 real limit)
89 toolong:lda     #<EINVAL        ; file name is too long
90         ldx     #>EINVAL
91         jmp     seterr
92
93 str_end:iny                     ; room for terminating zero
94         cpy     #128            ; we only can handle lenght < 128
95         bcs     toolong
96         sty     tmp3            ; save size
97         jsr     subysp          ; make room on the stack
98
99         ; copy filename to the temp. place on the stack
100         lda     #0              ; end-of-string
101         sta     (sp),y          ; Y still contains length + 1
102         dey
103 loop2:  lda     (ptr4),y
104         sta     (sp),y
105         dey
106         bpl     loop2           ; bpl: this way we only support a max. length of 127
107
108         ; uppercase the temp. filename
109         ldx     sp+1
110         lda     sp
111         jsr     _strupr
112
113         ; leave X and Y pointing to the modified filename
114         lda     sp
115         ldx     sp+1
116
117 .endif  ; defined UCASE_FILENAME
118
119         ldy     tmp4
120
121         ;AX - points to filename
122         ;Y  - iocb to use, if open needed
123         jsr     newfd           ; maybe we don't need to open and can reuse an iocb
124                                 ; returns fd num to use in tmp2, all regs unchanged
125         bcs     doopen          ; C set: open needed
126         lda     #0              ; clears N flag
127         beq     finish
128
129 doopen: sta     ICBAL,y
130         txa
131         sta     ICBAH,y
132         ldx     tmp4
133         lda     #OPEN
134         sta     ICCOM,x
135         jsr     CIOV
136
137         ; clean up the stack
138
139 finish: php
140         txa
141         pha
142         tya
143         pha
144
145 .ifdef  UCASE_FILENAME
146         ldy     tmp3            ; get size
147         jsr     addysp          ; free used space on the stack
148 .endif  ; defined UCASE_FILENAME
149
150         jsr     incsp4          ; clean up stack
151
152         pla
153         tay
154         pla
155         tax
156         plp
157
158         bpl     ok
159         jsr     fddecusage      ; decrement usage counter of fd as open failed
160         jmp     __do_oserror
161
162 ok:     lda     tmp2            ; get fd
163         ldx     #0
164         stx     __oserror
165         rts
166
167 .endproc
168
169
170 ; find a free iocb
171 ; no entry parameters
172 ; return ZF = 0/1 for not found/found
173 ;        index in X if found
174 ; all registers destroyed
175
176 .proc   findfreeiocb
177
178         ldx     #0
179         ldy     #$FF
180 loop:   tya
181         cmp     ICHID,x
182         beq     found
183         txa
184         clc
185         adc     #$10
186         tax
187         cmp     #$80
188         bcc     loop
189         inx                     ; return ZF cleared
190 found:  rts
191
192 .endproc
193
194
195 ; clear iocb except for ICHID field
196 ; expects X to be index to IOCB (0,$10,$20,etc.)
197 ; all registers destroyed
198
199 .proc   clriocb
200
201         inx                     ; don't clear ICHID
202         ldy     #15
203         lda     #0
204 loop:   sta     ICHID,x
205         dey
206         inx
207         bne     loop
208         rts
209
210 .endproc