	name msxhp1
; File MSXHP1.ASM
	include mssdef.h
;       Copyright (C) 1982,1991, Trustees of Columbia University in the
;       City of New York.  Permission is granted to any individual or
;       institution to use, copy, or redistribute this software as long as
;       it is not sold for profit and this copyright notice is retained.
; System dependent module for HP150.
; Use with file MSUHP1.ASM (keyboard translator)
; Edit history
; 2 March 1991 version 3.10
; Nov. 24, 1990. Remove references to prserr to make linker happy.
; Nov. 21, 1990. Dump capture buffer (cptdmp) when exiting connect mode. [jan]
; Sept. 1990. Read 20 characters a time from dcomm. Read keyboard
;  once every 16 reads of dc port. Start port at 7 bits so firmware
;  flow control works. Disable our own flow control. Now works at 4800
;  baud with no flow control.
; August 1990 update to 3.0. Incorporate tektronix. Add replay. [jan].
; John Nyenhuis, Purdue University, School of Electrical Engineering
; West Lafayette, Indiana 47907 USA (317)494-3524  nyenhuis@ecn.purdue.edu
; 1 July 1988 Version 2.31
; 11 Jan 1988 update to 2.30 consistency level.
; 1 Jan 1988 version 2.30


writechar   macro saying
	pushf
	push	dx
	push	ax
	mov	ah,2
	mov	dl,saying
	int	dos
	pop	ax
	pop	dx
	popf
endm

writestring   macro saying
	pushf
	push	ax
	push	dx
	mov	ah,prstr
	mov	dx,offset saying
	int	dos
	pop	dx
	pop	ax
	popf
endm

saveregs macro
	push	ax
	push	bx
	push	cx
	push	dx
	push	es
	push	di
	push	si
	push	ds
	push	bp
	pushf
endm

restoreregs  macro
	popf
	pop	bp
	pop	ds
	pop	si
	pop	di
	pop	es
	pop	dx
	pop	cx
	pop	bx
	pop	ax
endm

;; below 40 publics are the minimum necessary
	public  baudst, ihostr, bdtab, getbaud, chrout, pcwait, putmod
	public  serrst, trnprs, prtchr, poscur, outchr, dtrlow, vts, puthlp
	public	vtstat, coms, cquery, ctlu, shomodem, portval, getmodem
	public  term, dumpscr, cmblnk, cquit, locate, clearl, machnam, lclini
	public  sendbl, comptab, sendbr, clrmod, cstatus, termtb, serhng
	public  clrbuf, beep, serini
;;additional system dependent publics
	public	termtog, kclrscn, kdos, snull, cquit, cquery
	public	toterminal, klogtog, setchtab, vtstbl

false	equ	0
true	equ	1
instat	equ	6
print_out equ	05h			; dos function to print to printer
prtscr	equ	80h			; print screen pressed

wrdev	equ	40H
rddev	equ	3fH
open	equ	3dH
close	equ	3eH
rdchan	equ	2
e_send_break equ 6
e_ioctl equ	44h		; DOS i/o control function
passall equ	0803h		; Port transparency mode [WHM]
xofcnt	equ	32		; number of characters to send xoff
xoncnt	equ	16		; number of characters to send xon
dos201	equ	201h
dos211	equ	20bh		; dosnum for 2.11
data   segment public 'data'
	extrn	lclexit:word, flags:byte, trans:byte, dmpname:byte
	extrn	kbdflg:byte, rxtable:byte, denyflg:word, repflg:byte
	extrn	diskio:byte ; for replay feature
	extrn	dosnum:word, agiosbuff:byte
	extrn	sloghnd:word     ; session log handle from msster
	extrn	prnhand:word

machnam db	'HP-150$'
erms40	db	cr,lf,'?Warning: Unrecognized baud rate$'
erms41	db	cr,lf,'?Warning: Cannot open com port$'
noimp	db	cr,lf,'Command not implemented.$'
hngmsg	db	cr,lf,' The phone should have hungup.',cr,lf,'$'
hnghlp	db	cr,lf,' The modem control lines DTR and RTS for the current'
	db	' port are forced low (off)'
	db	cr,lf,' to hangup the phone. Normally, Kermit leaves them'
	db	' high (on) when it exits.'
	db	cr,lf,'$'
msmsg1	db	cr,lf,' Communications port is not ready.$'
msmsg2	db	cr,lf,' Communications port is ready.$'
rdbuf	db	80 dup (0)		; temp buf
setktab db	0
setkhlp db	0
shkmsg	db	'?Not implemented.'
shklen	equ	$-shkmsg
anspflg	db	0			; printing active status
crlf	db	cr,lf,'$'
delstr	db	BS,BS,'  ',BS,BS,'$'	; Delete string
clrlin	db	cr,ESCAPE,'K$'
xofsnt	db	0			; Say if we sent an XOFF
xofrcv	db	0			; Say if we received an XOFF
invseq	db	ESCAPE,'&dJ$'		; Reverse video
nrmseq	db	ESCAPE,'&d@$'		; Normal mode
ivlseq	db	80 dup (' '),ESCAPE,'A','$' ; [ak] Make a line inverse video
keydelay db 0				; delay for keyboard reads
tmp	db	0,'$'
temp	dw	0
temp1	dw	0
temp2	dw	0

eightstatustxt	db 'No. Bits: $'
eightflg	db eightbitnum
transparencytxt db 'Port Status: $'
transparentflg	db transonnum
rawtxt		db 'Port Mode: $'
rawflg		db rawonnum
tekstatustxt	db 'Tek Auto Entry: $'
tekbyte		db tekonnum	  ; tek auto entry
temp3		dw 0


; structure for status information table sttab.
stent	struc
sttyp	dw  0			; type (actually routine to call)
msg	dw  0			; message to print
val2	dw  0			; needed value: another message, or tbl addr
tstcel	dw  0			; address of cell to test, in data segment
basval	dw  0			; base value, if non-zero
stent	ends

			; table with datacomm status for the status command
vtstbl stent <srchkw,eightstatustxt,termtb,eightflg> ; tell 7 or 8 bits
stent <srchkw,transparencytxt,termtb,transparentflg> ; tell if transparent
stent <srchkw,rawtxt,termtb,rawflg>		; tell if raw or cooked
stent <srchkw,tekstatustxt,termtb,tekbyte>	; tell if raw or cooked
	dw 0					; end of table

; Entries for choosing communications port
comptab db	4				; four entries
	mkeyw	'1',1
	mkeyw	'2',2
	mkeyw	'COM1',1
	mkeyw	'COM2',2

port1	prtinfo	<0FFFH,0,defpar,1,0,defhand,floxon,0>
port2	prtinfo	<0FFFH,0,defpar,1,0,defhand,floxon,0>
portval	dw	port1			; Default is to use port 1

bdtab	db	 9	       		; baud rate table
	 mkeyw	 '110',0
	 mkeyw	 '150',1
	 mkeyw	 '300',2
	 mkeyw	 '600',3
	 mkeyw	 '1200',4
	 mkeyw	 '2400',5
	 mkeyw	 '4800',6
	 mkeyw	 '9600',7
	 mkeyw	 '19200',8

			 ; mappings for baud settings from hp to our table
ourbdtab db  0,0	   ; not applicable
	 db  1,0	   ; na
	 db  2,0	   ; 110
	 db  3,0	   ; na
	 db  4,1	   ; 150
	 db  5,2	   ; 300
	 db  6,3	   ; 600
	 db  7,4	   ; 1200
	 db  8,0	   ; na
	 db  9,0	   ; na
	 db  10,5	   ; 2400
	 db  11,0	   ; na
	 db  12,6	   ; 4800
	 db  13,0	   ; na
	 db  14,7	   ; 9600
	 db  15,8	   ; 19200
	 			; mappings for baud setting from our table to hp
ourbdtab1  db  0,2	   ; 300
	 db  1,4	   ; 150
	 db  2,5	   ; 300
	 db  3,6	   ; 600
	 db  4,7	   ; 1200
	 db  5,10	   ; 2400
	 db  6,12	   ; 4800
	 db  7,14	   ; 9600
	 db  8,15	   ; 19200


setchtab  db   1; set file character-set table
	mkeyw	  'CP437',437

sevenbitnum	equ 7
eightbitnum	equ 8
transonnum	equ 9
transoffnum	equ 10
rawonnum	equ 11
rawoffnum	equ 12
tekonnum	equ 13
tekoffnum	equ 14

termtb	db	10		   ; entries for Status, not Set
	mkeyw	'HP150',ttgenrc
	mkeyw	'Tek4014',tttek
	mkeyw	'7bit',sevenbitnum

	mkeyw	'8bit',eightbitnum
	mkeyw	'OnTransparency',transonnum
	mkeyw	'OffTransparency',transoffnum
	mkeyw	'Raw',rawonnum
	mkeyw	'Cooked',rawoffnum
	mkeyw	'EnableTek',tekonnum
	mkeyw	'DisableTek',tekoffnum


; variables for serial interrupt handler

source	db	bufsiz DUP(?)	; Buffer for data from port
bufout	dw	0		; buffer removal ptr
count	dw	0		; Number of chars in int buffer
bufin	dw	0		; buffer insertion ptr
telflg	db	0		; Are we acting as a terminal
clreol	db	ESCAPE,'K$'
prttab	dw	com1,com2
com1	db	'COM1',0
com2	db	'COM2',0
blank	db	ESCAPE,'H',ESCAPE,'J$'
movcur	db	ESCAPE,'&a'
colno	db	20 dup (0)
ten	db	10
prthnd	dw	0
argadr	dw	0		; address of arg blk from msster.asm
parmsk	db	0ffh		; 8/7 bit parity mask, for reception
flowoff db	0		; flow-off char, Xoff or null (if no flow)
flowon	db	0		; flow-on char, Xon or null
captrtn dw	cptchr		; routine to call for captured output
logflag db	false		; if true, we are logging session
; (we have taken cptchr from msster and placed in
; in msxhp1 to avoid flow control problems)
tempbuf dw	10 dup(0)
ourarg	termarg <>

;;new stuff to scan escape sequences from comm port  [jan]
stringtab	dw    tekst1,tekst2	 ; strings for matching
		dw    tekst3
numstrings	equ   3			; number of strings to match
disptab		dw    toteknoplay,totekplay	  ; dispatch table
		dw    leavetek
		dw    ignoreall, ignoreall
tekst1		db    escape,'[?38h',0	;1st string to get into tek mode [jan]
tekst2		db    escape,FF,0	;2nd string to get into tek mode [jan]
tekst3		db    escape,'[?38l',0	; string to exit tekmode
stringchekbuff	db	16 dup (0)
stringchekcnt	dw	 0		; characters already in buffer
matchsofar	dw	false		; no match yet
match		dw	0
playem		db	false		; don't play back switch characters
; end of data for string scannine
prtrdy		db	true	 ; if false, we get out of connect mode

capbuf		db	 cptsiz dup (0)	; session logging buffer
capbp		dw	 capbuf
caplft		dw	 cptsiz
capterr	    db escape,'Error in writing log file ','$'
alpha_disp  db escape,'&s0P',escape,'&s0Q','$'	      ; alpha active
tek_disp    db escape,'&s1P',escape,'&s0Q',escape,'*t1D','$' ; tek active
alpha_on    db escape,'*dE','$'	    ; turn on alpha display
alpha_off   db escape,'*dF','$'	    ; turn off alpha display
tek_on	    db escape,'*dC','$'	      ; turn on tek display
tek_off	    db escape,'*dD','$'	      ; turn off tek display
alpha_clear db escape,'H',escape,'J', '$' ; clear alpha
tek_clear   db escape,'*dA',escape,'*dL',escape,'*d0,380O','$'; clear tek
to_term_msg db 'Entering Firmware terminal '
	    db 'Press SHIFT STOP to return to Kermit','$'

;;;; Data for reading data comm configuration in firmware
;*******************************************
;
e_cnp_rom_segment equ 0000h
e_cnp_entry equ 045ch
e_dhp_entry equ 0425h
e_dhp_driver equ 042ah
e_long_call equ 09ah
;
e_port1_read	equ 2
e_port2_read	equ 4
e_port1_save	equ 2
e_port2_save	equ 11

e_port1	equ 1			 ; values for the two physcial ports.
e_port2 equ 2

e_true equ 1
e_false equ 0
;
;************** LOCAL DECLARATIONS **************
;
;
CONFIGURATION_DATA_AREA struc
predef_values db ?
barrel_index db ?
dc_port db ?
dc_bool1 db ?
dc_bool2 db ?
dc_baud_rate db ?
dc_parity db ?
dc_clock db ?
dc_asterisk db ?
dc_recv_pace db ?
dev_token  dw ? 
CONFIGURATION_DATA_AREA ends

dc_status_struc struc		; status for datacomm
eightbit	db 0		; true if 8 bit, false if 7 bit
transparent	db 0	  ; true if transparent, false if not transparent
raw		db 0		; true if raw, false if cooked
dc_status_struc ends

; scratch space.
;
err_flag	db 0
readid		dw 0
saveid		dw 0
work_config CONFIGURATION_DATA_AREA	<>
dc_status dc_status_struc <true,true,true>

;
;************************************
;
; Macros for absolute long calls.
;
;************************************
;
call_cnp_entry macro
	db  e_long_call
	dw  e_cnp_entry
	dw  e_cnp_rom_segment
endm
call_dhp_entry macro
	db  e_long_call
	dw  e_dhp_entry
	dw  e_cnp_rom_segment
endm

call_dhp_driver macro
	db  e_long_call
	dw  e_dhp_driver
	dw  e_cnp_rom_segment
endm
baud_port equ 0ch    ; port address of baud rate controller
;
; table to print out value of a nibble on the screen
asciitab  db '0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'
;
porta_baud	db 0	     ; stored baud codes
portb_baud	db 0
start_porta_baud db 0
start_portb_baud db 0
data   ends


code	segment public 'code'
	extrn	comnd:near, dopar:near, atoi:near, prompt:near
	extrn	sleep:near,statc:near, srchkw:near
	extrn	msuinit:near, keybd:near		; in msuhp1.asm
	extrn	keybdopen:near, keybdclose:near		; in msuhp1.asm
	extrn	getkey:near				; in msuhp1.asm
	extrn	clearlabels:near, labelsoftkeys:near	; in msuhp1.asm
	extrn	displaylogoffkey:near, displaylogonkey:near ; in msuhp1
	extrn	pntchr:near, pntflsh:near

	assume	cs:code, ds:data, es:nothing

; Clear the input buffer before sending a packet.

CLRBUF	PROC	NEAR
	cmp	 repflg,0		; doing replay?
	je	 clrb0			; e => no replay
	ret				; don't clear if replaying
clrb0:	push	 ax			; need to save for CROSHAIR in msggri
	cli
	mov	ax,offset source
	mov	bufin,ax
	mov	bufout,ax
	mov	count,0
	sti
clrb1:	call	prtchr			; get a character
	jnc	clrb1			; until there aren't any more
	nop
	pop	ax
	ret
CLRBUF	ENDP

; Common routine to clear to end-of-line

CLEARL	PROC	NEAR
	push	ax
	push	dx
	mov	dx,offset clreol
	mov	ah,prstr
	int	dos
	pop	dx
	pop	ax
	ret
CLEARL endp

; Set the baud rate for the current port, based on the value
; in the portinfo structure.  Returns carry clear.

BAUDST	PROC	NEAR
	mov	dx,offset bdtab		; baud rate table, ascii
	xor	bx,bx			; help is the table itself
	mov	ah,cmkey		; get keyword
	call	comnd
	jc	baudst1			; c = failure
	push	bx			; save result
	mov	ah,cmeol		; get confirmation
	call	comnd
	pop	bx
	jc	baudst1			; c = failure
	mov	si,portval
	mov	ax,[si].baud		; remember original value
	mov	[si].baud,bx		; set the baud rate
	call	dobaud			; use common code
	clc
baudst1:ret
BAUDST	ENDP

				; on entrance bx has baud rate from bdtab
dobaud	proc	near		; updated by [jan] to set baud
	mov	ax,portval
	cmp	ax,offset port1 ; using port 1?
	jne	dobaud1		; ne => not using port 1
	mov	al,1		; port 1 set
	mov	ah,bl		; baud code
	call	set_baud	; set the baud rate
	ret
dobaud1:mov	al,2		;  set port 2 baud
	mov	ah,bl		; ah has baud code
	call	set_baud
	ret
dobaud endp

; Send the break signal out data comm
sendbl:					; long break (same as regular h
sendbr: mov	al,e_send_break		; regular break
	call	dc_ioctl
	clc				; clear carry bit (stay in Connect)
	ret

; Set some data comm ioctl option.  AL has function code
dc_ioctl proc	near
	push	ax			; save regs
	push	bx
	push	cx
	push	dx
	mov	ah,8h
	mov	tempbuf,ax
	mov	dx,offset tempbuf
	mov	ah,e_ioctl
	mov	al,3
	mov	bx,prthnd
	mov	cx,2
	int	dos
	pop	dx			; restore regs
	pop	cx
	pop	bx
	pop	ax
	ret
dc_ioctl endp

shomodem proc	near
	mov	ah,cmeol	; get a confirm
	call	comnd
	jnc	shomod00	; nc => success
	ret			; get out if failure
shomod00:
	cmp	prthnd,0	; Got a handle yet?
	jne	shmod0		; Yup just go on
	call	opnprt		; Else 'open' the port
shmod0: mov	dx,offset msmsg1 ; say port is not ready
	mov	bx,prthnd
	mov	al,7		; output status command
	mov	ah,ioctl	; ask DOS to look for us
	int	dos
	jc	shmod1		; c = call failed, device not ready
	or	al,al
	jz	shmod1		; not ready
	mov	dx,offset msmsg2 ; say port is ready
shmod1: mov	ah,prstr
	int	dos
	clc
	ret
shomodem endp

getmodem proc near
	mov	al,0
	ret
getmodem endp

; Put the char in AH to the serial port.  This assumes the
; port has been initialized.  Should honor xon/xoff.  Skip returns on
; success, returns normally if the character cannot be written
outchr	proc	near
	push	cx
	or	ah,ah		; sending a null?
	jz	outch2		; z = yes
	xor	cx,cx		; clear counter
	cmp	ah,flowoff	; sending xoff?
	jne	outch1		; ne = no
	mov	xofsnt,false	; supress xon from chkxon buffer routine
outch1: cmp	xofrcv,true	; Are we being held?
	jne	outch2		; No - it's OK to go on
	loop	outch1		; held, try for a while
	mov	xofrcv,false	; timed out, force it off and fall thru
outch2: push	dx		; Save register
	mov	al,ah		; Parity routine works on AL
	call	dopar		; Set parity appropriately
				; Begin revised output routine
	mov	byte ptr temp,al ; put data there
	cmp	prthnd,0	; Got a handle yet?
	jne	outch3		; Yup just go on
	call	opnprt		; Else 'open' the port
outch3: push	bx
	mov	bx,prthnd	; port handle
	mov	cx,1		; one byte to write
	mov	dx,offset temp	; place where data will be found
	mov	ah,write2	; dos 2 write to file/device
	int	dos
	pop	bx		; restore registers
	pop	dx
	pop	cx
	clc
	ret
outchr	endp

; Get a file handle for the communications port.  Use DOS call to get the
; next available handle.  If it fails, ask user what value to use (there
; should be a predefined handle for the port, generally 3).  The open
; will fail if the system uses names other than "COM1" or "COM2".
opnprt	proc  near
	mov	al,flags.comflg
	dec	al		; flags.comflg is 1 for com1, 2 for com2
	mov	ah,0
	push	si
	mov	si,ax
	shl	si,1			; double index
	mov	dx,prttab[si]
	pop	si
	mov	ah,open2
	mov	al,2
	int	dos
	jnc	opnpr2
	mov	ah,prstr		; it didn't like the string
	mov	dx,offset erms41
	int	dos
	ret
opnpr2: mov	prthnd,ax		; Call succeeded
	call	set_port_param		; set appropriate parameters
	call	serini			; set appropriate parameters
	ret
opnprt	endp

; This routine blanks the screen.

CMBLNK	PROC	NEAR		; This is stolen from the IBM example
	push	ax
	push	dx
	mov	ah,prstr
	mov	dx,offset blank
	int	dos
	pop	dx
	pop	ax
	ret
CMBLNK	ENDP

LOCATE	PROC	NEAR
	mov	dx,0		; Go to top left corner of screen
	jmp	poscur		; Go and move the cursor
LOCATE	ENDP

; To get the baud, it is likely we would need to 
; directly access the UART. Not implemented.
GETBAUD PROC	NEAR
	ret
GETBAUD ENDP


; Carry set if no character available at the port. If carry clear,
; returns with char in al, # of chars in buffer in dx.

PRTCHR	PROC	NEAR
	cmp	repflg,0	; doing replay?
	je	prtch0		; e=> not doing replay
	jmp	getrepchr	; get replay character if in replay
prtch0:
	push	bx
	push	cx
	push	si
	cmp	prthnd,0	; have a handle yet?
	jne	prtch1		; yes, keep going
	call	opnprt
prtch1: cmp	count,0		; no characters?
	jne	prtch2		; no, go fill buffer
	mov	bx,prthnd
	mov	al,rdchan
	mov	ah,ioctl
	mov	dx,offset source ; buffer to read into
	mov	cx,20		; read 20 characters at a time
				; More characters cause problems for
				; early firmware versions
	int	dos
	jc	prtch4		; c = error
	mov	count,ax	; reset count
	mov	keydelay, -1	; read keyboard next go around
	mov	dx,ax		; needed to obey rules
	or	ax,ax
	jz	prtch4		; still no chars
	mov	bufout,offset source ; this is output ptr
prtch2: dec	count
	mov	dx,count	; return count in dx
	mov	si,bufout
	cld
	lodsb			; get character
	mov	bufout,si	; update ptr
prtch3: pop	si
	pop	cx
	pop	bx
	clc			; clc if there is a character
	ret			; exit success
prtch4: pop	si
	pop	cx
	pop	bx
	stc			 ; set carry if no characters
	ret
PRTCHR	ENDP

; IHOSTS - Initialize the host by sending XON, or equivalent, and enter the
; cycle of clear input buffer, wait 1 second, test if buffer empty then exit
; else repeat cycle. Requires that the port be initialized before hand.
; Ihosts is used by the local send-file routine just after initializing
; the serial port.
; 22 March 1986 [jrd]

IHOSTS	PROC	NEAR
	push	ax		; save the registers
	push	bx
	push	cx
	push	dx
	mov	bx,portval	; port indicator
	mov	ax,[bx].flowc	; put Go-ahead flow control char in ah
	or	ah,ah		; don't send null if flow = none
	jz	ihosts1		; z = null
	call	outchr		; send it (release Host's output queue)
ihosts1:call	clrbuf		; clear out interrupt buffer
	pop	dx		; empty buffer. we are done here
	pop	cx
	pop	bx
	pop	ax
	ret
IHOSTS	ENDP

; IHOSTR - initialize the remote host for our reception of a file by
; sending the flow-on character (XON typically) to release any held
; data. Called by receive-file code just after initializing the serial
; port.		22 March 1986 [jrd]
IHOSTR	PROC	NEAR
	push	ax		; save regs
	push	bx
	push	cx
	mov	bx,portval	; port indicator
	mov	ax,[bx].flowc	; put Go-ahead flow control char in ah
	or	ah,ah		; don't send null if flow = none
	jz	ihostr1		; z = null
	call	outchr		; send it (release Host's output queue)
ihostr1:pop	cx
	pop	bx
	pop	ax
	ret
IHOSTR	ENDP

DTRLOW	PROC	NEAR		; Global proc to Hangup the Phone by making
	mov	ah,cmline	; allow text to be able to display help
	mov	bx,offset rdbuf	; dummy buffer
	mov	dx,offset hnghlp ; help message
	call	comnd		; get a confirm
	jnc	dtrlow1		; nc => success
	ret			; get out if failure
dtrlow1:call	serhng		; drop DTR and RTS
	writestring hngmsg	; tell user of success
	clc			; success
	ret
DTRLOW	ENDP

; Hang up the Phone. Similar to SERRST except it just forces DTR and RTS low
; to terminate the connection. 29 March 1986 [jrd]
; Calling this twice without intervening calls to serini should be harmless.
; Returns normally. Implemented by [jan].
SERHNG	PROC	NEAR
	 mov	al,5			; modem disconnect code
	 call	dc_ioctl
	 clc				; stay in connect mode
	 ret
SERHNG	ENDP

; Position the cursor according to contents of DX

POSCUR	PROC	NEAR
	push	ax			; save regs
	push	dx
	push	di
	push	es
	mov	ax,ds
	mov	es,ax			; address data segment
	cld
	mov	di,offset colno
	mov	al,dl			; column
	call	nout
	mov	al,'c'
	stosb
	mov	al,dh			; row
	call	nout
	mov	al,'Y'
	stosb
	mov	al,'$'
	stosb
	mov	dx,offset movcur
	mov	ah,prstr
	int	dos			; print the sequence
	pop	es			; restore regs
	pop	di
	pop	dx
	pop	ax
	ret
POSCUR	ENDP

NOUT	PROC	NEAR
	cbw			; extend to word
	div	byte ptr ten	; divide by 10
	or	al,al		; any quotient?
	jz	nout1		; no, forget this
	push	ax		; save current result
	call	nout		; output high order
	pop	ax		; restore
nout1:	mov	al,ah		; get digit
	add	al,'0'		; make printable
	stosb
	ret			; put in buffer and return
NOUT	endp

; Write a line in inverse video at the bottom of the screen...
; the line is passed in dx, terminated by a $.	Returns normally.
putmod	proc	near
	push	dx		; preserve message
	mov	dx,24 * 100H	; line 24
	call	poscur
	mov	dx,offset invseq ; put into inverse video
	mov	ah,prstr
	int	dos
	pop	dx
	int	dos
	mov	dx,offset nrmseq ; normal videw
	int	dos
	ret			; and return
putmod	endp

; Clear the mode line written by putmod.  Returns normally.
clrmod	proc	near
	mov	dx,24 * 100H
	call	poscur
	call	clearl
	ret
clrmod	endp

; Put a help message one the screen in reverse video.  Pass
; the message in AX, terminated by a null.  Returns normally.
; The message is put wherever the cursor currently is located.
puthlp	proc	near
	push	ax			; save some regs
	push	si
	push	dx
	push	ax
	mov	ah,prstr		; Leave some room before the message
	mov	dx,offset crlf
	int	dos
	pop	si			; Put message address here
puth0:	mov	ah,prstr
	mov	dx,offset invseq	; Put into reverse video
	int	dos
	mov	ah,prstr
	mov	dx,offset ivlseq	; Make line inverse video
	int	dos
	cld
puth1:	lodsb
	cmp	al,0			; Terminated with a null
	je	puth2
	mov	dl,al
	mov	ah,conout
	int	dos
	cmp	al,lf			; Line feed?
	je	puth0			; e = yes, clear the next line
	jmp	puth1			; else, just keep on writing
puth2:	mov	dx,offset crlf
	mov	ah,prstr
	int	dos
	mov	dx,offset nrmseq	; Normal video
	int	dos
	pop	si
	pop	dx
	pop	ax
	ret
puthlp	endp

; Perform a delete.

DODEL	PROC	NEAR
	push	ax
	push	dx
	mov	ah,prstr
	mov	dx,offset delstr	; Erase character
	int	dos
	pop	dx
	pop	ax
	ret
DODEL	ENDP

; Perform a Control-U.

CTLU	PROC	NEAR
	push	ax
	push	dx
	mov	ah,prstr
	mov	dx,offset clrlin
	int	dos
	pop	dx
	pop	ax
	ret
CTLU	ENDP

COMS	PROC	NEAR
	mov	dx,offset comptab	; comms port table
	mov	bx,0			; use keywords as help
	mov	ah,cmkey		; parse keyword
	call	comnd
	jnc	coms1			; nc => success
	ret				; get out if failure
coms1:	push	bx
	mov	ah,cmeol
	call	comnd			; Get a confirm
	jc	comx			; didn't get a confirm
	call	serrst			; close existing port before opening
	pop	bx			; the new one
	mov	flags.comflg,bl		; Set the comm port flag
	cmp	flags.comflg,1		; Using Com 1?
	jne	coms2			; ne = no
	mov	portval,offset port1
	call	serini			; initialize new port
	ret
coms2:	mov portval,offset port2	; use Com2
	call serini			; initialize port
	ret
comx:	pop bx
	ret
COMS	ENDP

VTS	PROC	NEAR			; Set Term code
	mov	dx, offset termtb
	mov	bx,0
	mov	ah,cmkey
	call	comnd
	jnc	vts1			; nc => success
	ret				; return if failure
vts1:	push	bx
	mov	ah,cmeol
	call	comnd
	jnc	vts2			; nc=> success
	pop	bx
	ret				; return if failure
vts2:	pop	bx			; bl has number from termtb
	mov	di,offset dc_status
	cmp	bl,eightbitnum		; doing 8 bits?
	jne	vts3
	mov	[di].eightbit,true
	call	set_port_param		; set port parameters
	clc
	ret
vts3:	cmp	bl,sevenbitnum		; doing 7 bits?
	jne	vts4			; ne => not 7 bits
	mov	[di].eightbit,false
	call	set_port_param		; set port parameters
	clc
	ret
vts4:	cmp	bl,transonnum		; transparency on?
	jne	vts5
	mov	[di].transparent,true
	call	set_port_param		; set port parameters
	clc
	ret
vts5:	cmp	bl,transoffnum		; transparency off?
	jne	vts6
	mov	[di].transparent,false
	call	set_port_param		; set port parameters
	clc
	ret
vts6:	cmp	bl,rawonnum		; make port raw?
	jne	vts7
	mov	[di].raw,true
	call	set_port_param		; set port parameters
	clc
	ret
vts7:	cmp	bl,rawoffnum		; cook the port?
	jne	vts7a
	mov	[di].raw,false
	call	set_port_param		; set port parameters
	clc
	ret
vts7a:	cmp	bl,tekonnum		; enable tek?
	jne	vts7b			; ne => don't enable
	and	denyflg,not tekxflg	; clear tekx bit
	mov	tekbyte,bl		; for status display
	clc
	ret
vts7b:	cmp	bl,tekoffnum		; disable tek
	jne	vts8			; ne => don't disable
	or	denyflg,tekxflg		; set tek deny bit
	mov	tekbyte,bl		; for status display
	clc
	ret
vts8:	cmp	bl,ttgenrc		; hp150 emulation selected?
	jne	vts9
	mov	flags.vtflg,bl		; set emulator type
	clc
	ret
vts9:	cmp	bl,tttek		; tek emulation selected?
	jne	vts10
	mov	flags.vtflg,bl
vts10:	clc
	ret				; success
VTS	ENDP


VTSTAT	PROC	NEAR			; For Status display
	mov	bx,offset vtstbl	; table of things to show
	jmp	statc			; common status code
VTSTAT	ENDP

; Save the screen to a buffer and then append buffer to a disk file. [jrd]
; Default filename is Kermit.scn; actual file can be a device too. Filename
; is determined by mssset and is passed as pointer dmpname.

DUMPSCR PROC	NEAR	; Dumps screen contents to a file. Just Beeps here
	call	beep
	ret
DUMPSCR ENDP


lclini proc near
	saveregs
	call	read_baud		; use firmware to read baud rates
	mov	lclexit,offset lclose	; routine to call when closing
	mov	prtrdy,true		; port is ready
	mov	flags.vtflg,0		; no terminal emulation. [jrd]
	mov	prthnd,0		; no port handle yet. [jrd]
	call	msuinit			; initialize keyboard module msugen
	call	serini			; initialize port
	restoreregs
	ret
lclini	endp



; Wait for the # of milliseconds in ax, for non-IBM compatibles.
; Thanks to Bernie Eiben for this one.
pcwait	proc	near
	mov	cx, 180		; hp150 has effective clock of only 3.6 MHz!!!
pcwai1: sub	cx,1		; inner loop takes 20 clock cycles
	jnz	pcwai1
	dec	ax		; outer loop counter
	jnz	pcwait		; wait another millisecond
	ret
pcwait	endp

; Initialization for using serial port.	 Returns normally.
; Attempts to put port device in binary mode. [jrd]
SERINI	PROC	NEAR
	cld			; Do increments in string operations
	cmp prthnd,0		; Got a handle yet?
	jne serin0

	push bx
	call opnprt		; Else 'open' the port
	pop bx
serin0: push bx
	mov bx,portval		; get port [jrd]
	mov parmsk,0ffh		; parity mask, assume parity is None
	cmp [bx].parflg,parnon	; is it None?
	je serin1		; e = yes
	mov parmsk,07fh		; no, pass lower 7 bits as data
serin1: mov bx,[bx].flowc	; get flow control chars
	mov flowoff,bl		; xoff or null
	mov flowon,bh		; xon or null
	pop bx
	clc			; carry clear for success
	ret
SERINI	ENDP

SERRST	PROC	NEAR
	 push bx		 ; save reg
	push di
	mov bx,prthnd
	cmp bx,0		; none there?
	je serrs6		; no, don't try to close
; return the port to the orignal status
	mov bx, prthnd		; handle
	call  cookedon		; cook the port first
	mov al, e_port1		; assume port 1
	mov bx, offset port1
	cmp portval, bx		; are we using port 1?
	je  serrs2
	mov al, e_port2	       ; using port 2
serrs2: call get_config_values ; read configuration di points to work_config
	mov  al, 1	       ; assume 7 bit mode
	test [di].dc_bool2, 2	; if bit2 set => 7 bit
	jnz serrs3	       ; nx => yes 7 bit
	mov al,2	       ; 2 for 8 bit
serrs3: call dc_ioctl	       ; update the number of bits
	mov al, 4	       ; disable data comm transparency
	call dc_ioctl
	mov bx, prthnd		; port handle in bx for close
	mov ah,close
	int dos			; close handle
	mov prthnd,0		; the port is now closed
serrs6: pop di
	pop bx
	ret			; All done
SERRST	ENDP

; Generate a short beep.

BEEP	PROC	NEAR
	mov dl,bell
	mov ah,conout
	int dos
	ret
BEEP	ENDP

; Dumb terminal emulator.  Doesn't work too well above 1200 baud (and
; even at 1200 baud you sometimes lose the first one or two characters
; on a line). Does capture (logging), local echo, debug display, tests
; for printer/logging device not ready. 27 Sept 86 [jrd].
term	proc	near
	mov	argadr,ax		; save argument ptr
	mov	si,ax			; this is source
	mov	di,offset ourarg	; place to store arguments
	push	es			; save register
	push	ds
	pop	es			; make es point to datas segment
	mov	cx,size termarg
	cld
	rep	movsb			; copy into our arg blk
	pop	es			; recover reg
	mov	ax,ourarg.captr
;;;	   mov captrtn,ax		; buffer capture routine
	call	pntflsh			; flush printer buffer
	mov	keydelay,0		; initizize keyboard counter [jan]
	mov	parmsk,0ffh		; parity mask, assume parity = None
	call	keybdopen		; turn on keycode mode
	call	labelsoftkeys
	call	displaylogkey	; decide whehter to display logging softkey
	cmp	flags.vtflg,tttek	; in tektronix emulation?
	jne	term0			; ne=> doing alpha
	call	tekini			; initialize emulator

term0:	mov	parmsk,0ffh		; 8 bit parity by default
	cmp	ourarg.parity,parnon	; is parity None?
	je	term1			; e = yes, keep all 8 bits
	mov	parmsk,07fh		; else keep lower 7 bits

term1:	cmp	prtrdy,false		; ready to read port?
	jne	term2		 	; ne = yes
	mov	kbdflg,'C'	 	; so we exit connect mode
	mov	prtrdy,true	 	; get ready for next connect
	jmp	term5		 	; get out
term2:	call	portchr			; get char from port, mask parity
	jnc	short term4		; nc = no char, go on
	call	stringchek		; check the string for escape sequence
	jnc	short term4		; nc => no key to show
term3:	call	outtty	  		; display and capture char
term4:	inc	keydelay		; increment counter
	mov	ah,keydelay		; move into ah
	and	ah,15			; clear high bits and read keyboard
	jne	term1			; once each 16 reads of serial port
	call	keybd			; call keyboard translator in msu
	jnc	term1			; nc = no char or have processed it
term5:					; carry set = quit Connect mode
	call	pntflsh			; flush printer buffer
	call	clearlabels		; blank softkey labels
	call	keybdclose		; turn off keycode mode
	writestring alpha_disp		; make sure we are in alpha upon exit
	writestring alpha_on		; turn on alpha
	writestring tek_off		; turn off tek
	call	test_baud_change	; check for baud change
	call	cptdmp			; empty the capture buffer
	ret
term	endp


; put the character in al to the screen, do capture and printing,
; does translation for Set Input command.
; Adapted from msyibm.asm [jrd]
outtty	proc	near
	test	flags.remflg,d8bit	; keep 8 bits for displays?
	jnz	outnp8			; nz = yes, 8 bits if possible
	and	al,7fh			; remove high bit
outnp8: cmp	rxtable+256,0		; is translation off?
	je	outnp7			; e = yes, off
	push	bx			; Translate incoming char
	mov	bx,offset rxtable	; address of translate table
	xlatb				; new char is in al
	pop	bx
outnp7:	cmp	logflag,true		; are we logging?
	jne	outnoc			; ne => no, forget logging
	push	ax			; save char
	call	captrtn			; give it captured character
	pop	ax			; restore character and keep going
outnoc:	test	anspflg,prtscr		; should we be printing?
	jz	outnop			; no, keep going
	call	pntchr			; queue char for printer
	jnc	outnop			; nc = successful print
	push	ax
	call	beep			; else make a noise and
	call	trnprs			;  turn off printing
	pop	ax
outnop: cmp	flags.vtflg,0		; emulating a terminal?
	jnz	outnop1			; nz = yup, go do something smart
	test	ourarg.flgs,trnctl	; debug? if so use dos tty mode
	jz	outnp4			; z = no
	mov	ah,conout
	cmp	al,7fh			; Ascii Del char or greater?
	jb	outnp1			; b = no
	je	outnp0			; e = Del char
	push	ax			; save the char
	mov	dl,7eh			; output a tilde for 8th bit
	int	dos
	pop	ax			; restore char
	and	al,7fh			; strip high bit
outnp0: cmp	al,7fh			; is char now a DEL?
	jne	outnp1			; ne = no
	and	al,3fH			; strip next highest bit (Del --> '?')
	jmp	outnp2			; send, preceded by caret
outnp1: cmp	al,' '			; control char?
	jae	outnp3			; ae = no
	add	al,'A'-1		; make visible
outnp2: push	ax			; save char
	mov	dl,5eh			; caret
	int	dos			; display it
	pop	ax			; recover the non-printable char
outnp3: mov	dl,al
	int	dos
	ret
outnp4: ;cmp	 al,bell		 ; bell (Control G)?
	;jne	 outnp5			 ; ne = no
	;jmp	 beep			 ; use short beep, avoid char loss
outnop1:
outnp5:	 
	mov	dl,al			 ; write without intervention
	mov	ah,6			; direct console i/o
	int	dos			; else let dos display char
	ret				; and return
outtty	endp


; send the character in al out to the serial port; handle echoing.
; Can send an 8 bit char while displaying only 7 bits locally.
outprt	proc	near
	test	ourarg.flgs,lclecho	; echoing?
	jz	outpr1			; z = no, forget it
	push	ax			; save char
	call	outtty			; print it
	pop	ax			; restore
outpr1: mov	ah,al			; this is where outchr expects it
	call	outchr			; output to the port
	ret
outprt	endp

; Get a char from the serial port manager
; returns with carry on if a character is available
portchr proc	near
	call	prtchr			; character at port?
	jnc	portc1			; nc = yes there is a character
portc0: clc				; no carry -> no character
	ret				; and return
portc1: and	al,parmsk		; apply 8/7 bit parity mask
	stc				; have a character
	ret				; and return
portchr endp

;; keyboard translator action routines, system dependent, called from msugen.
; These are invoked by a jump instruction. Return carry clear for normal
; processing, return carry set to exit Connect mode (kbdflg has transfer char)

chrout	proc	near
	cmp	repflg,0		; in replay mode?
	je	chrout1			; e=> not doing replay
	jmp	repchrout		; display the replay character
chrout1:call	outprt			; put char in al to serial port
	clc				; stay in Connect mode
	ret
chrout	endp

trnprs:	push	ax			; toggle Copy screen to printer
	test	anspflg,prtscr		; should we be printing?
	jnz	trnpr2			; nz = yes, its on and going off
	mov	ah,ioctl
	mov	al,7			; get output status of printer
	push	bx
	mov	bx,prnhand		; file handle for system printer
	int	dos
	pop	bx
	jc	trnpr1			; c = printer not ready
	cmp	al,0ffh			; Ready status?
	je	trnpr2			; e = Ready	
trnpr1:	call	beep			; Not Ready, complain
	jmp	short trnpr3		; and ignore request
trnpr2:	xor	anspflg,prtscr		; toggle print flag
trnpr3:	pop	ax
	clc
	ret

displaylogkey  proc near		; display logging softkey?
	test	flags.capflg, logses	; session logging enables?
	jz	displaylogkey3		; z= no, forget it
	cmp	logflag, true		; are we logging?
	jne	displaylogkey1		; ne => not logging
	call	 displaylogoffkey	  ; off key if capturing
	jmp	 displaylogkey2	       ; make a good exit
displaylogkey1:
	call   displaylogonkey	       ; show log on function key
displaylogkey2:
	clc
	ret
displaylogkey3:
	mov  logflag, false	 ; not logging
	clc
	ret
displaylogkey  endp

klogtog	 proc	near			; toggle session logging key
	test	flags.capflg, logses	; session logging enables?
	jz	klogtogn		; z= no, forget it
	cmp	logflag, true		; are we capturing?
	jne	klogtog1		; ne => not logging
	mov	logflag, false		; turn off loggin
	push	bx
	mov	bx, argadr
	and	[bx].flgs, not capt	; tell kermit we are stopping capture
	and	ourarg.flgs, not capt	; turn off local capture flag
	pop	bx			; restore the register
	call	displaylogkey		; turn on appropriate log key
	call	cptdmp			; dump the capture buffer to file
	jmp	klogtog2
klogtog1:
	 mov	logflag, true		 ; turn on logging
	push	bx
	mov	bx, argadr
	or	[bx].flgs, capt	       ; tell kermit we are resuming capture
	or	ourarg.flgs, capt      ; turn on local capture flag
	pop	bx		       ; restore the register
	call  displaylogkey	      ; turn on log off key
klogtog2: clc
	  ret
klogtogn: mov logflag, false	       ; not logging so turn off flag
	  clc
	  ret
klogtog	  endp


snull:	mov	ah,0			; send a null
	call	outchr			; send without echo or logging
	clc
	ret

kdos:	mov	al,'P'			; Push to DOS
	jmp	short cmdcom
cstatus:
	 mov	 al,'S'			 ; these commands exit Connect mode
	jmp	short cmdcom
cquit:
	 mov	 al,'C'
	jmp	short cmdcom
cquery:
	mov	al,'?'
	jmp	short cmdcom
cmdcom: mov	kbdflg,al		; pass char to msster.asm via kbdflg
	stc				; say exit Connect mode
	ret
					;; end of action routines

; set comm port parameters based on dc_status structure
set_port_param proc near
	push	di
	cmp	prthnd,0			; got a handle yet
	jne	set_port_param1			; ne = yes
	call	opnprt
	jmp	set_port_param5		; opnprt calls this so don't repeat
set_port_param1:
	mov	di,offset dc_status
	cmp	[di].eightbit,true		; doing 8 bit?
	je	set_port_param2			; e=> yes, doing 8 7 bit
	mov	eightflg,sevenbitnum	; so status knows we have seven bits
	mov	al,1				; dc_ioctl code  for 7 bit
	call	dc_ioctl
	jmp	set_port_param2a		; check transparent
set_port_param2:
	mov	eightflg,eightbitnum	; so status knows we have eight bits
	mov	al,2				; code for 8 bit
	call	dc_ioctl
set_port_param2a:
	cmp	[di].transparent,true		; in transparency mode?
	je	set_port_param3			; e=> yes
	mov	transparentflg,transoffnum ; so status knows transparency off
	mov	al,4				; code to disable transparency
	call	dc_ioctl
	jmp	set_port_param3a		; check raw/cooked situation
set_port_param3:
	mov	transparentflg,transonnum  ; so status knows transparency on
	mov	al,3				; code to enable transparency
	call	dc_ioctl
set_port_param3a:
	cmp	[di].raw,true			; raw mode set?
	je	set_port_param4			; e => raw on
	mov	rawflg,rawoffnum		; so status knows we're cooked
	mov	bx,prthnd			; cooked on needs port handle
	call	cookedon
	jmp	set_port_param5			; done
set_port_param4:
	mov	rawflg,rawonnum			; tell status port is raw
	mov	bx,prthnd			; port handle for raw on
	call	rawon
set_port_param5:
	pop	di
	clc
	ret
set_port_param endp

;check string to see if we need to do something special

stringchek  proc  near
       cmp   stringchekcnt,0	 ; nobody in yet?
       jne   stringchek1	 ; ne => already have characters
       cmp   al,escape		 ; is this escape?
       je    stringchek1	 ; it is escape, so go and process
       cmp   al,escape+80h	 ; in case parity is odd
       je    stringchek1	 ; process escape
       stc			 ; display the character
       ret			 ; return quickly if nothing to do
stringchek1:			 ; here is escape already in
       saveregs
       and     al,07fh		 ;strip high bit
       mov     bx,stringchekcnt
       mov     stringchekbuff[bx],al  ;put character in buffer
       inc     stringchekcnt	      ;one more character in buffer
       call    stringtest	 ; does the string in stringchekbuff match?
       cmp	match,0		 ; 0 means no match
       je      stringchek2
       mov     si,match		   ; here means we have a match
       shl     si,1		   ; multiply by 2
       dec     si
       dec     si		   ; 1=0, 2=1 etc
       call    disptab[si]	   ; call appropriate function
       call    stringbuffplay	      ; play back the buffer
       clc			   ; don't display
       jmp     stringchek3	   ; return and don't display character
stringchek2:
	 clc			  ; don not display
	 cmp   matchsofar,true	  ; do we have a match so far
	 je    stringchek3	     ; e=true , get out
	 mov   playem,true
	 call  stringbuffplay	       ; clean out the buffer
	 clc			   ; don't display character
stringchek3:
	 restoreregs
	 ret
stringchek   endp

;test to see if input string is a match to toggle terminal  [jan]


; stringtab gives addresses of 0 terminated strings
; teststring in stringchekbuff
; numstrings is the number to checked
; matchsofar will have be true if there is a possilbe match
; match will be non-zero 1, 2, 3 indicating number of match if a match
; if no match yet, match will be 0
; severaal registers get destroyed
stringtest proc near
	mov	matchsofar,false	; assume no match
	mov	match,0			; no match
	xor	si,si			; pointer to string tab
	dec	si
	dec	si			; step back 1 item
	mov	cx,0			; cx points to number of string
strtst1:
	inc	cx			; strings number
	cmp	cx,numstrings		; done parsing table?
	ja	strtst5			; we're done, get out of here
	mov	di,offset stringchekbuff
	inc	si
	inc	si			; point to next item
	mov	bx,stringtab[si]	; offset of string
strtst2:
	mov	al,[di]			; stringchekbuff in al
	mov	ah,[bx]			; string element to test in ah
	cmp	al,0			; end of stringchekbuff
	jne	strtst2a		; ne=> not at end of buffer
	mov	matchsofar,true		; we have a match so far
	jmp	strtst5			; return to caller
strtst2a:
	cmp	ah,0			; at end of string?
	je	strtst1			; failure, go to next string
	cmp	ah,al			; match?
	jne	strtst1			; no match, on to next string
					; here if match
	mov	ah,[bx+1]		; next byte from string
	cmp	ah,0			; are we done with string?
	je	strtst3			; e => yes, a match
	inc	bx			; next element in string
	inc	di			; next character in stringchekbuff
	jmp	strtst2			; check next item in string
strtst3:				; here if we have a match
	 mov	match,cx
	 mov	matchsofar,true
strtst5:ret
stringtest endp



;play back characters in string buffer ..called by stringchek
stringbuffplay proc near
	xor      bx,bx
	mov      cx,stringchekcnt
stringbuffplay1:
	mov	al,stringchekbuff[bx]
	cmp	playem,true		; playback characters?
	jne	stringbuffplay2		; ne = no don't play back
	push	bx			; save index
	push	cx			; save count
	call	outtty			; print the character
	pop 	cx			; restore count
	pop 	bx			; restore index
stringbuffplay2:
	mov      stringchekbuff[bx],0	; set to 0
	inc      bx			; point to next character
	loop     stringbuffplay1	; repeat until buffer is empty
	mov      stringchekcnt,0	; now no characters in buffer
	ret
stringbuffplay endp

ignoretek proc near	       ; ignore this escape sequence in tek mode
	mov	playem,false
	cmp	flags.vtflg,tttek      ; are in in tek emulation
	je	ignoretek1	       ; e=yes do not play back
	mov	playem,true
ignoretek1:ret
ignoretek endp

ignoreall proc near			; always ignore this escape sequence
	mov	playem,false
	call	beep	 		; let user know of illegal sequence
	ret
ignoreall endp

totekplay proc near			; turn on tektronix
	mov	playem,true	 	; play back characters
	jmp	totek
totekplay endp

toteknoplay proc near
	mov	playem,false
	jmp	totek
toteknoplay endp


totek proc near				; turn on tektronix
	test	denyflg,tekxflg		; tek auto entry enabled?
	jz	totek1
	mov	playem,true		; play back characters
	ret
totek1:	cmp	flags.vtflg,tttek	; already doing tek
	je	totek2
	call	termtog			; toggle to tektronix
totek2: ret
totek endp

leavetek proc near			; turn off tektronix
	mov	playem,false		; don't play back characters
	test	denyflg,tekxflg		; tek auto entry/exit enabled?
	jz	leavetek1
	mov	playem,true		; play back characters
	ret
leavetek1:
	cmp	flags.vtflg,tttek	; already doing tek
	jne	leavetek2		; ne => doing alpha so ignore
	call	termtog			; toggle to alpha
leavetek2:ret
leavetek endp

getrepchr proc	near	      ; get replay character for file
      mov    ah,readf2	      ; read from replay file
      mov    bx,diskio.handle
      mov    cx,1	      ; read 1 character
      mov    dx,offset rdbuf  ; to this buffer
      int    dos
      jc     getrepchr1	      ; c => failure
      cmp    ax,cx	      ; read the byte?
      jne    getrepchr1
      mov    al,rdbuf	      ; al has character
      clc		      ; character available in al
      ret
getrepchr1:
      call   beep	     ; announce file is done
      call   beep
      call   waitkey	      ; wait for a key to be pressed
      mov    prtrdy,false    ; so we exit connect mode
      stc
      ret		     ; no character available
getrepchr    endp

repchrout  proc	 near		; process key in al  while replaying
	and   al,7fh		; strip parity
repchrout1:
	cmp   al,'C'-40h	; Control C?(to exit playback mode)
	je    repchrout3	; e=> yes, return failure
	cmp   al,XOFF		; user wants to stop?
	jne   repchrout2	; ne => ok to continue
	call  waitkey		 ; wait and get a key
	jmp   repchrout1	; now process this key
repchrout2:
	clc			; return success
	ret
repchrout3:
	mov   prtrdy,false	; exit terminal
	stc			; exit connect mode
	ret
repchrout  endp

termtog proc  near			; toggle terminal type [jan]
	cmp	flags.vtflg,tttek	; doing tek emulation ?
	jne	termtog1		; ne means  doing tek
	writestring tek_off		; turn off tek
	writestring alpha_disp		; turn on alpha
	writestring alpha_on		; and turn on the alpha
	mov	flags.vtflg,ttgenrc	; turn on alpha display
	clc
	ret
termtog1:mov	flags.vtflg,tttek	; turn on tek display
	writestring alpha_off		; turn off alpha
	writestring tek_disp
	writestring tek_on		; and turn on the tek
	clc				; do not exit Connect mode
	ret				; stay in connect mode
termtog endp

kclrscn proc near			; clear the screen
	cmp	flags.vtflg,tttek	; doing tek emulation
	je	kclrscn1		; e=> yes
	writestring alpha_clear		; clear the alpha
	clc				; stay in connect mode
	ret				; return to caller
kclrscn1:writestring tek_clear		; clear the tektronix
	clc				; stay in connect mode
	ret
kclrscn	 endp

waitkey proc near		; wait for a key to be pressed
waitkey0:call	getkey		; get a key; carry set => no key; code in ax
	jc	waitkey0	; repeat until its pressed
	ret
waitkey endp

tekini proc near			; initialize tek emulator
	writestring alpha_off
	writestring tek_disp			; enable tektronix
	writestring tek_on			; turn on tek
	ret
tekini	endp


toterminal proc near   			; go to firmware terminal mode
	cmp	dosnum,dos211		; dos 2.11 or above?
	jae	toterminal1		; ae=> ok to go to terminal
	mov	ah,2
	mov	dl,7
	int	dos			; ring the bell
	clc				; stay in connect mode
	ret
toterminal1:
	call	clearlabels		; blank softkey labels
	call	keybdclose		; get out of keycode
	writestring to_term_msg
	mov	ax,1750
	call	pcwait			; 1 3/4 second time to read message
	mov	bx,offset agiosbuff
	mov	word ptr [bx],26  	; function code to get into terminal
	mov	ax,4403h		; io control write
	mov	bx,1			; console handle
	mov	cx,2			; 2 bytes in buffer
	mov	dx,offset agiosbuff
	int	dos			; now in terminal mode
	call	labelsoftkeys 		; turn keys on when we return
	call	keybdopen		; back to keycode mode
	clc				; stay in connect mode
	ret				; back to terminal
toterminal endp

cookedon proc near			; cook handle in bx
	push	ax
	push	dx			; save registers
	push	bx			; save handle
	mov 	ax,4400h		; get device information
	int 	dos
	xor 	dh,dh			; clear high byte
	and 	dl,0dfh		; clear raw bit without changing other bits
	mov 	ax,4401h		; put device information
	pop 	bx			; restore handle
	int 	dos			; turn off raw mode
	pop 	dx			; restore registers
	pop 	ax
	clc				; always returns success
	ret
cookedon endp

rawon proc near
	push	ax
	push	dx			; save registers
	push	bx			; save handle
	mov 	ax,4400h		; get device information
	int 	dos
	xor 	dh,dh			; clear high byte
	or  	dl,20h			; set raw bit
	mov 	ax,4401h		; put device information
	pop 	bx			; restore handle
	int 	dos			; turn on raw mode
	pop 	dx
	pop 	ax			; restore registers
	clc				; always returns success
	ret
rawon endp

;;;cptchr and cptdmp taken from msster to fix the problem
; of com buffer overflow with logging the session
cptchr	proc	near			; session capture routine, char in al
	push	di
	mov	di,capbp		; buffer pointer
	mov	byte ptr [di],al
	inc	capbp
	pop	di
	dec	caplft			; decrement chars remaining
	jg	cptch1			; more room, forget this part
	call	cptdmp			; dump the info
cptch1:	ret
cptchr	endp

cptdmp	proc	near			; empty the capture buffer
	push	ax
	push	bx
	push	cx
	push	dx
	mov	bx,sloghnd		; get file handle
	cmp	bx,0			; is file open?
	jle	cptdm1			; le = no, skip it
	push	bx			; save handle
	mov	bx,portval		; doing flow control?
	cmp	[bx].floflg,0		; e = no
	je	cptdmp01	
	cmp	xofsnt,true		; have we sent xoff?
	je	cptdmp01		; don't send it again
	mov	ah,flowoff		; get the xoff
	or	ah,ah			; null (no flow control?)
	jz	cptdmp01
	call	outchr			; send xoff to port
	mov	xofsnt,true		; remember we've sent it
cptdmp01:pop	bx			; restore handle
	mov	cx,cptsiz		; original buffer size
	sub	cx,caplft		; minus number remaining
	jl	cptdm2			; means error
	jcxz	cptdm1			; z = nothing to do
	mov	dx,offset capbuf	; the capture routine buffer
	mov	ah,write2		; write with filehandle
	int	dos			; write out the block
	jc	cptdm2			; carry set means error
	mov	capbp,offset capbuf
	mov	caplft,cptsiz		; init buffer ptr & chrs left
	jmp	short cptdm1
cptdm2:	and	flags.capflg,not logses	; so please stop capturing
;	and	targ.flgs,not capt	; so please stop capturing
and ourarg.flgs, not capt  ; so please stop capturing
	mov	dx,offset capterr	; tell user the bad news
	mov	ah,prstr
	int	dos
cptdm1: cmp	xofsnt, true	  	; xoff sent
	jne	cptdm02
	mov	ah,flowon		; get the xon
	or	ah,ah		  	; null?
	jz	cptdm02
	call	outchr		  	; send xon
	mov	xofsnt,false	  	; remember we've sent it
cptdm02:pop	dx
	pop	cx
	pop	bx
	pop	ax
	ret
cptdmp	endp

test_baud_change proc near		; check if firmware baud changed
	mov	al,e_port1
	call	get_config_values
	mov	al,[di].dc_baud_rate
	cmp	al,start_porta_baud ; baud rate changed by firmware (via user)
	je	test_baud_change1	; e = not changed
	call	read_bauda		; redo port a baud
test_baud_change1:
	mov	al,e_port2		; check if port 2 changed
	call	get_config_values
	mov	al,[di].dc_baud_rate
	cmp	al,start_portb_baud
	je	test_baud_change2	; e = not changed
	call	read_baudb		; read port b baud
test_baud_change2:
	ret
test_baud_change endp

read_baud proc near
	call	read_bauda	  	; read port 1 baud
	call	read_baudb	  	; read port 2 baud
	ret
read_baud endp

read_bauda proc near	  ; read baud on port 1 and update port info
	mov	al,e_port1
	call	get_config_values	; get port 1 configuration
	mov	si,offset port1
	mov	di,offset work_config
	mov	bl,[di].dc_baud_rate	; baud rate into bl
	mov	start_porta_baud,bl	; remember startup baud
	mov	portb_baud,bl		; remember startup baud
	mov	di,offset ourbdtab	; translate hp baud into kermit code
	shl	bl,1			; multiply by 2 for 2 bytes per entry
	xor	bh,bh
	mov	bl,[di+bx+1]
	mov	[si].baud,bx		; write baud in port 1 info
	ret
read_bauda endp

; Read the port 2 status
read_baudb proc near
	mov	al,e_port2
	call	get_config_values	; get port 2 configuration
	mov	si,offset port2
	mov	di,offset work_config
	mov	bl,[di].dc_baud_rate	; baud rate into bl
	mov	start_portb_baud,bl	; remember startup baud
	mov	portb_baud,bl		; current baud on port b
	mov	di,offset ourbdtab	; translate hp baud into kermit code
	shl	bl,1		      ; multiply by 2 since 2 bytes per entry
	xor	bh,bh
	mov	bl,[di+bx+1]
	mov	[si].baud,bx		; write baud in port 2 info
	ret
read_baudb endp

;;; read data comm configuration. taken off dc.asm from compuserve
;*******************************************
;
; Firmware Programming Notes:
;
; 1) The firmware has a modular structure and generally consists
;	 of a bunch of processing modules which all have a separate
;	 logical segment and a limited number of entry points
;	 (generally only one).
; 2) The desired processing is accessed by passing the required
;	 parameters and the proper function code on entry to a
;	 module.
; 3) A call to a procedure outside the logical module is always
;	 a long call and inter segment (logical segment).
; 4) Parameters for a call to a procedure outside the logical
;	 module are pushed on the stack. This includes the function
;	 code.	The procedure called has the responsibility of
;	 cleaning up the stack.
; 5) The procedure called should always return status in AX.
;	 Registers BX, CX, and DX may also contain outputs.
; 6) The caller should always assume registers AX, BX, CX, and
;	 DX have been modified. The caller should always assume
;	 registers SI, DI, SP, BP, DS, ES, and SS are the same on
;	 return.
; 7) Calls to external procedures are made through jump tables
;	 at the beginning of each rom.	Thus the application is
;	 insulated from re-releases of the HP150 firmware.
;
;*******************************************
page;
;*************** GRYPHON DECLARATIONS ************
; To simplify external linking to absolute firmware jump locations,
; we include the long calls as constants. Note that we still have
; some measure of ROM independence because we entry the routines
; through fixed jump tables at the start of the RAM.
;
;-------------------------------------------
;
; COMMENTS:
; 1) The bytes PREDEF_VALUES and BARREL_INDEX are used by
;	 configuration processing during normal operation where a
;	 configuration form is brought onto the screen. Their
;	 values can be set and then ignored.
; 2) The bytes DC_PORT through DC_RECV_PACE are the actual
;	 datacomm configuration values.
; 3) The word DC_DEVICE_TOKEN is used to access the datacomm
;	 device.
;
;-------------------------------------------

;*******************************************
;
; The data format for the datacomm configuration values are as
; follows:
;
;	1) DC_PORT=	2	(port 1)
;			11	(port 2)
;
;	2) DC_BOOL1	(a graphical representation follows)
;	3) DC_BOOL2
;
;	 HP Point-to-Point Boolean Bit Positions
;
;	    7	    6	    5	    4	    3	    2	    1	    0
;	+-------+-------+-------+-------+-------+-------+-------+-------+
;	| 1 Stop| CS(CB)|  SRR	| RR(CF)|  SRR	| SR(CH)|  Chk	|  ENQ	|
;	|  Bit	|  Xmit | Invert|  Recv |  Xmit |	| Parity|  ACK	|
;	+-------+-------+-------+-------+-------+-------+-------+-------+
;	| TR(CD)| DM(CC)|	|	|	|	| 7 Data|  Xmit |
;	|	|  Xmit |	|	|	|	|  Bits |  Pace |
;	+-------+-------+-------+-------+-------+-------+-------+-------+
;
;	 DC_BOOL1:
;
;		Bit 0:		0 = No		1 = Yes
;		Bit 1:		0 = No		1 = Yes
;		Bit 2:		0 = Lo		1 = Hi
;		Bit 3:		0 = No		1 = Yes
;		Bit 4:		0 = No		1 = Yes
;		Bit 5:		0 = No		1 = Yes
;		Bit 6:		0 = No		1 = Yes
;		Bit 7:		0 = 2 Stop Bits 1 = 1 Stop Bit
;
;	 DC_BOOL2:
;
;		Bit 0:		0 = None	1 = Xon/Xoff
;		Bit 1:		0 = 8 Data Bits 1 = 7 Data Bits
;		Bit 6:		0 = No		1 = Yes
;		Bit 7:		0 = Lo		1 = Hi
;
;	4) DC_BAUD_RATE =	02H	 (110 Baud)
;				04H	 (150 Baud)
;				05H	 (300 Baud)
;				06H	 (600 Baud)
;				07H	(1200 Baud)
;				0AH	(2400 Baud)
;				0CH	(4800 Baud)
;				0EH	(9600 Baud)
;				0FH	(19200 Baud)
;
;	5) DC_PARITY =		0	(Zeros)
;				1	(Ones)
;				2	(Even)
;				3	(Odd)
;				4	(None)
;
;	6) DC_CLOCK =		0	(INT CLOCK)
;				1	(EXT X1 CLOCK)
;				2	(EXT X16 CLOCK)
;
;	7) DC_ASTERISK =	0	(No Asterisk)
;				1	(DM Asterisk)
;				2	(RR Asterisk)
;				3	(Line Asterisk)
;				4	(CS Asterisk)
;
;	8) DC_RECV_PACE =	0	(No Recv Pace)
;				1	(Xon/Xoff Recv Pace)
;				2	(TR(CD) Recv Pace)
;
;*******************************************
;
;
;-------------------------------------------
;
; PROCEDURE NAME:	GET_CONFIG_VALUES
;
; FUNCTION:
; 1) Specify a block of configuration parameters to be obtained
;	 by config processing.	The parameters define how datacomm
;	 is configured.
; 2) Config processing will get the data out of NVRAM.	The
;	 values reflect the current configuration of the 150.
; 3) The data is written into the data area supplied by the
;	 caller and is in the format used by the datacomm driver.
;
; INPUTS:
; 1) DS - segment of CONFIGURATION_DATA_AREA
; 2) DI - offset of CONFIGURATION_DATA_AREA
;
; OUTPUTS:
;	 The configuration data area will have all the necessary
;	 values needed to specify the datacomm configuration.	These
;	 can be modified so when they are passed to the datacomm
;	 driver, the new configuration will take effect.
;
; REGISTERS MODIFIED: ax, bx, cx, dx
;
;-------------------------------------------
GET_CONFIG_VALUES proc near

	mov	readid,e_port1_read
	mov	saveid,e_port1_save
	cmp	al,e_port1
	je	init90
	mov	readid,e_port2_read
	mov	saveid,e_port2_save
init90:	mov	di,offset work_config
	;----------------------------------------
	; Initialize the variables of the config data area required
	; by config processing.
	;----------------------------------------
	mov	[di].PREDEF_VALUES,3
	mov	[di].BARREL_INDEX,6
	mov	ax,readid
	mov	[di].DC_PORT,al

	;----------------------------------------
	; Get the datacomm configuration values.
	;----------------------------------------
	mov	ah,al			; Port X config type in AH
	mov	al,4			; full duplex, hardwired form.
	push	ax
	mov	ax,0201h		; 01 -> Personality ID
	push	ax			; C02 -> Config values are required.
	push	ds			; segment of CONFIGURATION_DATA_AREA
	push	di			; pointer to start of data area
	lea	ax,[di].DC_PORT		; pointer to start of config values
	push	ax
	mov	ax,3			; function code for CNP_GET_DEV_CONFIG
	push	ax
	CALL_CNP_ENTRY
	mov	ax,saveid
	mov	[di].dc_port,al
	ret
GET_CONFIG_VALUES endp


; Set baud  port (1 or 2) in al, Kermit baud code from bdtab in ah.
; First translate Kermit baud into HP baud
set_baud proc near 
	mov	dx,ax			; save baud and port
	mov	di,offset ourbdtab1
	mov	bl,ah			; put baud code in bl
	xor	bh,bh			; bh=0 for indexing
	shl	bl,1			; x2 since two bytes per baud entry
	mov	al,[di+bx+1]		; al now has hp baud code
	cmp	dl,1			; is it port 1?
	je	set_baud1		; e = yes
	mov	portb_baud,al		; save it
	mov	cl,4
	shl	al,cl			; port b in left nibble
	or	al,porta_baud		; port a baud in right nibble
	out	baud_port,al		; write the port a and port b baud
	clc				; success
	ret
set_baud1:				; set port 1 baud
	mov	porta_baud,al		; save the baud
	mov	dl,portb_baud
	mov	cl,4
	shl	dl,cl
	or	al,dl	     ; port a in right nibble , port b in left nibble
	out	0ch,al			; write the port a and port b baud
	clc				; success
	ret
set_baud endp

lclose proc near			; this gets called when kermit quits
	mov	al,e_port1		; reset baud to match firmware values
	call	get_config_values
	mov	al,[di].dc_baud_rate	; port a baud rate
	push	ax			; save this baud
	mov	al,e_port2
	call	get_config_values
	mov	bl,[di].dc_baud_rate	; port 2 baud rate
	mov	cl,4
	shl	bl,cl			; port b baud in left nibble
	pop	ax			; al has port a baud
	or	al,bl			; both bauds in al
	out	baud_port,al		; write the baud rate
	ret
lclose endp

code	ends
	end
