1
0
mirror of https://github.com/cc65/cc65.git synced 2024-12-28 22:30:12 +00:00
cc65/libsrc/atari/read.s
cpg 61ca515494 small optimization; fix line buffered read of length 0
git-svn-id: svn://svn.cc65.org/cc65/trunk@3065 b7a2c559-68d2-44c3-8de9-860c34a00d81
2004-06-01 20:25:44 +00:00

181 lines
2.9 KiB
ArmAsm

;
; Christian Groessler, Jun-2004
;
; 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
.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
.ifdef LINEBUF
; line oriented input
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
.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
.endif ; .ifdef LINEBUF