        name msyv9t
; File MSYV9T.ASM
; Last modification: 7 August 1986

; Kermit system dependent module for VICTOR 9000/SIRIUS

; SPECIAL VERSION WITH NEAR COMPLETE SUPPORT OF TEKTRONIX 4010 EMULATION

; edit history:
; 7 August 1986 fill out procedure DUMPSCR - it was borrowed from MSYIBM
;  modified to fit the Victor format.  It required a modification of
;  LCLYINI to get the character set base [bgp]
;      7-DEC-85 ORIGINAL        BGP
;     20-FEB-86 CORRECTED FOR ERROR IN PUTMOD IN MSXV9000       (BGP)
;     22-FEB-86 CLEANED UP CHARACTER SET FOR TEK EMULATION      (BGP)
;     22-FEB-86 ADDED CODE TO SWALLOW ANSI ESCAPE SEQUENCES IN
;               HEATH EMULATION MODE                            (BGP)
; ************************************************************
; Remove segment Graph and replace it with memory dynamically allocated
; from DOS via procedure sbrk in mssker.  Do allocation, verify that it
; is in the correct chunk of memory (and fix if necessary), initialize
; scrseg, and clear the area, all done in lclyini.    17 March 86
; Joe R. Doupnik
; Add global procedure Dumpscr, called by Ter in file msster, to dump screen
;   to a file. Just does a beep for now. 13 April 1986 [jrd]
;
; Added 'full' VT100 emulation using code by Andreas Stumpf
; (ZRZS@DS0RUS1I).    The significant parts that are not emulated are
;   esc c  - reset terminal
;   esc N  - ??
;   esc O  - ??
;   esc n  - ??
;   esc l  - ??
;   esc o  - ??
;   esc <  - go to ANSI mode (from VT52)
;   esc [ q    - fiddle with the LED's
;   esc [ h    - some modes not supported
;   esc [ l    - some modes not supported
;   esc [ i    - ??
;   esc [ p    - ??
;   esc [ y    - ??
; and some codes that are not VT100 'standard' are supported
;   esc [ E    - ??
;   esc [ F    - ??
;   esc [ G    - ??
;   esc [ L    - ??
;   esc [ M    - ??
;   esc [ @    - ??
;   esc [ P    - ??
;   esc [ X    - ??
;   esc [ d    - ??
;   esc [ e    - ??
; 22 April 86 Bryan G. Peterson

        public  term, lclyini, vts, vtstat ; entry points
        public  dumpscr                         ; [jrd]
        include mssdef.h

;   Some extra ASCII definitions
ENQ     EQU     5
ETB     EQU     17H
VTAB    EQU     0BH
SUB     EQU     1AH
GS      EQU     1DH
US      EQU     1FH

CLEAR   EQU     0F1H                    ; Key to clear screen
CURSOR_CHR EQU  '_'                     ; The cursor character
CURSOR_TIME EQU 100                     ; cursor on countdown period
;       this is the number of unsuccessful tries on getting a charcter
;       from the input port before turning on the cursor.

X_MAX   EQU     799
Y_MAX   EQU     399
TEK_X_MAX EQU   1023
TEK_Y_MAX EQU   780
TEXT_X_MAX EQU  789
TEXT_Y_MAX EQU  389
RPLINE  EQU     11                      ; rows per text line
CPCHAR  EQU     11                      ; columns per text character
R_MARG  EQU     781                     ; right margin position
CUR_LEN EQU     10                      ; length of arms on graphics cursor

FALSE   EQU     0
TRUE    EQU     1

SEG_CRTC EQU    0E800H                  ; segment for crt controller
OFF_CRTC EQU    0                       ; offset for crt controller

modfrm  struc                           ; format of mode line
        db      ' Esc chr: '
m_echr  db      2 dup (?)
        db      ', Port: '
m_prt   db      1 dup (?)
        db      ', Speed: '
m_baud  db      4 dup (?)
        db      ', Parity: '
m_par   db      4 dup (?)
        db      ', Echo: '
m_echo  db      3 dup (?)
        db      ', Type '
m_hlp   db      2 dup (?)
        db      '? for Help'
        db      ' $'                    ; must be dollar terminated
modfrm  ends

DATAS   segment public 'datas'

        extrn flags:byte        ; to get access to emulation
        extrn   dmpname:byte,filtst:byte ; [jrd] [bgp]

termhlp db      CR,LF,'Terminal type of Heath-19, VT100, or Tektronix$'
termtbl db      5
        mkeyw   'Heath-19',TTHEATH
        mkeyw   'none',TTGENRC  ; nothing
        mkeyw   'Tektronix',TTGENRC ; nothing is going to be Tektronix
        mkeyw   'VT100',TTVT100
        mkeyw   'VT102',TTVT100
tek_msg db      CR,LF,'Status will show emulation as NONE'
        db      ' - actually emulating TEKTRONIX$'
; stuff for screen routines
wflags  label   word            ; so we can push yflags
yflags  db      ?               ; status flags...
        db      0               ; extra byte for flags
flags1  db      0               ; internal flags.
prtscr  equ     80h                     ; print screen pressed
inited  equ     08h                     ; been here before...
wrapped equ     04h                     ; on if wrapped on last char...
esc_ch  db      ?
argadr  dw      ?                       ; address of arg blk
crt_cols db     ?
crt_lins db     ?
modbuf  modfrm  <>                      ; mode line buffer
; routine to call for captured output
captrtn dw      ?
; some static data for mode line
unkbaud db      'Unk '                  ; must be 4 chars...
baudn   db      '45.5'
        db      '  50'
        db      '  75'
        db      ' 110'
        db      ' 135'
        db      ' 150'
        db      ' 300'
        db      ' 600'
        db      '1200'
        db      '1800'
        db      '2000'
        db      '2400'
        db      '4800'
        db      '9600'
        db      '19.2'
        db      '38.4'
baudnsiz  equ   16                      ; # of baud rates known (tbl size / 4)
parnams db      'Even'
        db      'Mark'
        db      'None'
        db      'Odd '                  ; must be 4 chars
        db      'Spc '
offmsg  db      'Off'
onmsg   db      'On '
lclmsg  db      'Lcl'
remmsg  db      'Rem'

portno  db      ?

tscreen dw      1920 dup (?)            ; place to save text screen
tcurloc db      2 dup (?)               ; column,row
tscrseg dw      0F000H
rptcur  db      27,'n$'                 ; request cursor location
escseq  db      0                       ; ANSI escape sequence indicator
                                        ; 0=none, 1=escape, 2=[

; stuff for the Tektronix emulation
;;;[jrd]scrloc  dw      screen
;;;[jrd]scrseg  dw      seg graph               ; screen segment
                                        ; Order is essential:scrloc then scrseg
scrloc  dw      0                       ; offset of screen memory [jrd]
scrseg  dw      0                       ; segment of screen memory [jrd]

tek_allowed db  TRUE                    ; flag for screen memory ok
no_tek_msg db   CR,LF,'SCREEN MEMORY ALLOCATION FAILED'
        db      ' - TEKTRONIX EMULATION NOT ALLOWED',BELL,CR,LF,'$'
first_in db     TRUE                    ; this is the first time emulating
intens  db      14                      ; CRT intensity setting
status_line dw  80 dup (?)              ; for CRT status line

bit_mask db     1,2,4,8,16,32,64,128
combine dw      pixel_or
t_combine dw    word_or
start   dw      0,0                     ; vector start point
endpt   dw      0,0                     ; end point (victor coords)
cur_x   dw      0                       ; tek coordinates of current point
cur_y   dw      780
text_x  dw      0                       ; text cursor location (victor coords)
text_y  dw      0                       ; upper left corner
cursor_cnt dw   0                       ; cursor countdown
cursor  db      FALSE                   ; cursor state flag
full_flag db    FALSE                   ; flags page full condition
x_inc   dw      1
y_inc   dw      1
delta_x dw      0
delta_y dw      0
part_accum dw   0                       ; accumulator for line
temp    dw      0                       ; temporary storage
c_mask  dw      0                       ; mask for character work
cur_stp dw      1                       ; graphics cursor step
crs_hor dw      0,0,0                   ; cursor horizontal line (x1,x2,y)
crs_ver dw      0,0,0                   ; cursor vertical line (y1,y2,x)
prtesc  db      FALSE                   ; escape from port in GIN mode
trmesc  db      FALSE                   ; escape from terminal in GIN mode


graph_mode db   FALSE                   ; graphics mode flag
echo_supp db    FALSE                   ; echoplex suppression flag
visible db      0                       ; 0 to move, 1 to draw
hiy     dw      0
loy     db      0
hix     dw      0
lox     db      0
lsb     db      0
escflag db      0
tekjump dw      TEKTXT,TEKESC,TEKHIY,TEKHIX

; The next variable defines the bit masks for the text font
font    dw      0,20H,70H,20H,20H,0,20H,20H,0,0,0 ; !
        dw      0,88H,88H,88H,0,0,0,0,0,0,0 ; "
        dw      0,88H,88H,3FEH,88H,3FEH,88H,88H,0,0,0 ; #
        dw      0,1FCH,222H,22H,1FCH,220H,222H,1FCH,0,0,0 ; $
        dw      0,10CH,8CH,40H,20H,10H,188H,184H,0,0,0 ; %
        dw      0,10H,28H,10H,28H,144H,84H,178H,0,0,0 ; &
        dw      0,30H,30H,20H,10H,0,0,0,0,0,0 ; '
        dw      0,40H,20H,10H,10H,10H,20H,40H,0,0,0 ; (
        dw      0,10H,20H,40H,40H,40H,20H,10H,0,0,0 ; )
        dw      0,104H,88H,50H,3FEH,50H,88H,104H,0,0,0 ; *
        dw      0,20H,20H,20H,3FEH,20H,20H,20H,0,0,0 ; +
        dw      0,0,0,0,0,0,30H,30H,20H,10H,0 ; ,
        dw      0,0,0,0,3FEH,0,0,0,0,0,0 ; -
        dw      0,0,0,0,0,0,30H,30H,0,0,0 ; .
        dw      0,100H,80H,40H,20H,10H,8,4,0,0,0 ; /
        dw      0,0F8H,184H,242H,222H,212H,10CH,0F8H,0,0,0 ; 0
        dw      0,20H,30H,20H,20H,20H,20H,70H,0,0,0 ; 1
        dw      0,1FCH,202H,200H,1FCH,2,2,3FEH,0,0,0 ; 2
        dw      0,3FEH,100H,80H,1C0H,200H,202H,1FCH,0,0,0 ; 3
        dw      0,102H,102H,102H,3FEH,100H,100H,100H,0,0,0 ; 4
        dw      0,3FEH,2,2,1FEH,200H,200H,1FEH,0,0,0 ; 5
        dw      0,1FCH,2,2,1FEH,202H,202H,1FCH,0,0,0 ; 6
        dw      0,3FEH,100H,80H,40H,20H,20H,20H,0,0,0 ; 7
        dw      0,0F8H,104H,88H,1FCH,202H,202H,1FCH,0,0,0 ; 8
        dw      0,1FCH,202H,202H,3FCH,200H,200H,1FCH,0,0,0 ; 9
        dw      0,0,30H,30H,0,0,30H,30H,0,0,0 ; :
        dw      0,0,30H,30H,0,0,30H,30H,20H,10H,0 ; ;
        dw      0,80H,40H,20H,10H,20H,40H,80H,0,0,0 ; <
        dw      0,0,0,3FEH,0,3FEH,0,0,0,0,0 ; =
        dw      0,8,10H,20H,40H,20H,10H,8,0,0,0 ; >
        dw      0,1FCH,202H,200H,1E0H,20H,0,20H,0,0,0 ; ?
        dw      0,1FCH,202H,3E2H,212H,1E2H,2,1FCH,0,0,0 ; @
        dw      0,70H,88H,104H,3FEH,202H,202H,202H,0,0,0 ; A
        dw      0,0FEH,102H,102H,1FEH,202H,202H,1FEH,0,0,0 ; B
        dw      0,1FCH,202H,2,2,2,202H,1FCH,0,0,0 ; C
        dw      0,1FEH,202H,202H,202H,202H,202H,1FEH,0,0,0 ; D
        dw      0,3FEH,2,2,7EH,2,2,3FEH,0,0,0 ; E
        dw      0,3FEH,2,2,7EH,2,2,2,0,0,0 ; F
        dw      0,1FCH,202H,2,382H,202H,202H,3FCH,0,0,0 ; G
        dw      0,202H,202H,202H,3FEH,202H,202H,202H,0,0,0 ; H
        dw      0,0F8H,20H,20H,20H,20H,20H,0F8H,0,0,0 ; I
        dw      0,3E0H,80H,80H,80H,80H,84H,78H,0,0,0 ; J
        dw      0,202H,102H,82H,7EH,82H,102H,202H,0,0,0 ; K
        dw      0,2,2,2,2,2,2,3FEH,0,0,0 ; L
        dw      0,306H,28AH,252H,222H,202H,202H,202H,0,0,0 ; M
        dw      0,206H,20AH,212H,222H,242H,282H,302H,0,0,0 ; N
        dw      0,1FCH,202H,202H,202H,202H,202H,1FCH,0,0,0 ; O
        dw      0,1FEH,202H,202H,1FEH,2,2,2,0,0,0 ; P
        dw      0,1FCH,202H,202H,202H,282H,102H,2FCH,0,0,0 ; Q
        dw      0,1FEH,202H,202H,1FEH,82H,102H,202H,0,0,0 ; R
        dw      0,1FCH,202H,2,1FCH,200H,202H,1FCH,0,0,0 ; S
        dw      0,3FEH,20H,20H,20H,20H,20H,20H,0,0,0 ; T
        dw      0,202H,202H,202H,202H,202H,302H,2FCH,0,0,0 ; U
        dw      0,202H,202H,202H,104H,88H,50H,20H,0,0,0 ; V
        dw      0,202H,202H,202H,222H,222H,154H,88H,0,0,0 ; W
        dw      0,104H,88H,50H,20H,50H,88H,104H,0,0,0 ; X
        dw      0,202H,104H,88H,50H,20H,20H,20H,0,0,0 ; Y
        dw      0,3FEH,80H,40H,20H,10H,8,3FEH,0,0,0 ; Z
        dw      0,70H,10H,10H,10H,10H,10H,70H,0,0,0 ; [
        dw      0,4,8,10H,20H,40H,80H,100H,0,0,0 ; \
        dw      0,70H,40H,40H,40H,40H,40H,70H,0,0,0 ; ]
        dw      0,20H,70H,0A8H,124H,20H,20H,20H,0,0,0 ; ^
        dw      0,0,0,0,0,0,0,0,0,0,7FFH ; _
        dw      0,10H,20H,40H,0,0,0,0,0,0,0 ; `
        dw      0,0,0,0F8H,100H,1F8H,104H,2F8H,0,0,0 ; a
        dw      0,4,4,0FCH,104H,104H,104H,0FCH,0,0,0 ; b
        dw      0,0,0,0F8H,104H,4,4,1F8H,0,0,0 ; c
        dw      0,100H,100H,1F8H,104H,104H,104H,1F8H,0,0,0 ; d
        dw      0,0,0,0F8H,104H,1FCH,4,1F8H,0,0,0 ; e
        dw      0,20H,50H,10H,38H,10H,10H,10H,0,0,0 ; f
        dw      0,0,0,1F8H,104H,104H,104H,1F8H,100H,100H,0F8H ; g
        dw      0,4,4,0FCH,104H,104H,104H,104H,0,0,0 ; h
        dw      0,0,20H,0,20H,20H,20H,20H,0,0,0 ; i
        dw      0,0,40H,0,40H,40H,40H,40H,40H,50H,20H ; j
        dw      0,4,4,44H,24H,3CH,44H,84H,0,0,0 ; k
        dw      0,30H,20H,20H,20H,20H,20H,0F8H,0,0,0 ; l
        dw      0,0,0,1DEH,222H,222H,222H,222H,0,0,0 ; m
        dw      0,0,0,0FCH,104H,104H,104H,104H,0,0,0 ; n
        dw      0,0,0,0F8H,104H,104H,104H,0F8H,0,0,0 ; o
        dw      0,0,0,0FCH,104H,104H,104H,0FCH,4,4,4 ; p
        dw      0,0,0,1F8H,104H,104H,104H,1F8H,100H,300H,100H ; q
        dw      0,0,0,0FCH,104H,4,4,4,0,0,0 ; r
        dw      0,0,0,0F8H,4,0F8H,100H,0FCH,0,0,0 ; s
        dw      0,10H,10H,78H,10H,10H,50H,20H,0,0,0 ; t
        dw      0,0,0,84H,84H,84H,84H,178H,0,0,0 ; u
        dw      0,0,0,104H,104H,88H,50H,20H,0,0,0 ; v
        dw      0,0,0,222H,222H,222H,222H,1DCH,0,0,0 ; w
        dw      0,0,0,88H,50H,20H,50H,88H,0,0,0 ; x
        dw      0,0,0,104H,104H,104H,104H,1F8H,100H,100H,0F8H ; y
        dw      0,0,0,0F8H,40H,20H,10H,0F8H,0,0,0 ; z
        dw      0,0C0H,20H,20H,10H,20H,20H,0C0H,0,0,0 ; {
        dw      0,20H,20H,20H,20H,20H,20H,20H,0,0,0 ; |
        dw      0,18H,20H,20H,40H,20H,20H,18H,0,0,0 ; }
        dw      0,0,1CH,222H,1C0H,0,0,0,0,0,0 ; ~

; stuff for ANSI emulation [as]
SUPERBIOS equ   0dfh            ; SuperBios-Interrupt

tt      struc                   ; structure of keyboardtable
head    dw      2 dup (?)
kd0     db      104*3 dup (?)
kd12    dw      104*3 dup (?)
extrtabl db     256 dup (?)
tt      ends

afirst  db      0
; Parameterblock for setting/getting of keyboard-table
parmblock db    3
laenge  dw      1196            ; length of table
offs    dw      offset oldtable
segm    dw      seg oldtable
; block for call to get Console-driver-address
condev  dw      1
drivadr dd      0               ; address of consoledriver
;
oldtable tt     <,,,>           ; saved old keytable
numtbl  tt      <,,,>           ; Table with Num-Keypad
apptbl  tt      <,,,>           ; Table with Appl-Keypad
; In order to avoid smashing stuff that may already be in the multi-char
; sequence table for the keyboard (or as little as possible) put it near the
; end of the table - the following parameters tells how deep into the table
; to start putting stuff
START_EXTRTBL EQU 160
; Cursorsequences ANSI
appcur  db      0               ; flag for cursor key modes
curseq  db      3,ESC,'[A',3,ESC,'[B',3,ESC,'[D',3,ESC,'[C'
curapp  db      3,ESC,'OA',3,ESC,'OB',3,ESC,'OD',3,ESC,'OC'
; Applikationkeypad
appkeys db      0               ; flag for keypad modes
applik  db      3,ESC,'[A',3,ESC,'[B',3,ESC,'[D',3,ESC,'[C'
        db      3,ESC,'OP',3,ESC,'OQ',3,ESC,'OR',3,ESC,'OS'
        db      3,ESC,'Ow',3,ESC,'Ox',3,ESC,'Oy',3,ESC,'Om'
        db      3,ESC,'Ot',3,ESC,'Ou',3,ESC,'Ov',3,ESC,'Ol'
        db      3,ESC,'Oq',3,ESC,'Or',3,ESC,'Os',3,ESC,'OM'
        db      3,ESC,'Op',3,ESC,'On'
sesctbl db      'DEHMNOZn|o[>=78c<' ; table for characters following single ESC
sesclen equ     $-sesctbl
; now the table for routines to process those characters
sescsub dw      processD
        dw      processE
        dw      processH
        dw      processM
        dw      ignore
        dw      ignore
        dw      procc0          ; same as ESC [0c
        dw      ignore
        dw      ignore
        dw      ignore
        dw      processbra
        dw      processgt
        dw      processeq
        dw      process7
        dw      process8
        dw      ignore
        dw      ignore
; table for the last characters in a ESC'[' sequence
mesctbl db      '`EFGABCDHLM@PXKJfghilmrcnpyqde'
mesclen equ     $-mesctbl
; processing routine table for ESC'[' sequences
mescsub dw      proce
        dw      proce
        dw      procuf
        dw      procug
        dw      curmov
        dw      curmov
        dw      curmov
        dw      curmov
        dw      procH
        dw      procL
        dw      procM
        dw      procAt
        dw      procP
        dw      procX
        dw      procK
        dw      procJ
        dw      procH
        dw      procg
        dw      prochl
        dw      ignore
        dw      prochl
        dw      proclm
        dw      procr
        dw      procc
        dw      procn
        dw      ignore
        dw      ignore
        dw      ignore
        dw      procld
        dw      procle
;
top     db      1               ; scrolling region margins
bottom  db      24
escpnt  dw      offset escstring
escstring db    80 dup (?)      ; save area for Escape sequence
tabstops db     0,0,0,0,0,0,0,0 ; tabulator stops
        db      1,0,0,0,0,0,0,0
        db      1,0,0,0,0,0,0,0
        db      1,0,0,0,0,0,0,0
        db      1,0,0,0,0,0,0,0
        db      1,0,0,0,0,0,0,0
        db      1,0,0,0,0,0,0,0
        db      1,0,0,0,0,0,0,0
        db      1,0,0,0,0,0,0,0
        db      1,0,0,0,0,0,0,0
chrset_mask db  0               ; mask for selecting character set

char_base dw    0               ; screen character base
dmphand dw      0               ; handle for screen dump [bgp]
dumpbuf db      80 dup (?),CR,LF ; line buffer for screen dump
dumpsep db      FF,CR,LF        ; put in file between screen dumps
dmperr  db      '  WARNING:  CAN NOT OPEN THE SCREEN DUMP FILE  $'

DATAS   ends

;;;[jrd]GRAPH   segment public 'graph'
;;;[jrd]
;;;[jrd]screen  db      40000 dup (?)           ; area for screen
;;;[jrd]
;;;[jrd]GRAPH   ends


CODE    segment public 'code'                   ; code segment
        extrn   prtchr:near,outchr:near,cmblnk:near,poscur:near
        extrn   putmod:near,clrmod:near,beep:near,sbrk:near     ; [jrd]
        extrn   comnd:near,isfile:near                          ; [bgp]
        assume  cs:code,ds:datas,es:datas

; do initialization local to this module...
; mainly get console driver address to speed up screen access [as]
; Modified by [jrd] to allocate memory dynamically rather than via a static
; program segment (Graph).    Allocation is paragraph aligned.
; Modified by [bgp] to check location of memory allocated and modify it if
; necessary.      Memory for screen must lie either entirely within the first
; 64K of memory, or within the second 64K of memory due to architecture of
; the CRT controller connections.   It must also be aligned on an exact
; multiple of 32 bytes (rather than just on paragraph alignment).
; 7 August 1986 added code to get character set base for dump [bgp]

LCLYINI proc    near
        mov     ah,DCONIO
        mov     dl,ESC          ; to set nowrap
        int     DOS
        mov     dl,'w'
        int     DOS
        mov     ax,ds
        mov     es,ax
        mov     ax,14           ; function 'get driveraddress'
        mov     bx,offset condev
        int     SUPERBIOS       ; address is now in drivadr
; get screen set up
        mov     ax,40016D       ; #memory bytes for screen [jrd]
        call    sbrk            ; memory allocator proc in mssker
        cmp     ax,1000H        ; start in lower half? [bgp sub-mod]
        jge     lclyini1        ; no
        cmp     ax,63BH         ; maximum segment in lower half
        jl      lclyini3        ; low enough to work, go on
        push    es              ; save this for now
        mov     es,ax           ; use right segment
        mov     bx,1000H        ; find size of junk block to keep
        sub     bx,ax           ; 1000H - old segment = paragraphs to keep
        mov     ah,SETBLK       ; change block size
        int     DOS
        jc      lclyini2        ; failed!
        mov     ax,40016D       ; memory bytes for screen
        call    sbrk            ; get them
        jmp     lclyini3        ; they should be okay...
lclyini1:
        cmp     ax,163BH        ; maximum segment in top half
        jl      lclyini3        ; ok - go on
lclyini2:                       ; Tektronix emulation screen won't work...
        mov     dx,offset no_tek_msg ; tell the user we can't do it
        mov     ah,PRSTR
        int     DOS
        mov     tek_allowed,FALSE ; and flag it
        jmp     lclyini4

lclyini3:                       ; Tektronix will work fine
        inc     ax              ; force round-up
        shr     ax,1            ; divide by two
        shl     ax,1            ; multiply by two - now multiple of 32
        mov     scrseg,ax       ; save it [end bgp sub-mod]
        push    es
        call    clrscr          ; make sure it is clear
        pop     es              ; end of mod [jrd]
        mov     tek_allowed,TRUE ; flag that tektronix ok

lclyini4:
        push    es
        mov     ax,0F000H       ; point at base of screen memory
        mov     es,ax
        mov     ax,word ptr es:3838 ; note:  this should be the last character
                                ; of the last line on the screen - if it was
                                ; cleared as Kermit usually does when it starts
                                ; up, this will be a space - it must be a space!
        and     ax,7FFH         ; strip off mode bits
        sub     ax,' '          ; minus which char it is
        mov     char_base,ax    ; and save it
        pop     es
        ret
LCLYINI endp

; We need to save the arguments to TERM where they are a little more
; accessible than in the way they were passed

ARGINI  proc    near                    ; read passed arguments
        mov     bx,argadr               ; base of argument block
        mov     al,[bx].flgs            ; get flags
        and     al,CAPT+EMHEATH+HAVTT+TRNCTL+LCLECHO+MODOFF+LNWRAP
        mov     yflags,al               ; mask for allowable and save
        and     flags1,not (PRTSCR)     ; these are allowable
                                        ; (others remain).
        mov     al,[bx].prt
        cmp     al,portno               ; using same port?
        je      argin1                  ; yes, go on
        and     flags1,not inited       ; else re-init stuff
        mov     first_in,TRUE           ; graphics too...
argin1:
        mov     portno,al               ; update port number
        mov     al,[bx].cols
        mov     crt_cols,al
        mov     al,[bx].rows
        mov     crt_lins,al             ; init # of rows and cols
        mov     ax,[bx].captr
        mov     captrtn,ax              ; buffer capture routine
        mov     al,[bx].escc
        mov     esc_ch,al
        ret                             ; that's it
ARGINI  endp

; We need to generate the mode line and output it

MODLIN  proc    near                    ; turn on mode line
        push    ds
        pop     es                      ; make sure es is correct
        mov     al,esc_ch
        mov     modbuf.m_echr,' '       ; first char is initial space
        mov     modbuf.m_hlp,' '        ; goes here too.
        cmp     al,32                   ; printable?
        jnb     modl1                   ; yes, keep going
        add     al,40h                  ; made printable
        mov     modbuf.m_echr,'^'       ; note control char
        mov     modbuf.m_hlp,'^'
modl1:
        mov     modbuf.m_echr+1,al      ; fill in character
        mov     modbuf.m_hlp+1,al
        mov     bx,argadr               ; get argument block
        mov     al,[bx].baudb           ; get baud bits
        mov     si,offset unkbaud       ; assume unknown baud
        cmp     al,baudnsiz             ; too big?
        jnb     modl2                   ; yes, use default
        mov     cl,2                    ; each is 4 bytes long
        shl     al,cl
        mov     ah,0
        add     ax,offset baudn
        mov     si,ax
modl2:
        mov     cx,size m_baud          ; length of baud space
        mov     di,offset modbuf.m_baud
        rep     movsb                   ; copy in baud rate
        mov     al,[bx].parity          ; get parity code
        mov     cl,2                    ; each is 4 bytes long...
        shl     al,cl
        mov     ah,0
        add     ax,offset parnams       ; names of parity settings
        mov     si,ax
        mov     cx,4                    ; each is 4 long
        mov     di,offset modbuf.m_par
        rep     movsb
        mov     si,offset remmsg        ; Assume remote echoing.
        test    yflags,lclecho          ; Is remote side echoing?
        jz      modl4                   ; Yes, keep going
        mov     si,offset lclmsg        ; Else it's local echoing.
modl4:
        mov     cx,3                    ; size of on/off
        mov     di,offset modbuf.m_echo
        rep     movsb
        mov     al,'1'
        cmp     portno,1                ; port 1?
        je      modl5                   ; yes, keep going
        mov     al,'2'
modl5:
        mov     modbuf.m_prt,al         ; fill in port number
        mov     dx,offset modbuf        ; where it is
        call    putmod
        ret
MODLIN  endp

; This is the entry point for terminal emulation
; Added option of VT100 emulation

TERM    proc    near            ; terminal emulator entry point
        mov     argadr,ax       ; save argument ptr
        push    es              ; save caller's extra segment address
        mov     ax,seg datas
        mov     es,ax
        call    argini          ; init options from arg address
        cmp     flags.vtflg,TTGENRC ; emulating TEKTRONIX?
        jne     term0           ; no
        call    tek4010         ; go look like a TEKTRONIX
        jmp     quit1
term0:
        test    flags1,inited   ; have we run yet?
        jz      term1           ; no, forget this part
        call    restscr         ; restore screen
        jmp     term2
term1:
        call    cmblnk          ; clear it off
term2:
        or      flags1,inited   ; remember we've run already.
        call    clrmod          ; empty mode line
        test    yflags,modoff   ; is mode line disabled?
        jnz     term3           ; yes, skip it
        call    modlin          ; turn on mode line
term3:
        cmp     flags.vtflg,TTVT100 ; emulating VT100?
        jne     lp
        call    ansie
        jmp     quit
lp:
        call    portchr         ; char at port?
         jnc    chkinp          ; no, keep going
; we want to swallow any ANSI escapes that come for now
;     they are all of the form ESC [ nn ; nn ; nn ; nn a
;     where n is a numeric character, and a is a non-numeric character
        cmp     escseq,0        ; escape sequence in progress?
        jne     eat_esc_seq     ; yes
        cmp     al,ESC          ; got an escape?
        jne     no_esc          ; no
        mov     escseq,1        ; yes, flag it
        jmp     chkinp
eat_esc_seq:
        cmp     escseq,1        ; got [?
        jne     eat_esc_seq2    ; yes
        cmp     al,'['
        je      eat_esc_seq1
        push    ax              ; not [, print esc and char
        mov     al,ESC
        call    outtty          ; send the escape
        pop     ax              ; and the following character
        mov     escseq,0        ; no escape sequence
        jmp     no_esc
eat_esc_seq1:
        mov     escseq,2        ; flag [
        jmp     chkinp
eat_esc_seq2:
        cmp     al,';'          ; check for terminator
        je      chkinp
        cmp     al,'0'
        jl      end_esc
        cmp     al,'9'
        jg      end_esc
        jmp     chkinp          ; no terminator, keep eating
end_esc:
        mov     escseq,0        ; end of sequence
        jmp     chkinp
no_esc:
        call    outtty          ; print on terminal
chkinp:
        mov     ah,DCONIO       ; Get it with no checking
        mov     dl,0FFH
        int     DOS
        cmp     al,0            ; anything there?
        je      lp              ; no...
        cmp     al,esc_ch       ; escape character?
        je      quit            ; yes, stop here
        call    outprt
        jmp     chkinp          ; and keep going
quit:
        call    clrmod          ; erase mode line
        call    savescr         ; save screen
quit1:
        mov     al,yflags
        mov     bx,argadr
        mov     [bx].flgs,al    ; update flags in arg block
        pop     es              ; restore segment register
        ret                     ; and return to caller
TERM    endp

; ANSI, VT100 emulation by Andreas Stumpf

ANSIE   proc    near
        cmp     afirst,1        ; have we run yet?
        jnz     ansi2           ; no, forget this part
        mov     bx,ds           ; now restore keyboard too
        mov     es,bx
        mov     bx,offset parmblock
        mov     ax,18
        int     SUPERBIOS
        jmp     ansi3
ansi2:
        call    initansi
ansi3:
        mov     afirst,1        ; remember we've run already.
portc:
        call    portchr         ; char at port?
         jnc    achkinp         ; no, get char from keyboard
         call   doansi          ; handle it somehow
achkinp:
        mov     ah,DCONIO       ; Get it with no checking
        mov     dl,0FFH
        int     DOS
        cmp     al,0            ; anything there?
        je      portc           ; no...
        cmp     al,esc_ch       ; escape character?
        je      aquit           ; yes, stop here
        call    outprt          ; send it
        jmp     portc           ; look for next char
aquit:
        call    finiansi        ; fix keyboard up
        ret
ANSIE   endp

; DOANSI actually takes care of emulating the ANSI screen control stuff
; code by Andreas Stumpf - it expects the character to be in al

DOANSI  proc    near
        cmp     al,ESC          ; got an escape?
        jne     w00
        jmp     procesc0        ; escape terminates Escape-sequence,
w00:                            ; so it has to be tested first
        cmp     al,'X'-40h      ; Control-X ?
        jne     w0
        jmp     ignore
w0:
        cmp     al,'Z'-40h      ; Control-Z
        jne     w01
        jmp     ignore
w01:
        cmp     escseq,0        ; escape sequence in progress?
        je      w02
        jmp     procesc         ; yes
w02:
        cmp     al,' '
        jl      controls
        jmp     noesc
controls:
        cmp     al,LF           ; Linefeed,Formfeed and Vertical tab are
                                ; processed as 'Scroll down, if at
                                ; bottom margin, same function as ESC'D'
        jne     w1
        jmp     processD        ; perform scrolling if necessary
w1:     cmp     al,FF
        jne     w2
        jmp     processD
w2:     cmp     al,11           ; vertical tab
        jne     w3
        jmp     processD
w3:     cmp     al,TAB          ; horizontal tab
        jne     w4
        call    get_cur_pos     ; get cursor position
        mov     al,dh           ; work on it here
        mov     cx,80
        sub     cl,al           ; # of cols to search for tab
        cmp     cl,0            ; already off the end?
        jg      t0              ; no
        mov     cl,0
        jmp     t1              ; go to right margin
t0:
        xor     ah,ah
        mov     di,offset tabstops
        add     di,ax           ; address of first tabstop to look for
        cld
        mov     ax,1            ; compare table with 1
        repnz   scasb           ; cl=0 is right margin
t1:
        sub     cl,80
        neg     cl
        mov     dh,cl           ; set new col pos
        call    set_cur_pos     ; done...
        jmp     ignore
w4:     cmp     al,14           ; shift to extra set?
        jne     w5
        mov     chrset_mask,80H ; set top bit on these
        jmp     ignore
w5:     cmp     al,15           ; shift to normal set?
        jne     w6
        mov     chrset_mask,0   ; clear top bit
        jmp     ignore

w6:
        jmp     noesc

procesc0:                       ; start of escape sequence processing
        mov     escpnt,offset escstring
        mov     escseq,1        ; flag it
        jmp     doansi_d        ; done with it

procesc:                        ; have just got an escape
        cmp     escseq,1        ; single char ESCape ?
        je      procesc1        ; yes process it
        inc     escseq
        inc     escpnt          ; store escape sequence for
        mov     bx,escpnt       ; further processing
        mov     [bx],al
        cmp     escseq,3
        jg      proccont1
        cmp     al,'?'          ; 1st char after ESC'[' may be a '?'
        jne     proccont1
        jmp     doansi_d        ; done with it
proccont1:
        cmp     al,';'
        jne     proccont2
        jmp     doansi_d
proccont2:
        cmp     al,'-'          ; may be first char of a number
        jne     proccont3       ; continue checking
        mov     bx,escpnt
        cmp     byte ptr [bx-1],'0' ; preceding char in [0..9] ?
        jl      procmin1        ; if yes, then syntax error =>
        jmp     ignore          ; ignore Escapesequence
procmin1:
        cmp     byte ptr [bx-1],'9'
        jg      procmin2
        jmp     ignore
procmin2:
        jmp     doansi_d
proccont3:
        cmp     al,'0'
        jl      proccont
        cmp     al,'9'
        jg      proccont
        jmp     doansi_d        ; ESC-seq hasn't finished yet
proccont:
        jmp     procmulti       ; other char than 0..9 ';' => process them
procesc1:       ; function dispatcher for single char Escapesequences
        mov     di,offset sesctbl
        mov     cx,sesclen
        cld
        repnz   scasb           ; search for legal char following ESC
        cmp     al,[di-1]
        jnz     notrecognized
        mov     bx,sesclen
        sub     bx,cx           ; get offset in table
        dec     bx
        shl     bx,1
        add     bx,offset sescsub
        mov     escseq,0        ; Escape sequence has finished
        jmp     [bx]
notrecognized:
        jmp     noesc

processbra:                     ; introduction of multi-char Escapesequence
        mov     escseq,2
        inc     escpnt
        mov     bx,escpnt
        mov     [bx],al         ; save that char
        jmp     doansi_d        ; and get next one

processH:
        call    get_cur_pos     ; get cursor position
        mov     al,dh           ; get column here
        dec     al              ; range 0 to 79
        mov     bx,offset tabstops
        xor     ah,ah
        add     bx,ax
        mov     byte ptr [bx],1
        jmp     ignore

processD:
        call    get_cur_pos     ; get cursor position
        cmp     dl,bottom       ; is it last line?
        je      delline         ; yes, need to insert
        inc     dl              ; move down one line
        call    set_cur_pos
        jmp     ignore          ; done
delline:                        ; perform a scroll-up
        push    dx              ; save where we were
        mov     dl,top
        mov     dh,1            ; goto (top,1)
        call    set_cur_pos
        mov     al,ESC
        call    outtty
        mov     al,'M'          ; delete line
        call    outtty
        pop     dx              ; get back where we were
        push    dx
        mov     dh,1            ; column 1
        call    set_cur_pos
        mov     al,ESC
        call    outtty
        mov     al,'L'          ; insert line
        call    outtty
        pop     dx              ; get it back again
        cmp     dh,1
        je      processD1       ; done
        call    set_cur_pos     ; move to final position
processD1:
        jmp     ignore

processE:
        mov     al,CR           ; same as ESC'D', but in col 1
        call    outtty          ; so write out Carriage return
        jmp     processD

processM:
        call    get_cur_pos     ; get cursor position
        cmp     dl,top
        je      insline         ; yes, jump to insert
        dec     dl              ; move up one
        call    set_cur_pos
        jmp     ignore
insline:                        ; perform a scroll-down
        push    dx              ; save current position
        mov     dl,bottom
        mov     dh,1            ; 1. position to bottom margin
        call    set_cur_pos
        mov     al,ESC          ; 2. delete line
        call    outtty
        mov     al,'M'
        call    outtty
        mov     dl,top
        mov     dh,1            ; 3. position to top margin
        call    set_cur_pos
        mov     al,ESC
        call    outtty
        mov     al,'L'          ; 4. insert line with ESC 'L'
        call    outtty
        pop     dx              ; get back my position
        cmp     dh,1            ; first col?
        je      processM1       ; yes
        call    set_cur_pos
processM1:
        jmp     ignore          ; all done

processeq:                      ; set applikation keypad
        mov     ax,ds
        mov     es,ax
        mov     cx,8
        mov     di, offset apptbl.extrtabl
        add     di,START_EXTRTBL ; don't want to start at the top
        cmp     appcur,0        ; cursor keys application ?
        je      peq1
        mov     si,offset curapp
        jmp     peq2
peq1:   mov     si,offset curseq
peq2:   rep     movsw           ; move cursor keys to key-table
        mov     appkeys,1
        mov     bx,offset parmblock
        mov     byte ptr [bx],2
        mov     offs,offset apptbl
        mov     ax,18
        int     SUPERBIOS       ; set new keytable
        jmp     ignore

processgt:                      ; set numeric keypad
        mov     ax,ds
        mov     es,ax
        mov     cx,8
        mov     di, offset numtbl.extrtabl
        add     di,START_EXTRTBL ; don't want to start at the top
        cmp     appcur,0
        je      pgt1
        mov     si,offset curapp
        jmp     pgt2
pgt1:   mov     si,offset curseq
pgt2:   rep     movsw
        mov     appkeys,0
        mov     bx,offset parmblock
        mov     byte ptr [bx],2
        mov     offs,offset numtbl
        mov     ax,18
        int     SUPERBIOS
        jmp     ignore

process7:                       ; save cursor position
        mov     al,ESC
        call    outtty
        mov     al,'j'
        jmp     noesc

process8:                       ; restore cursor position
        mov     al,ESC
        call    outtty
        mov     al,'k'
        jmp     noesc

procmulti:      ; function dispatcher for multi-character escape-sequences
                ; AL has terminating character
        mov     cx,ds
        mov     es,cx
        mov     di,offset mesctbl
        mov     cx,mesclen
        cld
        repnz   scasb
        cmp     al,[di-1]
        jnz     notrec          ; didn't find it in table
        mov     bx,mesclen
        sub     bx,cx           ; get offset in table
        dec     bx
        shl     bx,1
        add     bx,offset mescsub
        jmp     [bx]
notrec: jmp     noesc

curmov: ; process Cursor movements
        cmp     escseq,3        ; has no mumeric argument
        jne     pars
curmov0:
        mov     al,ESC
        call    outtty
        mov     bx,escpnt
        mov     al,[bx]
        jmp     noesc           ; print it without '['
pars:                           ; parse numeric argument
        mov     bx,offset escstring+2 ; skip ESC'['
        call    getnum          ; getnum returns the number in DL
        xor     dh,dh
        cmp     dl,80
        jg      curmovend
        cmp     dl,0
        jl      curmovend
        je      curmov0
        mov     cx,dx           ; becomes loop counter
        mov     bx,escpnt
        mov     bl,[bx]         ; put last char of sequence in bl
parsl2:
        mov     al,ESC
        call    outtty
        mov     al,bl
        call    outtty
        loop    parsl2
curmovend:
        jmp     ignore          ; ignore invalid positioning

procg:
        mov     bx,offset escstring+2
        call    getnum
        cmp     dl,0
        jne     procg1
        call    get_cur_pos
        mov     al,dh           ; current col here
        dec     al              ; range 0 to 79
        mov     bx,offset tabstops
        xor     ah,ah
        add     bx,ax
        mov     byte ptr [bx],0
        jmp     ignore
procg1:
        cmp     dl,3
        jne     procg3
        mov     cx,80
        push    es
        push    ds
        pop     es              ; make sure in right segment
        mov     di,offset tabstops
        xor     ax,ax
        rep     stosb
        pop     es              ; get old es back
procg3:
        jmp     ignore

procE:
        mov     al,CR           ; go to col 1
        call    outtty
procle:
        mov     bx,escpnt
        mov     byte ptr [bx],'B' ; process cursor down
        jmp     curmov

procuF:
        mov     al,CR           ; go to col 1
        call    outtty
        mov     bx, escpnt
        mov     byte ptr [bx],'A' ; cursor up
        jmp     curmov

procuG:
        mov     bx,offset escstring+2
        call    getnum
        cmp     dl,0
        jg      procug1
        mov     dl,1
procug1:
        cmp     dl,80
        jle     procug2
        mov     dl,80
procug2:
        mov     cl,dl
        call    get_cur_pos
        mov     dh,cl           ; set new column
        call    set_cur_pos
        jmp     ignore

procld:
        mov     bx,offset escstring+2
        call    getnum
        cmp     dl,0
        jg      procld1
        mov     dl,1
procld1:
        cmp     dl,24
        jle     procld2
        mov     dl,24
procld2:
        mov     cl,dl
        call    get_cur_pos
        mov     dl,cl
        call    set_cur_pos
        jmp     ignore

procH:                          ; position cursor
        mov     bx,offset escstring+2
        call    getnum
        cmp     dl,1
        jge     procH0
        mov     dl,1            ; provide default for invalid address
procH0:
        cmp     dl,24
        jg      badH
        cmp     byte ptr [bx],';'
        jne     procH01
        inc     bx
procH01:
        push    dx              ; save row value
        call    getnum
        pop     ax              ; get it back here
        cmp     dl,1
        jge     procH1
        mov     dl,1
procH1:
        cmp     dl,80
        jg      badH
        mov     dh,dl           ; get in right places
        mov     dl,al
        call    set_cur_pos
badH:
        jmp     ignore

procL:
        mov     bx,offset escstring+2
        call    getnum
        mov     cx,dx
        cmp     cx,0
        jg      procL0
        mov     cx,1
        jmp     procL1
procL0:
        cmp     cx,24
        jle     procL1
        mov     cx,1
procL1:
        call    get_cur_pos
        mov     bh,dl
        mov     bl,dh           ; save these
procL2:                         ; perform a insert line
        mov     dl,bottom
        mov     dh,1
        call    set_cur_pos
        mov     al,ESC
        call    outtty
        mov     al,'M'
        call    outtty
        mov     dl,bh           ; get in right place
        mov     dh,bl
        call    set_cur_pos
        mov     al,ESC
        call    outtty
        mov     al,'L'
        call    outtty
        loop    procL2
        jmp     ignore

procM:
        mov     bx,offset escstring+2
        call    getnum
        mov     cx,dx
        cmp     cx,0
        jg      procM0
        mov     cx,1
        jmp     procM1
procM0:
        cmp     cx,24
        jle     procM1
        mov     cx,1
procM1:
        call    get_cur_pos
        mov     bh,dl
        mov     bl,dh
procM2:                         ; perform a delete line
        mov     al,ESC
        call    outtty
        mov     al,'M'
        call    outtty
        mov     dl,bottom
        mov     dh,1
        call    set_cur_pos
        mov     al,ESC
        call    outtty
        mov     al,'L'
        call    outtty
        mov     dl,bh           ; get in right places
        mov     dh,bl
        call    set_cur_pos
        loop    procM2
        jmp     ignore

procAt:                         ; insert blank characters
        mov     bx,offset escstring+2
        call    getnum
        mov     cx,dx
        sub     cx,1
        mov     al,ESC
        call    outtty
        mov     al,'@'
        call    outtty
        mov     al,' '
        call    outtty
        mov     al,BS
        call    outtty
        cmp     cx,0
        jle     procat1
procat2:
        mov     al,' '
        call    outtty
        mov     al,BS
        call    outtty
        loop    procat2
procat1:
        mov     al,ESC
        call    outtty
        mov     al,'O'
        call    outtty
        jmp     ignore

procP:
procX:
        mov     bx,offset escstring+2
        call    getnum
        mov     cx,dx
        cmp     cx,0
        jg      procX1
        mov     cx,1
procX1:
        mov     al,ESC
        call    outtty
        mov     al,'N'
        call    outtty
        loop    procX1
        jmp     ignore

procr:                          ; set margins
        mov     top,1
        mov     bottom,24
        mov     bx,offset escstring+2
        call    getnum
        cmp     dl,1
        jl      procr1
        cmp     dl,23
        jg      procr1
        mov     top,dl
procr1:
        inc     bx
        call    getnum
        cmp     dl,top
        jl      procr2
        cmp     dl,24
        jg      procr2
        mov     bottom,dl
procr2:
        mov     dh,1            ; After inspecting what the VAX EDT editor does,
        mov     dl,1            ; it appears that ESC [ Pn r should leave
        call    set_cur_pos     ; the cursor in the upper left corner [bgp]
        jmp     ignore

procc:                          ; Terminal status request
        mov     bx,offset escstring+2
        cmp     byte ptr [bx],'>'
        je      procc2
        cmp     byte ptr [bx],'0'
        je      procc0
        cmp     byte ptr [bx],'c'
        je      procc0
        jmp     ignore
procc0:
        push    wflags          ; need to save these
        and     yflags,not lclecho ; force no echo for these
        mov     al,ESC
        call    outprt
        mov     al,'['
        call    outprt
        mov     al,'?'
        call    outprt
        mov     al,'1'
        call    outprt
        mov     al,';'          ; signal AVO option - we sort of have it
        call    outprt
        mov     al,'2'
        call    outprt
        mov     al,'c'
        call    outprt
        pop     wflags          ; get back old flags
procc2:
        jmp     ignore

procn:                          ; device status report
        mov     bx,offset escstring+2
        cmp     byte ptr [bx],'5'
        je      procn5
        cmp     byte ptr [bx],'6'
        je      procn6
        jmp     ignore
procn5:                         ; return operating status 'no malfunction'
        push    wflags          ; force no echo
        and     yflags,not lclecho
        mov     al,ESC
        call    outprt
        mov     al,'['
        call    outprt
        mov     al,'0'
        call    outprt
        mov     al,'n'
        call    outprt
        pop     wflags
        jmp     ignore
procn6:                         ; report cursor position
        push    wflags          ; force no echo
        and     yflags,not lclecho
        call    get_cur_pos
        mov     al,dh           ; get column here
        sub     al,1fh          ; get binary column
        aam
        add     ax,3030h        ; change to ASCII
        push    ax
        mov     al,dl           ; get line here now
        sub     al,1fh          ; convert to binary
        aam                     ; and to ...
        add     ax,3030h        ; ASCII
        mov     bx,ax
        mov     al,ESC          ; put string out in form : ESC'['line';'col'R'
        call    outprt
        mov     al,'['
        call    outprt
        cmp     bh,30h          ; don't need leading zero
        je      procc61
        mov     al,bh
        call    outprt
procc61:
        mov     al,bl
        call    outprt
        mov     al,';'
        call    outprt
        pop     bx
        cmp     bh,30h
        je      procc62
        mov     al,bh
        call    outprt
procc62:
        mov     al,bl
        call    outprt
        mov     al,'R'
        call    outprt
        pop     wflags          ; get these back
        jmp     ignore

proclm:                         ; do screen attributes
        mov     bx,offset escstring+2
proclm1:
        call    getnum
        cmp     dl,0
        jne     proclm2
        mov     al,ESC
        call    outtty
        mov     al,')'
        call    outtty
        mov     al,ESC
        call    outtty
        mov     al,'q'
        call    outtty
        mov     al,ESC
        call    outtty
        mov     al,'1'
        call    outtty
        jmp     proclm5
proclm2:
        cmp     dl,1
        jne     proclm3
        mov     al,ESC
        call    outtty
        mov     al,'('
        call    outtty
        jmp     proclm5
proclm3:
        cmp     dl,4
        jne     proclm4
        mov     al,ESC
        call    outtty
        mov     al,'0'
        call    outtty
        jmp     proclm5
proclm4:
        cmp     dl,7
        jne     proclm5
        mov     al,ESC
        call    outtty
        mov     al,'p'
        call    outtty
proclm5:
        cmp     byte ptr [bx],'m'
        je      proclm6
        inc     bx
        jmp     proclm1
proclm6:
        jmp     ignore

procJ:
        cmp     escseq,3
        je      procJ0
        mov     bx,offset escstring+2 ; skip ESC'['
        call    getnum
        cmp     dl,0
        je      procJ0
        cmp     dl,1
        je      procJ1
        cmp     dl,2
        je      procJ2
        jmp     ignore          ; ignore others
procJ0:
        mov     al,ESC
        call    outtty
        mov     al,'J'
        jmp     noesc
procJ1:
        mov     al,ESC
        call    outtty
        mov     al,'b'
        jmp     noesc
procJ2:
        mov     al,ESC
        call    outtty
        mov     al,'E'
        jmp     noesc

prochl:
        mov     bx,offset escstring+2 ; skip ESC'['
        call    getnum
        cmp     [escstring+2],'?'
        je      quest
        mov     bx,escpnt
        mov     bl,[bx]         ; contains 'h' or 'l'
        cmp     dl,4
        jne     not4
        mov     al,ESC
        call    outtty
        mov     al,'@'
        cmp     bl,'l'
        jne     enterins
        mov     al,'O'
enterins:
        jmp     noesc
not4:                           ; ignore the others
        jmp     ignore
quest:                          ; sequence like ESC'[?'nn'h'
        mov     bx,escpnt
        mov     bl,[bx]
        cmp     dl,1
        jne     not1
        mov     cx,8
        cmp     appkeys,0
        je      q1
        mov     offs,offset apptbl
        mov     di, offset apptbl.extrtabl
        jmp     q2
q1:     mov     offs,offset numtbl
        mov     di, offset numtbl.extrtabl
q2:     add     di,START_EXTRTBL ; don't want to start at the top
        cmp     bl,'l'
        je      q3
        mov     si,offset curapp
        mov     appcur,1
        jmp     q4
q3:     mov     si,offset curseq
        mov     appcur,0
q4:     rep     movsw
        mov     bx,offset parmblock
        mov     byte ptr [bx],2
        mov     ax,18
        int     SUPERBIOS
        jmp     ignore
not1:
        cmp     dl,5
        jne     not5
        mov     al,ESC
        call    outtty
        mov     al,'p'
        cmp     bl,'h'
        je      isreverse
        mov     al,'q'
isreverse:
        jmp     noesc
not5:
        cmp     dl,7
        jne     not7
        mov     al,ESC
        call    outtty
        mov     al,'v'
        cmp     bl,'h'
        je      autowrap
        mov     al,'w'
autowrap:
        jmp     noesc
not7:                           ; ignore the others
        jmp     ignore

procK:
        cmp     escseq,3
        je      procK0
        mov     bx,offset escstring+2 ; skip ESC'['
        call    getnum
        cmp     dl,0
        je      procK0
        cmp     dl,1
        je      procK1
        cmp     dl,2
        je      procK2
        jmp     ignore          ; ignore others
procK0:
        mov     al,ESC
        call    outtty
        mov     al,'K'
        jmp     noesc
procK1:
        mov     al,ESC
        call    outtty
        mov     al,'o'
        jmp     noesc
procK2:
        mov     al,ESC
        call    outtty
        mov     al,'l'
        jmp     noesc

noesc:                          ; That wasn't valid! (or print last char)
        or      al,chrset_mask  ; set top bit right for specified set
        call    outtty          ; print it out...
ignore:                         ; Here to flag end of escape or ignore
        mov     escseq,0        ; one that we don't like
doansi_d:
        ret                     ; Here when we have no more to do
DOANSI  endp

; GETNUM gets a number from escapestring, returns it in DL.
;   Input: pointer in BX.  Destroys BX, CX, DH. Finishes on first
;   encounteder non-numeric char except '-'.     Assumes correct syntax
;   ('-' only as first char - checked in procmulti)

GETNUM  proc    near
        xor     dx,dx
        cmp     bx,escpnt       ; is it to end of string already?
        jge     getn4           ; yes - just exit with zero
        xor     ch,ch           ; assume positive number
        cmp     byte ptr [bx],'?' ; first char may be a questionmark
        jne     getn1
        inc     bx
getn1:
        mov     cl,[bx]
        cmp     cl,';'
        je      getn3
        cmp     cl,'-'
        jne     getn2
        mov     ch,-1
getn2:
        cmp     cl,'0'
        jl      getn3
        cmp     cl,'9'
        jg      getn3
        sub     cl,'0'
        shl     dl,1            ; multiply by 10 (=1010b)
        mov     dh,dl
        shl     dl,1
        shl     dl,1
        add     dl,dh
        add     dl,cl
        inc     bx
        cmp     bx,escpnt
        jl      getn1
getn3:
        cmp     ch,-1
        jne     getn4
        neg     dx
getn4:
        ret
GETNUM  endp

; initialize keyboard and tables to build it [as]

INITANSI proc   near
        cld
        mov     bx,ds
        mov     es,bx
        mov     bx,offset parmblock
        mov     ax,18
        int     SUPERBIOS       ; get old keyboard
        or      ax,ax
        jz      ansi01
        jmp     aend
ansi01: mov     cx,598          ; copy it
        mov     si,offset oldtable
        mov     di,offset numtbl
        rep     movsw
        mov     si,offset numtbl ; Index in Table
        mov     byte ptr [si].kd0+25,7fh ; DEL to Backspace-key

; set cursorkeys
        mov     word ptr [si].kd12+2*88,0A000h  ;
        mov     word ptr [si].kd12+2*89,0A000h  ; with auto-repeat
        mov     word ptr [si].kd12+2*98,0A000h
        mov     word ptr [si].kd12+2*99,0A000h
        mov     byte ptr [si].kd0+88,START_EXTRTBL ; offset in EXTRtabl
        mov     byte ptr [si].kd0+89,START_EXTRTBL+4
        mov     byte ptr [si].kd0+98,START_EXTRTBL+8
        mov     byte ptr [si].kd0+99,START_EXTRTBL+12
        mov     di,offset numtbl.extrtabl
        add     di,START_EXTRTBL ; Don't want to overwrite stuff
        mov     si,offset curseq
        mov     cx,8
        rep     movsw           ; move the new sequences to keytable

; copy complete table to build Applikation-keypad-table
        mov     cx,598
        mov     si,offset numtbl
        mov     di,offset apptbl
        rep     movsw

; now build keypad
        mov     si,offset apptbl
        mov     word ptr [si].kd12+2*28,8000h
        mov     word ptr [si].kd12+2*29,8000h
        mov     word ptr [si].kd12+2*30,8000h
        mov     word ptr [si].kd12+2*31,8000h
        mov     word ptr [si].kd12+2*49,8000h
        mov     word ptr [si].kd12+2*50,8000h
        mov     word ptr [si].kd12+2*51,8000h
        mov     word ptr [si].kd12+2*52,8000h
        mov     word ptr [si].kd12+2*69,8000h
        mov     word ptr [si].kd12+2*70,8000h
        mov     word ptr [si].kd12+2*71,8000h
        mov     word ptr [si].kd12+2*72,8000h
        mov     word ptr [si].kd12+2*90,8000h
        mov     word ptr [si].kd12+2*91,8000h
        mov     word ptr [si].kd12+2*92,8000h
        mov     word ptr [si].kd12+2*93,8000h
        mov     word ptr [si].kd12+2*100,8000h
        mov     word ptr [si].kd12+2*102,8000h
        mov     byte ptr [si].kd0+28,START_EXTRTBL+16 ; offset in EXTRtabl
        mov     byte ptr [si].kd0+29,START_EXTRTBL+20
        mov     byte ptr [si].kd0+30,START_EXTRTBL+24
        mov     byte ptr [si].kd0+31,START_EXTRTBL+28
        mov     byte ptr [si].kd0+49,START_EXTRTBL+32
        mov     byte ptr [si].kd0+50,START_EXTRTBL+36
        mov     byte ptr [si].kd0+51,START_EXTRTBL+40
        mov     byte ptr [si].kd0+52,START_EXTRTBL+44
        mov     byte ptr [si].kd0+69,START_EXTRTBL+48
        mov     byte ptr [si].kd0+70,START_EXTRTBL+52
        mov     byte ptr [si].kd0+71,START_EXTRTBL+56
        mov     byte ptr [si].kd0+72,START_EXTRTBL+60
        mov     byte ptr [si].kd0+90,START_EXTRTBL+64
        mov     byte ptr [si].kd0+91,START_EXTRTBL+68
        mov     byte ptr [si].kd0+92,START_EXTRTBL+72
        mov     byte ptr [si].kd0+93,START_EXTRTBL+76
        mov     byte ptr [si].kd0+100,START_EXTRTBL+80
        mov     byte ptr [si].kd0+102,START_EXTRTBL+84
        mov     di,offset apptbl.extrtabl
        add     di,START_EXTRTBL ; avoid overwriting stuff...
        mov     si,offset applik
        mov     cx,44
        rep     movsw           ; move new keycodes to table
        mov     bx,offset parmblock
        mov     byte ptr [bx],2
        mov     offs,offset numtbl ; set numeric keypad
        mov     ax,18
        int     SUPERBIOS
aend:
        ret
INITANSI endp

; Save old keyboard stuff when exiting [as]

FINIANSI proc   near
        mov     bx,offset parmblock
        mov     byte ptr [bx],2
        mov     dx,offset oldtable
        xchg    dx,offs         ; save old keyboard-type in dx
        mov     ax,18
        int     SUPERBIOS
        xchg    dx,offs         ; restore old keyboard-type
        ret
FINIANSI endp

; Get the current cursor location - row in dl, col in dh
; (1,1) is upper left corner

GET_CUR_POS proc near
        mov     al,ESC          ; request cursor location
        call    outtty
        mov     al,'n'
        call    outtty
        mov     ah,CONINQ       ; input no check
        int     DOS             ; gets the ESC
        int     DOS             ; gets the Y
        int     DOS
        sub     al,31
        mov     dl,al
        int     DOS
        sub     al,31
        mov     dh,al
        ret
GET_CUR_POS endp

; Set the cursor location - row in dl, col in dh
; (1,1) is upper left corner

SET_CUR_POS proc near
        push    dx              ; save it to be sure
        mov     al,ESC
        call    outtty
        mov     al,'Y'
        call    outtty
        pop     dx
        push    dx
        mov     al,dl           ; row
        add     al,31
        call    outtty
        pop     dx
        push    dx
        mov     al,dh           ; column
        add     al,31
        call    outtty
        pop     dx
        ret
SET_CUR_POS endp

; Save the screen so we can restore it

SAVESCR proc    near
        call    get_cur_pos     ; get cursor location
        mov     tcurloc,dl      ; this is line number
        mov     tcurloc+1,dh    ; this is column number
        mov     bx,SEG_CRTC     ; where crt controller is
        mov     es,bx
        mov     bx,OFF_CRTC
        mov     byte ptr es:[bx],12
        mov     ah,es:1[bx]
        and     ah,7            ; only want bottom 3 bits
        mov     byte ptr es:[bx],13
        mov     al,es:1[bx]
        shl     ax,1            ; multiply by 2 (was word address)
        mov     si,ax
        push    ds
        pop     es
        mov     ds,tscrseg
        mov     di,offset tscreen
        mov     cx,1920
        rep     movsw
        push    es
        pop     ds
        call    cmblnk          ; let them start with a blank one
        ret                     ; and return
SAVESCR endp

; Restore screen from scrsav buffer

RESTSCR proc    near
        call    cmblnk          ; start with a clear screen
        mov     si,offset tscreen
        mov     es,tscrseg
        xor     di,di           ; start at start
        mov     cx,1920         ; 1920 words to go
        rep     movsw
        mov     dx,word ptr tcurloc ; get cursor location
        call    set_cur_pos
        ret
RESTSCR 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.
; This reads the screen that was last saved by savescr - it is expected
; that savescr will be called just before this one.
; 7 August 1986 Add this routine - it is pirated from the file MSYIBM and
; modified to match the Victor's needs.  Note that a screen dump is not
; possible in Tektronix mode (unfortunately) since I'm not sure how to dump
; it in a way that would make sense.  [bgp]

DUMPSCR PROC    NEAR
        cmp     flags.vtflg,TTGENRC ; emulating Tektronix?
        jne     dumpxx          ; no, save screen
        jmp     dumptek         ; this won't do anything but beep
dumpxx:
        push    ax
        push    bx
        push    cx
        push    dx
        mov     dmphand,-1      ; preset illegal handle
        mov     dx,offset dmpname ; name of disk file, from mssset
        mov     ax,dx           ; where isfile wants name ptr
        call    isfile          ; what kind of file is this?
        jc      dmp5            ; c = no such file, create it
        test    byte ptr filtst.dta+21,1FH ; file attributes, ok to write?
        jnz     dmp0            ; nz=no.
        mov     al,1            ; writing
        mov     ah,OPEN2        ; open existing file
        int     DOS
        jc      dmp0            ; c=failure
        mov     dmphand,ax      ; save file handle
        mov     bx,ax           ; need handle here
        mov     cx,0FFFFH       ; set up file pointer
        mov     dx,-1           ; and offset
        mov     al,2            ; move to eof minus one byte
        mov     ah,LSEEK        ; and seek the end
        int     DOS
        jmp     dmp1

dmp5:   mov     ah,CREAT2       ; file did not exist
        mov     cx,20H          ; attributes, archive bit
        int     DOS
        mov     dmphand,ax      ; save file handle
        jnc     dmp1            ; nc=ok

dmp0:   call    clrmod          ; clear place for mode line
        mov     dx,offset dmperr ; get string to put there
        call    putmod          ; on mode line...
        pop     dx
        pop     cx
        pop     bx
        pop     ax
        ret

dmp1:   push    di              ; read screen buffer, write lines
        push    si
        push    es
        push    ds
        pop     es              ; make sure this is right
        mov     cx,24           ; 24 lines in buffer
        mov     si,offset tscreen ; where screen is saved
dmp2:   push    cx              ; save outer loop counter
        mov     di,offset dumpbuf ; data segment memory
        mov     cx,80           ; 80 columns
dmp3:   mov     ax,word ptr es:[si] ; read char + attribute
        and     ax,7FFH         ; take off attributes
        sub     ax,char_base    ; minus base
        mov     byte ptr [di],al ; store the char
        inc     si
        inc     si
        inc     di
        loop    dmp3            ; do for each column
        std                     ; set scan backward
        mov     cx,80           ; 80 columns
        mov     di,offset dumpbuf+79 ; end of line
        mov     al,' '          ; thing to scan over
        repe    scasb           ; scan until non-space
        cld                     ; set direction forward
        jz      dmp3a           ; z=all spaces
        inc     cx
        inc     di
dmp3a:  mov     word ptr [di+1],0A0DH ; append cr/lf
        add     cx,2            ; line count + cr/lf
        mov     dx,offset dumpbuf ; array to be written
        mov     bx,dmphand      ; need file handle
        mov     ah,WRITE2       ; write the line
        int     DOS
        pop     cx              ; get line counter again
        loop    dmp2            ; do next line
        mov     dx,offset dumpsep ; put in ff/cr/lf
        mov     cx,3            ; three bytes overall
        mov     ah,WRITE2       ; write them
        mov     bx,dmphand      ; file handle
        int     DOS
        mov     ah,CLOSE2       ; close the file now
        int     DOS
dmp6:   pop     es
        pop     si
        pop     di
        pop     dx
        pop     cx
        pop     bx
        pop     ax
        ret

dumptek:
        call    beep            ; what else should we do?
        ret
DUMPSCR ENDP

; Come to here to act somewhat like a Tektronix 4010 terminal...
TEK4010 proc    near
        push    es                      ; this will be used repeatedly
        mov     es,scrseg
        cmp     first_in,FALSE          ; been here before?
        je      tek0                    ; yes
        call    clrscr                  ; be sure screen is clear
        mov     first_in,FALSE          ; flag it
tek0:
        call    set_hires               ; set to hires screen
teklp:
        cmp     full_flag,FALSE         ; page full condition
        jne     tekcki                  ; yes, I can't accept anything
        call    portchr                 ; char at port?
         jnc    tekcki                  ; no, keep going
        call    tekhandle               ; go handle the character
tekcki:
        dec     cursor_cnt              ; decrement cursor countdown
        jnz     tekcki1                 ; not ready
        call    cursor_on               ; turn on cursor
tekcki1:
        mov     ah,DCONIO               ; Get it with no checking
        mov     dl,0FFH
        int     DOS
        cmp     al,0                    ; anything there?
        je      teklp                   ; no...
        cmp     al,esc_ch               ; escape character?
        je      tekquit                 ; yes, stop here
        cmp     al,CLEAR                ; is it the clear key?
        jne     tekcki2
        call    clrscr
        jmp     tekcki1
tekcki2:
        call    outprt
        jmp     tekcki1                 ; and keep going
tekquit:
        call    reset_hires             ; reset to normal screen
        pop     es
        ret
TEK4010 endp

; Take care of an incoming character

TEKHANDLE proc  near
        call    capture                 ; in case we should
        cmp     al,GS                   ; Group Separator?
        je      tek2graf                ; ->graphics with pen up
        cmp     al,ESC                  ; Escape?
        je      tek2esc                 ; ->handle special commands
        mov     bl,escflag
        xor     bh,bh
        call    tekjump[bx]             ; Go to right routine
        mov     cursor_cnt,CURSOR_TIME  ; init cursor countdown
        ret
;
tek2graf:
        mov     visible,0               ; Pen up
        mov     escflag,4               ; Get HIY next
        mov     graph_mode,TRUE
        ret
tek2esc:
        mov     escflag,2               ; ESC handler next
        ret
TEKHANDLE endp

; TEXT mode - just put text on screen

TEKTXT  proc    near
        call    cursor_off              ; be sure this is off
        cmp     text_x,TEXT_X_MAX       ; off screen?
        jle     tektxta
        mov     text_x,0                ; to left margin
        add     text_y,RPLINE
tektxta:
        cmp     text_y,TEXT_Y_MAX
        jle     tektxtb
        call    page_full               ; page is full!
        ret                             ; lost that character, oh well...
tektxtb:
        cmp     al,DEL                  ; Is it delete?
        jne     tektxt1
        ret
tektxt1:
        cmp     al,' '                  ; Is it control?
        jl      tektxt3
        cmp     echo_supp,FALSE         ; In echoplex suppression?
        jne     tektxt2                 ; Yes, don't print it
        call    character               ; Output it
        call    inc_char
tektxt2:
        ret
tektxt3:
        cmp     al,BELL
        jne     tektxt4
        call    beep
        mov     echo_supp,FALSE         ; Clear suppression
        ret
tektxt4:
        cmp     al,BS
        jne     tektxt6
        sub     text_x,CPCHAR           ; back up one
        cmp     text_x,0
        jge     tektxt5                 ; ok
        mov     text_x,R_MARG           ; right margin
        sub     text_y,RPLINE           ; back one line
        cmp     text_y,0                ; top?
        jge     tektxt5
        mov     text_y,0                ; top of screen
tektxt5:
        mov     echo_supp,FALSE         ; Clear suppression
        ret
tektxt6:
        cmp     al,TAB
        jne     tektxt7
        call    inc_char
        mov     echo_supp,FALSE         ; Clear suppression
        ret
tektxt7:
        cmp     al,LF                   ; Line feed?
        jne     tektxt9
        add     text_y,RPLINE           ; Down one line
        cmp     text_y,TEXT_Y_MAX       ; Past end?
        jle     tektxt8
        call    page_full               ; can't go any further!
        ret
tektxt8:
        mov     echo_supp,FALSE         ; Clear suppression
        ret
tektxt9:
        cmp     al,VTAB
        jne     tektxt11
        sub     text_y,RPLINE           ; Up one line
        cmp     text_y,0                ; Past top?
        jge     tektxt10
        mov     text_y,0
tektxt10:
        mov     echo_supp,FALSE         ; Clear suppression
        ret
tektxt11:
        cmp     al,CR                   ; It is return?
        jne     tektxt12
        mov     text_x,0                ; to left margin
        mov     echo_supp,FALSE         ; Clear suppression
        ret
tektxt12:
        ret
TEKTXT  endp

; Move the text position by one char, perform auto wrap, and
; check for page full

INC_CHAR proc   near
        add     text_x,CPCHAR           ; Move to next column
        cmp     text_x,TEXT_X_MAX       ; Past end?
        jle     inc_char0
        mov     text_x,0                ; Left margin
        add     text_y,RPLINE
        cmp     text_y,TEXT_Y_MAX       ; Past end?
        jle     inc_char0
        call    page_full               ; Take no more!
inc_char0:
        ret
INC_CHAR endp

; ESC mode - check what to do

TEKESC  proc    near
        cmp     al,FF                   ; Form feed?
        jne     tekesc1
        call    clrscr
        mov     echo_supp,FALSE         ; Clear suppression
        jmp     tekescq
tekesc1:
        cmp     al,SUB                  ; Control-Z?
        jne     tekesc2
        mov     escflag,0               ; Just in case
        mov     echo_supp,TRUE          ; echoplex suppression
        call    tekcrs                  ; Go to cross hairs
        ret                             ; Last char does its thing
tekesc2:
        cmp     al,ETB                  ; Make copy?
        jne     tekesc2a
        mov     echo_supp,FALSE         ; Clear suppression
        jmp     tekescq
tekesc2a:
        cmp     al,ENQ                  ; enquire?
        jne     tekesc3
        mov     echo_supp,TRUE          ; echoplex suppression
        call    send_stat
        jmp     tekescq                 ; do nothing for now ***
tekesc3:
        call    tektxt                  ; It's just text...
tekescq:
        mov     escflag,0               ; Now in full text mode
        mov     graph_mode,FALSE
        ret
TEKESC  endp

; Get coordinates   escflag=4->expect hiy, escflag=6->expect hix

TEKHIY  proc    near
tekhix:
        call    cursor_off              ; make sure it is off
        cmp     al,CR                   ; should we exit?
        jne     tekhi1
        mov     cur_x,0                 ; go to left margin
        mov     echo_supp,FALSE         ; Clear suppression
        jmp     go2text
tekhi1:
        cmp     al,US                   ; another exit?
        jne     tekhi2
        mov     echo_supp,FALSE         ; Clear suppression
        jmp     go2text
tekhi2:
        cmp     al,FF
        jne     tekhi3
        call    clrscr
        mov     echo_supp,FALSE         ; Clear suppression
        jmp     go2text
tekhi3:
        cmp     echo_supp,FALSE         ; In suppression
        jne     tekhi4                  ; Yes, ignore this...
        cmp     al,20H                  ; control character?
        jl      tekhi4
        cmp     al,40H
        jl      tekhi5                  ; 20-3F are HIX or HIY
        cmp     al,60H
        jl      tekhi7                  ; 40-5F are LOX
;   Get to here must be 60-7F -> LOY
        mov     ah,loy                  ; copy old loy
        mov     lsb,ah                  ; to lsb (in case 4014)
        and     al,1FH                  ; low 5 bits
        mov     loy,al
        cmp     escflag,6               ; 2nd in a row?
        je      tekhi4                  ; then previous was lsb anyway
        mov     lsb,0                   ; clear lsb
        mov     escflag,6               ; expect HIX next
tekhi4:
        ret
; Get either HIX or HIY depending on escflag
tekhi5:
        and     ax,1FH
        mov     cl,5
        shl     ax,cl                   ; multiply by 32
        cmp     escflag,4               ; looking for HIY?
        jne     tekhi6                  ; no, HIX
        mov     hiy,ax
        ret                             ; leave escflag=4
tekhi6:
        mov     hix,ax
        mov     escflag,4               ; look for HIY next
        ret
; Get LOX and do the movement
tekhi7:
        and     al,1FH
        mov     lox,al
        mov     ax,hix
        or      al,lox
        mov     cur_x,ax
        mov     dx,hiy
        or      dl,loy
        mov     cur_y,dx
        call    tek2victor              ; convert the coords
        mov     endpt,ax
        mov     endpt+2,dx              ; save them
        cmp     visible,0
        je      tekhi8
        call    line                    ; draw the line
tekhi8:
        mov     visible,1
        mov     ax,endpt
        mov     start,ax
        mov     ax,endpt+2
        mov     start+2,ax              ; end is now start
        mov     escflag,4               ; want HIY next
        ret
;
go2text:
        mov     escflag,0
        mov     graph_mode,FALSE
        mov     ax,cur_x
        mov     dx,cur_y
        call    tek2victor
        mov     text_x,ax
        sub     dx,10                   ; mov to upper left corner
        cmp     dx,0
        jge     go2text1
        xor     dx,dx
go2text1:
        mov     text_y,dx
        ret
TEKHIY  endp

; Go to CURSOR mode

TEKCRS  proc    near
        call    cursor_off
        mov     combine,offset pixel_xor
        mov     trmesc,FALSE
        mov     prtesc,FALSE
tekcrs_dr:
        mov     ax,cur_x                ; get x
        sub     ax,CUR_LEN              ; minus a little
        cmp     ax,0
        jge     tekcrs_dr1
        mov     ax,0
tekcrs_dr1:
        mov     dx,cur_y
        call    tek2victor
        mov     crs_hor,ax
        mov     crs_hor+4,dx
        mov     ax,cur_x
        add     ax,CUR_LEN              ; add a little
        cmp     ax,TEK_X_MAX
        jle     tekcrs_dr2
        mov     ax,TEK_X_MAX
tekcrs_dr2:
        mov     dx,cur_y
        call    tek2victor
        mov     crs_hor+2,ax
        mov     dx,cur_y                ; now y's
        sub     dx,CUR_LEN              ; minus a little
        cmp     dx,0
        jge     tekcrs_dr3
        mov     dx,0
tekcrs_dr3:
        mov     ax,cur_x
        call    tek2victor
        mov     crs_ver,dx
        mov     crs_ver+4,ax
        mov     dx,cur_y
        add     dx,CUR_LEN              ; plus a little
        cmp     dx,TEK_Y_MAX
        jle     tekcrs_dr4
        mov     dx,TEK_Y_MAX
tekcrs_dr4:
        mov     ax,cur_x
        call    tek2victor
        mov     crs_ver+2,dx
        call    draw_cursor             ; put it on
tekcrs_lp:
        mov     dl,0FFH
        mov     ah,DCONIO               ; get character
        int     DOS
        cmp     al,0                    ; anything?
        jne     tekcrs_hnd              ; take care of it
        call    portchr                 ; check port character
        jnc     tekcrs_lp               ; nothing there
        cmp     prtesc,FALSE            ; received escape?
        je      tekcrs_lp1              ; no
        mov     prtesc,FALSE
        cmp     al,FF
        je      tekcrs_abt
        cmp     al,ETB
        je      tekcrs_abt
        cmp     al,ENQ
        jne     tekcrs_lp
        call    send_stat               ; send status
        jmp     tekcrs_lp
tekcrs_lp1:
        cmp     al,BELL                 ; check for control and clear...
        je      tekcrs_abt
        cmp     al,BS
        je      tekcrs_abt
        cmp     al,CR
        je      tekcrs_abt
        cmp     al,TAB
        je      tekcrs_abt
        cmp     al,LF
        je      tekcrs_abt
        cmp     al,US
        je      tekcrs_abt
        cmp     al,ESC
        jne     tekcrs_lp               ; try for more
        mov     prtesc,TRUE
        jmp     tekcrs_lp
tekcrs_abt:
        mov     echo_supp,FALSE         ; clear echo suppression
        mov     escflag,0               ; and text mode
        jmp     tekcrs_xt               ; and leave
;
tekcrs_hnd:
        cmp     trmesc,FALSE            ; received escapes yet?
        jne     tekcrs_hnd2
        cmp     al,ESC                  ; escape character?
        je      tekcrs_hnd1
        jmp     tekcrs_done             ; finished
tekcrs_hnd1:
        mov     trmesc,TRUE             ; flag it
        jmp     tekcrs_lp
tekcrs_hnd2:
        cmp     al,'1'                  ; change step?
        jge     tekcrs_hnd2z
        jmp     tekcrs_done
tekcrs_hnd2z:
        cmp     al,'9'
        jle     tekcrs_hnd3
        cmp     al,'A'
        jne     tekcrs_hnd2a
        mov     ax,cur_stp
        add     cur_y,ax
        jmp     tekcrs_und              ; remove old and redraw
tekcrs_hnd2a:
        cmp     al,'B'
        jne     tekcrs_hnd2b
        mov     ax,cur_stp
        sub     cur_y,ax
        jmp     tekcrs_und              ; remove old and redraw
tekcrs_hnd2b:
        cmp     al,'C'
        jne     tekcrs_hnd2c
        mov     ax,cur_stp
        add     cur_x,ax
        jmp     tekcrs_und
tekcrs_hnd2c:
        cmp     al,'D'
        jne     tekcrs_hnd2d
        mov     ax,cur_stp
        sub     cur_x,ax
        jmp     tekcrs_und
tekcrs_hnd2d:
        jmp     tekcrs_done             ; its the one to send
tekcrs_hnd3:
        sub     al,'0'                  ; convert to number
        xor     ah,ah
        mov     cur_stp,ax              ; new step value
        mov     trmesc,FALSE
        jmp     tekcrs_lp
tekcrs_und:
        cmp     cur_x,0                 ; check for validity
        jge     tekcrs_und1
        mov     cur_x,0
        jmp     tekcrs_und2
tekcrs_und1:
        cmp     cur_x,TEK_X_MAX
        jle     tekcrs_und2
        mov     cur_x,TEK_X_MAX
tekcrs_und2:
        cmp     cur_y,0
        jge     tekcrs_und3
        mov     cur_y,0
        jmp     tekcrs_und4
tekcrs_und3:
        cmp     cur_y,TEK_Y_MAX
        jle     tekcrs_und4
        mov     cur_y,TEK_Y_MAX
tekcrs_und4:
        call    draw_cursor             ; remove the cursor
        mov     trmesc,FALSE
        jmp     tekcrs_dr               ; and draw new one
tekcrs_done:
        push    cur_y                   ; want current coords
        push    cur_x                   ; for sending
        call    send_coord              ; send character and coords
tekcrs_xt:
        call    draw_cursor             ; remove the cursor
        mov     ax,cur_x
        mov     dx,cur_y                ; need to set start point
        call    tek2victor
        mov     start,ax
        mov     start+2,dx
        mov     text_x,ax               ; set text point also
        sub     dx,10                   ; move to upper left corner
        cmp     dx,0
        jge     tekcrs_xt1
        xor     dx,dx
tekcrs_xt1:
        mov     text_y,dx
        mov     combine,offset pixel_or
        ret
TEKCRS  endp

; DRAW CURSOR expects to have the appropriate endpoints in CRS_HOR for
; the horizontal line (x1,x2,y) and CRS_VER for the vertical line (y1,y2,x)

DRAW_CURSOR proc near
        mov     ax,crs_hor
        mov     start,ax
        mov     ax,crs_hor+4
        mov     start+2,ax
        mov     endpt+2,ax
        mov     ax,crs_hor+2
        mov     endpt,ax
        call    line                    ; draw horizontal line
        mov     ax,crs_ver
        mov     start+2,ax
        mov     ax,crs_ver+4
        mov     start,ax
        mov     endpt,ax
        mov     ax,crs_ver+2
        mov     endpt+2,ax
        call    line                    ; draw vertical line
        ret
DRAW_CURSOR endp

; Convert TEK coords to VICTOR coords
;   entry:   ax=x, dx=y (tek)
;   exit:   ax=x, dx=y (victor)

TEK2VICTOR proc near
        push    dx                      ; save y for now
        mov     bx,X_MAX
        mul     bx
        mov     bx,TEK_X_MAX
        div     bx
        cmp     dx,TEK_X_MAX/2          ; need to round up?
        jl      tek2vic1
        inc     ax
tek2vic1:
        pop     dx
        push    ax                      ; save x now
        mov     ax,dx
        mov     bx,Y_MAX
        mul     bx
        mov     bx,TEK_Y_MAX
        div     bx
        cmp     dx,TEK_Y_MAX/2          ; need to round up?
        jl      tek2vic2
        inc     ax
tek2vic2:
        sub     ax,Y_MAX                ; need to swap it
        neg     ax
        mov     dx,ax
        pop     ax
        ret
TEK2VICTOR endp

; Set the CRT to hires mode

SET_HIRES proc  near
        push    es
        call    crt_lo_inten            ; so you don't see so much jump
        mov     ah,DCONIO
        mov     dl,27
        int     DOS
        mov     dl,'E'
        int     DOS                     ; let's start with a clear screen
        push    ds
        pop     es
        mov     ax,0F000H               ; this is status line
        mov     ds,ax
        mov     di,offset status_line   ; where to put it
        mov     si,3840
        cld
        mov     cx,80                   ; 80 words
        rep     movsw
        push    es
        pop     ds                      ; restore ds
        mov     bx,0E800H               ; CRT controller segment
        mov     es,bx
; fix the write to work on the VICKI - it has an 8086 [bgp and as]
        mov     byte ptr es:0,0         ; reg 0
        mov     byte ptr es:1,3AH
        mov     byte ptr es:0,1
        mov     byte ptr es:1,32H
        mov     byte ptr es:0,2
        mov     byte ptr es:1,34H
        mov     byte ptr es:0,3
        mov     byte ptr es:1,0C9H
        mov     byte ptr es:0,0AH       ; no cursor
        mov     byte ptr es:1,20H
; end VICKI fix
        xor     ah,ah                   ; assume using lower bank of memory
        test    scrseg,1000H            ; really?
        jz      set_hires1
        mov     ah,10H
set_hires1:
        or      ah,20H
; VICKI fix again...
        mov     byte ptr es:0,0CH       ; reg 12
        mov     byte ptr es:1,ah
        mov     byte ptr es:0,0DH
        mov     byte ptr es:1,0
        mov     byte ptr es:0,0EH
        mov     byte ptr es:1,0
        mov     byte ptr es:0,0FH
        mov     byte ptr es:1,0
; end VICKI fix
        mov     cx,4e2H                 ; 1250 locations to set
        mov     ax,scrseg               ; where screen is
        shr     ax,1                    ; /2
        mov     di,0F000H               ; in screen ram
        mov     es,di
        xor     di,di
set_hires2:
        stosw                           ; set one
        inc     ax                      ; next one
        loop    set_hires2
        call    crt_hi_inten
        pop     es
        ret
SET_HIRES endp

; Reset the CRT to lores mode

RESET_HIRES proc near
        push    es
        call    crt_lo_inten            ; to minimize jump
        mov     bx,0E800H               ; segment for CRT controller
        mov     es,bx
; VICKI fix
        mov     byte ptr es:0,0         ; reg 0
        mov     byte ptr es:1,5CH
        mov     byte ptr es:0,1
        mov     byte ptr es:1,50H
        mov     byte ptr es:0,2
        mov     byte ptr es:1,51H
        mov     byte ptr es:0,3
        mov     byte ptr es:1,0CFH
        mov     byte ptr es:0,0AH
        mov     byte ptr es:1,0         ; steady block cursor
        mov     byte ptr es:0,0CH
        mov     byte ptr es:1,0
        mov     byte ptr es:0,0DH
        mov     byte ptr es:1,0
        mov     byte ptr es:0,0EH
        mov     byte ptr es:1,0
        mov     byte ptr es:0,0FH
        mov     byte ptr es:1,0
; end VICKI fix
        mov     ah,DCONIO
        mov     dl,27
        int     DOS
        mov     dl,'E'
        int     DOS                     ; insure screen is clear
        mov     ax,0F000H               ; restore status line
        mov     es,ax
        mov     si,offset status_line
        mov     di,3840
        cld
        mov     cx,80                   ; one line
        rep     movsw
        call    crt_hi_inten
        pop     es
        ret
RESET_HIRES endp

; Set to lo intensity

CRT_LO_INTEN proc near
        mov     bx,0E804H               ; CRT controller segment
        mov     es,bx
        mov     al,es:0                 ; get current setting
        mov     ah,al                   ; save it
        and     al,1CH
        mov     intens,al               ; store it
        mov     al,ah
        and     al,0E3H                 ; zero intensity
        mov     es:0,al
        ret
CRT_LO_INTEN endp

; Set to hi intensity

CRT_HI_INTEN proc near
        mov     bx,0E804H               ; Crt controller segment
        mov     es,bx
        mov     al,es:0                 ; Get current setting
        and     al,0E3H                 ; Clear intensity
        or      al,intens               ; Set to correct value
        mov     es:0,al
        ret
CRT_HI_INTEN endp

; Clear the hires screen area

CLRSCR  proc    near
        les     di,dword ptr scrloc     ; get right location
        cld                             ; increment
        mov     cx,20000                ; 40000 bytes
        mov     ax,0
        rep     stosw                   ; doing it
        mov     cur_x,0                 ; set to home position
        mov     cur_y,780
        mov     hix,0
        mov     hiy,0
        mov     lox,0
        mov     loy,0
        mov     lsb,0
        mov     start,0
        mov     start+2,0
        mov     text_x,0
        mov     text_y,0
        mov     full_flag,FALSE         ; page isn't full
        mov     cursor,FALSE            ; cursor isn't on
        mov     cursor_cnt,CURSOR_TIME  ; set up cursor countdown
        ret
CLRSCR  endp

; Put the character in al on the screen at location pointed at by
; text_x,text_y.  Use combination routine pointed at by t_combine

CHARACTER proc  near
        cmp     al,' '                  ; is it a space?
        jne     character1              ; no
        ret                             ; just return...
character1:
        and     al,07FH                 ; Be sure it is in range...
        cmp     al,07FH                 ; Is it delete?
        jl      character1a
        ret                             ; Don't do it...
character1a:
        push    ax                      ; save the character
        mov     ax,text_y
        mov     dx,text_x
        call    convert_loc             ; get to where we are going
        les     di,dword ptr scrloc     ; get screen location
        add     si,di                   ; now we are in the right place
        mov     cx,text_y
        and     cx,0FH                  ; need mod(y,16)
        sub     cx,16
        neg     cx                      ; how many to do in this section
        cmp     cx,RPLINE               ; more than one line?
        jle     character1b
        mov     cx,RPLINE               ; make it just one line
character1b:
        mov     temp,cx                 ; need to remember this
        pop     ax                      ; get back the character
        sub     ax,'!'                  ; start with exclamation mark
        xor     ah,ah
        mov     dl,RPLINE               ; number of entries per character
        shl     dl,1                    ; they are word entries
        mul     dl
        mov     di,ax                   ; where to get bit patterns
        mov     dx,cx                   ; how many to do
        mov     cx,bx                   ; this is the number to shift
        or      cx,cx                   ; look at it
        jnz     character1c
        jmp     character8              ; no shifts necessary
character1c:
        cmp     cx,5                    ; this goes within one word
        jg      character4              ; spans word boundaries
character2:
        mov     bx,font[di]
        or      bx,bx                   ; is it zero?
        jz      character3
;;;[jrd]cmp     si,offset screen        ; too low?
        cmp     si,0                    ; too low? (start at 0 offset) [jrd]
        jb      character3
;;;[jrd]cmp     si,offset screen+39999  ; too high?
        cmp     si,39999                ; too high? [jrd]
        jae     character3
        shl     bx,cl                   ; shift to right place
        call    t_combine
character3:
        inc     di
        inc     di
        inc     si
        inc     si
        dec     dx                      ; done one row
        jnz     character2
        add     si,1568                 ; go to top of next major row
        mov     dx,RPLINE               ; how many we needed to do
        sub     dx,temp                 ; minus how many done
        mov     temp,RPLINE             ; claim we have done them all
        jg      character2              ; do the rest
        jmp     character10
character4:
        sub     cx,16                   ; convert to right shift
        neg     cx
        mov     ax,0FFFFH               ; need to build mask
        shl     ax,cl
        not     ax
        mov     c_mask,ax
character5:
        mov     bx,font[di]
        or      bx,bx                   ; zero?
        jz      character5a
;;;[jrd]cmp     si,offset screen        ; too low?
        cmp     si,0                    ; too low? (starts at 0 offset) [jrd]
        jb      character5a
;;;[jrd]cmp     si,offset screen+39999  ; too high?
        cmp     si,39999                ; too high? [jrd]
        jae     character5a
        jmp     character6
character5a:
        inc     si
        inc     si
        jmp     character7
character6:
        and     bx,c_mask               ; mask upper bits
        ror     bx,cl                   ; get first batch
        call    t_combine
        add     si,32                   ; next word column
        mov     bx,font[di]
        shr     bx,cl
        call    t_combine
        sub     si,30                   ; back to right column, plus 2
character7:
        inc     di
        inc     di
        dec     dx                      ; done one row
        jnz     character5
        add     si,1568                 ; go to top of next major row
        mov     dx,RPLINE               ; how many we needed to do
        sub     dx,temp                 ; minus how many done
        mov     temp,RPLINE             ; claim we have done them all
        jg      character5              ; do the rest
        jmp     character10
character8:
        mov     bx,font[di]
        or      bx,bx                   ; is it zero?
        jz      character9
;;;[jrd]cmp     si,offset screen        ; too low?
        cmp     si,0                    ; too low? (starts at 0 offset) [jrd]
        jb      character9
;;;[jrd]cmp     si,offset screen+39999  ; too high?
        cmp     si,39999                ; too high? [jrd]
        jae     character9
        call    t_combine
character9:
        inc     di
        inc     di
        inc     si
        inc     si
        dec     dx                      ; done one row
        jnz     character8
        add     si,1568                 ; go to top of next major row
        mov     dx,RPLINE               ; how many we needed to do
        sub     dx,temp                 ; minus how many done
        mov     temp,RPLINE             ; claim we have done them all
        jg      character8              ; do the rest
        jmp     character10
character10:
        ret
CHARACTER endp

; Cursor on - turn on the cursor if it isn't already on

CURSOR_ON proc  near
        cmp     cursor,FALSE
        jne     c_on_end                ; already on
        push    ax                      ; save this just in case
        mov     t_combine,offset word_xor ; set combine rule
        mov     ax,CURSOR_CHR
        call    character               ; print without advancing
        mov     t_combine,offset word_or ; set combine rule
        mov     cursor,TRUE             ; flag it
        pop     ax
c_on_end:
        ret
CURSOR_ON endp

; Cursor off - erase the cursor if it is there

CURSOR_OFF proc near
        cmp     cursor,FALSE
        je      c_off_end               ; already off
        push    ax
        mov     t_combine,offset word_xor ; set combine rule
        mov     ax,CURSOR_CHR
        call    character               ; print without advancing
        mov     t_combine,offset word_or ; set combine rule
        mov     cursor,FALSE            ; flag it
        pop     ax
c_off_end:
        ret
CURSOR_OFF endp

; Notify the user that the page is full, and set flag to wait for
; him to clear it.

PAGE_FULL proc  near
        mov     full_flag,TRUE          ; page is full!
        call    beep                    ; make some noise about it
        les     di,dword ptr scrloc     ; get screen location
        add     di,38424                ; lower left corner
        mov     ax,0FFFFH               ; set them all!
        or      es:[di],ax
        inc     di
        inc     di
        or      es:[di],ax
        inc     di
        inc     di
        or      es:[di],ax
        inc     di
        inc     di
        or      es:[di],ax
        ret
PAGE_FULL endp

; Connect points: start=startx, start+2=starty, endpt=endx, endpt+2=endy
;   Uses combination routine pointed at by combine

LINE    proc    near
        mov     dx,start                ; start x
        mov     ax,endpt                ; end x
        mov     x_inc,1                 ; assume incrementing
        sub     ax,dx
        jnb     line1                   ; correct
        neg     x_inc
        neg     ax
line1:
        mov     delta_x,ax              ; save delta
        mov     dx,start+2              ; start y
        mov     ax,endpt+2              ; end y
        mov     y_inc,1                 ; assume incrementing
        sub     ax,dx
        jnb     line2                   ; correct
        neg     y_inc
        neg     ax
line2:
        mov     delta_y,ax              ; save delta
        les     di,dword ptr scrloc     ; point at bit map region
        mov     dx,start
        mov     ax,start+2
        call    set_pixel               ; set start point
        mov     ax,delta_y
        cmp     ax,delta_x              ; which should we step on
        ja      line_y
;
line_x:
        mov     cx,delta_x              ; number of steps
        jcxz    line_x_done             ; nothing to do
        mov     ax,cx
        shr     ax,1                    ; delta_x/2
        mov     part_accum,ax
line_x_loop:
        mov     ax,x_inc
        add     start,ax
        mov     ax,delta_y
        sub     part_accum,ax
        jge     line_x_ok
        mov     ax,y_inc
        add     start+2,ax
        mov     ax,delta_x
        add     part_accum,ax
line_x_ok:
        mov     dx,start
        mov     ax,start+2
        call    set_pixel
        loop    line_x_loop
line_x_done:
        ret
;
line_y:
        mov     cx,delta_y              ; number of steps
        jcxz    line_y_done             ; nothing to do
        mov     ax,cx
        shr     ax,1                    ; delta_y/2
        mov     part_accum,ax
line_y_loop:
        mov     ax,y_inc
        add     start+2,ax
        mov     ax,delta_x
        sub     part_accum,ax
        jge     line_y_ok
        mov     ax,x_inc
        add     start,ax
        mov     ax,delta_y
        add     part_accum,ax
line_y_ok:
        mov     dx,start
        mov     ax,start+2
        call    set_pixel
        loop    line_y_loop
line_y_done:
        ret
LINE    endp

; Set pixel at location dx,ax

SET_PIXEL proc  near
        cmp     dx,X_MAX
        ja      set_range
        cmp     ax,Y_MAX
        ja      set_range
        call    convert_loc
        cmp     bx,8                    ; top byte?
        jb      set_noinc               ; no
        inc     si
        sub     bx,8
set_noinc:
        add     si,di                   ; correct offset to segment
        mov     bl,bit_mask[bx]
        call    combine
        ret
set_range:
        pop     bx                      ; pop one return address
        ret                             ; do nothing if off the screen
SET_PIXEL endp

; Convert x and y to word location and word bit number
;   entry: dx=x, ax=y, exit: si=byte number, bx=bit number

CONVERT_LOC proc near
        mov     si,ax
        and     si,0FH                  ; mod(y,16)
        mov     bx,ax
        and     bx,0FFF0H               ; 16*int(y/16)
        shl     bx,1                    ; *2 (need 50 times)
        add     si,bx                   ; that's 2
        shl     bx,1                    ; *4
        shl     bx,1                    ; *8
        shl     bx,1                    ; *16
        add     si,bx                   ; that's 18
        shl     bx,1                    ; *32
        add     si,bx                   ; that's 50
        mov     bx,dx
        and     bx,0FFF0H               ; 16*int(x/16)
        add     si,bx
        shl     si,1                    ; byte address
        mov     bx,dx
        and     bx,0FH                  ; mod(x,16)
        ret
CONVERT_LOC endp

; Or the mask in bl into byte at es:[si]

PIXEL_OR proc   near
        or      es:[si],bl
        ret
PIXEL_OR endp

; Exclusive-or mask in bl into byte at es:[si]

PIXEL_XOR proc  near
        xor     es:[si],bl
        ret
PIXEL_XOR endp

; Or the word in bx into word at es:[si]

WORD_OR proc    near
        or      es:[si],bx
        ret
WORD_OR endp

; Exclusive-or the word in bx into word at es:[si]

WORD_XOR proc   near
        xor     es:[si],bx
        ret
WORD_XOR endp

; Send the status out the back

SEND_STAT proc  near
        cmp     graph_mode,FALSE        ; in graph mode?
        je      send_stat1              ; No
        push    cur_y                   ; push current point, y first
        push    cur_x                   ; then x
        mov     al,39H                  ; bit 7=0, bit 6=1, bit 5=1 (no hcopy)
                                        ; bit 4=1 (ready for vector)
                                        ; bit 3=0 (graph mode)
                                        ; bit 2=0 (margin 0), bit 1=1
        call    send_coord              ; send it out
        ret
;
send_stat1:
        mov     ax,text_y               ; get current point
        add     ax,10                   ; move to lower left corner
        sub     ax,Y_MAX                ; need to swap it
        neg     ax
        mov     bx,TEK_Y_MAX            ; convert to tek coords
        mul     bx
        mov     bx,Y_MAX
        div     bx
        cmp     dx,Y_MAX/2              ; need to round up?
        jl      send_stat2
        inc     ax
send_stat2:
        cmp     ax,TEK_Y_MAX            ; up too far?
        jbe     send_stat3              ; okay
        mov     ax,TEK_Y_MAX
send_stat3:
        push    ax                      ; save y
        mov     ax,text_x
        mov     bx,TEK_X_MAX            ; convert to tek coords
        mul     bx
        mov     bx,X_MAX
        div     bx
        cmp     dx,X_MAX/2              ; need to round up?
        jl      send_stat4
        inc     ax
send_stat4:
        cmp     ax,TEK_X_MAX            ; up too far?
        jbe     send_stat5              ; okay
        mov     ax,TEK_X_MAX
send_stat5:
        push    ax                      ; save x
        mov     al,3DH                  ; bit 7=0, bit 6=1, bit 5=1 (no hcopy)
                                        ; bit 4=1 (ready for vector)
                                        ; bit 3=1 (not graph mode)
                                        ; bit 2=0 (margin 0), bit 1=1
        call    send_coord              ; send it out
        ret
SEND_STAT endp

; Send the byte currently in the al register out the port, then follow
; it by the coordinates - x is the first on the stack, y is the second
; on the stack (i.e., x was pushed last, and popped first)

SEND_COORD proc near
        call    outprt                  ; send byte in al
        pop     cx                      ; this is the return address
        pop     ax                      ; this is x coord
        pop     bx                      ; this is y coord
        push    cx                      ; return back on
        push    bx                      ; y back on
        push    ax                      ; x back on
        mov     cl,5                    ; shift to hix
        shr     ax,cl
        and     al,31                   ; keep 5 bits
        or      al,32                   ; this is hix now
        call    outprt
        pop     ax                      ; x again
        and     al,31
        or      al,64                   ; this is lox now
        call    outprt
        pop     ax                      ; get y coordinate
        push    ax                      ; save it again for a flash
        mov     cl,5                    ; shift to hiy
        shr     ax,cl
        and     al,31                   ; keep 5 bits
        or      al,32                   ; this is hiy now
        call    outprt
        pop     ax                      ; y again
        and     al,31
        or      al,96                   ; this is loy now
        call    outprt
;   Now for the termination string - use CR,EOT - this is the default for
;   the 4051 microcomputer which is supposed to look like a 4012 - I hope
;   they know what they are doing...
        mov     al,13
        call    outprt
        mov     al,4
        call    outprt
        ret
SEND_COORD endp

; Send the character in al out to the serial port
; Handle echoing also...

OUTPRT  proc    near
        test    yflags,lclecho  ; echoing?
        jz      outpr1          ; no, forget it
        cmp     flags.vtflg,TTGENRC ; doing TEKTRONIX?
        jz      outpr00         ; yes - echo it nicely
        cmp     flags.vtflg,TTVT100 ; doing VT100?
        jz      outpr0          ; yes - echo it nicely
        push    ax              ; save char
        call    outtty          ; print it
        pop     ax              ; restore
        jmp     outpr1
outpr00:
        cmp     full_flag,FALSE         ; page full?
        jne     outpr1                  ; forget this
        push    ax
        call    tekhandle               ; do the job in a smart way
        pop     ax
        jmp     outpr1
outpr0:
        push    ax              ; save char
        call    doansi
        pop     ax              ; restore
outpr1:
        mov     ah,al           ; this is where outchr expects it
        call    outchr          ; output to the port
         nop
         nop
         nop                    ; skip returns...
        ret
OUTPRT  endp

; Get a character from the serial port in al
; returns with carry on if a character is available

PORTCHR proc    near
        call    prtchr          ; character at port?
         jmp    short portc1    ; yes, go handle
        nop                     ; skip return is stupid...
        clc                     ; no carry -> no character
        ret                     ; and return...
portc1:
        and     al,7fh          ; we don't worry about parity here
        stc                     ; have a character
        ret                     ; and return
PORTCHR endp

; Put the character in al to the screen
; Directly call the console-driver to get better speed (4 times, ~19200
; baud)  [as]

OUTTTY  proc    near
        call    capture
        push    ax              ; these are modified by the driver
        push    bx
        push    cx
        push    dx
        push    si
        push    es
        mov     cl,al
        mov     ax,1
        call    dword ptr drivadr
        pop     es
        pop     si
        pop     dx
        pop     cx
        pop     bx
        pop     ax
        ret                     ; through
OUTTTY  endp

; Capture char in al to a file if we are supposed to

CAPTURE proc    near
        test    yflags,CAPT     ; capturing output?
        jz      nocap           ; no forget this part
        push    ax              ; save it
        call    captrtn
        pop     ax              ; get char back
nocap:
        test    flags1,PRTSCR   ; should we be printing?
        jz      noprt           ; no, go on
        push    ax              ; save char
        mov     ah,LSTOUT
        mov     dl,al
        int     DOS             ; out it goes
        pop     ax
noprt:
        ret
CAPTURE endp

; Set heath emulation on/off.
; Added VT100 emulation switch and TEKTRONIX switch - notifies of
; idiosyncracies if TEKTRONIX selected (also checks for allowability)
; [bgp]

VTS     proc    near
        mov     dx,offset termtbl
        mov     bx,offset termhlp
        mov     ah,CMKEY
        call    comnd
         jmp    vt1
        push    bx
        mov     ah,CMCFM
        call    comnd           ; Get a confirm.
         jmp    vt0             ;       Didn't get a confirm.
         nop
        pop     bx
        cmp     bl,TTGENRC      ; doing TEKTRONIX?
        jne     vt00            ; no
        cmp     tek_allowed,FALSE ; can we do TEKTRONIX?
        jne     vt000           ; yes
        mov     dx,offset no_tek_msg ; tell him we can't
        mov     ah,PRSTR
        int     DOS
        ret                     ; don't do anything
vt000:
        push    bx
        mov     dx,offset tek_msg ; tell him about status
        mov     ah,PRSTR
        int     DOS
        pop     bx
vt00:
        mov     flags.vtflg,bl  ; Set the emulation flag.
        ret
vt0:
        pop     bx
vt1:
        ret
VTS     endp

VTSTAT  PROC    NEAR    ; For Status display [jrd]
        ret             ; no emulator status to display
VTSTAT  ENDP

CODE    ends

        end

