]> git.sur5r.net Git - cc65/blob - libsrc/apple2/open.s
635b91e90f50d344129e53d8ba24e7fd4f50af10
[cc65] / libsrc / apple2 / open.s
1 ;
2 ; Oliver Schmidt, 30.12.2004
3 ;
4 ; int open (const char* name, int flags, ...);
5 ;
6 ; Be sure to keep the value priority of closeallfiles lower than that of
7 ; closeallstreams (which is the high level C file I/O counterpart and must be
8 ; called before closeallfiles).
9
10         .export         _open, closedirect, freebuffer
11         .destructor     closeallfiles, 17
12
13         .import         pushname, popname
14         .import         errnoexit, oserrexit
15         .import         _posix_memalign, _free
16         .import         addysp, incsp4, incaxy, pushax, popax
17
18         .include        "zeropage.inc"
19         .include        "errno.inc"
20         .include        "fcntl.inc"
21         .include        "mli.inc"
22         .include        "filedes.inc"
23
24 _open:
25         ; Throw away all parameters except name
26         ; and flags occupying together 4 bytes
27         dey
28         dey
29         dey
30         dey
31         jsr     addysp
32
33         ; Start with first fdtab slot
34         ldy     #$00
35
36         ; Check for free fdtab slot
37 :       lda     fdtab + FD::REF_NUM,y
38         beq     found
39
40         ; Advance to next fdtab slot
41         .assert .sizeof(FD) = 4, error
42         iny
43         iny
44         iny
45         iny
46
47         ; Check for end of fdtab
48         cpy     #MAX_FDS * .sizeof(FD)
49         bcc     :-
50
51         ; Load errno code
52         lda     #EMFILE
53
54         ; Cleanup stack
55 errno:  jsr     incsp4          ; Preserves A
56
57         ; Return errno
58         jmp     errnoexit
59
60         ; Save fdtab slot
61 found:  tya
62         pha
63
64         ; Alloc I/O buffer
65         lda     #<(fdtab + FD::BUFFER)
66         ldx     #>(fdtab + FD::BUFFER)
67         jsr     incaxy
68         jsr     pushax
69         lda     #$00
70         ldx     #>$0100
71         jsr     pushax          ; Preserves A
72         ldx     #>$0400
73         jsr     _posix_memalign
74         tay                     ; Save errno code
75
76         ; Restore fdtab slot
77         pla
78         sta     tmp2            ; Save fdtab slot
79
80         ; Check for error
81         tya                     ; Restore errno code
82         bne     errno
83
84         ; Get and save flags
85         jsr     popax
86         sta     tmp3
87
88         ; Get and push name
89         jsr     popax
90         jsr     pushname
91         bne     oserr1
92
93         ; Set pushed name
94         lda     sp
95         ldx     sp+1
96         sta     mliparam + MLI::OPEN::PATHNAME
97         stx     mliparam + MLI::OPEN::PATHNAME+1
98
99         ; Check for create flag
100         lda     tmp3            ; Restore flags
101         and     #O_CREAT
102         beq     open
103
104         ; PATHNAME already set
105         .assert MLI::CREATE::PATHNAME = MLI::OPEN::PATHNAME, error
106
107         ; Set all other parameters from template
108         ldx     #(MLI::CREATE::CREATE_TIME+1) - (MLI::CREATE::PATHNAME+1) - 1
109 :       lda     CREATE,x
110         sta     mliparam + MLI::CREATE::ACCESS,x
111         dex
112         bpl     :-
113
114         ; Create file
115         lda     #CREATE_CALL
116         ldx     #CREATE_COUNT
117         jsr     callmli
118         bcc     open
119
120         ; Check for ordinary errors
121         cmp     #$47            ; "Duplicate filename"
122         bne     oserr2
123
124         ; Check for exclusive flag
125         lda     tmp3            ; Restore flags
126         and     #O_EXCL
127         beq     open
128
129         lda     #$47            ; "Duplicate filename"
130
131         ; Cleanup name
132 oserr2: jsr     popname         ; Preserves A
133
134 oserr1: ldy     tmp2            ; Restore fdtab slot
135
136         ; Cleanup I/O buffer
137         pha                     ; Save oserror code
138         jsr     freebuffer
139         pla                     ; Restore oserror code
140
141         ; Return oserror
142         jmp     oserrexit
143
144 open:   ldy     tmp2            ; Restore fdtab slot
145
146         ; Set allocated I/O buffer
147         ldx     fdtab + FD::BUFFER+1,y
148         sta     mliparam + MLI::OPEN::IO_BUFFER         ; A = 0
149         stx     mliparam + MLI::OPEN::IO_BUFFER+1
150
151         ; Open file
152         lda     #OPEN_CALL
153         ldx     #OPEN_COUNT
154         jsr     callmli
155         bcs     oserr2
156
157         ; Get and save fd
158         ldx     mliparam + MLI::OPEN::REF_NUM
159         stx     tmp1            ; Save fd
160
161         ; Set flags and check for truncate flag
162         lda     tmp3            ; Restore flags
163         sta     fdtab + FD::FLAGS,y
164         and     #O_TRUNC
165         beq     done
166
167         ; Set fd and zero size
168         stx     mliparam + MLI::EOF::REF_NUM
169         ldx     #$02
170         lda     #$00
171 :       sta     mliparam + MLI::EOF::EOF,x
172         dex
173         bpl     :-
174
175         ; Set file size
176         lda     #SET_EOF_CALL
177         ldx     #EOF_COUNT
178         jsr     callmli
179         bcc     done
180
181         ; Cleanup file
182         pha                     ; Save oserror code
183         lda     tmp1            ; Restore fd
184         jsr     closedirect
185         pla                     ; Restore oserror code
186         bne     oserr2          ; Branch always
187
188         ; Store fd
189 done:   lda     tmp1            ; Restore fd
190         sta     fdtab + FD::REF_NUM,y
191
192         ; Convert fdtab slot to handle
193         .assert .sizeof(FD) = 4, error
194         tya
195         lsr
196         lsr
197
198         ; Cleanup name
199         jsr     popname         ; Preserves A
200
201         ; Return success
202         ldx     #$00
203         rts
204
205 freebuffer:
206         ; Free I/O buffer
207         lda     #$00
208         ldx     fdtab + FD::BUFFER+1,y
209         jmp     _free
210
211 closeallfiles:
212         ; All open files
213         lda     #$00
214
215 closedirect:
216         ; Set fd
217         sta     mliparam + MLI::CLOSE::REF_NUM
218
219         ; Call close
220         lda     #CLOSE_CALL
221         ldx     #CLOSE_COUNT
222         jmp     callmli
223
224         .rodata
225
226 CREATE: .byte   %11000011       ; ACCESS:       Standard full access
227         .byte   $06             ; FILE_TYPE:    Standard binary file
228         .word   $0000           ; AUX_TYPE:     Load address N/A
229         .byte   $01             ; STORAGE_TYPE: Standard seedling file
230         .word   $0000           ; CREATE_DATE:  Current date
231         .word   $0000           ; CREATE_TIME:  Current time