]> git.sur5r.net Git - cc65/blob - libsrc/atari/lseek.s
Don't add a mode when opening files for reading
[cc65] / libsrc / atari / lseek.s
1 ;
2 ; Christian Groessler, May 2002
3 ;
4 ; this file provides the lseek() function
5 ;
6 ; off_t __fastcall__ lseek(int fd, off_t offset, int whence);
7 ;
8
9
10         .export         _lseek
11         .import         incsp6,__oserror
12         .import         __inviocb,ldax0sp,ldaxysp,fdtoiocb
13         .import         __seterrno,__dos_type
14         .import         fd_table
15         .importzp       sreg,ptr1,ptr2,ptr3,ptr4
16         .importzp       tmp1,tmp2,tmp3
17         .include        "atari.inc"
18         .include        "errno.inc"
19         .include        "fd.inc"
20
21 ; seeking not supported, return -1 and ENOSYS errno value
22 no_supp:jsr     incsp6
23         lda     #<ENOSYS
24         ldx     #>ENOSYS
25         jsr     __seterrno
26         ldx     #0
27         stx     __oserror
28         dex
29         txa
30         sta     sreg
31         sta     sreg+1
32         rts
33
34 parmerr:
35 iocberr:jsr     incsp6
36         ldx     #255
37         stx     sreg
38         stx     sreg+1
39         jmp     __inviocb
40
41
42 ; lseek() entry point
43
44 .proc   _lseek
45
46         cpx     #0              ; sanity check whence parameter
47         bne     parmerr
48         cmp     #3              ; valid values are 0..2
49         bcs     parmerr
50         sta     tmp1            ; remember whence
51
52         ldy     #5
53         jsr     ldaxysp         ; get fd
54         jsr     fdtoiocb        ; convert to iocb in A, fd_table index in X
55         bmi     iocberr
56         sta     tmp3            ; remember iocb
57
58         jsr     chk_supp        ; check, whether seeking is supported by DOS/Disk
59         bcc     no_supp
60
61         ldx     tmp1            ; whence
62         beq     cur
63         dex
64         beq     end
65
66 ; SEEK_SET
67         dex
68         stx     ptr3
69         stx     ptr3+1
70         stx     ptr4
71         stx     ptr4+1
72         beq     cont
73
74 ; SEEK_CUR
75 cur:    ldx     tmp3
76         lda     #38             ; NOTE
77         sta     ICCOM,x
78         jsr     CIOV            ; read it
79         bmi     xxerr
80 l01:    lda     ICAX3,x         ; low byte of position
81         sta     ptr3
82         lda     ICAX4,x         ; med byte of position
83         sta     ptr3+1
84         lda     ICAX5,x         ; high byte of position
85         sta     ptr4
86         lda     #0
87         sta     ptr4+1
88         beq     cont
89
90 ; SEEK_END
91 end:    ldx     tmp3
92         lda     #39             ; get file size
93         sta     ICCOM,x
94         jsr     CIOV
95         bpl     l01
96
97 ; error returned from CIO
98 xxerr:  sty     __oserror
99         bmi     iocberr
100
101 ; check for offset 0, SEEK_CUR (get current position)
102 cont:   ldy     #3
103         jsr     ldaxysp         ; get upper word
104         sta     ptr1
105         stx     ptr1+1
106         jsr     ldax0sp         ; get lower word
107         stx     tmp2
108         ora     tmp2
109         ora     ptr1
110         ora     ptr1+1
111         bne     seek
112         lda     tmp1            ; whence (0 = SEEK_CUR)
113         bne     seek
114
115 ; offset 0, SEEK_CUR: return current fp
116 ret:    jsr     incsp6
117
118         lda     ptr4+1
119         sta     sreg+1
120         lda     ptr4
121         sta     sreg
122         ldx     ptr3+1
123         lda     ptr3
124
125 .if 0
126         ; return exactly the position DOS has
127         ldx     tmp3
128         lda     #38             ; NOTE
129         sta     ICCOM,x
130         jsr     CIOV            ; read it
131         bmi     xxerr
132         lda     #0
133         sta     sreg+1
134         lda     ICAX5,x         ; high byte of position
135         sta     sreg
136         lda     ICAX3,x         ; low byte of position
137         pha
138         lda     ICAX4,x         ; med byte of position
139         tax
140         pla
141 .endif
142
143         rts
144
145 parmerr1: jmp   parmerr
146
147 ; we have to call POINT
148 seek:   jsr     ldax0sp         ; get lower word of new offset
149         clc
150         adc     ptr3
151         sta     ptr3
152         txa
153         adc     ptr3+1
154         sta     ptr3+1
155         lda     ptr1
156         adc     ptr4
157         sta     ptr4
158         lda     ptr1+1
159         adc     ptr4+1
160         sta     ptr4+1
161         bne     parmerr1        ; resulting value too large
162
163         ldx     tmp3            ; IOCB
164         lda     ptr3
165         sta     ICAX3,x
166         lda     ptr3+1
167         sta     ICAX4,x
168         lda     ptr4
169         sta     ICAX5,x
170         lda     #37             ;POINT
171         sta     ICCOM,x
172         jsr     CIOV
173         bpl     ret
174         bmi     xxerr
175
176 .endproc
177
178 ; check, whether seeking is supported
179 ; tmp3:         iocb
180 ; X:            index into fd_table
181 ;
182 ; On non-SpartaDOS, seeking is not supported.
183 ; We check, whether CIO function 39 (get file size) returns OK.
184 ; If yes, NOTE and POINT work with real file offset.
185 ; If not, NOTE and POINT work with the standard ScNum/Offset values.
186 ; We remember a successful check in fd_table.ft_flag, bit 3.
187
188 chk_supp:
189         lda     fd_table+ft_flag,x
190         and     #8
191         bne     supp
192
193 ; do the test
194         lda     __dos_type
195         cmp     #SPARTADOS
196         bne     ns1
197         txa
198         pha
199         lda     DOS+1           ; get SpartaDOS version
200         cmp     #$40
201         bcs     supp1           ; SD-X (ver 4.xx) supports seeking on all disks
202         ldx     tmp3            ; iocb to use
203         lda     #39             ; get file size
204         sta     ICCOM,x
205         jsr     CIOV
206         bmi     notsupp         ; error code ? should be 168 (invalid command)
207
208 ; seeking is supported on this DOS/Disk combination
209
210 supp1:  pla
211         tax
212         lda     #8
213         ora     fd_table+ft_flag,x
214         sta     fd_table+ft_flag,x
215 supp:   sec
216         rts
217
218 notsupp:pla
219 ns1:    clc
220         rts
221