mirror of
https://github.com/cc65/cc65.git
synced 2024-12-23 04:30:10 +00:00
183 lines
4.5 KiB
ArmAsm
183 lines
4.5 KiB
ArmAsm
;
|
|
; 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
|
|
|
|
.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
|
|
|
|
.segment "EXTZP" : zeropage
|
|
|
|
index: .res 1 ; index into line buffer
|
|
cbs: .res 1 ; current buffer size: buflen - index
|
|
dataptr:.res 2 ; temp pointer to user buffer
|
|
copylen:.res 1 ; temp counter
|
|
|
|
.bss
|
|
|
|
buflen: .res 1 ; length of used part of buffer
|
|
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
|
|
|