Subversion Repositories Spectranet

[/] [branches/] [gnubinutils/] [modules/] [streams/] [io.asm] - Rev 380

Go to most recent revision | Compare with Previous | Blame | View Log

;The MIT License
;
;Copyright (c) 2009 Dylan Smith
;
;Permission is hereby granted, free of charge, to any person obtaining a copy
;of this software and associated documentation files (the "Software"), to deal
;in the Software without restriction, including without limitation the rights
;to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
;copies of the Software, and to permit persons to whom the Software is
;furnished to do so, subject to the following conditions:
;
;The above copyright notice and this permission notice shall be included in
;all copies or substantial portions of the Software.
;
;THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
;IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
;FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
;AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
;LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
;OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
;THE SOFTWARE.
; IO routines for streams
.include        "spectranet.inc"
.include        "streamvars.inc"
.include        "zxsysvars.inc"
.include        "sysvars.inc"
.include        "zxrom.inc"
.include        "defs.inc"
.text
.globl J_modcall
J_modcall:
        call F_fetchpage        ; get our memory page
        bit 5, l                ; Control stream?
        jp nz, F_control
        bit 6, l                ; Listen stream?
        jp nz, F_ctrlstream
        bit 7, l                ; MSB set?
        jr nz, F_input          ; Call the input routine
        call F_feedbuffer       ; Pass writes to the buffer
        jp F_leave

;----------------------------------------------------------------------------
; F_input
; Process input to a stream.
.globl F_input
F_input:
        push hl
        ld hl, ZX_TV_FLAG       ; the mode is considered unchanged
        res 3, (hl)
        pop hl

        call F_findmetadata     ; get a pointer to metadata in IX
        ld d, (ix+STRM_WRITEBUF); get tx buffer number
        ld a, (ix+STRM_WRITEPTR); get tx buffer pointer
        and a                   ; if nonzero, flush the buffer
        call nz, .flush1

.isinkey1:
        push hl
        ld hl, (ZX_ERR_SP)      ; fetch the current ERR_SP
        ld e, (hl)
        inc hl
        ld d, (hl)
        and a
        ld hl, 0x107F           ; Compare with ED_ERROR
        sbc hl, de
        pop hl
        jp nz, .doinkey1

.input1:
        ld d, (ix+STRM_READBUF) ; get the read buffer number
        ld e, (ix+STRM_READPTR) ; and the pointer
        ld a, (ix+STRM_FD)      ; get the fd
        ld (v_asave), a         ; save it for the loop operation
        xor a                   ; Is the buffer pointer at 
        cp e                    ; the start of the buffer?
        jr z, .getdata1         ; Yes - so read more data from the network
        
        ld b, (ix+STRM_REMAINING) ; remaining bytes in buffer
        ex de, hl               ; and put the buffer pointer in HL
        jr .unloadloop1

.getdata1:
        ld a, (v_asave)         ; Get the descriptor
        ld bc, 255              ; read up to 255 chars
        ld l, (ix+STRM_FLAGS)   ; check flags bit
        bit BIT_ISFILE, l       ; is a file?
        jr nz, .readfromfile1
        bit BIT_ISDIR, l        ; is a directory?
        jr nz, .readdir1
        push de                 ; save bufptr
        call RECV
        pop hl                  ; retrieve bufptr into hl
.readdone1:
        jp c, .readerr1
.readdirdone1:
        ld b, c                 ; get the length returned into B for djnz

.unloadloop1:
        ld a, (hl)
        cp 0x0d                 ; This is how the Interface 1 does it...
        jr z, .checkformore1    ; Either a CR
        cp 0x0a
        jr z, .checkformore1    ; or a linefeed
        cp '"'          
        call z, .addquote1      ; Escape the " character to prevent error C
        push hl
        push bc
        rst CALLBAS
        defw 0x0F85             ; ROM ADD-CHAR subroutine
        pop bc
        pop hl
        inc l
        djnz .unloadloop1
        ld d, (ix+STRM_READBUF) ; reset everything to get the next set
        ld e, 0                 ; of bytes
        ld (ix+STRM_READPTR), e 
        ld (ix+STRM_REMAINING), e
        jr .getdata1            ; go get it

.addquote1:                     ; small routine to add an extra "
        push hl                 ; character to the input stream to
        push bc                 ; prevent C Nonsense in BASIC
        rst CALLBAS
        defw 0x0F85
        pop bc
        pop hl
        ld a, '"'
        ret

.readfromfile1:
        push de
        push ix
        call READ
        pop ix
        pop hl                  ; unloadloop uses hl as pointer
        jr .readdone1
.readdir1:
        ld de, INTERPWKSPC      ; %opendir does not allocate a buffer
        call READDIR            ; so use temporary workspace.
        jp c, .readerr1         ; 
        ld hl, INTERPWKSPC
.readdirloop1:
        ld a, (hl)              ; never have a partial read doing READDIR.
        and a                   ; End of string?
        jr z, .exitnopop1       ; Return to BASIC
        push hl
        rst CALLBAS             ; Feed INPUT
        defw 0x0F85
        pop hl
        inc hl
        jr .readdirloop1

.exitnopop1:
        ld a, 0x0d              ; BASIC expects this to end INPUT
        ld l, 0                 ; signal "munge the stack"
        scf
        jp F_leave

.checkformore1:
        dec b                   ; do what djnz would have done if it
        xor a                   ; had got to the end...
        cp b                    ; no more chars left?
        jr z, .cleardown1
        inc l                   ; next byte in the buffer
        ld a, (hl)              ; see what it is
        cp 0x0d
        jr z, .checklastcr1
        cp 0x0a
        jr z, .checklastcr1
.saveposition1:
        ld (ix+STRM_READPTR), l ; save the current position
        ld (ix+STRM_REMAINING), b       ; save bytes remaining
        jr .exitnopop1
.cleardown1:
        ld (ix+STRM_READPTR), 0 ; clear bufpos
        ld (ix+STRM_REMAINING), 0       ; clear bufsz
        jr .exitnopop1

.checklastcr1:
        dec b                   ; have we finally finished?
        xor a
        cp b
        jr z, .cleardown1       ; yes, just leave now.
        inc l                   ; otherwise advance the buffer
        jr .saveposition1       ; and save where we got to

.flush1:
        dec a                   ; make actual end position, not new char pos
        ld e, a                 ; make buffer LSB
        call F_flushbuffer
        ret

.doinkey1:
        ld a, (ix+STRM_FD)      ; get the socket
        ld (v_asave), a         ; save it
        call POLLFD             ; anything to receive?
        jr c, .readerr1         ; Read error?
        jr z, .nodata1          ; No hay nada

        ld a, (v_asave)         ; get the fd back
        ld de, INTERPWKSPC
        ld bc, 1                ; read one byte
        call RECV
        jr c, .readerr1
        ld a, (INTERPWKSPC)
        ld l, 1                 ; signal "don't munge the stack"
        scf                     ; signal 'character available'
        ret
        
.nodata1:
        xor a                   ; carry and zero reset - no data
        ld l, 1                 ; signal "don't munge the stack"
        jp F_leave

.readerrpop1:
        pop hl                  ; fix the stack
.readerr1:                      ; TODO error handling
        ld hl, (oneof_line)     ; see if we have a line number to go to
        ld a, h
        or l
        jr nz, .eof_jump1

        ld hl, INTERPWKSPC
        call ITOH8
        ld hl, INTERPWKSPC
        call PRINT42
        or 1                    ; reset carry, reset zero: EOF
        ld l, 1                 ; signal "don't munge the stack"
        jp F_leave

.eof_jump1:
        ld (ZX_NEWPPC), hl      ; set the line number
        xor a
        ld (ZX_NSPPC), a        ; and statement number to 0
        jp .exitnopop1          ; exit *without* error

;--------------------------------------------------------------------------
; F_ctrlstream
; Handle a control stream (read only) - at the moment, only listening
; sockets.
.globl F_ctrlstream
F_ctrlstream:
        ld a, l                 ; convert the function
        and 0x0F                ; number to the stream number
        rlca
        rlca
        rlca                    ; LSB of control stream metadata
        ld h, 0x10              ; MSB of metadata
        add a, 4                ; A=LSB of fd
        ld l, a
        ld a, (hl)              ; get the socket descriptor
        
        call POLLFD             ; Poll this fd and see if it's ready
        
        ld hl, ZX_TV_FLAG       ; the mode is considered unchanged
        res 3, (hl)

        jr z, .nodata2          ; Socket has no events

        ld a, '1'               ; indicate event
        ld l, 1                 ; signal "don't munge the stack"
        scf                     ; signal 'character available'
        ret
        
.nodata2:
        xor a                   ; carry and zero reset - no data
        ld l, 1                 ; signal "don't munge the stack"
        jp F_leave

;-------------------------------------------------------------------------
; F_findmetadata
; Finds the data block for the stream in L
.globl F_findmetadata
F_findmetadata:
        ld a, l                 ; convert the function number to the 
.globl F_findmetadata_a
F_findmetadata_a:               ; stream number.
        and 0x0F
        rlca
        rlca
        rlca                    ; A now = LSB
        ld h, 0x10              ; H now = MSB
        ld l, a
        push hl
        pop ix                  ; transfer the address to IX
        ret

;F_debugprint
;       ld (0x3200), ix
;       pop ix
;       inc ix
;       inc ix
;       push ix
;       push af
;       push bc
;       push de
;       push hl
;       ld h, (ix-1)
;       ld l, (ix-2)
;       call PRINT42
;       pop hl
;       pop de
;       pop bc
;       pop af
;       ld ix, (0x3200)
;       ret
;STR_CHECKFORMORE defb "checkformore\n",0
;STR_READDONE   defb "readdone\n",0
;STR_INPUT      defb "input\n",0
;STR_CLEARDOWN  defb "cleardown\n",0
;STR_SAVEPOS    defb "savepos\n",0


Go to most recent revision | Compare with Previous | Blame | View Log