; a program to receive disk files from a remote computer
;
cpm     equ     0
prtmsg  equ     9
open    equ     15
close   equ     16
write   equ     21
create  equ     22
setdma  equ     26
sys     equ     0005h
fcb     equ     005ch
bios    equ     0e800h
pfm     equ     0f000h
const   equ     bios+6
conin   equ     bios+9
conout  equ     bios+12
siost   equ     pfm+18
sioin   equ     pfm+21
sioout  equ     pfm+24
cr      equ     0dh
lf      equ     0ah
dollar  equ     24h
ctlq    equ     11h
ctls    equ     13h
ctlz    equ     1ah
;
        org     100h
start   lxi     sp,stack
        lxi     d,fcb
        mvi     c,open
        call    sys
        cpi     4
        jnc     make            ; check if file exists
        lxi     d,exists        ; file already exist
        mvi     c,prtmsg
        call    sys
        jmp     cpm
;
make    lxi     d,fcb           ; file does not exist
        mvi     c,create
        call    sys
        cpi     4
        jc      setpt           ; check if space on disk
        lxi     d,cannot        ; no space left
        mvi     c,prtmsg
        call    sys
        jmp     cpm
;
setpt   lxi     h,buffer        ; OK to write file
        mvi     b,0
        push    b               ; save character count
        push    h               ; save buffer address
        pop     d
        push    d
        mvi     c,setdma
        call    sys
        lxi     d,rdcom         ; prompt for read command
        mvi     c,prtmsg
        call    sys
comand  call    conin           ; get input characters and
        cpi     cr              ;  loop until carriage return
        jz      com1
        push    psw
        mov     c,a
        call    conout          ; echo characters to console
        pop     psw
        call    sioout          ;  and send to remote computer
        jmp     comand
com1    mvi     c,cr            ; echo carriage return and
        call    conout
        mvi     c,lf            ;  line feed
        call    conout
        mvi     a,cr            ; send carriage return and
        call    sioout
strd    call    sioin
        cpi     lf              ;  wait for echo of line feed
        jnz     strd
;
; read file from remote computer
;
firstr  call    siost           ; this part of the program
        jz      firstr          ;   ignores a carriage return
        call    sioin           ;   if it is the first
        cpi     cr              ;   character received
        jnz     read0
read    call    const           ; any character typed on keyboard
        jnz     endrd           ;  will end program
        call    siost           ; check if character from SIO
        jz      read            ;   and loop if not
        call    sioin           ; get character
read0   push    psw
        mov     c,a
        call    conout          ; echo it to console
        pop     psw
        pop     h               ; and put it in buffer
        mov     m,a
        inx     h
        pop     b
        inr     b
        mov     a,b
        cpi     128             ; check for full buffer
        jnz     read2
        mvi     a,ctls          ; send control-S if full
        call    sioout
        call    stall           ; wait for last characters
        lxi     d,fcb
        mvi     c,write         ; write buffer
        call    sys
        cpi     0               ; check if write is successful
        jz      restor          ; write is OK
        lxi     d,eom
        mvi     c,prtmsg
        call    sys
        lxi     d,fcb
        mvi     c,close
        call    sys
        jmp     cpm
;
; move overflow characters into buffer
;
restor  lda     tmpcnt
        lxi     h,buffer
        cpi     0               ; check if any overflow
        jz      read1           ; no overflow
        mov     b,a
        push    h
        lxi     h,tmp
loop    mov     c,m             ; move characters to buffer
        inx     h
        shld    tmpadd          ; save tmp address
        pop     h               ; get buffer address
        mov     m,c             ; put character in buffer
        inx     h
        push    h               ; save buffer address
        lhld    tmpadd          ; get tmp address
        dcr     b
        jnz     loop            ; loop if any characters left
        pop     h
        lda     tmpcnt
;
; start reading again
;
read1   push    psw
        push    h
        mvi     a,ctlq          ; send control-Q
        call    sioout
        jmp     read
;
read2   push    b
        push    h
        jmp     read
;
; end read
;    remove last two characters (the prompt from the remote
;    computer) if possible and flush buffer
;
endrd   pop     h
        pop     b
        mov     a,b
        cpi     0
        jz      end1a
        dcx     h
        dcr     b
        mov     a,b
        cpi     0
        jz      end1a
        dcx     h
        dcr     b
;
; fill buffer with control z and write buffer
;
end1a   mvi     a,ctlz
        mov     m,a
        inx     h
        inr     b
        mov     a,b
        cpi     128             ; is buffer full?
        jnz     end1a           ; no
        lxi     d,fcb           ; yes
        mvi     c,write         ;  so write buffer
        call    sys
        cpi     0
        jz      end2
        lxi     d,eom
        mvi     c,prtmsg
        call    sys
end2    lxi     d,endp
        mvi     c,prtmsg
        call    sys
        lxi     d,fcb
        mvi     c,close         ; close file
        call    sys
        jmp     cpm
;
; wait routine to get characters sent after control-S
;
stall   mvi     a,0
        sta     tmpcnt
        lxi     h,tmp
        shld    tmpadd
        mvi     a,40
s1      call    t500
        push    psw
        call    getch
        pop     psw
        dcr     a
        jnz     s1
        ret
;
; inner delay loop
;
t500    push    psw
        mvi     a,255
t500a   xthl
        xthl
        dcr     a
        jnz     t500a
        pop     psw
        ret
;
; get overflow characters and put in "tmp"
;
getch   call    siost
        rz
        call    sioin
        lhld    tmpadd
        mov     m,a
        inx     h
        shld    tmpadd
        mov     c,a
        call    conout
        lda     tmpcnt
        inr     a
        sta     tmpcnt
        ret
;
tmpcnt  ds      1
tmpadd  ds      2
tmp     ds      32
cannot  db      'cannot create file$'
exists  db      'file already exists$'
rdcom   db      'enter file read command  $'
eom     db      'disk out of free space  $'
endp    db      'copy completed$'
        ds      64
stack   ds      1
buffer  ds      1
;
        end     start




