;
-; Christian Groessler, August 2000
+; Christian Groessler, May 2002
;
; this file provides the lseek() function
;
.export _lseek
- .import incsp6,__errno,__oserror
- .importzp sreg
+ .import incsp6,__oserror
+ .import __inviocb,ldax0sp,ldaxysp,fdtoiocb
+ .import __seterrno
+ .import fd_table
+ .importzp sreg,ptr1,ptr2,ptr3,ptr4
+ .importzp tmp1,tmp2,tmp3
.include "atari.inc"
.include "errno.inc"
+ .include "fd.inc"
-.proc _lseek
-
-; dummy implementation, return -1 and ENOSYS errno value
- jsr incsp6
+; seeking not supported, return -1 and ENOSYS errno value
+no_supp:jsr incsp6
lda #<ENOSYS
- sta __errno
- lda #>ENOSYS
- sta __errno+1
+ ldx #>ENOSYS
+ jsr __seterrno
ldx #0
stx __oserror
dex
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 #38 ; 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 #39 ; get file size
+ sta ICCOM,x
+ jsr CIOV
+ bpl l01
+
+; error returned from CIO
+xxerr: sty __oserror
+ bmi iocberr
+
+; 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 #38 ; 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 #37 ;POINT
+ sta ICCOM,x
+ jsr CIOV
+ bpl ret
+ bmi xxerr
+
.endproc
+
+; check, whether seeking is supported
+; tmp3: iocb
+; X: index into fd_table
+;
+; We check, whether CIO function 39 (get file size) returns OK.
+; If yes, NOTE and POINT work with real file offset. @@@ check out more DOS versions @@@
+; 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
+unkn: txa
+ pha
+ ldx tmp3 ; iocb to use
+ lda #39 ; get file size
+ sta ICCOM,x
+ jsr CIOV
+ bmi notsupp ; error code ? should be 168 (invalid command)
+
+; seeking is supported on this DOS/Disk combination
+
+ pla
+ tax
+ lda #8
+ ora fd_table+ft_flag,x
+ sta fd_table+ft_flag,x
+supp: sec
+ rts
+
+notsupp:pla
+ clc
+ rts
+