; begin kermit2.asm [18]
 
MAIN    SEGMENT PARA PUBLIC 'MAIN'
START   PROC  FAR
        ASSUME  CS:MAIN,DS:DATAS,SS:STACK,ES:NOTHING
 
        push ds                 ; Save system data area.
        sub ax,ax               ; Get a zero.
        push ax                 ; Put zero return addr on stack.
 
        mov ax,datas            ; Initialize DS.
        mov ds,ax
	sub ax,ax

        mov oldstk,sp           ; Save old stack pointer.

        call cmblnk             ; Clear the screen.
	call locate

        mov ah,prstr            ; Print the version header.
        mov dx,offset versio
        int dos

	mov ah,setdma		; Set disk transfer address.
	mov dx,offset buff
	int dos

IF ibmpc
	mov dx,mdmcom		; LCR -- Initialize baud rate.
	in al,dx
	mov bl,al
	or ax,80H
	out dx,al
	mov dx,mdmdat
	mov ax,baud
	out dx,al
	inc dx
	mov al,ah
	out dx,al
	mov dx,mdmcom
	mov al,bl
	out dx,al
ENDIF
IF Z100
	mov bx,ds		; Set up pointer to config info
	mov es,bx		;  .  .  .
	mov bx,offset auxcnf	;  .  .  .
	mov ah,chr_status	; Get the function code
	mov al,chr_sfgc		; And the subfunction to get config
	call bios_auxfunc	; Get the block
ENDIF

; This is the main KERMIT loop.  It prompts for and gets the users commands.

kermit: mov dx,offset kerm
        call prompt             ; Prompt the user.
        mov dx,offset comtab
        mov bx,offset tophlp
        mov ah,cmkey
        call comnd
         jmp kermt2
        call bx                 ; Call the routine returned.
         jmp kermt3
        cmp extflg,0            ;  Check if the exit flag is set.
        jne krmend              ;  If so jump to KRMEND.
        jmp kermit              ; Do it again.
 
kermt2: mov ah,prstr
        mov dx,offset ermes1    ;  Give an error.
        int dos
        jmp kermit

kermt3: mov ah,prstr
        mov dx,offset ermes3    ;  Give an error.
        int dos
        jmp kermit
 
krmend: 
        mov sp,oldstk
        ret
 
START   ENDP
 
 
; These are some utility routines.
 
;       Abort
 
ABORT   PROC    NEAR
        mov state,'A'           ; Otherwise abort.
        ret
ABORT   ENDP
 
;       NAK
 
NAK     PROC    NEAR
        mov ax,pktnum           ; Get the packet number we're waiting for.
        mov argblk,ax
        mov argbk1,0
        mov ah,'N'              ; NAK that packet.
        call spack
	 jmp abort
        ret                     ; Go around again.
NAK     ENDP

; Position cursor for an error message.

ERPOS	PROC 	NEAR
IF ibmpc
	mov ah,2
	mov bh,0
	mov dx,screrr
	int bios
	ret
ENDIF
IF Z100
	mov dx,offset screrr	; Get address of string to position cursor
	mov ah,prstr		; Get the function code
	int dos			; Print the addressing string
	ret			; And return
ENDIF
ERPOS	ENDP

; Position cursor for number of retries message.

RTPOS	PROC 	NEAR
IF ibmpc
	mov ah,2
	mov bh,0
	mov dx,scrnrt
	int bios
	ret
ENDIF
IF Z100
	mov ah,prstr		; Get the function to print string
	mov dx,offset scrnrt	; Get the address of the string
	int dos			; Print the string
	ret			; And return
ENDIF
RTPOS	ENDP

; Print err message that found a non-standard-Ascii char in the file.

BITERR	PROC	NEAR
	push bx
IF ibmpc
	mov ah,2
	mov bh,0
	mov dx,scrhi
	int bios
ENDIF
IF Z100
	mov ah,prstr		; Get the function to print string
	mov dx,offset scrhi	; Get the address of the string
	int dos			; Print the string
ENDIF
	mov ah,prstr
	mov dx,offset hibit
	int dos
	pop bx
	ret
BITERR	ENDP		

;	This routine prints out the escape character in readable format.  

ESCPRT	PROC	NEAR		; [6 start]
	mov dl,escchr
	cmp dl,' '
	jge escpr2
	push dx
	mov ah,prstr
	mov dx,offset esctl
	int dos
	pop dx
	add dl,040H		; Make it printable.
escpr2:	mov ah,conout
	int dos
	ret
ESCPRT	ENDP			; [6 end]
 
;       FCB must be remembered if found "*" in filename.      [7 start]
; 	Copy from place addressed by BX to place addressed by DI.
;	Also use to get the filename to the FCB from the DTA.

FCBCPY	PROC	NEAR
fcbcp1:	cmp cl,0
	je fcbcp2
	mov ah,[bx]
	mov [di],ah
	dec cl
	inc bx
	inc di
	jmp fcbcp1
fcbcp2:	ret
FCBCPY	ENDP	

;       This routine sets up the data for init packet (either the
;       Send_init or ACK packet).
 
RPAR    PROC    NEAR
        mov ah,rpsiz            ; Get the receive packet size.
        add ah,' '              ; Add a space to make it printable.
        mov [bx],ah             ; Put it in the packet.
        mov ah,rtime            ; Get the receive packet time out.
        add ah,' '              ; Add a space.
        mov 1[bx],ah            ; Put it in the packet.
        mov ah,rpad             ; Get the number of padding chars.
        add ah,' '
        mov 2[bx],ah            ; Put it in the packet.
        mov ah,rpadch           ; Get the padding char.
        add ah,100O             ; Uncontrol it.
        and ah,7FH
        mov 3[bx],ah            ; Put it in the packet.
        mov ah,reol             ; Get the EOL char.
        add ah,' '
        mov 4[bx],ah            ; Put it in the packet.
        mov ah,rquote           ; Get the quote char.
        mov 5[bx],ah            ; Put it in the packet.
        mov ah,06H              ; Six pieces of data.
        ret
RPAR    ENDP
 
;       This routine reads in all the send_init packet information.
 
SPAR    PROC    NEAR
        mov temp4,ax            ; Save the number of arguments.
        mov ah,[bx]             ; Get the max packet size.
        sub ah,' '              ; Subtract a space.
        mov spsiz,ah            ; Save it.
        mov ax,temp4
        cmp al,3                ; Fewer than three pieces?
        jge spar1
        ret                     ; If so we are done.
spar1:  mov ah,2[bx]            ; Get the number of padding chars.
        sub ah,' '
        mov spad,ah
        mov ax,temp4
        cmp al,4                ; Fewer than four pieces?
        jge spar2
        ret                     ; If so we are done.
spar2:  mov ah,3[bx]            ; Get the padding char.
        add ah,100O             ; Re-controlify it.
        and ah,7FH
        mov spadch,ah
        mov ax,temp4
        cmp al,5                ; Fewer than five pieces?
        jge spar3
        ret                     ; If so we are done.
spar3:  mov ah,4[bx]            ; Get the EOL char.
        sub ah,' '
        mov seol,ah
        mov ax,temp4
        cmp al,6                ; Fewer than six pieces?
        jge spar4
        ret                     ; If so we are done.
spar4:  mov ah,5[bx]            ; Get the quote char.
        mov squote,ah
        ret
SPAR    ENDP
 
 
;       Initialize buffers and clear line.
 
INIT    PROC    NEAR
	call cmblnk
	call locate
        mov ah,prstr            ; Put statistics headers on the screen.
        mov dx,offset outlin
        int dos
        call init1
        ret
INIT    ENDP
 
INIT1   PROC    NEAR
        mov chrcnt,bufsiz              ; Number of chars left.
        mov bufpnt,offset buff         ; Addr for beginning.
        ret
INIT1   ENDP

;  Clear out the old filename on the screen. 

CLRFLN	PROC	NEAR
IF ibmpc
	mov ah,2
	mov bh,0
	mov dx,scrfln
	int bios
	mov ax,0920H			; Clear out the old filename.
	mov bx,7
	mov cx,12
	int bios
	ret
ENDIF
IF Z100
	mov ah,prstr		; Get print string function
	mov dx,offset scrfln	; and string to move cursor
	int dos			; Print the string
	mov ah,prstr		; Get the function again
	mov dx,offset clreol	; And the sequence to clear to EOL
	int dos			; Do it
	ret			; And return
ENDIF
CLRFLN	ENDP

;       RECEIVE command
 
READ    PROC    NEAR
	mov bx,offset data	; Where to put text (if any).  [8 start]
	mov ah,cmtxt
        call comnd              ; Get text or confirm.
         jmp kermt3
	cmp ah,0		; Read in any chars?
	je read1		; A regular receive.
	mov al,ah
	mov ah,0
	mov argbk1,ax		; Remember number of chars we read.
	mov ah,'$'		; Use for printing.
	mov [bx],ah
	call init		; Clear line and initialize buffers.
	call clrfln		; Prepare to print filename.
	mov ah,prstr
	mov dx,offset data	; Print file name.
	int dos
	mov argblk,0		; Start at packet zero.
	mov ah,'R'		; Receive init packet.
	call spack		; Send the packet.
	 jmp kermt3
	jmp read12						; [8 end]
read1:  call init               ; Clear the line and initialize the buffers.
read12: mov numpkt,0            ; Set the number of packets to zero.
        mov numrtr,0            ; Set the number of retries to zero.
        mov pktnum,0            ; Set the packet number to zero.
        mov numtry,0            ; Set the number of tries to zero.
	call serini		; Initialize serial port. [14]
        call rtpos		; Position cursor.
        mov ax,numrtr
        call nout               ; Write the number of retries.
        mov state,'R'           ; Set the state to receive initiate.
read2:  
IF ibmpc
	mov ah,2		; Position cursor.
	mov dx,scrst
	mov bh,0
	int bios
ENDIF
IF Z100
	mov ah,prstr		; Get print string function
	mov dx,offset scrst	; and string to move cursor
	int dos			; Print the string
ENDIF
	mov ah,prstr            ; Be informative.
        mov dx,offset infms1
        int dos
IF ibmpc
	mov ah,2
	mov dx,scrnp
	mov bh,0
	int bios
ENDIF
IF Z100
	mov ah,prstr		; Get print string function
	mov dx,offset scrnp	; and string to move cursor
	int dos			; Print the string
ENDIF
        mov ax,numpkt
        call nout               ; Write the number of packets.
        mov ah,state            ; Get the state.
        cmp ah,'D'              ; Are we in the data send state?
        jne read3
        call rdata
        jmp read2
read3:  cmp ah,'F'              ; Are we in the file receive state?
        jne read4
        call rfile              ; Call receive file.
        jmp read2
read4:  cmp ah,'R'              ; Are we in the receive initiate state?
        jne read5
        call rinit
        jmp read2
read5:  cmp ah,'C'              ; Are we in the receive complete state?
        jne read6
	call serrst		; Reset serial port. [14]
IF ibmpc
	mov ah,2		; Position cursor.
	mov dx,scrst
	mov bh,0
	int bios
ENDIF
IF Z100
	mov ah,prstr		; Get print string function
	mov dx,offset scrst	; and string to move cursor
	int dos			; Print the string
ENDIF
        mov ah,prstr
        mov dx,offset infms3    ; Plus a little cuteness.
        int dos
	cmp belflg,0		; Bell desired?  [17a]
	je readnb		; No.  [17a]
	mov dx,offset ender	; Ring them bells.    [4]
	int dos			; [4]
readnb:				; [17a -- new label]
IF ibmpc
	mov ah,2
	mov dx,scrrpr		; Put prompt here.
	mov bh,0
	int bios
ENDIF
IF Z100
	mov ah,prstr		; Get print string function
	mov dx,offset scrrpr	; and string to move cursor
	int dos			; Print the string
ENDIF
        jmp rskp
read6: 	call serrst		; Reset serial port. [14]
IF ibmpc
	mov ah,2		; Position cursor.
	mov dx,scrst
	mov bh,0
	int bios
ENDIF
IF Z100
	mov ah,prstr		; Get print string function
	mov dx,offset scrst	; and string to move cursor
	int dos			; Print the string
ENDIF
        mov ah,prstr
	mov dx,offset infms4    ; Plus a little cuteness.
        int dos
	mov dx,offset ender	; Ring them bells.   [4]
	int dos			;  [4]
IF ibmpc
	mov ah,2
	mov dx,scrrpr
	mov bh,0
	int bios
ENDIF
IF Z100
	mov ah,prstr		; Get print string function
	mov dx,offset scrrpr	; and string to move cursor
	int dos			; Print the string
ENDIF
        jmp rskp
READ    ENDP
 
 
;       Receive routines
 
;       Receive init
 
RINIT   PROC    NEAR
        mov ah,numtry           ; Get the number of tries.
        cmp ah,imxtry           ; Have we reached the maximum number of tries?
        jl rinit2
	call erpos		; Position cursor.
        mov dx,offset ermes7
        mov ah,prstr
        int dos                 ; Print an error message.
        jmp abort               ; Change the state to abort.
rinit2: inc ah                  ; Increment it.
        mov numtry,ah           ; Save the updated number of tries.
        call rpack              ; Get a packet.
         jmp nak                ;  Trashed packet: nak, retry.
        cmp ah,'S'              ; Is it a send initiate packet?
        jne rinit3              ; If not see if its an error.
        mov ah,numtry           ; Get the number of tries.
        mov oldtry,ah           ; Save it.
        mov numtry,0            ; Reset the number of tries.
        mov ax,argblk           ; Returned packet number.  (Synchronize them.)
        inc ax                  ; Increment it.
        and ax,3FH              ; Turn off the two high order bits.
        mov pktnum,ax           ; Save modulo 64 of the number.
        mov bx,numpkt
        inc bx                  ; Increment the number of packets.
        mov numpkt,bx
        mov ax,argbk1           ; Get the number of arguments received.
        mov bx,offset data      ; Get a pointer to the data.
        call spar               ; Get the data into the proper variables.
        mov bx,offset data      ; Get a pointer to our data block.
        call rpar               ; Set up the receive parameters.
	xchg ah,al
	mov ah,0
        mov argbk1,ax           ; Store the returned number of arguments.
        mov ah,'Y'              ; Acknowledge packet.
        call spack              ; Send the packet.
	 jmp abort
        mov ah,'F'              ; Set the state to file send.
        mov state,ah
        ret
rinit3: cmp ah,'E'              ; Is it an error packet?
        jne rinit4
        call error
rinit4: jmp abort
RINIT   ENDP
 

;       Receive file
 
RFILE   PROC    NEAR
        cmp numtry,maxtry       ; Have we reached the maximum number of tries?
        jl rfile1
	call erpos		; Position cursor.
        mov dx,offset ermes8
        mov ah,prstr
        int dos                 ; Print an error message.
        jmp abort               ; Change the state to abort.
rfile1: inc numtry              ; Save the updated number of tries.
        call rpack              ; Get a packet.
         jmp nak                ;  Trashed packet: nak, retry.
        cmp ah,'S'              ; Is it a send initiate packet?
        jne rfile2              ;  No, try next type.
        cmp oldtry,imxtry       ; Have we reached the maximum number of tries?
        jl rfil12               ; If not proceed.
	call erpos		; Position cursor.
        mov dx,offset ermes7
        mov ah,prstr
        int dos                 ; Print an error message.
        jmp abort               ; Change the state to abort.
rfil12: inc oldtry              ; Save the updated number of tries.
        mov ax,pktnum           ; Get the present packet number.
        dec ax                  ; Decrement.
        cmp ax,argblk           ; Is the packet's number one less than now?
        je rfil13
        jmp nak                 ; No, NAK and try again.
rfil13: call rtpos              ; Position cursor.
        inc numrtr              ; Increment the number of retries.
        mov ax,numrtr
        call nout               ; Write the number of retries.
        mov numtry,0            ; Reset the number of tries.
        mov bx,offset data      ; Get a pointer to our data block.
        call rpar               ; Set up the parameter information.
	xchg ah,al
	mov ah,0
        mov argbk1,ax           ; Save the number of arguments.
        mov ah,'Y'              ; Acknowledge packet.
        call spack              ; Send the packet.
	 jmp abort
        ret
rfile2: cmp ah,'Z'              ; Is it an EOF packet?
        jne rfile3              ;  No, try next type.
        cmp oldtry,maxtry       ; Have we reached the maximum number of tries?
        jl rfil21               ; If not proceed.
        call erpos              ; Position cursor.
        mov dx,offset ermes9
        mov ah,prstr
        int dos                 ; Print an error message.
        jmp abort               ; Change the state to abort.
rfil21: inc oldtry              ; Increment it.
        mov ax,pktnum           ; Get the present packet number.
        dec ax                  ; Decrement.
        cmp ax,argblk           ; Is the packet's number one less than now?
        je rfil24
        jmp nak                 ; No, NAK and try again.
rfil24: call rtpos              ; Position cursor.
        inc numrtr              ; Increment the number of retries
        mov ax,numrtr
        call nout               ; Write the number of retries.
        mov numtry,0
        mov argbk1,0            ; No data.  (The packet number is in argblk.)
        mov ah,'Y'              ; Acknowledge packet.
        call spack              ; Send the packet.
	 jmp abort
        ret
rfile3: cmp ah,'F'              ; Start of file?
        jne rfile4
        mov ax,argblk           ; Get the packet number.
        cmp ax,pktnum           ; Is it the right packet number?
        je rfil32
        jmp nak                 ; No, NAK it and try again.
rfil32: inc ax                  ; Increment the packet number.
        and ax,3FH              ; Turn off the two high order bits.
        mov pktnum,ax           ; Save modulo 64 of the number.
        inc numpkt              ; Increment the number of packets.
        call gofil              ; Get a file to write to.
         jmp abort
        call init1              ; Initialize all the buffers.
        mov ah,numtry           ; Get the number of tries.
        mov oldtry,ah           ; Save it.
        mov numtry,0            ; Reset the number of tries.
        mov argbk1,0            ; No data.  (The packet number is in argblk.)
        mov ah,'Y'              ; Acknowledge packet.
        call spack              ; Send the packet.
	 jmp abort
        mov state,'D'           ; Set the state to data receive.
        ret
rfile4: cmp ah,'B'              ; End of transmission.
        jne rfile5
        mov ax,pktnum
        cmp ax,argblk           ; Do we match?
        je rfil41
        jmp nak                 ; No, NAK it and try again.
rfil41: mov argbk1,0            ; No data.  (Packet number already in argblk).
        mov ah,'Y'              ; Acknowledge packet.
        call spack              ; Send the packet.
	 jmp abort
        mov state,'C'           ; Set the state to complete.
        ret
rfile5: cmp ah,'E'              ; Is it an error packet.
        jne rfile6
        call error
rfile6: jmp abort
RFILE   ENDP
 
 
;       Receive data
 
RDATA   PROC    NEAR
        cmp numtry,maxtry       ; Get the number of tries.
        jl rdata1
        call erpos              ; Position cursor.
        mov dx,offset erms10
        mov ah,prstr
        int dos                 ; Print an error message.
        jmp abort               ; Change the state to abort.
rdata1: inc numtry              ; Save the updated number of tries.
        call rpack              ; Get a packet.
         jmp nak                ;  Trashed packet: nak, retry.
        cmp ah,'D'              ; Is it a data packet?
	je rdat11
        jmp rdata2              ;  No, try next type.
rdat11: mov ax,pktnum           ; Get the present packet number.
        cmp ax,argblk           ; Is the packet's number correct?
        jz rdat14
        cmp oldtry,maxtry       ; Have we reached the maximum number of tries?
        jl rdat12               ; If not proceed.
	call erpos              ; Position cursor.
        mov dx,offset erms10
        mov ah,prstr
        int dos                 ; Print an error message.
        jmp abort               ; Change the state to abort.
rdat12: inc oldtry              ; Save the updated number of tries.
;        dec pktnum              ; Decrement present packet number.  [14]
        mov ax,pktnum
	dec ax			; [14]
        cmp ax,argblk           ; Is the packet's number one less than now?
        je rdat13
        jmp nak                 ; No, NAK it and try again.
rdat13: call rtpos              ; Position cursor.
        inc numrtr              ; Increment the number of retries
        mov ax,numrtr
        call nout               ; Write the number of retries.
        mov numtry,0            ; Reset number of tries.
        mov argbk1,0            ; No data.  (The packet number is in argblk.)
        mov ah,'Y'              ; Acknowledge packet.
        call spack              ; Send the packet.
	 jmp abort
        ret
rdat14: inc ax                  ; Increment the packet number.
        and ax,3FH              ; Turn off the two high order bits.
        mov pktnum,ax           ; Save modulo 64 of the number.
        inc numpkt              ; Increment the number of packets.
        mov ah,numtry           ; Get the number of tries.
        mov oldtry,ah           ; Save it.
        mov ax,argbk1           ; Get the length of the data.
        call ptchr
         jmp abort              ;  Unable to write out chars; abort.
        mov numtry,0            ; Reset the number of tries.
        mov argbk1,0            ; No data.  (Packet number still in argblk.)
        mov ah,'Y'              ; Acknowledge packet.
        call spack              ; Send the packet.
	 jmp abort
        ret
rdata2: cmp ah,'F'              ; Start of file?
        jne rdata3              ;  No, try next type.
        cmp oldtry,maxtry       ; Have we reached the maximum number of tries?
        jl rdat21               ; If not proceed.
	call erpos		; Position cursor.
        mov dx,offset ermes8
        mov ah,prstr
        int dos                 ; Print an error message.
        jmp abort               ; Change the state to abort.
rdat21: inc oldtry              ; Save the updated number of tries.
        mov ax,pktnum
	dec ax			; [14 Omitted accidentally - D.T.]
        cmp ax,argblk           ; Is the packet's number one less than now?
        je rdat22
        jmp nak                 ; No, NAK it and try again.
rdat22: call rtpos              ; Position cursor.
        inc numrtr              ; Increment the number of retries
        mov ax,numrtr
        call nout               ; Write the number of retries.
        mov numtry,0            ; Reset number of tries.
        mov argbk1,0            ; No data.  (The packet number is in argblk.)
        mov ah,'Y'              ; Acknowledge packet.
        call spack              ; Send the packet.
	 jmp abort
        ret
rdata3: cmp ah,'Z'              ; Is it a EOF packet?
	je rdat3x				; [13]
        jmp rdata4               ; Try and see if its an error. [13]
rdat3x: mov ax,pktnum           ; Get the present packet number. [13]
        cmp ax,argblk           ; Is the packet's number correct?
        je rdat32
        jmp nak                 ; No, NAK it and try again.
rdat32: inc ax                  ; Increment the packet number.
        and ax,3FH              ; Turn off the two high order bits.
        mov pktnum,ax           ; Save modulo 64 of the number.
        inc numpkt
rdat33: mov bx,bufpnt           ; Get the dma pointer.
	mov ax,80H
        sub ax,chrcnt           ; Get the number of chars left in the DMA.
	cmp ax,80H		;   [13 start]
	jne rdat34
	call outbuf		; Write out buffer if no room for ^Z.
	 jmp abort
	mov ax,0		;   [13 end]
rdat34: mov cl,'Z'-100O         ; Put in a ^Z for EOF.
        mov [bx],cl
	inc ax
	dec chrcnt
	mov cx,chrcnt
	mov temp,cx
	inc bx
rdt3:	inc ax
	cmp ax,80H
	jg rdat35		; Pad till full.
	mov cl,0		; Use nulls.
	mov [bx],cl
	inc bx
        jmp rdt3
rdat35: call outbuf             ; Output the last buffer.
         jmp abort              ;  Give up if the disk is full.
	call fixfcb
        mov ah,closf            ; Close up the file.
        mov dx,offset fcb
        int dos
        mov ah,numtry           ; Get the number of tries.
        mov oldtry,ah           ; Save it.
        mov numtry,0            ; Reset the number of tries.
        mov argbk1,0            ; No data.  (The packet number is in argblk.)
        mov ah,'Y'              ; Acknowledge packet.
        call spack              ; Send the packet.
	 jmp abort
        mov state,'F'
        ret
rdata4: cmp ah,'E'                      ; Is it an error packet.
        jne rdata5
        call error
rdata5: jmp abort
RDATA   ENDP

FIXFCB  PROC	NEAR	
	mov bx,offset fcb+18
	mov di,offset filsiz
	mov ax,[bx]
	mov [di],ax
	mov bx,offset fcb+16
	mov ax,[bx]
	mov 2[di],ax
	mov ax,temp		; Get number of chars in last buffer full.
	sub filsiz+2,ax		; Get real file size.
	sbb filsiz,0
	mov bx,offset fcb+18
	mov di,offset filsiz
	mov ax,[di]
	mov [bx],ax
	mov bx,offset fcb+16
	mov ax,2[di]
	mov [bx],ax
	ret
FIXFCB	ENDP
; end kermit2.asm [18]
.f
>VE4fRR3Rv >yu  R Fd>y t R QF ~ FU>y t>V}?| ~u