diff --git a/libsrc/atari/lseek.s b/libsrc/atari/lseek.s index 27bc1ad65..259d89ab2 100644 --- a/libsrc/atari/lseek.s +++ b/libsrc/atari/lseek.s @@ -1,5 +1,5 @@ ; -; Christian Groessler, August 2000 +; Christian Groessler, May 2002 ; ; this file provides the lseek() function ; @@ -8,19 +8,21 @@ .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+1 + ldx #>ENOSYS + jsr __seterrno ldx #0 stx __oserror dex @@ -29,4 +31,184 @@ 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 +