]> git.sur5r.net Git - cc65/blob - libsrc/apple2/open.s
POSIX file I/O by Oliver Schmidt
[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         __aligned_malloc, _free
16         .import         addysp, incsp4, 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         .if     .sizeof(FD) = 4
41
42         ; Advance to next fdtab slot
43         iny
44         iny
45         iny
46         iny
47
48         .else
49         .error  "Assertion failed"
50         .endif
51
52         ; Check for end of fdtab
53         cpy     #MAX_FDS * .sizeof(FD)
54         bcc     :-
55
56         ; Load errno codes
57         lda     #ENOMEM ^ EMFILE
58 enomem: eor     #ENOMEM
59
60         ; Cleanup stack
61         jsr     incsp4          ; Preserves A
62
63         ; Return errno
64         jmp     errnoexit
65
66         ; Save fdtab slot
67 found:  tya
68         pha
69
70         ; Alloc I/O buffer
71         lda     #$00
72         ldx     #>$0400
73         jsr     pushax          ; Preserves A
74         ldx     #>$0100
75         jsr     __aligned_malloc
76
77         ; Restore fdtab slot
78         pla
79         tay
80
81         ; Get and check I/O buffer high byte
82         txa
83         beq     enomem
84
85         ; Set I/O buffer high byte (low byte remains zero)
86         sta     fdtab + FD::BUFFER+1,y
87
88         sty     tmp2            ; Save fdtab slot
89
90         ; Get and save flags
91         jsr     popax
92         sta     tmp3
93
94         ; Get and push name
95         jsr     popax
96         jsr     pushname
97         bne     oserr1
98
99         ; Set pushed name
100         lda     sp
101         ldx     sp+1
102         sta     mliparam + MLI::OPEN::PATHNAME
103         stx     mliparam + MLI::OPEN::PATHNAME+1
104
105         ; Check for create flag
106         lda     tmp3            ; Restore flags
107         and     #O_CREAT
108         beq     open
109
110         .if     MLI::CREATE::PATHNAME = MLI::OPEN::PATHNAME
111
112         ; PATHNAME already set
113
114         .else
115         .error  "Assertion failed"
116         .endif
117
118         ; Set all other parameters from template
119         ldx     #(MLI::CREATE::CREATE_TIME+1) - (MLI::CREATE::PATHNAME+1) - 1
120 :       lda     CREATE,x
121         sta     mliparam + MLI::CREATE::ACCESS,x
122         dex
123         bpl     :-
124
125         ; Create file
126         lda     #CREATE_CALL
127         ldx     #CREATE_COUNT
128         jsr     callmli
129         bcc     open
130
131         ; Check for ordinary errors
132         cmp     #$47            ; "Duplicate filename"
133         bne     oserr2
134
135         ; Check for exclusive flag
136         lda     tmp3            ; Restore flags
137         and     #O_EXCL
138         beq     open
139
140         lda     #$47            ; "Duplicate filename"
141         
142         ; Cleanup name
143 oserr2: jsr     popname         ; Preserves A
144
145 oserr1: ldy     tmp2            ; Restore fdtab slot
146
147         ; Cleanup I/O buffer
148         pha                     ; Save oserror code
149         jsr     freebuffer
150         pla                     ; Restore oserror code
151         
152         ; Return oserror
153         jmp     oserrexit
154
155 open:   ldy     tmp2            ; Restore fdtab slot
156
157         ; Set allocated I/O buffer
158         ldx     fdtab + FD::BUFFER+1,y
159         sta     mliparam + MLI::OPEN::IO_BUFFER         ; A = 0
160         stx     mliparam + MLI::OPEN::IO_BUFFER+1
161
162         ; Open file
163         lda     #OPEN_CALL
164         ldx     #OPEN_COUNT
165         jsr     callmli
166         bcs     oserr2
167
168         ; Get and save fd
169         ldx     mliparam + MLI::OPEN::REF_NUM
170         stx     tmp1            ; Save fd
171
172         ; Set flags and check for truncate flag
173         lda     tmp3            ; Restore flags
174         sta     fdtab + FD::FLAGS,y
175         and     #O_TRUNC
176         beq     done
177
178         ; Set fd and zero size
179         stx     mliparam + MLI::EOF::REF_NUM
180         ldx     #$02
181         lda     #$00
182 :       sta     mliparam + MLI::EOF::EOF,x
183         dex
184         bpl     :-
185
186         ; Set file size
187         lda     #SET_EOF_CALL
188         ldx     #EOF_COUNT
189         jsr     callmli
190         bcc     done
191
192         ; Cleanup file
193         pha                     ; Save oserror code
194         lda     tmp1            ; Restore fd
195         jsr     closedirect
196         pla                     ; Restore oserror code
197         bne     oserr2          ; Branch always
198
199         ; Store fd
200 done:   lda     tmp1            ; Restore fd
201         sta     fdtab + FD::REF_NUM,y
202
203         .if     .sizeof(FD) = 4
204
205         ; Convert fdtab slot to handle
206         tya
207         lsr
208         lsr
209
210         .else
211         .error  "Assertion failed"
212         .endif
213
214         ; Cleanup name
215         jsr     popname         ; Preserves A
216         
217         ; Return success
218         ldx     #$00
219         rts
220
221 freebuffer:
222         ; Free I/O buffer
223         lda     #$00
224         ldx     fdtab + FD::BUFFER+1,y
225         jmp     _free
226
227 closeallfiles:
228         ; All open files
229         lda     #$00
230
231 closedirect:
232         ; Set fd
233         sta     mliparam + MLI::CLOSE::REF_NUM
234
235         ; Call close
236         lda     #CLOSE_CALL
237         ldx     #CLOSE_COUNT
238         jmp     callmli
239
240         .rodata
241
242 CREATE: .byte   %11000011       ; ACCESS:       Standard full access
243         .byte   $06             ; FILE_TYPE:    Standard binary file
244         .word   $0000           ; AUX_TYPE:     Load address N/A
245         .byte   $01             ; STORAGE_TYPE: Standard seedling file
246         .word   $0000           ; CREATE_DATE:  Current date
247         .word   $0000           ; CREATE_TIME:  Current time