File: lseek.s

package info (click to toggle)
cc65 2.19-2
  • links: PTS
  • area: main
  • in suites: forky, sid, trixie
  • size: 20,268 kB
  • sloc: ansic: 117,151; asm: 66,339; pascal: 4,248; makefile: 1,009; perl: 607
file content (226 lines) | stat: -rw-r--r-- 5,479 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
;
; Christian Groessler, May 2002
;
; this file provides the lseek() function
;
; off_t __fastcall__ lseek(int fd, off_t offset, int whence);
;


        .export         _lseek
        .import         incsp6,__oserror
        .import         __inviocb,ldax0sp,ldaxysp,fdtoiocb
        .import         __dos_type
        .import         fd_table
        .importzp       sreg,ptr1,ptr2,ptr3,ptr4
        .importzp       tmp1,tmp2,tmp3
        .include        "atari.inc"
        .include        "errno.inc"
        .include        "fd.inc"

; seeking not supported, return -1 and ENOSYS errno value
no_supp:jsr     incsp6
        lda     #<ENOSYS
        jsr     __directerrno   ; returns with $FFFF in AX
        sta     sreg
        sta     sreg+1
        rts

parmerr:
iocberr:jsr     incsp6
        ldx     #255
        stx     sreg
        stx     sreg+1
        jmp     __inviocb


; lseek() entry point

.proc   _lseek

        cpx     #0              ; sanity check whence parameter
        bne     parmerr
        cmp     #3              ; valid values are 0..2
        bcs     parmerr
        sta     tmp1            ; remember whence

        ldy     #5
        jsr     ldaxysp         ; get fd
        jsr     fdtoiocb        ; convert to iocb in A, fd_table index in X
        bmi     iocberr
        sta     tmp3            ; remember iocb

        jsr     chk_supp        ; check, whether seeking is supported by DOS/Disk
        bcc     no_supp

        ldx     tmp1            ; whence
        beq     cur
        dex
        beq     end

; SEEK_SET
        dex
        stx     ptr3
        stx     ptr3+1
        stx     ptr4
        stx     ptr4+1
        beq     cont

; SEEK_CUR
cur:    ldx     tmp3
        lda     #NOTE
        sta     ICCOM,x
        jsr     CIOV            ; read it
        bmi     xxerr
l01:    lda     ICAX3,x         ; low byte of position
        sta     ptr3
        lda     ICAX4,x         ; med byte of position
        sta     ptr3+1
        lda     ICAX5,x         ; high byte of position
        sta     ptr4
        lda     #0
        sta     ptr4+1
        beq     cont

; SEEK_END
end:    ldx     tmp3
        lda     #GETFL
        sta     ICCOM,x
        jsr     CIOV
        bpl     l01

; error returned from CIO
xxerr:  tya
        pha
        jsr     incsp6
        pla
        jsr     __mappederrno   ; returns with $FFFF in AX
        sta     sreg
        sta     sreg+1
        rts

; check for offset 0, SEEK_CUR (get current position)
cont:   ldy     #3
        jsr     ldaxysp         ; get upper word
        sta     ptr1
        stx     ptr1+1
        jsr     ldax0sp         ; get lower word
        stx     tmp2
        ora     tmp2
        ora     ptr1
        ora     ptr1+1
        bne     seek
        lda     tmp1            ; whence (0 = SEEK_CUR)
        bne     seek

; offset 0, SEEK_CUR: return current fp
ret:    jsr     incsp6

        lda     ptr4+1
        sta     sreg+1
        lda     ptr4
        sta     sreg
        ldx     ptr3+1
        lda     ptr3

.if 0
        ; return exactly the position DOS has
        ldx     tmp3
        lda     #NOTE
        sta     ICCOM,x
        jsr     CIOV            ; read it
        bmi     xxerr
        lda     #0
        sta     sreg+1
        lda     ICAX5,x         ; high byte of position
        sta     sreg
        lda     ICAX3,x         ; low byte of position
        pha
        lda     ICAX4,x         ; med byte of position
        tax
        pla
.endif

        rts

parmerr1: jmp   parmerr

; we have to call POINT
seek:   jsr     ldax0sp         ; get lower word of new offset
        clc
        adc     ptr3
        sta     ptr3
        txa
        adc     ptr3+1
        sta     ptr3+1
        lda     ptr1
        adc     ptr4
        sta     ptr4
        lda     ptr1+1
        adc     ptr4+1
        sta     ptr4+1
        bne     parmerr1        ; resulting value too large

        ldx     tmp3            ; IOCB
        lda     ptr3
        sta     ICAX3,x
        lda     ptr3+1
        sta     ICAX4,x
        lda     ptr4
        sta     ICAX5,x
        lda     #POINT
        sta     ICCOM,x
        jsr     CIOV
        bpl     ret
        bmi     xxerr

.endproc

; check whether seeking is supported
; tmp3:         iocb
; X:            index into fd_table
;
; On non-SpartaDOS, seeking is not supported.
; We check, whether CIO function 39 (get file size) returns OK.
; If yes, NOTE and POINT work with real file offset.
; If not, NOTE and POINT work with the standard ScNum/Offset values.
; We remember a successful check in fd_table.ft_flag, bit 3.

chk_supp:
        lda     fd_table+ft_flag,x
        and     #8
        bne     supp

; do the test
        lda     __dos_type
        cmp     #SPARTADOS
        beq     :+
        cmp     #BWDOS
        beq     :+
        cmp     #REALDOS
        bne     ns1
:       txa
        pha
        lda     DOS+1           ; get SpartaDOS version
        cmp     #$40
        bcs     supp1           ; SD-X (ver 4.xx) supports seeking on all disks
        ldx     tmp3            ; iocb to use
        lda     #GETFL
        sta     ICCOM,x
        jsr     CIOV
        bmi     notsupp         ; error code ? should be 168 (invalid command)

; seeking is supported on this DOS/Disk combination

supp1:  pla
        tax
        lda     #8
        ora     fd_table+ft_flag,x
        sta     fd_table+ft_flag,x
supp:   sec
        rts

notsupp:pla
ns1:    clc
        rts