; begin kermit4.asm [18]

; Here is the bulk of the file I/O.  Good luck.
;       File routines
 
;       Output the chars in a packet.

FILEIO	PROC	NEAR 	

ptchr:  mov temp1,ax            ; Save the size.
        mov bx,offset data      ; Beginning of received packet data.
        mov outpnt,bx           ; Remember where we are.
        mov ch,rquote		; Quote char.
ptchr1: dec temp1               ; Decrement # of chars in packet.
	jnl pt1
        jmp rskp                ; Return successfully if done.
pt1:    dec chrcnt              ; Decrement number of chars in dta.
        jns ptchr2              ; Continue if space left.
        call outbuf             ; Output it if full.
         jmp r                  ;  Error return if disk is full.
ptchr2: mov bx,outpnt           ; Get position in output buffer.
        mov ah,[bx]                     ; Grab a char.
        inc bx
        mov outpnt,bx           ; and bump pointer.
        cmp ah,ch               ; Is it the quote char?
        jne ptchr4              ; If not proceed.
        mov ah,[bx]                     ; Get the quoted character
        inc bx
        mov outpnt,bx           ; and bump pointer.
        dec temp1               ; Decrement # of chars in packet.
        mov dh,ah               ; Save the char.
        and ah,80H                      ; Turn off all but the parity bit.
        mov dl,ah               ; Save the parity bit.
        mov ah,dh                       ; Get the char.
        and ah,7FH                      ; Turn off the parity bit.
        cmp ah,ch               ; Is it the quote char?
        jz ptchr3               ; If so just go write it out.
        mov ah,dh                       ; Get the char.
        add ah,40H                      ; Make it a control char again.
        and ah,7FH                      ; Modulo 128.
ptchr3: or ah,dl                ; Or in the parity bit.
ptchr4: mov bx,bufpnt           ; Destination buffer.
        mov [bx],ah                     ; Store it.
        inc bx
        mov bufpnt,bx           ; Update the pointer
        jmp ptchr1              ; and loop to next char.


        ; output the buffer, reset bufpnt and chrcnt
 
outbuf: push bx
        mov ah,writef           ; The write code.
        mov dx,offset fcb
        int dos		         ; Write the record.
        pop bx
        cmp al,0                        ; Successful.
        jz outbf1
	cmp al,01
	jz outbf0
	call erpos
	mov ah,prstr
	mov dx,offset erms17	; Record length exceeds dta.
	int dos
	ret
outbf0: call erpos
	mov ah,prstr            ; Tell about it.
        mov dx,offset erms11    ; Disk full error.
        int dos
        ret
outbf1: mov bx,offset buff      ; Addr for beginning.
        mov bufpnt,bx           ; Store addr for beginning.
        mov ax,bufsiz-1         ; Buffer size.
        mov chrcnt,ax           ; Number of chars left.
        jmp rskp


;       Get the chars from the file.
 
gtchr:  mov ch,squote           ; Keep quote char in c.
        mov ah,filflg           ; Get the file flag.
        cmp ah,0                        ; Is there anything in the DMA?
        jz gtchr0               ; Yup, proceed.
        mov cl,0                ; No chars yet.
        call inbuf
         jmp gtceof             ; No more chars, go return EOF.
gtchr0: mov al,spsiz            ; Get the maximum packet size.
        sub al,5                ; Subtract the overhead.
        mov ah,0
        mov temp1,ax            ; Number of chars we're to get.
        mov bx,offset filbuf            ; Where to put the data.
        mov cbfptr,bx           ; Remember where we are.
        mov cl,0                ; No chars.
gtchr1: dec temp1               ; Decrement the number of chars left.
        jns gtchr2              ; Go on if there is more than one left.
        mov al,cl                       ; Return the count in A.
	mov ah,0
        jmp rskp
gtchr2: mov ax,chrcnt
        dec ax
        jl gtchr3
        mov chrcnt,ax
        jmp gtchr4
gtchr3: call inbuf              ; Get another buffer full.
         jmp gtceof
	cmp chrcnt,0
	jne gtchr4
	sub cl,2		; Don't count controllified Z.
	mov al,cl
	mov ah,0
	jmp rskp
gtchr4: mov bx,bufpnt           ; Position in DMA.
        mov ah,[bx]                     ; Get a char from the file.
        inc bx
        mov bufpnt,bx
        mov dh,ah               ; Save the char.
        and ah,80H                      ; Turn off all but parity.
        mov dl,ah               ; Save the parity bit.
        mov ah,dh                       ; Restore the char.
        and ah,7FH                      ; Turn off the parity.
        cmp ah,' '                      ; Compare to a space.
        jl gtchr5               ; If less then its a control char, handle it.
        cmp ah,del                      ; Is the char a delete?
        jz gtchr5               ; Go quote it.
        cmp ah,ch               ; Is it the quote char?
        jne gtchr8              ; If not proceed.
        dec temp1               ; Decrement the char total remaining.
        mov bx,cbfptr           ; Position in character buffer.
        mov [bx],ah                     ; Put the char in the buffer.
        inc bx
        mov cbfptr,bx
        inc cl                  ; Increment the char count.
        jmp gtchr8
gtchr5: or ah,dl                ; Turn on the parity bit.
        cmp ah,('Z'-100O)               ; Is it a ^Z?
        jne gtchr7              ; If not just proceed.
        mov ah,eoflag           ; EOF flag set?
        cmp ah,0
        jz gtchr6               ; If not just go on.
        mov bx,bufpnt
        mov ax,chrcnt
        mov dh,al               ; Get number of chars left in DMA.
gtch51: dec dh
        mov ah,dh
        jns gtch52              ; Any chars left?
        mov chrcnt,0            ; If not, say so.
        mov al,cl                       ; Return the count in A.
	mov ah,0
        jmp rskp
gtch52: mov ah,[bx]                     ; Get the next char.
        inc bx                  ; Move the pointer.
        cmp ah,('Z'-100O)               ; Is it a ^Z?
        jz gtch51               ; If so see if they rest are.
 
gtchr6: mov ah,('Z'-100O)       ; Restore the ^Z.
gtchr7: xchg ah,al
        mov ah,0
        mov temp2,ax            ; Save the char.
        dec temp1               ; Decrement char counter.
        mov bx,cbfptr           ; Position in character buffer.
        mov [bx],ch                     ; Put the quote in the buffer.
        inc bx
        mov cbfptr,bx
        inc cl                  ; Increment the char count.
        mov ax,temp2            ; Get the control char back.
        xchg al,ah
        add ah,40H                      ; Make the non-control.
        and ah,7fH                      ; Modulo 200 octal.
gtchr8: mov bx,cbfptr           ; Position in character buffer.
        or ah,dl                ; Or in the parity bit.
        mov [bx],ah                     ; Put the char in the buffer.
        inc bx
        mov cbfptr,bx
        inc cl                  ; Increment the char count.
        jmp gtchr1              ; Go around again.
 
gtceof: cmp cl,0		; Had we gotten any data?
	je gteof0		; Nope.
	mov al,cl
	mov ah,0
	jmp rskp
gteof0: mov ah,0FFH             ; Get a minus one.
        ret


inbuf:  mov ah,eoflag           ; Have we reached the end?
        cmp ah,0
        jz inbuf0
        ret                     ; Return if set.
inbuf0: push bx                 
	push cx
	mov bx,offset buff      ; Set the r/w buffer pointer.
        mov bufpnt,bx
        mov ah,readf            ; Read a record.
        mov dx,offset fcb
        int dos
	mov cx,filsiz
	cmp cx,0		; Check for 128 chars or less left.
	jne inbuf1		; Still have data left.
	mov ax,ds
	mov es,ax
	mov si,offset filsiz+2
	mov di,offset bufhex
	cmps filsiz+2,es:bufhex
	ja inbuf1		; More than 128 chars.
	mov eoflag,0FFH		; Set End-of-file.
	mov cx,filsiz+2
	mov chrcnt,cx		; Return proper number of chars.
        mov filflg,0		; Buffer not empty.
	pop cx
	pop bx
	jmp rskp
inbuf1:	sub filsiz+2,80H	; Sent another 128 chars.
	sbb filsiz,0		; Account for the doubleword.
	mov al,80H		; Use as counter for number of chars read.
	pop cx
	pop bx
	cmp filflg,0		; Ever used DMS?
	jnz inbf21		; Nope, then don't change count.
	dec al			; Fix boundary error.
inbf21: mov ah,0                ; Zero the flag (buffer not empty).
	mov chrcnt,ax		; Number of chars read from file.
        mov filflg,0		; Buffer not empty.
	jmp rskp

getfil: mov ah,0FFH
        mov filflg,ah           ; Nothing in the DMA.
        mov ax,0
        mov eoflag,ah           ; Not the end of file.
        mov bx,offset fcb+0CH
        mov [bx],ax             ; Zero the current block number.
        mov bx,offset fcb+0EH
        mov [bx],ax             ; Ditto for Lrecl.
        mov bx,offset fcb+20H
        mov [bx],ah             ; Zero the current record (of block).
	inc bx
	mov [bx],ax		; Same for record (of file). 
	mov bx,offset fcb+23H
	mov [bx],ax
        mov ah,openf            ; Open the file.
        mov dx,offset fcb
        int dos
	mov bx,offset fcb+18	; File size in bytes (hi order word).
	mov di,offset filsiz	; Where to put the info. 
	mov ax,[bx]
	mov [di],ax
	mov bx,offset fcb+16	; Lo order word.
	mov ax,[bx]
	mov 2[di],ax
	sub filsiz+2,1		; Don't count the ^Z.
	sbb filsiz,0
        jmp rskp


gtnfil: cmp wldflg,0		; Was there a "*"?		[7 start]
	je gtn5			; Nope.
	mov bx,offset cpfcb	; Get FCB from last check for file.  
	mov di,offset fcb	; Copy to FCB.
	mov cl,37		; Size of FCB.
	call fcbcpy
gtn2:	mov ah,snext
	mov dx,offset fcb	; More files?
	int dos
	cmp al,0FFH
	je gtn5
	mov bx,offset fcb
	mov di,offset cpfcb
	mov cl,37
	call fcbcpy		; Copy from FCB.
	mov di,offset fcb+1	; Get name of next file to send.
	mov bx,offset buff+1
	mov cl,11
	call fcbcpy
	call getfil		; Initialize
	 jmp r
	jmp rskp			
gtn5:	mov wldflg,0		; Reset wild card flag.
	ret			 			;  [7 end]


;       Get the file name (including host to micro translation)
 
gofil:  mov bx,offset data      ; Get the address of the file name.
        mov datptr,bx           ; Store the address.
        mov bx,offset fcb+1            ; Address of the FCB.
        mov fcbptr,bx           ; Save it.
        mov ax,0
        mov temp1,ax            ; Initialize the char count.
        mov temp2,ax
	mov si,offset fcb
        mov [si],ah             ; Set the drive to default to current.
        mov ch,' '
gofil1: mov [bx],ch                     ; Blank the FCB.
        inc bx
        inc ah
        cmp ah,0BH                      ; Twelve?
        jl gofil1
gofil2: mov bx,datptr           ; Get the NAME field.
        mov ah,[bx]
        inc bx
        mov datptr,bx
        cmp ah,'.'                      ; Seperator?
        jne gofil3
        mov bx,offset fcb+9H
        mov fcbptr,bx
        mov ax,temp1
        mov temp2,ax
        mov temp1,9H
        jmp gofil6
gofil3: cmp ah,0                        ; Trailing null?
        jz gofil7               ; Then we're done.
        mov bx,fcbptr
        mov [bx],ah
        inc bx
        mov fcbptr,bx
        mov ax,temp1            ; Get the char count.
        inc ax
        mov temp1,ax
        cmp ax,8H                       ; Are we finished with this field?
        jl gofil2
gofil4: mov temp2,ax
        mov bx,datptr
        mov ah,[bx]
        inc bx
        mov datptr,bx
        cmp ah,0
        jz gofil7
        cmp ah,'.'                      ; Is this the terminator?
        jne gofil4              ; Go until we find it.
gofil6: mov bx,datptr           ; Get the TYPE field.
        mov ah,[bx]
        inc bx
        mov datptr,bx
        cmp ah,0                        ; Trailing null?
        jz gofil7               ; Then we're done.
        mov bx,fcbptr
        mov [bx],ah
        inc bx
        mov fcbptr,bx
        inc temp1               ; Increment char count.
        cmp temp1,0CH                   ; Are we finished with this field?
        jl gofil6
gofil7: mov bx,datptr
	mov ah,'$'
        mov [bx],ah             ; Put in a dollar sign for printing.
	call clrfln
        mov ah,prstr            ; Print the file name.
        mov dx,offset data
        int dos
        mov ah,flwflg           ; Is file warning on?
        cmp ah,0
	jnz gf7x
        jmp gofil9              ; If not, just proceed.
gf7x:   mov ah,openf            ; See if the file exists.
        mov dx,offset fcb
        int dos
        cmp al,0FFH             ; Does it exist?
	jnz gf8x
        jmp gofil9               ; If not create it.
gf8x:	
IF ibmpc
	mov ah,2		; Position cursor.
	mov dx,scrfr
	mov bh,0
	int bios
ENDIF
IF Z100
	mov ah,prstr		; Get print string function
	mov dx,offset scrfr	; and string to move cursor
	int dos			; Print the string
ENDIF
        mov ah,prstr            ; Inform the user we are renaming the file.
        mov dx,offset infms5
        int dos
        mov ax,temp2            ; Get the number of chars in the file name.
        cmp ax,0
        jne gofil8
        mov ax,temp1
        mov temp2,ax
gofil8: mov ch,0
        mov cl,al
	mov al,0			; Says if first field is full.
        cmp cl,9H                       ; Is the first field full?
        jne gofl81
        mov al,0FFH             ; Set a flag saying so.
        dec cl
gofl81: mov bx,offset fcb              ; Get the FCB.
        add bx,cx               ; Add in the character number.
	mov ah,'&'
        mov [bx],ah             ; Replace the char with an ampersand.
	push ax
        push bx
        mov ah,openf            ; See if the file exists.
        mov dx,offset fcb
        int dos
        pop bx
        cmp al,0FFH             ; Does it exist?
	pop ax
        jz gofl89               ; If not create it.
        cmp al,0                      ; Get the flag.
        jz gofl83
        dec cl                  ; Decrement the number of chars.
        cmp cl,0
        jz gofl88               ; If no more, die.
        jmp gofl81
gofl83: inc cl                  ; Increment the number of chars.
        cmp cl,9H                       ; Are we to the end?
        jl gofl81               ; If not try again ; else fail. 
 
gofl88: call erpos		; Position cursor.
	mov ah,prstr            ; Tell the user that we can't rename it.
        mov dx,offset ermes4
        int dos
        ret
 
gofl89: mov bx,offset fcb+0CH          ; Point past the end of the file name.
        mov dh,[bx]                     ; Save the present contents.
	mov ah,'$'
        mov [bx],ah             ; Put in a dollar sign.
        push dx
        mov ah,prstr            ; Print the file name.
        mov dx,offset fcb+1
        int dos
        pop dx
        mov bx,offset fcb+0CH          ; Restore over the dollar sign.
        mov [bx],dh
gofil9: mov ah,delf             ; Delete the file if it exists.
        mov dx,offset fcb
        int dos
        mov ax,0
        mov si,offset fcb+0CH
        mov [si],ax             ; Zero current block.
        mov si,offset fcb+0EH
        mov [si],ax             ; Same for Lrecl.
        mov si,offset fcb+20H
        mov [si],ah             ; Zero the current record (within block).
	inc si
	mov [si],ax		; Zero record (within file).
	mov si,offset fcb+23H
	mov [si],ax
        mov ah,makef            ; Now create it.
        mov dx,offset fcb
        int dos
        cmp al,0FFH             ; Is the disk full?
	je gf9x
        jmp rskp
gf9x:   call erpos		; Position cursor.
	mov ah,prstr            ; If so tell the user.
        mov dx,offset erms11
        int dos
        ret

FILEIO	ENDP
; end kermit4.asm [18]
   ; Close the file.
        mov dx,offset fcb
        int dos

        call gtnfil             ; Get the next file.
     