]> git.sur5r.net Git - cc65/blobdiff - libsrc/atari/read.s
Merge pull request #48 from efornara/time_fix
[cc65] / libsrc / atari / read.s
index ef16ae8cef34c9d0907ca4410a08879fbadacc1e..acb415efd319330642a1ec87f8024f679fae5bfc 100644 (file)
 ;
-; Christian Groessler, Apr-2000
+; Christian Groessler, Jul-2005
 ;
 ; int __fastcall__ read(int fd,void *buf,int count)
 ;
 
-       .include "atari.inc"
-       .import __rwsetup,__do_oserror,__inviocb,__oserror
-       .export _read
-
-_read: jsr     __rwsetup       ; do common setup for read and write
-       beq     done            ; if size 0, it's a no-op
-       cpx     #$FF            ; invalid iocb?
-       beq     _inviocb
-       lda     #GETCHR         ; iocb command code
-       sta     ICCOM,x
-       jsr     CIOV            ; read it
-       bpl     done
-       cpy     #EOFERR         ; eof is treated specially
-       beq     done
-       jmp     __do_oserror    ; update errno
-
-done:  lda     ICBLL,x         ; buf len lo
-       pha                     ; save
-       lda     ICBLH,x         ; get buf len hi
-       tax                     ; to X
-       lda     #0
-       sta     __oserror       ; clear system dependend error code
-       pla                     ; get buf len lo
-       rts
+        .include "atari.inc"
+        .import __rwsetup,__do_oserror,__inviocb,__oserror
+        .export _read
+
+_read:  jsr     __rwsetup       ; do common setup for read and write
+        beq     done            ; if size 0, it's a no-op
+        cpx     #$FF            ; invalid iocb?
+        beq     _inviocb
+
+.ifdef  LINEBUF
+        ; E: should be always at IOCB #0
+        ; fixme: what happens when user closes and reopens stdin?
+        cpx     #0              ; E: handler (line oriented keyboard input)?
+        beq     do_line
+.endif
+
+        lda     #GETCHR         ; iocb command code
+        sta     ICCOM,x
+        jsr     CIOV            ; read it
+        bpl     done
+        cpy     #EOFERR         ; eof is treated specially
+        beq     done
+        jmp     __do_oserror    ; update errno
+
+done:   lda     ICBLL,x         ; buf len lo
+        pha                     ; save
+        lda     ICBLH,x         ; get buf len hi
+        tax                     ; to X
+okdone: lda     #0
+        sta     __oserror       ; clear system dependend error code
+        pla                     ; get buf len lo
+        rts
 
 _inviocb:
-       jmp     __inviocb
+        jmp     __inviocb
+
+
+.ifdef  LINEBUF
+
+; line oriented input
+
+        .segment        "EXTZP" : zeropage
+
+index:  .res    1               ; index into line buffer
+buflen: .res    1               ; length of used part of buffer
+cbs:    .res    1               ; current buffer size: buflen - index
+dataptr:.res    2               ; temp pointer to user buffer
+copylen:.res    1               ; temp counter
+
+        .bss
+
+linebuf:.res    LINEBUF         ; the line buffer
+
+        .code
+
+do_line:
+        lda     buflen          ; line buffer active?
+        bne     use_buf         ; yes, get data from there
+
+        ; save user buffer address & length
+        ; update IOCB to point to line buffer
+        lda     ICBLL,x
+        pha
+        lda     #LINEBUF
+        sta     ICBLL,x
+        ;--------
+        lda     ICBLH,x
+        pha
+        lda     #0
+        sta     ICBLH,x
+        ;--------
+        lda     ICBAL,x
+        pha
+        lda     #<linebuf
+        sta     ICBAL,x
+        ;--------
+        lda     ICBAH,x
+        pha
+        lda     #>linebuf
+        sta     ICBAH,x
+
+        lda     #GETREC
+        sta     ICCOM,x
+        jsr     CIOV            ; read input data
+        bpl     newbuf
+        cpy     #EOFERR         ; eof is treated specially
+        beq     newbuf
+        pla                     ; fix stack
+        pla
+        pla
+        pla
+        jmp     __do_oserror    ; update errno
+
+newbuf:
+        lda     ICBLL,x         ; get # of bytes read
+        sta     buflen
+        lda     #0
+        sta     index           ; fresh buffer
+
+        ; restore user buffer address & length
+        pla
+        sta     ICBAH,x
+        ;--------
+        pla
+        sta     ICBAL,x
+        ;--------
+        pla
+        sta     ICBLH,x
+        ;--------
+        pla
+        sta     ICBLL,x
+
+        ; fall into use_buf
+        lda     buflen
+
+; return bytes from line buffer
+; use buflen and index to access buffer
+; update index
+; use dataptr as a temporary pointer
+
+use_buf:
+        sec
+        sbc     index           ; size of unread data in the buffer
+        sta     cbs
+
+        lda     ICBLL,x         ; buf len lo
+        cmp     cbs             ; larger than buffer size?
+        beq     bl1
+        bcs     btsmall         ; yes, adjust length
+
+bl1:    lda     ICBLH,x         ; get buf len hi
+        bne     btsmall         ; buffer too small: buffer contents < read size
+
+; copy ICBLL,x bytes
+
+icbll_copy:
+
+        lda     ICBAL,x         ; buffer address
+        sta     dataptr
+        lda     ICBAH,x         ; buffer address
+        sta     dataptr+1
+        lda     ICBLL,x
+        sta     copylen
+        pha                     ; remember for return value
+        ldy     #0
+        ldx     index
+
+copy:   lda     linebuf,x
+        sta     (dataptr),y
+        iny
+        inx
+        dec     copylen
+        bne     copy
+
+        pla                     ; length
+        pha                     ; save length to return at okdone
+
+        clc
+        adc     index
+        sta     index
+        cmp     buflen          ; buffer used up?
+        bcc     c1              ; not yet
+
+        lda     #0
+        sta     buflen          ; indicate empty line buffer
+
+c1:     ldx     #0
+        jmp     okdone          ; return to caller
+
+btsmall:
+        lda     cbs
+        sta     ICBLL,x
+        bpl     icbll_copy
+
+.endif          ; .ifdef LINEBUF
+