home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
kermit.columbia.edu
/
kermit.columbia.edu.tar
/
kermit.columbia.edu
/
bin
/
mskermit
/
msvv90sea.exe
/
V9KERMSC.EXE
/
MSYV90.ASM
< prev
Wrap
Assembly Source File
|
1993-07-03
|
94KB
|
3,723 lines
name msyv90
; File MSYV90.ASM
; Copyright (C) 1982,1991, Trustees of Columbia University in the
; City of New York. Permission is granted to any individual or
; institution to use, copy, or redistribute this software as long as
; it is not sold for profit and this copyright notice is retained.
; Kermit system dependent module for VICTOR 9000/SIRIUS
; Use with msuv90.asm and msxv90.asm.
; SPECIAL VERSION WITH NEAR COMPLETE SUPPORT OF TEKTRONIX 4010 EMULATION
; as of MS-DOS KERMIT version 3.02. Victor 9000 Kermit without
; Tektronix emulation will no longer be supported.
;
; Edit history:
; 2 March 1991 version 3.10
; Last modification: 2 March 1991
; 6 Dec 1988 Replace dynamic screen space with static segment aagraph (see
; NOTE WELL msg below), add control of 7/8 bit displays, add TRANSLATE INPUT
; table workings. [jrd]
; 1 Mar 1988 add TERMTB terminal status display table and correct use
; of tektronix mode set to match that implemented in MSYIBM as of version
; 2.30. Also add use of CAN (control-X) to exit tektronix temporary
; mode. [bgp]
; 20 Sept 1987 clarify sequence of translation and 8 bit display. [jrd]
; 11 Sept 1987 Modify page_full routine for Tektronix emulation so that
; the indicator box put in the lower left corner of the screen on page
; full condition is put in with exclusive or instead of simple or. Then
; modified the homescr routine to remove that indicator box using an
; exclusive or operation if the page full condition exists and to be sure
; that the old text cursor is removed before moving the current cursor
; location to the upper left corner. [bgp]
; 7 Sept 1987 Remove keep_delete, filter null in portch, filter DEL in
; terminal read section for VT100 (pass through for Tek), add parmsk. [jrd]
; 29 August 1987 add temporary Tektronix mode so that the receipt of an
; ESCAPE FF (Tektronix clear screen sequence) will go to Tektronix mode with
; a clear screen. It will go back to the previous mode on the receipt of
; an ESCAPE US sequence or by entering the escape character.
; 29 August 1987 add support for keyboard translation. This uses a
; modified version of the translator for the GENERIC MS-DOS version.
; This modification required the addition of the following routines:
; CQUERY - help on connect
; CSTATUS - show status of connect
; CQUIT - exit from connect
; CHANG - hangup the phone (drop dtr)
; DMPSCN - dump the screen
; TRNPRS - toggle printer dump status
; SNULL - send a null
; KDOS - push to DOS
; KLOGOFF - suspend session logging
; KLOGON - resume session logging
; CPAGE - clear tektronix screen
; CHOME - move to home on tektronix screen
; 9 February 1987 Added set of keep_delete (byte) = 0 if delete to be
; ignored by serial port routines [bgp]
; 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 - confidence tests
; 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, extmacro, vtmacname, vtmaclen, setchtab
public cquery, cstatus, cquit, snull, kdos ; [bgp]
public klogof, klogon, cpage, chome ; [bgp]
public chang, trnprs, dmpscn, chrout ; [bgp]
public termtb, trnmod
public sescur, sesdisp, setnbios, fcsrtype
; NOTE WELL - The Victor 9000 machine requires high resolution (graphics)
; memory to be located in the first 128KB of system memory, even though
; programs are loaded into the same area(!). Here we define a special graphics
; segment, aagraph, and request the assembler to located segments
; as shown below, with _STACK last!
; Further we MUST place MSYV90.OBJ first in the Link list of .objs.
; [jrd 8 Dec 1988].
;
; Start Stop Length Name Class
; 00000H 09C5FH 09C60H AAGRAPH KCODE
; 09C60H 14FB0H 0B351H CODE KCODE
; 14FC0H 1768FH 026D0H CODE1 KCODE
; 17690H 17690H 00000H CODE2 KCODE
; 17690H 24E9BH 0D80CH DATA KDATA
; 24EA0H 2627FH 013E0H DATA1 KDATA
; 26280H 26280H 00000H _TEXT CODE
; 26280H 26280H 00000H _DATA DATA
; 26280H 26280H 00000H CONST CONST
; 26280H 26280H 00000H _BSS BSS
; 26280H 26FC7H 00D48H _STACK STACK
;
AAGRAPH SEGMENT PUBLIC 'kcode'
DB 40032 DUP (?) ; graphics memory
AAGRAPH ENDS
; Do the "include mssdef.h" file after the aagraph declaration.
include mssdef.h
; Some extra ASCII definitions
ENQ EQU 5
VTAB EQU 0BH
ETB EQU 17H
CAN EQU 18H
GS EQU 1DH
US EQU 1FH
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 ' Help:'
m_hlp db 2 dup (?)
db '? Port:'
m_prt db 1 dup (?)
db ' Speed:'
m_baud db 5 dup (?)
db ' Parity:'
m_par db 4 dup (?)
db ' Echo:'
m_echo db 3 dup (?)
m_term db 13 dup (' ') ; 13 bytes for terminal type
m_prn db 3 dup (' ') ; show PRN when printer is on
db ' $' ; must be dollar terminated
modfrm ends
data segment
extrn rdbuf:byte, flags:byte ; to get access to emulation
extrn dmpname:byte, filtst:byte, trans:byte, prnhand:word
extrn kbdflg:byte,rxtable:byte,taklev:byte,takadr:word,mcctab:byte
termhlp db CR,LF,'Terminal type of Heath-19, VT102, VT52, none,'
db ' or Tek4010$'
termtb db 5
mkeyw 'Heath-19',ttheath
mkeyw 'none',ttgenrc
mkeyw 'Tek4010',tttek
mkeyw 'VT102',ttvt100
mkeyw 'VT52',ttvt52
setchtab db 1 ; Set File Character-Set table
mkeyw 'CP437',437 ; hardware default Code Page
tty_generic db ' None '
tty_tek4010 db ' Tektronix '
tty_heath db ' Heath-19 '
tty_vt102 db ' VT-102 '
tty_vt52 db ' VT-52 '
tty_unkn db ' Unknown '
; 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...
argadr dw ? ; address of arg blk
crt_cols db 80 ; number of screen columns (typ 80)
crt_lins db 24 ; number of screen rows - 1 (typ 24)
oldsp dw 0 ; offset to longjmp to for i/o failure
vtmacname dw 0 ; pointer to selected macro name
vtmaclen db 0
sescur dw 0
modbuf modfrm <> ; mode line buffer
; routine to call for captured output
captrtn dw ?
; some static data for mode line
unkbaud db 'Unkwn' ; must be 5 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 '19200'
db '38400'
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=[, <0 eat chars
; until =0
; stuff for the Tektronix emulation
; Order is essential:scrloc then scrseg
scrloc dw 0 ; offset of screen memory [jrd]
scrseg dw 0 ; segment of screen memory [jrd]
parmsk db ? ; 8/7 bit parity mask, for reception
temp_tek db FALSE ; for temporary tektronix mode [bgp]
temp_mode dw 0 ; previous mode for temp tek mode [bgp]
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,ESCAPE,'[A',3,ESCAPE,'[B',3,ESCAPE,'[D',3,ESCAPE,'[C'
curapp db 3,ESCAPE,'OA',3,ESCAPE,'OB',3,ESCAPE,'OD',3,ESCAPE,'OC'
; Applikationkeypad
appkeys db 0 ; flag for keypad modes
applik db 3,ESCAPE,'[A',3,ESCAPE,'[B',3,ESCAPE,'[D',3,ESCAPE,'[C'
db 3,ESCAPE,'OP',3,ESCAPE,'OQ',3,ESCAPE,'OR',3,ESCAPE,'OS'
db 3,ESCAPE,'Ow',3,ESCAPE,'Ox',3,ESCAPE,'Oy',3,ESCAPE,'Om'
db 3,ESCAPE,'Ot',3,ESCAPE,'Ou',3,ESCAPE,'Ov',3,ESCAPE,'Ol'
db 3,ESCAPE,'Oq',3,ESCAPE,'Or',3,ESCAPE,'Os',3,ESCAPE,'OM'
db 3,ESCAPE,'Op',3,ESCAPE,'On'
sesctbl db 'DEHMNOZn|o[>=78c<)(#' ; table for char following single ESCAPE
db FF ; ESCAPE FF goes temporary tektronix [bgp]
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 ESCAPE [0c
dw ignore
dw ignore
dw ignore
dw processbra
dw processgt
dw processeq
dw process7
dw process8
dw ignore
dw ignore
dw processrp
dw processlp
dw processlb
dw process_ff ; temporary tektronix mode [bgp]
; table for the last characters in a ESCAPE'[' sequence
mesctbl db '`EFGABCDHLM@PXKJfghilmrcnpyqde'
mesclen equ $-mesctbl
; processing routine table for ESCAPE'[' 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
crlf db cr,lf
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: cannot open the screen dump file$'
data ends
code1 segment
; Control text cursor. AL = 0 for off, 1 for on (nominally underline)
fcsrtype proc far
call csrtype
ret
fcsrtype endp
code1 ends
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]
extrn msuinit:near, keybd:near ; [bgp]
extrn pntchr:near, pntflsh:near
assume cs:code,ds:data,es:nothing
; do initialization local to this module...
; mainly get console driver address to speed up screen access [as]
; 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 flags.vtflg,ttvt102 ; start as a VT102
call msuinit ; init keyboard module msuv90 [bgp]
mov ah,DCONIO
mov dl,ESCAPE ; 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
; setup screen
mov ax,aagraph ; segment of graphics memory (See Note above)
cmp ax,1000H ; start in lower half? [bgp sub-mod]
jae lclyini1 ; ae = no
cmp ax,63BH ; maximum segment in lower half
jb lclyini3 ; b = low enough to work, go on
lclyini1:
cmp ax,163BH ; maximum segment in top half
jb lclyini3 ; b = 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 is 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+TRNCTL+LCLECHO+MODOFF
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 ax,[bx].captr
mov captrtn,ax ; buffer capture routine
mov parmsk,0ffh ; parity mask, assume parity = None
cmp [bx].parity,parnon ; is parity None?
je argini1 ; e = yes, keep all 8 bits
mov parmsk,07fh ; else keep lower 7 bits
argini1:ret ; that's it
ARGINI endp
; Toggle Mode Line
trnmod proc near
cmp flags.modflg,1 ; mode line enabled and owned by us?
jne trnm1 ; ne = no, don't touch it
test yflags,modoff ; mode line already off?
jnz trnm2 ; nz = yes, go turn on
or yflags,modoff ; say modeline is toggled off
call clrmod ; clear mode line
trnm1: clc ; clear c bit so don't exit Connect
ret
trnm2: cmp flags.vtflg,0 ; emulating a terminal?
jne trnm3 ; ne = yes
push dx ; scroll screen to save bottom line
mov ah,prstr ; for terminal type none
mov dx,offset crlf
int dos
pop dx
trnm3: call modlin ; turn on modeline
and yflags,not modoff ; say modeline is not toggled off
clc
ret
trnmod endp
; We need to generate the mode line and output it
MODLIN proc near ; turn on mode line
push es
push ds
pop es ; make sure es is correct
mov al,trans.escchr ; Connect mode escape character
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,5 ; each is 5 bytes long
mul 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
cld
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 ; 1=1
je modl5
mov al,'2' ; 0=2
modl5:
mov modbuf.m_prt,al ; fill in port number
mov cl,13
mov di,offset modbuf.m_term ; fill in terminal type
mov si,offset tty_generic ; assume generic first
cmp flags.vtflg,TTGENRC
je modl6
mov si,offset tty_heath ; try heath
cmp flags.vtflg,TTHEATH
je modl6
mov si,offset tty_vt102 ; try vt100
cmp flags.vtflg,TTVT100
je modl6
mov si,offset tty_vt52 ; try vt52
cmp flags.vtflg,TTVT52
je modl6
mov si,offset tty_tek4010 ; try tektronix
cmp flags.vtflg,TTTEK
je modl6
mov si,offset tty_unkn
modl6:
rep movsb
mov modbuf.m_prn,' ' ; assume not printing
mov modbuf.m_prn+1,' '
mov modbuf.m_prn+2,' '
test yflags,PRTSCR
jz modl7 ; not
mov modbuf.m_prn,'P'
mov modbuf.m_prn+1,'R'
mov modbuf.m_prn+2,'N'
modl7:
mov dx,offset modbuf ; where it is
call putmod
pop es
ret
MODLIN endp
; This is the entry point for terminal emulation
; Added option of VT100 emulation
TERM proc near ; terminal emulator entry point
mov oldsp,sp ; remember stack for i/o failure,
mov argadr,ax ; save argument ptr
push es ; save caller's extra segment address
mov ax,seg data
mov es,ax
call argini ; init options from arg address
call save_mode ; [bgp]
cmp flags.vtflg,TTTEK ; 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 lp1 ; nc = yes
jmp chkinp ; no, keep going
; we want to swallow any ANSI escapes that come for now
; they are all of the form ESCAPE [ nn ; nn ; nn ; nn a
; where n is a numeric character, and a is a non-numeric character
lp1: test flags.remflg,d8bit ; keep 8 bits for displays?
jnz lp2 ; nz = yes
and al,7fh ; strip 8th bit
lp2: cmp escseq,0 ; escape sequence in progress?
jne eat_esc_seq ; yes
cmp al,ESCAPE ; 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,FF ; ESCAPE FF is go temp tek mode [bgp]
jne eat_esc_seq0 ; no [bgp]
cmp tek_allowed,FALSE ; is tek mode allowed? [bgp]
jne eat_esc_seq00 ; yes, do it [bgp]
mov dx,offset no_tek_msg ; tell them about it [bgp]
mov ah,PRSTR ; [bgp]
int DOS ; [bgp]
jmp end_esc ; all through [bgp]
eat_esc_seq00:
mov escseq,0 ; not doing escape now [bgp]
call savescr ; save current screen [bgp]
call tektemp ; do it for a while [bgp]
jnc eat_esc_seq000 ; carry=exit like esc char [bgp]
call clrmod ; clear mode line [bgp]
jmp quit1 ; screen already saved [bgp]
eat_esc_seq000:
call restscr ; restore the screen [bgp]
jmp end_esc ; all through [bgp]
eat_esc_seq0:
cmp al,'['
je eat_esc_seq1
push ax ; not [, print esc and char
mov al,ESCAPE
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: cmp rxtable+256,0 ; translation turned off?
je no_esc1 ; e = yes, no translation
push bx
mov bx,offset rxtable ; address of translate table
xlatb ; new char is in al
pop bx
no_esc1:call outtty ; print on terminal
chkinp: call keybd ; get and translate a key [bgp]
jc quit ; carry=esc character entered - quit [bgp]
jmp lp ; keep looping [bgp]
quit: call clrmod ; erase mode line
call savescr ; save screen
quit1: call rest_mode ; [bgp]
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?
jc achkinp ; c = no, get char from keyboard
call doansi ; handle it somehow
achkinp:
call keybd ; get and translate a key stroke [bgp]
jnc portc ; carry=esc char entered - quit [bgp]
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
test flags.remflg,d8bit ; keep 8 bits for displays?
jnz w00a ; nz = yes
and al,7fh ; strip 8th bit
w00a: cmp al,ESCAPE ; got an escape?
jne w00 ; ne = no
jmp procesc0 ; escape terminates Escape-sequence,
w00: ; so it has to be tested first
cmp escseq,0 ; escape sequence in progress?
jne w0a ; ne = yes, no translation
cmp rxtable+256,0 ; translation turned off?
je w0a ; e = yes, no translation
push bx
mov bx,offset rxtable ; address of translate table
xlatb ; new char is in al
pop bx
w0a: 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,' '
jb controls
or al,chrset_mask ; [bgp]
jmp noesc
controls:
cmp al,LF ; Linefeed,Formfeed and Vertical tab are
; processed as 'Scroll down, if at
; bottom margin, same function as ESCAPE'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: cmp al,DEL ; DEL char? [jrd]
jne w7 ; ne = no
jmp ignore ; ignore DEL
w7: jmp noesc ; else echo char to screen.
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 escseq,0 ; [bgp]
jle proccont1a ; [bgp]
cmp al,'?' ; 1st char after ESCAPE'[' may be a '?'
jne proccont1
proccont1a:
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 ; ESCAPE-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 ESCAPE
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,ESCAPE
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,ESCAPE
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 ESCAPE'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,ESCAPE ; 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,ESCAPE
call outtty
mov al,'L' ; 4. insert line with ESCAPE '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,ESCAPE
call outtty
mov al,'j'
jmp noesc
process8: ; restore cursor position
mov al,ESCAPE
call outtty
mov al,'k'
jmp noesc
process_ff: ; temporary tektronix mode if allowed [bgp]
cmp tek_allowed,FALSE ; ok? [bgp]
jne process_ff1 ; yes [bgp]
mov dx,offset no_tek_msg ; tell them [bgp]
mov ah,PRSTR ; [bgp]
int DOS ; [bgp]
jmp ignore ; end of sequence [bgp]
process_ff1:
call savescr ; save the screen [bgp]
mov escseq,0 ; [bgp]
call tektemp ; [bgp]
jc process_ff2 ; carry=esc char entered [bgp]
call restscr ; restore the screen [bgp]
jmp ignore ; end of sequence [bgp]
process_ff2:
pop ax ; return address from call to DOANSI [bgp]
; this is kludgey but it is necessary to
; make this look like we are actually at
; the point right after calling keybd and
; receiving an esc char.
call finiansi ; restore old keyboard [bgp]
pop ax ; imagine that we have returned from ANSI [bgp]
call clrmod ; clear off the mode line [bgp]
jmp quit1 ; normal exit but no save screen! [bgp]
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,ESCAPE
call outtty
mov bx,escpnt
mov al,[bx]
jmp noesc ; print it without '['
pars: ; parse numeric argument
mov bx,offset escstring+2 ; skip ESCAPE'['
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,ESCAPE
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,ESCAPE
call outtty
mov al,'M'
call outtty
mov dl,bh ; get in right place
mov dh,bl
call set_cur_pos
mov al,ESCAPE
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,ESCAPE
call outtty
mov al,'M'
call outtty
mov dl,bottom
mov dh,1
call set_cur_pos
mov al,ESCAPE
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,ESCAPE
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,ESCAPE
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,ESCAPE
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 ESCAPE [ 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,ESCAPE
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,ESCAPE
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,ESCAPE ; put string out in form : ESCAPE'['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,ESCAPE
call outtty
mov al,')'
call outtty
mov al,ESCAPE
call outtty
mov al,'q'
call outtty
mov al,ESCAPE
call outtty
mov al,'1'
call outtty
jmp proclm5
proclm2:
cmp dl,1
jne proclm3
mov al,ESCAPE
call outtty
mov al,'('
call outtty
jmp proclm5
proclm3:
cmp dl,4
jne proclm4
mov al,ESCAPE
call outtty
mov al,'0'
call outtty
jmp proclm5
proclm4:
cmp dl,7
jne proclm5
mov al,ESCAPE
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 ESCAPE'['
call getnum
cmp dl,0
je procJ0
cmp dl,1
je procJ1
cmp dl,2
je procJ2
jmp ignore ; ignore others
procJ0:
mov al,ESCAPE
call outtty
mov al,'J'
jmp noesc
procJ1:
mov al,ESCAPE
call outtty
mov al,'b'
jmp noesc
procJ2:
mov al,ESCAPE
call outtty
mov al,'E'
jmp noesc
prochl:
mov bx,offset escstring+2 ; skip ESCAPE'['
call getnum
cmp [escstring+2],'?'
je quest
mov bx,escpnt
mov bl,[bx] ; contains 'h' or 'l'
cmp dl,4
jne not4
mov al,ESCAPE
call outtty
mov al,'@'
cmp bl,'l'
jne enterins
mov al,'O'
enterins:
jmp noesc
not4: ; ignore the others
jmp ignore
quest: ; sequence like ESCAPE'[?'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,ESCAPE
call outtty
mov al,'p'
cmp bl,'h'
je isreverse
mov al,'q'
isreverse:
jmp noesc
not5:
cmp dl,7
jne not7
mov al,ESCAPE
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 ESCAPE'['
call getnum
cmp dl,0
je procK0
cmp dl,1
je procK1
cmp dl,2
je procK2
jmp ignore ; ignore others
procK0:
mov al,ESCAPE
call outtty
mov al,'K'
jmp noesc
procK1:
mov al,ESCAPE
call outtty
mov al,'o'
jmp noesc
procK2:
mov al,ESCAPE
call outtty
mov al,'l'
jmp noesc
processrp:
processlp:
processlb:
mov escseq,-1 ; have to eat one char
jmp doansi_d ;
noesc: ; That wasn't valid! (or print last char)
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
cld
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*101,8000h ; [bgp]
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+101,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
cld
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,ESCAPE ; request cursor location
call outtty
mov al,'n'
call outtty
mov ah,CONINQ ; input no check
int DOS ; gets the ESCAPE
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,ESCAPE
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
push es ; [bgp]
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
cld
rep movsw
push es
pop ds
call cmblnk ; let them start with a blank one
pop es ; [bgp]
ret ; and return
SAVESCR endp
; Restore screen from scrsav buffer
RESTSCR proc near
push es ; [bgp]
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
pop es ; [bgp]
ret
RESTSCR endp
; Save the mode line so it can be restored when we are through [bgp]
SAVE_MODE proc near
push es ; to be sure
mov bx,SEG_CRTC ; where crt controller is
mov es,bx
mov bx,OFF_CRTC
mov byte ptr es:[bx],12 ; high screen origin register
mov ah,es:1[bx]
and ah,7 ; need bottom 3 bits
mov byte ptr es:[bx],13 ; low screen origin register
mov al,es:1[bx]
shl ax,1 ; multiply by 2 (was word address)
add ax,3840 ; where status line is
mov si,ax
mov di,offset status_line ; where to put it
mov cx,80 ; 80 words long
push ds
pop es
mov ds,tscrseg ; setment of screen
cld
rep movsw
push es
pop ds ; restore ds
pop es ; and this too
ret
SAVE_MODE endp
; Restore mode line in case someone has something on it [bgp]
REST_MODE proc near
push es ; to be sure...
mov bx,SEG_CRTC ; where crt controller is
mov es,bx
mov bx,OFF_CRTC
mov byte ptr es:[bx],12 ; high screen origin register
mov ah,es:1[bx]
and ah,7 ; need bottom 3 bits
mov byte ptr es:[bx],13 ; low screen origin register
mov al,es:1[bx]
shl ax,1 ; multiply by 2 (was word address)
add ax,3840 ; where status line is
mov di,ax
mov si,offset status_line ; where to get it
mov cx,80 ; 80 words long
mov es,tscrseg ; segment of screen
cld
rep movsw
pop es ; restore this
ret
REST_MODE 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,TTTEK ; 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
mov cursor_cnt,CURSOR_TIME ; init cursor countdown timer
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 tekcki1 ; yes, I can't accept anything
call portchr ; char at port?
jc tekcki ; c = 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:
call keybd ; get and translate a key [bgp]
jnc teklp ; carry=esc char entered - quit [bgp]
tekquit:
call reset_hires ; reset to normal screen
pop es
ret
TEK4010 endp
; Come to here to temporarily act somewhat like a Tektronix 4010 terminal...
; Added 29 August 1987 to allow ANSI or VT52 to go directly to Tektronix
; mode. This is entered at a point where conditions should be like a
; clear screen was just received (ESCAPE FF). We should exit on the receipt
; of an ESCAPE US sequence or if the esc char is entered from the keyboard.
; If the esc char is entered then return with carry set. [bgp]
; For compatibility we will also exit if a CAN (ctrl-X) is received (to be
; like the IBM-PC version).
TEKTEMP proc near
push es ; this will be used repeatedly
mov es,scrseg
mov ax,flags.vtflg
mov temp_mode,ax ; save current emulation
mov flags.vtflg,TTTEK ; set to tek emulation
mov temp_tek,TRUE ; this is temporary mode...
mov echo_supp,FALSE ; clear echo suppression
mov cursor_cnt,CURSOR_TIME ; init cursor countdown timer
mov escflag,0 ; not in escape sequence
mov graph_mode,FALSE ; in full text mode
call clrscr ; be sure screen is clear
mov first_in,FALSE ; flag it
call set_hires ; set to hires screen
tektlp:
cmp full_flag,FALSE ; page full condition
jne tektcki1 ; yes, I can't accept anything
call portchr ; char at port?
jc tektcki ; c = no, keep going
and al,7fh ; Tek gets only 7 bit characters
call tekhandle ; go handle the character
tektcki:
dec cursor_cnt ; decrement cursor countdown
jnz tektcki1 ; not ready
call cursor_on ; turn on cursor
tektcki1:
call keybd ; get and translate a key
jnc tektlp ; carry=esc char entered - quit
call reset_hires ; reset to normal screen
mov ax,temp_mode
mov flags.vtflg,ax ; reset to previous emulation
mov temp_tek,FALSE ; clear temp tektronix emulation
pop es
stc ; set carry - this is full quit
ret
TEKTEMP endp
; Take care of an incoming character
TEKHANDLE proc near
cmp escseq,0 ; escape sequence in progress?
jne tekhand1 ; ne = yes, no translation
cmp rxtable+256,0 ; translation turned off?
je tekhand1 ; e = yes, no translation
push bx
mov bx,offset rxtable ; address of translate table
xlatb ; new char is in al
pop bx
tekhand1:call capture ; in case we should
cmp al,GS ; Group Separator?
je tek2graf ; ->graphics with pen up
cmp al,ESCAPE ; 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 ; ESCAPE 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:
cmp al,CAN ; Is it CAN (control-X)?
jne tektxt13
cmp temp_tek,FALSE ; in temporary mode?
je tektxt13 ; no, just continue!
mov echo_supp,FALSE ; clear suppression
mov escflag,0 ; place in full text mode
mov graph_mode,FALSE
mov ax,temp_mode
mov flags.vtflg,ax ; reset emulation mode
mov temp_tek,FALSE ; clear temporary mode
pop ax ; this is return to tekhandle
pop ax ; this is return to tektemp
call reset_hires ; have to make it look like a tektquit
pop es ; with a carry clear state
clc
ret
tektxt13:
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
; ESCAPE 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,CTLZ ; 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:
cmp al,US ; return from temp tek mode [bgp]
jne tekesc4
cmp temp_tek,FALSE ; in temporary mode?
je tekescq ; no, just continue!
mov echo_supp,FALSE ; clear suppression
mov escflag,0 ; place in full text mode
mov graph_mode,FALSE
mov ax,temp_mode
mov flags.vtflg,ax ; reset emulation mode
mov temp_tek,FALSE ; clear temporary mode
pop ax ; this is return to tekhandle
pop ax ; this is return to tektemp
call reset_hires ; have to make it look like a tektquit
pop es ; with a carry clear state
clc
ret
tekesc4:
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
jc tekcrs_lp ; c = 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,ESCAPE
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,ESCAPE ; 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
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 lo res 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
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
jmp clrscr1
homescr: ; keyboard translator verb entry [bgp]
call cursor_off ; make sure it is off
cmp full_flag,TRUE ; in page full condition?
jne clrscr1 ; no, just go home the cursor
les di,dword ptr scrloc ; get screen location
add di,38424 ; get to lower left corner
mov ax,0FFFFH ; want to clear them all
xor es:[di],ax ; need to clear page full indicator
inc di ; box in the lower left corner which
inc di ; was put there when the page filled
xor es:[di],ax ; up earlier
inc di
inc di
xor es:[di],ax
inc di
inc di
xor es:[di],ax
clrscr1:
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
cmp si,0 ; too low? (start at 0 offset) [jrd]
jb character3
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
cmp si,0 ; too low? (starts at 0 offset) [jrd]
jb character5a
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
cmp si,0 ; too low? (starts at 0 offset) [jrd]
jb character9
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!
xor es:[di],ax
inc di
inc di
xor es:[di],ax
inc di
inc di
xor es:[di],ax
inc di
inc di
xor 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
OUTPRT proc near
test yflags,lclecho ; echoing?
jz outpr1 ; z = no, forget it
cmp flags.vtflg,TTTEK ; doing TEKTRONIX?
je outpr00 ; e = yes, echo it nicely
cmp flags.vtflg,TTVT100 ; doing VT100?
je outpr0 ; e = 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
jc outpr4 ; c = failure
ret
outpr4: jmp endcon ; failure, end connection
OUTPRT endp
; Get a character from the serial port in al
; returns with carry clear if a character is available
PORTCHR proc near
call prtchr ; character at port?
jnc portc1 ; nc = yes
portc0: ret
portc1: and al,parmsk ; apply 8/7 bit parity mask
or al,al ; is it a null char?
jz portc0 ; z = yes, ignore it
portc2: clc ; 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
; Translation taken from msyibm with minimal modification
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
call pntchr ; printer routine
jnc noprt ; nc = successful print
push ax
call beep ; else make a noise and
call trnprs ; turn off printing
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]. With the addition of the official TEKTRONIX terminal type
; we no longer have to warn about weird results.
VTS proc near
mov dx,offset termtb
mov bx,offset termhlp
mov ah,CMKEY
call comnd
jc vtx ; c = failure
push bx
mov ah,cmeol
call comnd ; Get a confirm
pop bx
jc vtx
cmp bx,TTTEK ; doing TEKTRONIX?
jne vt1 ; no
cmp tek_allowed,FALSE ; can we do TEKTRONIX?
jne vt1 ; yes
mov dx,offset no_tek_msg ; tell him we can't
mov ah,PRSTR
int DOS
ret ; don't do anything
vt1: mov flags.vtflg,bx ; Set the emulation flag.
vtx: ret
VTS endp
VTSTAT PROC NEAR ; For Status display [jrd]
ret ; no emulator status to display
VTSTAT ENDP
; Control text cursor. AL = 0 for off, 1 for on (nominally underline)
csrtype proc far
push dx
mov escstring,ESCAPE
mov escstring+1,'y'
mov escstring+2,'5'
mov escstring+3,'$'
or al,al ; set mode?
jnz csrty1 ; nz = yes
dec escstring+1 ; 'x' is reset mode ESC x 5
csrty1: mov dx,offset escstring ; pass string to screen console
mov ah,PRSTR
int DOS
pop dx
ret
csrtype endp
; The following are keyboard translator access routines added 29 August 1987.
; They are invoked by a jump instruction. They must return carry clear to
; continue processing or carry set to exit from Connect mode, in which case
; kbdflg will have the transfer character in it. [bgp]
chrout: call outprt ; send a character out the port
clc
ret
cpage: cmp flags.vtflg,TTTEK ; only works on tektronix emulation
jne cpage1
call clrscr ; clear the tektronix screen
clc
ret
cpage1: call beep
clc
ret
chome: cmp flags.vtflg,TTTEK ; only works on tektronix emulation
jne chome1
call homescr ; home the tektronix screen
clc
ret
chome1: call beep
clc
ret
cquery: mov al,'?'
jmp cmdcom
cstatus:mov al,'S'
jmp cmdcom
cquit: mov al,'C'
jmp cmdcom
chang: mov al,'H'
jmp cmdcom
kdos: mov al,'P'
jmp cmdcom
cmdcom: mov kbdflg,al ; pass to msster.asm via kbdflg
stc ; need to exit connect mode
ret
dmpscn: cmp flags.vtflg,TTTEK ; emulating tektronix?
jne dmpscn1 ; no, do it
jmp dmpscn2 ; can't on tektronix...
dmpscn1:call savescr ; have to save screen to dump it
call dumpscr
call restscr ; need to put it back again too
clc
ret
dmpscn2:call beep ; nothing else to do I guess
clc
ret
snull: xor ah,ah ; send a null
call outchr ; send without echo or logging
clc
ret
klogof: mov bx,argadr ; need to fix args
and [bx].flags,not CAPT ; clear capture flag
and yflags,not CAPT ; also local copy
clc
ret
klogon: test flags.capflg,LOGSES ; logging enabled?
jz klogon1
mov bx,argadr ; need to fix args
or [bx].flags,CAPT ; set capture flag
or yflags,CAPT ; also local copy
klogon1:clc
ret
trnprs: push ax ; toggle ^ PrtSc screen to printer
test yflags,prtscr ; are we currently printing?
jnz trnpr2 ; nz = yes, its on and going off
push bx
mov bx,prnhand ; file handle for system printer
mov ah,ioctl
mov al,7 ; get output status of printer
int dos
pop bx
jc trnpr1 ; c = printer not ready
cmp al,0ffh ; Ready status?
je trnpr2 ; e = Ready
trnpr1: call beep ; Not Ready, complain
jmp trnpr3 ; and ignore request
trnpr2: xor yflags,prtscr ; flip the flag
test yflags,modoff ; mode line off?
jnz trnpr3 ; nz = yes
call modlin ; else rewrite mode line
trnpr3: pop ax
clc ; return carry clear (don't quit)
ret
; Error recovery routine used when outchr reports unable to send character
; or when vtmacro requests exiting Connect mode.
; Exit Connect mode cleanly, despite layers of intermediate calls.
endcon proc near
call pntflsh ; flush printer buffer
mov kbdflg,'C' ; report 'C' to TERM's caller
mov sp,oldsp ; recover startup stack pointer
; TERM caller's return address is now
; on the top of stack. A longjmp.
jmp quit ; exit Connect mode cleanly
endcon endp
; Invoked by keyboard translator when an unknown keyboard verb is used as
; a string definition, such as {\ktest}. Enter with vtmacname pointing to
; uppercased verb name, asciiz, and vtmaclen set to its length.
extmacro proc near
jmp vtmacro ; finish in common code
extmacro endp
;
; Reference Macro structure for db number of entries (mac names)
; is file table mcctab |-> db length of macroname, excl '$'
; mssset.asm each entry |-> db 'macroname','$'
; where these |-> dw segment:0 of definition string
; are stored. (offset part is always 0)
; Definition string in db length of <string with null>
; buffer macbuf db 'string with trailing null'
;
vtmacro proc near ; common code for macros vtsmac,vtrmac
push bx ; and Product
push cx
push si
push di
push es
mov ax,ds
mov es,ax
mov di,offset rdbuf+1 ; macro def buffer starts here
mov si,vtmacname ; pointer to macro name
mov cl,vtmaclen ; length of macro name<sp/null>text
xor ch,ch
mov [di-1],cl ; counted string field
cld
rep movsb ; copy to rdbuf
mov byte ptr [di],0 ; null terminator
mov si,offset rdbuf+1 ; look for name-text separator
mov cl,vtmaclen
xor ch,ch
vtmac1: lodsb
cmp al,' ' ; space separator?
je vtmac1a ; e = yes, stop here
or al,al ; null terminator?
jz vtmac1a ; e = yes, stop here
loop vtmac1
inc si ; to do null lenght correctly
vtmac1a:sub si,offset rdbuf+1+1 ; compute length of macro name
mov cx,si
mov vtmaclen,cl ; save a macro name length
; check for existence of macro
mov bx,offset mcctab ; table of macro names
mov cl,[bx] ; number of names in table
xor ch,ch
jcxz vtmacx ; z = empty table, do nothing
inc bx ; point to length of first name
vtmac2: mov al,[bx] ; length of this name
xor ah,ah
cmp al,vtmaclen ; length same as desired keyword?
jne vtmac3 ; ne = no, search again
mov si,bx
inc si ; point at first char of name
push cx ; save name counter
push di ; save reg
mov cl,vtmaclen ; length of name, excluding '$'
xor ch,ch
mov di,vtmacname ; point at desired macro name
push es ; save reg
push ds
pop es ; make es use data segment
cld
repe cmpsb ; match strings
pop es ; need current si below
pop cx
pop di ; recover saved regs
je vtmac4 ; e = matched
vtmac3: add bx,ax ; step to next name, add name length
add bx,4 ; + count, dollar sign, def word ptr
loop vtmac2 ; try next name
vtmacx: pop es
pop di
pop si ; no macro, return to Connect mode
pop cx
pop bx
ret
vtmac4: cmp taklev,maxtak ; room in Take level?
jge vtmacx ; ge = no, exit with no action
inc taklev ; increment take level
add takadr,size takinfo ; make a new Take entry/macro
mov bx,takadr ; point to current macro structure
mov ax,ds ; segment of rdbuf
mov [bx].takbuf,ax ; segment of definition string struc
mov cl,rdbuf ; length of whole string
xor ch,ch
mov [bx].takcnt,cx ; number of chars in definition
mov [bx].takargc,0 ; our argument count
mov [bx].takptr,offset rdbuf+1 ; where to read next command char
mov [bx].taktyp,0ffh ; flag as a macro
pop es
pop di
pop si
pop cx
pop bx
jmp endcon ; exit Connect mode
vtmacro endp
; Service SET NETBIOS-NAME name command at Kermit prompt level
setnbios proc near
ret
setnbios endp
sesdisp proc near
ret
sesdisp endp
CODE ends
end