; begin kermit6.asm [18]
 
IF ibmpc
source	db	2048 DUP(?)	; Buffer for data from port.
srcpnt	dw	0		; Pointer in buffer (DI).
count	dw	0		; Number of chars in int buffer.
savesi	dw	0		; Save SI register here.	
telflg	db	0		; Are we acting as a terminal. [16] [17c]
ENDIF

;       This is the CONNECT command.
 
TELNET  PROC    NEAR
        mov ah,cmcfm
        call comnd              ; Get a confirm.
         jmp r                  ;  Didn't get a confirm.
        mov ah,prstr            ; Output
        mov dx,offset crlf      ; a crlf.
        int dos
	mov dx,offset tmsg1
	int dos
	call escprt
	mov ah,prstr
	mov dx,offset tmsg3
	int dos
	mov ah,3		;DK2
	mov bh,0		;DK2
	int bios		;DK2
	dec dh			;DK2  -- DT
	mov ah,2		;DK2
	int bios		;DK2
	mov cs:telflg,0FFH	; Turn on Telnet flag.  [16] [17c]
	call serini		; Initialize serial port. [14]
IF ibmpc
	xor ax,ax
	mov cx,ds		; Save DS in CX.
	mov ds,ax		; Use low core.
	mov bx,6CH		; "break" interrupt vector.
	push [bx]
	mov bx,6EH
	push [bx]
	mov bx,6CH
	mov ax,offset intret
	mov es,ax
	mov [bx],es		; ignore break int's (pt to "iret").
	mov bx,6EH
	mov [bx],cs
	mov ds,cx
	mov ssp,sp		; Save SP to make an easy return.
ENDIF
IF Z100
	mov ssp,sp		; Save current stack pointer.
ENDIF
telnoe: call plup		; Char at port (type to console) ?
IF ibmpc
	cmp al,ESC
	jne telx
	jmp telesc
ENDIF
telx:	cmp al,DEL		; Don't bother with deletes.
	je telnoe
	cmp al,XOFF		; Skip all the following too.
	je telnoe
	cmp al,XON	
	je telnoe
	cmp al,00H		; Null.
	je telnoe
IF ibmpc
	cmp al,BELL
	jne nobell
	call beep
	jmp telnoe
nobell:	cmp al,TAB		; Tab ? [15]
	jne notab		; No, skip the jump [15]
	call dotab		; Yes, handle the tab [15]
	jmp telnoe		; And get the next character [15]
notab:	call dotty		;DK2 Use our own TTY I/O
	jmp telnoe
ENDIF
IF Z100
	mov dl,al		; Get the character
	mov ah,dconio		; and the function
	int dos			; type the character
	jmp telnoe		; Get next character
ENDIF
TELNET  ENDP

;DK2 Put character in AL to the screen
DOTTY	PROC NEAR
	push ax
	mov ah,3		;Get cursor
	mov bh,0
	int bios
	pop ax
	cmp al,8		;Backspace?
	je dotty3
	cmp al,0DH		;CR?
	je dotty4
	cmp al,0AH		;LF?
	je dotty5
	cmp incmod,0		;I/C?
	jne dotty7
	mov ah,9		;Ordinary character
	mov bx,curatt
	mov cx,1
	int bios
	mov ah,2
	mov bh,0
	inc dl			;Step cursor
	cmp dl,80		;Overflow?
	jne dotty2
	ret
dotty1:	inc dh
dotty6:	mov ah,2
dotty2:	int bios
	ret
dotty3:	dec dl			;BS
	jge dotty6
	ret
dotty4:	mov dl,0		;CR
	jmp dotty6
dotty5:	cmp dh,23		;LF
	jl dotty1
	mov ah,8		;Get attribute of last line
	int bios
	mov bh,ah
	mov ax,0601H		;Scroll
	sub cx,cx
	mov dx,174FH
	jmp dotty2
dotty7:	mov temp,ax		;DK6 Save the character
	mov temp1,dx		;Save the cursor
	mov dl,78		;Start shift at end of line
	mov temp2,dx
	mov ah,1		;Turn off cursor
	mov ch,20H
	int bios
dotty8:	mov ah,2		;Position to col M
	mov bh,0
	mov dx,temp2
	int bios
	mov ah,8		;Read char/attr
	int bios
	mov cx,ax		;Save it
	mov ah,2		;Position to col M+1
	inc dx
	int bios
	mov ah,9		;Write char/attr
	mov al,cl
	mov bl,ch
	mov cx,1
	int bios
	dec dx
	dec temp2
	cmp dx,temp1
	jne dotty8
	mov ah,2		;Position
	mov bh,0
	int bios
	mov ax,temp		;Write the char
	mov ah,9
	mov bx,curatt		;In the current video mode
	mov cx,1
	int bios
	mov ah,2		;Step to next column
	inc dl
	int bios
	mov ah,1		;Turn on cursor
	mov cx,0B0CH
	int bios
	ret
DOTTY	ENDP

EXTLN	PROC	NEAR
IF ibmpc
	call serrst		; Reset serial port. [14]
	mov sp,ssp
	xor bx,bx
	mov cx,ds		; Save DS register.
	mov ds,bx		; Address low memory.
	mov bx,6EH
	pop [bx]
	mov bx,6CH
	pop [bx]
;	mov bx,mdmintv+2		; Restore old interrupt vectors.
;	pop [bx]
;	mov bx,mdmintv
;	pop [bx]
	mov ds,cx		; Restore DS.
	xor bx,bx
;	sti
ENDIF
IF Z100
	mov sp,ssp	
ENDIF
	mov ah,prstr
	mov dx,offset tmsg2
	int dos
	mov cs:telflg,0		; Not acting as terminal anymore. [16] [17c]
	jmp rskp
EXTLN	ENDP

;[14 start]       Common initialization for using serial port.

SERINI	PROC	NEAR
IF ibmpc
	cli			; Disable interrupts
	cld			; Do increments in string operations
	xor ax,ax		; Address low memory
	mov es,ax
	mov bx,30H		; Save serial card interrupt vector
	mov ax,es:[bx]
	mov savsci,ax
	mov ax,offset serint	; And point it to my routine
	mov es:[bx],ax
	mov bx,32H
	mov ax,es:[bx]
	mov savscs,ax
	mov es:[bx],cs
	lea ax,cs:source	; Initialize the pointers
	mov cs:srcpnt,ax
	mov cs:savesi,ax
	mov cs:count,0
	mov di,cs:srcpnt	; Where to store bytes
	mov ax,cs		; Ready ES for string operations
	mov es,ax
	mov si,0		; Where to fetch bytes
	in al,21H		; Set up 8259 interrupt controller
	and al,0EFH		; Enable INT4
	out 21H,al
	mov dx,03FBH		; Set up the serial card
	mov al,3
	out dx,al
	mov dx,03F9H
	mov al,1		; Set up interrupt enable register
	out dx,al
	mov dl,0FCH		; Enable interrupts from serial card
	mov al,0BH
	out dx,al
	sti			; Allow interrupts
	mov dl,0F8H
	in al,dx
ENDIF
	ret
SERINI	ENDP

SERRST	PROC	NEAR
IF ibmpc
	cli			; Disable interrupts
	mov dx,03FCH		; Disable modem interrupts
	mov al,3
	out dx,al
	in al,21H		; Interrupt controller
	or al,10H		; Inhibit IRQ4
	out 21H,al
	xor bx,bx		; Address low memory
	mov es,bx
	mov bx,30H		; Restore the serial card interrupt vector
	mov ax,savsci
	mov es:[bx],ax
	mov bx,32H
	mov ax,savscs
	mov es:[bx],ax
	sti
ENDIF
	ret
SERRST	ENDP					; [14 end]

; *********** serial port interrupt routine ********

IF ibmpc
SERINT  PROC  NEAR
	push dx
	push ax
	push es
	push di
	cld
	mov di,cs:srcpnt	; Registers for storing data.
	mov ax,cs
	mov es,ax
	mov dx,mdmsts		; Asynch status port.
	in al,dx
	test al,mdminp		; Data available?
	jz retint		; Nope.
	mov dx,mdmdat
	in al,dx
	mov ah,0FFH		; Assume X-fer mode. [16 start]
	cmp cs:telflg,0		; File transfer or terminal mode? [17c]
	jz srint0
	mov ah,7FH		; Terminal mode (7 bits only). 
srint0:	and al,ah		; Fiddle with input. [16 end]
	jz retint		; Ignore nulls.
	cmp al,7FH		; Ignore rubouts, too.
	jz retint
	stosb			; Store char in buffer.
	lea ax,cs:source
	sub di,ax
	and di,7FFH		; Truncate buffer here.
	add di,ax
	inc cs:count
retint:	mov cs:srcpnt,di
	sti
	mov al,eoicom
	out intcon1,al		;Send End-of-Interrupt to 8259.
	pop di
	pop es
	pop ax
	pop dx
intret:	iret
SERINT	ENDP
ENDIF

PLUP	PROC	NEAR
	call conchr		; Check keyboard.   [15 begin]
	 jmp extln		; Exit from Telnet
	 nop			; In case it is a short jump (Z100)
	call prtchr		; Check serial port
	 ret			; Got a character
	 nop			; Use up three bytes.  [15 end] 
	 nop
	jmp plup
PLUP	ENDP

;************************System Dependent****************************
 
; These I/O routines are similar to those just above.
 
PRTCHR  PROC    NEAR
IF ibmpc
	cmp cs:count,0
	jnz prtch2
	jmp rskp		; No data - check console.
prtch2: cli			; Disable int's.
	mov cx,ds
	mov ax,cs
	mov ds,ax
	mov si,cs:savesi
	lodsb			; Get char from buffer.
	lea dx,cs:source
	sub si,dx
	and si,7FFH		; Truncate buffer after here.
	add si,dx
	dec cs:count
	mov cs:savesi,si 
	mov ds,cx
	sti			; Renable int's.
	ret
ENDIF
IF Z100
	push bx			; Save BX
	mov ah,chr_status	; Get the function we want
	mov al,chr_sfgs		; Get the subfunction to get status
	call bios_auxfunc	; Perform the function
	cmp bl,0		; Anything in queue?
	jne prtch1		; Yes, go get it
	pop bx			; Restore BX
	jmp rskp		; No, give skip return
prtch1:	mov ah,chr_read		; Want to read character
	call bios_auxfunc	; Do it
	and al,07FH		; Strip off parity bit
	pop bx			; And restore BX
	ret
ENDIF
PRTCHR  ENDP


; Generate a short beep.

IF ibmpc
BEEP	PROC	NEAR
	mov al,10110110B	; Gen a short beep (long one losses data.)
	out timer+3,al		; Code snarfed from Technical Reference.
	mov ax,freq		; [18]
	out timer+2,al
	mov al,ah
	out timer+2,al
	in al,port_b
	mov ah,al
	or al,03
	out port_b,al
	mov cx,bellen		; [18]
	mov bl,1
beep0:  loop beep0
	dec bl		
	jnz beep0
	mov al,ah
	out port_b,al
	ret
BEEP	ENDP 
ENDIF
 
CONCHR  PROC    NEAR
IF ibmpc
	mov ah,1		; Get keyboard status.
	int keyb
	jnz cnc0x	
	jmp rskp
cnc0x:	mov ah,0		; Read a char.
	int keyb
	cmp al,0		; Special char (cntrl-break)?
	jnz nobrk		; Nope.
	cmp ah,3		; 3 in ah means nul code.
	jz nobrk		; Pass nulls.  [14]
	cmp ah,83		; Del Key?  [14]
	je cnc1r		; Yes - send a rubout. [14]
	cmp ah,0		; Cntrl-Break?
	jne cnc1y
	xor cx,cx
	mov dx,03fbH
	in al,dx
	or al,40H		; Set send-break bit
	out dx,al
pause:	loop pause
	xor al,40H
	out dx,al
cnc1y:	jmp rskp	
ENDIF
IF Z100
	mov ah,dconio		; Determine if character present
	mov dl,0ffH		; Want input
	int dos			; Get status
	cmp al,00H		; Any characters there?
	jne nobrk		; if not, forget it
	jmp rskp		; Give skip return
ENDIF

cnc1r:
IF CMU				; [15]
	mov al,BS		; BS (will be converted to DEL) [15]
	jmp nobrk
ENDIF				; [15]
	mov al,07FH		; ASCII rubout.  [14]
nobrk:  mov dl,al		; Store char here.
	mov ah,escchr           ; Get the escape char.
        cmp ah,dl               ; Is it an escape char?
        jz intchr               ; If so go process it.
IF CMU				; [15 begin]
	cmp dl,BS		; Is it a backspace ?
	jnz cch0		; No, check for delete
	mov dl,DEL		; Yes, get a delete
	jmp cch1		; And send that instead
cch0:	cmp dl,DEL		; Is it a delete ?
	jnz cch1		; No, done checking then
	mov dl,BS		; Yes, use a backspace
cch1:	mov ax,dx		; Copy character back to AX
ENDIF				; [15 end]
	call dopar		; Set parity (if any).   [10]
	mov dx,ax
	push dx
        call prtout             ; Output the char to the port.
	pop dx
        mov ah,ecoflg           ; Get the echo flag.
        cmp ah,0                        ; Is it turned on?
	jnz cnc1x
        jmp rskp                 ; If not we're done here.
cnc1x:  and dl,7FH
	cmp dl,BS		; Backspace?
	je cnc2x
	cmp dl,CR		; Carriage return?
	je cnc2x
IF ibmpc
	cmp dl,BELL
	jne cnc2y
	call beep
	jmp rskp
ENDIF
cnc2y:	cmp dl,20H		; Is it a control char?
	jge cnc2x	
	jmp rskp
cnc2x:	mov ah,dconio           ; Direct console output.
        int dos                 ; Echo the char.
        jmp rskp
CONCHR  ENDP
 
CONN	PROC	NEAR	 
intchr: mov ah,dconio           ; Direct console I/O.
        mov dl,0FFH             ; Input.
        int dos                 ; Get a char.
	mov ah,al
	cmp ah,0                        ; Is the char a null?
        jz intchr               ; If so, go until we get a char.
        mov bh,ah               ; Save the actual char.
        and ah,137O             ; Convert to upper case.
        cmp ah,'C'                      ; Is it close?
        jne intch0
        ret
intch0: cmp ah,'S'                      ; Is it status?
	jnz inc0x
        jmp stat01               ; If so, jump to stat01 (it will return).
inc0x:  mov ah,bh                       ; Get the char.
        cmp ah,'?'                      ; Is it help?
        jne intch1              ; If not, go to the next check.
        mov dx,offset inthlp    ; If so, get the address of the help message.
        mov ah,prstr            ; Print it.
        int dos
        jmp intchr              ; Get another char.
intch1: mov ch,ah               ; Put the char into another reg.
        mov ah,escchr           ; Get the escape char.
        cmp ah,ch               ; Is it the escape char?
        jne intch2              ; If not, go send a beep to the user.
	mov al,ch
	call dopar		; Set parity.     [10] 
intc11: mov dl,al
	call prtout             ; Output it.
        jmp rskp                ; Return, we are done here.
intch2: mov dl,'G'-100O         ; Otherwise send a beep.
        mov ah,dconio
        int dos
        jmp rskp

; Another similar I/O routine.
 
;************************System Dependent****************************
 
prtout: mov al,dl               ; Char must be in al.
IF ibmpc
	mov dx,mdmdat
	out dx,al
ENDIF
IF Z100
	call bios_auxout	; Send the character
ENDIF
        ret
CONN	ENDP

; [15 begin]
DOTAB	PROC NEAR
	mov ah,3		; Read current cursor position.
	mov bh,0		; This screen
	int bios		; From bios
	cmp dl,72		; Are we at the last tab stop ?
	jl dotab0		; No, move to the next
	cmp dl,79		; Are we at the end ?
	je dotab2		; Yes, just return
	add dl,1		; No, move forward one position
	jmp dotab1		; Set the cursor position
dotab0:	mov al,dl		; Get the column into al
	push dx			; Save the current cursor position
	xor ah,ah		; Zero the high end of ax
	mov bl,8		; Get an eight
	xor bh,bh		; Zero high byte
	div bl			; Divide by 8
	mov al,ah		; Put the remainder in the low end
	xor ah,ah		; Zero the high end
	mov cl,8		; Get an 8 into cl
	xor ch,ch		; Zero high byte
	sub cl,al		; Subtract al from cl
	xor ch,ch		; Zero high end
	pop dx			; Restore the current cursor position
	add dl,cl		; And subtract column mod 8
dotab1:	mov ah,2		; Set cursor position
	mov bh,0		; This screen
	int bios		; Bios call
dotab2:	ret			; Return
DOTAB	ENDP

; [15 end]

TELESC	PROC	NEAR
IF ibmpc
	cmp vtflg,0		; Is vt52 flag on?
	jne vt0
	jmp telnoe		; Don't do escape stuff if it's off.
vt0:	call plup
        mov ah,al                       ; Get the char.
	cmp ah,'Y'		; Special char - move cursor.
	jne vt1
	jmp movcur
vt1:	cmp ah,'<'		;DK2 Start-ANSI?
	je vtexit		;DK2 Yes, ignore
	cmp ah,'['		;DK2 An ANSI command?
	je vtansi		;DK2 Yes, do it
	cmp ah,'@'		;DK2 Insert characters?
	jne vtnins		;DK2
	mov incmod,1		;DK2
	jmp telnoe		;DK2
vtnins:	cmp ah,'p'		;DK2 Inverse?
	jne vtninv		;DK2
	jmp vtinvi		;DK2
vtninv:	cmp ah,'q'		;DK2 Normal?
	jne vtnino		;DK2
	jmp vtinvo		;DK2
vtnino:	cmp ah,'A'		;DK2 Less than an 'A'?
        jl vtig                 ; Yes - ignore.
        cmp ah,'O'+1            ;DK2 Greater than 'O'?
        jns vtig                ; Yes - ignore.
        mov al,'A'
        sub ah,al               ; Else make into index.
        shl ah,1
        mov bx,offset ttab      ; Load base addr of table.
	mov cl,ah               ; Move a into cx.
        mov ch,00H              ; Zero out high byte.
        add bx,cx               ; Double add index+offset.
	mov bx,[bx]		; Get address of routine to call.
	jmp bx
vtig:                           ; Ignore escape sequence.
        push ax                 ; Push the char to be output.
        mov dl,esc              ; Load an escape.
        mov ah,conout           ; The function code
        int dos                 ; and the syscal.
        pop ax                  ; Restore the character
        mov dl,ah               ; and move to output register.
        mov ah,conout           ; The function
        int dos                 ; and the syscall.
ENDIF
vtexit:	jmp telnoe		;DK2 Return home.

;DK2 ANSI I/D L
vtansi:	call plup
	cmp al,'?'
	je vtanso
	sub al,30H
	mov temp,ax
	call plup
	cmp al,"9"
	jg vtans1
	sub al,30H
	mov temp2,ax
	mov ax,temp
	mov dl,10
	mul dl
	add ax,temp2
	mov temp,ax
	call plup
vtans1:	cmp al,'L'
	jne vtans2
	mov ah,3		;Get cursor position
	mov bh,0
	int bios
	mov temp1,dx
	mov cx,dx		;Do a N-line scroll
	mov cl,0
	mov dx,184FH
	mov ax,temp
	mov ah,7
	mov bh,7
	int bios
	jmp vtans3
vtans2: cmp al,'M'
	jne vtans4
	mov ah,3
	mov bh,0
	int bios
	mov temp1,dx
	mov ax,temp
	mov ah,6
	mov cx,dx
	mov dx,184FH
	mov bh,7
	int bios
vtans3: mov dx,temp1		;Restore cursor position
	mov dl,0
	mov ah,2
	mov bh,0
	int bios
vtans4:	jmp telnoe
vtanso: call plup
	call plup
	jmp telnoe

vtinvi: mov curatt,0070H	;DK2 Reverse video
	jmp telnoe		;DK2
vtinvo: mov curatt,0007H	;DK2 Normal video
	jmp telnoe		;DK2
TELESC	ENDP

IF ibmpc
TEL	PROC	NEAR
movcur:	call plup
	sub al,32
	mov dh,al
	mov temp,dx		; Save row position here.
	call plup
	mov dx,temp		; Restore
	sub al,32		; Comes with 37Q added on (& starts at 1).
	mov dl,al
	mov bh,0
	mov ah,2
	int bios
	jmp telnoe

curup:	mov ah,3		; Cursor up function.
	mov bh,0
	int bios
	cmp dh,0
	je cup0
	sub dh,1
	mov ah,2
	int bios
cup0:	jmp telnoe

curdwn:	mov ah,3		; Cursor down.
	mov bh,0
	int bios
	cmp dh,24
	je cdn0
	add dh,1
	mov ah,2
	int bios
cdn0:	jmp telnoe

currt:	mov ah,3		; Cursor right.
	mov bh,0
	int bios
	cmp dl,79
	je crt0
	add dl,1
	mov ah,2
	int bios
crt0:	jmp telnoe

curlft:	mov ah,3		; Cursor left.
	mov bh,0
	int bios
	cmp dl,0
	je clt0
	sub dl,1
	mov ah,2
	int bios
clt0:	jmp telnoe

curskp:	jmp vtig		; Ignore for now.

curclr:	call locate		; Home the cursor [15]
	jmp curscr		; And clear the screen [15]

curhm:	call locate
	jmp telnoe

curscr:	mov ah,3		; Clear to end of screen.
	mov bh,0
	int bios
	cmp dx,0
	jne csr0
	call cmblnk
	jmp telnoe
csr0:	cmp dl,0
	je csr1
	push dx
	call curln
	pop dx
	add dh,1
	mov dl,0
csr1:	mov cx,dx
	mov dx,184FH
	mov bh,7
;	mov al,25
;	sub al,ch
	mov al,0
	mov ah,7
	int bios
	jmp telnoe

curln:	mov ah,3		; Clear to end of line.
	mov bh,0
	int bios		; Get current cursor position
	mov cx,dx
	mov dl,79
	mov ah,7
	mov al,0
	mov bh,7
	int bios
	jmp telnoe

inslin:	mov ah,3		; Get cursor position.
	mov bh,0
	int bios
	mov temp,dx		; Save here.
	mov cx,dx
	mov cl,0		; Start at beginning of row.
	mov dx,184FH		; End at lower corner of screen.
	mov ax,0701H
	mov bh,7
	int bios		; Scroll down one line.
	mov dx,temp		; Get back where we were.
	mov dl,0
	mov ah,2
	mov bh,0
	int bios
	jmp telnoe

dellin: mov ah,3
	mov bh,0
	int bios		; Get current cursor position. 
	mov temp,dx		; Remember the place.
	mov ax,0601H		; Scroll up one line.
	mov cx,dx
	mov cl,0		; Start at beginning of row.
	mov dx,184FH
	mov bh,7
	int bios
	mov dx,temp
	mov dl,0
	mov ah,2
	mov bh,0
	int bios
	jmp telnoe

;DK2 Delete character
delchr:	mov ah,3		;Get cursor position
	mov bh,0
	int bios
	mov temp,dx
	mov ah,1		;Turn off cursor
	mov ch,20H
	int bios
delch1:	mov ah,2		;Position to col M+1
	inc dl
	int bios
	mov ah,8		;Get char/attr
	int bios
	mov cx,ax		;Save it
	dec dl			;Position to col M
	mov ah,2
	int bios
	mov ah,9		;Write char/attr
	mov al,cl
	mov bl,ch
	mov cx,1
	int bios
	inc dl			;Next column
	cmp dl,79		;About to write to col 80?
	jne delch1		;No
	mov ah,2		;Position to col 80
	int bios
	mov ah,9		;Write char/attr
	mov al,' '
	int bios
	mov ah,2		;Reset cursor
	mov dx,temp
	int bios
	mov ah,1
	mov cx,0B0CH
	int bios
	jmp telnoe

;DK2 Cancel Insert Character mode
insmox:	mov incmod,0
	jmp telnoe
TEL	ENDP
ENDIF	
; end kermit6.asm [18]
mp ah,'N'              ; NAK?
        jne seot3               ; Is it error.
        call rtpos              ; Position curso