;+ This is MSYP98.ASM   VT100 emulation for NEC-PC9801          by.H.Fujii
;
; Update History
; 17-Apr-1991 vt_ourarg in vt100_modlin1 for modeline is changed.
;             prn_out is replaced by pntchr.
;             [these are done by Joe Doupnik]
; 01-Sep-1990 DCS is interpreted. Bugs for C0 characters in ESC/CSI seq.
;             have been fixed.
;             Saved CX in vt100_modlin.
; 29-Jul-1990 DCS is separated and ignored.
; 27-Jul-1990 For MS-Kermit v3.02
; 25-Jun-1990 Fixed bug of ESC FF (forgot to clear ESC flag).
; 04-Aug-1989 Fixed wrong ESC M (reverse index) and ESC E (next line).
; 30-May-1989 ESC [ 0 m resets colors to default (color in command mode).
; 21-Apr-1989 Backquote modification for display is moved to disp_char.
; 19-Apr-1989 Put CR/LF for CSI*;1H in the cooked-log file.
; 16-Apr-1989 Installed Cooked log
; 17-Jan-1989 Bug in VT100_color. Highlight color set was wrong.
; 03-Dec-1988 Bug report from Mikami-san at NTT software lab. for
;             ESC[;r.  The routine for 'set scroll region' is fixed.
; 06-Nov-1988 Bug found in VT100_SAVE.  In some situation, VT100 screen
;             is not restored correctly.
; 10-Sep-1988 Autoprint feateres are installed
; 14-Aug-1988 Roll-Up/Down features with simple circular movement.
;
; ESC sequence
; - General rule -
;   1) 2-byte sequence
;      a) ESC Fs terminated by 6/0 - 7/14 (standard sequence)
;      b) ESC Fp terminated by 3/0 - 3/15 (private sequence)
;      c) ESC Fe terminated by 4/0 - 5/15 (C1 control character)
;   2) multibyte sequnce
;      a) ESC I...I Fp terminated by 3/0 - 3/15 (private sequence)
;      b) ESC I...I Ft terminated by 4/0 - 7/14 (standard sequence)
;      where I is 2/0 - 2/15
;
; Cotrol sequence
;   1) CSI P...P I...I Ft terminated by 4/0 - 6/15 (standard sequence)
;   2) CSI P...P I...I Fp terminated by 7/0 - 7/14 (private sequence)
;      where CSI is 9/11 or ESC 5/11 (one of ESC Fe sequnce)
;            P is 3/0 - 3/15,
;                 3/11 is separator
;                 3/15 is private parameter introducer
;            I is 2/0 - 2/15
;
; CRT display character
;
;   Character plane
;              F E D C B A 9 8   7 6 5 4 3 2 1 0
;             +-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+
;             |      0        | |    ANK code   |         ANK
;             +-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+
;
;             +-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+
;             |0|   JIS 2nd   | |JIS 1st - '20'X|     Kanji Left half
;             +-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+
;             |1|   JIS 2nd   | |JIS 1st - '20'X|     Kanji Right half
;             +-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+
;
;
;   Attribute plane
;              F E D C B A 9 8   7 6 5 4 3 2 1 0
;             +-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+
;             |      N/A      | |G|R|B| | | | | |
;             +-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+
;                                ^ ^ ^ ^ ^ ^ ^ ^
;                                | | | | | | | |
;                                | | | | | | | secret (0)
;                                | | | | | | blink (1)
;                                | | | | | reverse (1)
;                                | | | | underline (1)
;                                | | | vertical line/graph pattern
;                                color
;
;
; The following Japanese Industrial Standards specify the Kana-Kanji treatment
; for information interchange.
;
;   JIS C 6226:
;     Code of the Japanese Graphic Character Set
;     for Information Intercahnge
;
;   JIS C 6228:
;     Code Extension Techniques for Use with the Code
;     for Information Interchange .
;
; In these standards, each byte of the multi-byte code is in the range
; 2/1 - 7/14. Each character is specified by an index of the current character
; table. In 7-bit environment, every index is the character code itself (or the
; first byte of the multi-byte character code). In 8-bit environment, there are
; two sets of current character table, called GL and GR.  A GL-character is
; specified by the character code itself, and a GR-character is specified by
; the character code with 8-th bits on.
; As intermediate character sets, four sets of characters can be used at onece.
; These sets are called G0, G1, G2 and G3.  To invoke these sets to the current
; character set(s),
;
; in 7-bit environment,
;
;   0/F       Shift In                Invoke G0 character set
;   0/E       Shift Out               Invoke G1 character set
;   ESC 6/E   Locking Shift 2         Invoke G2 character set
;   ESC 6/F   Locking Shift 3         Invoke G3 character set
;
;   ESC 4/E   Single Shift 2          Invoke G2 character
;   ESC 4/F   Single Shift 3          Invoke G3 character
;
; in 8-bit environment,
;
;   0/F       Locking Shift 0         Invoke G0 character set to GL
;   0/E       Locking Shift 1         Invoke G1 character set to GL
;   ESC 7/E   Locking Shift 1 Right   Invoke G1 character set to GR
;   ESC 6/E   Locking Shift 2         Invoke G2 character set to GL
;   ESC 7/D   Locking Shift 2 Right   Invoke G2 character set to GR
;   ESC 6/F   Locking Shift 3         Invoke G3 character set to GL
;   ESC 7/C   Locking Shift 3 Right   Invoke G3 character set to GR
;
;   8/E       Single Shift 2          Invoke G2 character
;   8/F       Single Shift 3          Invoke G3 character.
;
; To designate the single-byte character set, (JIS C 6228: 5.3.7)
;   ESC 2/8 F      and ESC 2/12 F              to G0 character set
;   ESC 2/9 F      and ESC 2/13 F              to G1 character set
;   ESC 2/10 F     and ESC 2/14 F              to G2 character set
;   ESC 2/11 F     and ESC 2/15 F              to G3 character set
;
;   where F is a final character in the range 3/0 - 7/14 which specifies the
;   character set. For example,
;
;       F        Character Set
;      ----      -------------
;      4/1       UK
;      4/2       US (ASCII)
;      4/9       JIS Katakana
;      4/10      JIS Roman
;      4/11      Germany
;      5/2       France
;      5/4       Chinese Roman
;      5/9       Italy
;      5/10      Spain
;      5/11      Greek
; .
;
; To designate the multi-byte character set, (JIS C 6226: 5.3.8)
;   ESC 2/4 F      and ESC 2/4 2/12 F          to G0 character set
;   ESC 2/4 2/9 F  and ESC 2/4 2/13 F          to G1 character set
;   ESC 2/4 2/10 F and ESC 2/4 2/14 F          to G2 character set
;   ESC 2/4 2/11 F and ESC 2/4 2/15 F          to G3 character set
;
;   where F is a final character in the range 3/0 - 7/14 which specifies the
;   character set. For example,
;
;       F        Character Set
;      ---       -------------
;      4/0       JIS C 6226 - 1978
;      4/1       Chinese Kanji
;      4/2       JIS C 6226 - 1983
;  .
;
; Corresponding Internatial Standard is ISO 2022.
;
	include	mssdef.h
	include	msxp98.h
;
NUL	equ	0
CSI	equ	9Bh
;
ROLLMEM_MIN	equ	40		; minimum & maximum number of
ROLLMEM_MAX	equ	4000		; paragraphs for roll-back buffer
;
 
CHR_REV		equ	04h
CRT_TXT_SEG	equ	0A000h
 
PRIVP_FLG	equ	08000h
 
in_ESC_MODE	equ	1
in_CSI_MODE	equ	2
in_DCS_MODE	equ	3
 
VT52_DCA_L	equ	64
VT52_DCA_C	equ	65
 
IN_SIXEL	equ	66
 
	public	vt100,vt100_ini,vt100_save,vt100_restore,vt100_reset
	public	vt100_modlin, vt100_dump, vt100_color
	public	vt100_rupn, vt100_rdnn, vt100_prnl, vt100_prns
	public	set_modlin
	public	prn_chk
 
	public	char_SS, char_GL, char_GR
	public	gnrm_color, gbck_color
 
data 	segment	public 'data'
 
	extrn	flags:byte, trans:byte
	extrn	cpu_clock:byte, vtgrph_flg:byte, vttest_flg:byte
	extrn	curkey_mode:byte, keypad_mode:byte
	extrn	display_mode:byte
	extrn	keyin_dos:byte
	extrn	kanji_rcode:byte, kanji_scode:byte
	extrn	vt100_cursr:byte
	extrn	vt100_flags:byte, vt100_pflag:byte
	extrn	vt100_lflag:byte, vt100_gflag:byte
	extrn	vt_ourarg:byte
	extrn	def_color:byte, scn_color:byte
 
vt_saveseg	dw	?		; segment address to save screen
vt_rollseg	dw	?		; segment address to roll-up screen
vt_rollmxs	dw	?		; maximum segment address allocated
vt_rollmxl	dw	?
vt_rollcur	dw	?		; current segment address
vt_rollcln	dw	0		; current line number of the buffer
vt_rollfil	dw	1
vt_rollnum	dw	0
 
vt_init		db	0
vt_wrap		db	0		; wrap request flag
vt_graph	db	0
vt_chrset	db	0
vt_chratr	db	0		; current character attributes
vt_blkatr	db	0		; blank area attributes
vt_nrmatr	db	0E1h		; normal character attributes
vt_hglatr	db	0C0h		; highlight character attribute
vt_modatr	db	0C5h		; mode line character attributes
 
vt_in_stat	db	0		; in status line flag
vt_stat_type	db	1		; status line type
stat_col	db	0		; column in status line
stat_row	db	24		; row of the status line (from 0)
 
sixel_disp_on	db	0, 0
 
save_flags	db	?
save_graph	db	?
save_chrset	db	?
save_chratr	db	?
save_blkatr	db	?
 
vt_knjmode	db	0		; Kanji mode if 1
vt_kanji1	db	0		; Kanji 1st byte
vt_kanji2	db	0
 
; The fllowing parameters are used for ESC/CSI/DCS sequence.
;   seq_stage:  0  normal character stage
;               1  in ESC seq.
;               2  in ESC intermediate stage
;               3  in CSI (parameter) stage.
;               4  in CSI intermediate stage
;               5  in DCS (parameter) stage.
;               6  in DCS intermediate stage
;
spec_mode	db	0
spec_stage	db	0
I_pnt		dw	0
I_buf		db	128 dup (?)
P_pnt		dw	0
P_buf		dw	128 dup (?)
 
priv_pflg	dw	0
priv_char	db	0
 
char_SS		dw	0		; GL for single shift
char_GL		dw	?
char_GR		dw	?
 
char_save_SS	dw	?
char_save_GL	dw	?
char_save_GR	dw	?
 
char_G0		db	CSET_JISROMAN
char_G1		db	CSET_DECGRAPH
char_G2		db	CSET_JISKATAKANA
char_G3		db	CSET_JISC6226
 
char_save_G0	db	?
char_save_G1	db	?
char_save_G2	db	?
char_save_G3	db	?
 
; Normal PC98 color table
;
gnrm_color	db	000h,000h,000h		;  0:black
		db	000h,000h,0ffh		;  1:blue
		db	0ffh,000h,000h		;  2:red
		db	0ffh,000h,0ffh		;  3:magenta
		db	000h,0ffh,000h		;  4:green
		db	000h,0ffh,0ffh		;  5:cyan
		db	0ffh,0ffh,000h		;  6:yellow
		db	0ffh,0ffh,0ffh		;  7:white
		db	0afh,0afh,0afh		;  8:light-gray
		db	000h,000h,0afh		;  9:dark-blue
		db	0afh,000h,000h		; 10:dark-red
		db	0afh,000h,0afh		; 11:dark-magenta
		db	000h,0afh,000h		; 12:dark-green
		db	000h,0afh,0afh		; 13:dark-cyan
		db	0afh,0afh,000h		; 14:dark-yellow
		db	07fh,07fh,07fh		; 15:dark-gray
;
gbck_color	db	000h,000h,000h		;  0:
		db	000h,000h,000h		;  1:
		db	000h,000h,000h		;  2:
		db	000h,000h,000h		;  3:
		db	000h,000h,000h		;  4:
		db	000h,000h,000h		;  5:
		db	000h,000h,000h		;  6:
		db	000h,000h,000h		;  7:
		db	000h,000h,000h		;  8:
		db	000h,000h,000h		;  9:
		db	000h,000h,000h		; 10:
		db	000h,000h,000h		; 11:
		db	000h,000h,000h		; 12:
		db	000h,000h,000h		; 13:
		db	000h,000h,000h		; 14:
		db	000h,000h,000h		; 15:
 
vt_gset		db	0EAh,087h,009h,00Ch,00Dh,00Ah,0DFh,08Fh
		db	015h,00Bh,09Bh,099h,098h,09Ah,08Fh,094h
		db	094h,095h,081h,080h,093h,092h,090h,091h
		db	096h,01Dh,01Ch,01Eh,01Fh,0F1h,0A5h,020h
 
		even
C0_func_tab	dw	vt_disp_none		; 00H NUL
		dw	vt_disp_none		; 01H SOH
		dw	vt_disp_none		; 02H STX
		dw	vt_disp_none		; 03H ETX
		dw	vt_disp_none		; 04H EOT
		dw	vt_disp_none		; 05H ENQ
		dw	vt_disp_none		; 06H ACK
		dw	vt_disp_BEL		; 07H BEL
		dw	vt_disp_BS		; 08H BS
		dw	vt_disp_HT		; 09H HT
		dw	vt_disp_LF		; 0AH LF
		dw	vt_disp_LF		; 0BH VT
		dw	vt_disp_LF		; 0CH FF
		dw	vt_disp_CR		; 0DH CR
		dw	vt_disp_SO		; 0EH SO
		dw	vt_disp_SI		; 0FH SI
;
		dw	vt_disp_none		; 10H DLE
		dw	vt_disp_none		; 11H DC1 (XON)
		dw	vt_disp_none		; 12H DC2
		dw	vt_disp_none		; 13H DC3 (XOFF)
		dw	vt_disp_none		; 14H DC4
		dw	vt_disp_none		; 15H NAK
		dw	vt_disp_none		; 16H SYN
		dw	vt_disp_none		; 17H ETB
		dw	vt_disp_CAN		; 18H CAN
		dw	vt_disp_none		; 19H EM
		dw	vt_disp_SUB		; 1AH SUB
		dw	vt_disp_ESC		; 1BH ESC
		dw	vt_disp_none		; 1CH FS
		dw	vt_disp_GS		; 1DH GS
		dw	vt_disp_none		; 1EH RS
		dw	vt_disp_none		; 1FH US
;
		even
vram_line	dw	0000h		; 0-line
		dw	00a0h		; 1
		dw	0140h		; 2
		dw	01e0h		; 3
		dw	0280h		; 4
		dw	0320h		; 5
		dw	03c0h		; 6
		dw	0460h		; 7
		dw	0500h		; 8
		dw	05a0h		; 9
		dw	0640h		;10
		dw	06e0h		;11
		dw	0780h		;12
		dw	0820h		;13
		dw	08c0h		;14
		dw	0960h		;15
		dw	0a00h		;16
		dw	0aa0h		;17
		dw	0b40h		;18
		dw	0be0h		;19
		dw	0c80h		;20
		dw	0d20h		;21
		dw	0dc0h		;22
vram_botm_line	dw	0e60h		;23
vram_last_line	dw	0f00h		;24
;
I_am_vt52	db	3
		db	ESCAPE,"/Z"
I_am_vt102	db	5
		db	ESCAPE,"[?6c"
I_am_vt220	db	16
		db	ESCAPE,"[?62;1;2;6;7;8c"
I_am_fine	db	4
		db	ESCAPE,"[0n"
My_cursor_is	db	ESCAPE,"["
		db	10 dup (?)
cur_col		db	0
cur_row		db	0
cur_save_col	db	0
cur_save_row	db	0
 
text_col	db	0
text_row	db	0
text_top	db	0
text_bottom	db	0
 
color_index_table	db	0, 2, 4, 6, 1, 3, 5, 7
;
vt_phys_top	db	0
vt_phys_bottom	db	23
 
vt_top		db	0
vt_bottom	db	23
 
tabstops	db	80 dup (?)	; tab stop table
		db	1,1		; guard
 
nam_none	db	'          '
nam_vt52	db	'VT52      '
nam_vt100	db	'VT102 '
LED_buff	db	'....'
nam_tek		db	'TEK4010/14'
nam_prn		db	' PRN'
nam_nprn	db	'    '
 
dump_pntr	dw	?
dump_buffer	db	256	dup (?)
dump_mode	db	0
 
watch_pnd	dw	0
watch_buf	db	12 dup (?)
watch_lvl	db	0
watch_mod	db	0
 
;
; Kermit mode line buffer
;
mode_len	db	0
mode_ker	db	'Esc-chr: '
mode_esc	db	'^]'
		db	'  help: '
mode_hlp	db	'^]'
		db	'?  port:'
mode_prt	db	'1'
		db	' speed:'
mode_spd	db	'     '
		db	' parity:'
mode_pty	db	'none'
		db	' echo:'
mode_ech	db	'rem'
		db	' '
mode_trm	db	'          '
mode_prn	db	'    '
MODE_LINE_LENG	= $ - mode_len
 
unkbaud		db	' Unk '	; must be 5 characters
baudname	db	' 45.5'
		db	'  50 '
		db	'  75 '
		db	' 110 '
		db	'134.5'
		db	' 150 '
		db	' 300 '
		db	' 600 '
		db	' 1200'
		db	' 1800'
		db	' 2000'
		db	' 2400'
		db	' 4800'
		db	' 9600'
		db	'19200'
		db	'38400'
		db	'57.6K'
		db	'115 K'
BAUDNSIZ	equ	18
 
parityname	db	'even'		; must be 4 characters
		db	'mark'
		db	'none'
		db	'odd '
		db	'spc '
 
lclename	db	'loc'
remename	db	'rem'
 
data	ends
 
code	segment	public	'code'
	assume	cs:code,ds:data,es:nothing
 
	extrn	sbrk:near		; memory allocation routine in mssker
	extrn	s2jis:near, jis2s:near	; in MSZP98
	extrn	set_cursor:near		; in MSZP98
	extrn	set_gpalette:near	; in MSGP98
	extrn	gdisp_on:near, gdisp_off:near	; in MSGP98
	extrn	tek4014_color:near	; in MSGP98
	extrn	set_gcolor:near		; in MSGP98
	extrn	pntchr:near
	extrn	outcapt:near		; in MSXP98
	extrn	set_cur_color:near	; in MSXP98
	extrn	sixel_in:near		; in MSGP98
	extrn	sixel_clear:near	; in MSGP98
	extrn	sixel:near		; in MSGP98
;
; VT100 terminal emulator
;
;
;-----------------------------------------------------------
;
; Initilization routine
; This is called from lclini, local initialization routine.
 
VT100_INI	PROC	NEAR
	cmp	vt_init,0
	je	vt100_ini_1
	jmp	vt100_ini_ex
vt100_ini_1:
	mov	vt_init,1
;
; Allocate memory to save screen
;
	mov	ax,2000h	; display + attributes
	call	sbrk
	mov	vt_saveseg,ax
;
; Check the memory size
;
	mov	bx,0FFFFh	; allocate full integer (must fail)
	mov	ah,ALLOC	; memory allocation
	int	DOS		; system call. BX has number of free para.
	mov	ax,bx
	cmp	ax,2000		; keep 32K for COMMAND.COM (in parag. size)
	ja	vt100_ini_r1
	mov	ax,ROLLMEM_MIN
	jmp	vt100_ini_r2
vt100_ini_r1:
	sub	ax,2000
	cmp	ax,ROLLMEM_MAX
	jbe	vt100_ini_r2
	mov	ax,ROLLMEM_MAX
vt100_ini_r2:
	xor	dx,dx
	mov	cx,20		; number of parag. per line
	div	cx
	mov	vt_rollmxl,ax
	mov	cx,20		; number of parag. per line
	mul	cx
	push	ax		; save number of parag.
	mov	bx,ax
	mov	ah,ALLOC	; allocate memory
	int	DOS
	mov	vt_rollseg,ax
	mov	vt_rollcur,ax
	mov	vt_rollcln,0
	mov	vt_rollfil,1
	pop	bx
	add	ax,bx
	mov	vt_rollmxs,ax
;
vt100_ini_ex:
	call	vt100_soft_res	; reset software parameters
	ret
VT100_INI	ENDP
 
VT100_RESET	PROC	NEAR
	call	vt100_soft_res
	call	vt100_restore
	call	vt100_modlin
	ret
VT100_RESET	ENDP
 
VT100_SOFT_RES	PROC	NEAR
;
; Software reset terminal (* means not supported yet)
;  * Text cursor      On
;    Insert/Replace   Replace
;    Origin Mode      Absolute
;    Autowrap         Off
;  * Keyboard Action  Unlocked
;    Keypad Mode      Numeric
;    Cursor Key Mode  Normal
;    Top Margin       1
;    Bottom Margin    24
;    Character Sets   default
;    Video Character  Normal
;
	push	ax
	push	bx
;
	mov	sixel_disp_on,0		; no sixel display
	mov	vt100_gflag,1
	push	si
	mov	si,offset def_color	; set color to default
	call	set_cur_color
	call	vt100_color
	pop	si
;
	mov	vt_in_stat,0		; main screen
	mov	vt_stat_type,1
;
	mov	ax,'..'			; LED-clear
	mov	bx,offset LED_buff
	mov	[bx],ax
	mov	[bx+2],ax
;
	and	vt100_flags,(not INSERT_BIT)
	and	vt100_flags,(not ORIGIN_BIT)
	and	vt100_flags,(not AUTOWRAP_BIT)
	mov	vt100_pflag,0		; flags for printer control
	mov	vt100_cursr,0		; cursor style
	mov	curkey_mode,0
	mov	keypad_mode,0
	mov	cur_col,0
	mov	cur_row,0
	mov	cur_save_col,0
	mov	cur_save_row,0
	mov	al,vt_nrmatr
	mov	vt_chratr,al
	mov	vt_blkatr,al
	mov	al,vt_phys_top
	mov	vt_top,al
	mov	al,vt_phys_bottom
	mov	vt_bottom,al
	mov	priv_pflg,0
;
	mov	char_G0,CSET_JISROMAN
	mov	char_G1,CSET_DECGRAPH
	mov	char_G2,CSET_JISKATAKANA
	mov	char_G3,CSET_JISC6226
;
	mov	vt_graph,0
	mov	char_SS,0
	mov	char_GL,offset char_G0
	mov	char_GR,offset char_G3
;
; Erase save area
;
	push	es
	push	di
	cld
	mov	ax,vt_saveseg
	mov	es,ax
	mov	di,0		; offset address
	mov	cx,0800h
	mov	ax,0020h
	rep	stosw
	mov	al,vt_blkatr
	xor	ah,ah
	mov	cx,0800h
	rep	stosw
;
	pop	di
	pop	es
;
; Initialize TAB table
;
	push	cx
	push	dx
;
	mov	bx,offset tabstops
	mov	cx,80
	xor	ax,ax
vt_ini_t1:
	mov	dl,0
	test	ax,7
	jnz	vt_ini_t2
	mov	dl,1
vt_ini_t2:
	push	bx
	add	bx,ax
	mov	byte ptr [bx],dl
	pop	bx
	inc	ax
	loop	vt_ini_t1
;
	pop	dx
	pop	cx
;
	call	set_modlin		; set Kermit modeline buffer
	call	save_cursor
	pop	bx
	pop	ax
	ret
VT100_SOFT_RES	ENDP
 
;
; save VT100 screen
;
VT100_SAVE	PROC	NEAR
	push	ax
	push	cx
	push	dx
	push	ds
	push	es
;
	cld
;
	mov	ah,0Dh			; stop display
	int	BIOS
;
	mov	ax,vt_saveseg
	mov	es,ax			; destination segment address
	mov	di,0
	mov	si,vram_line		; set source address [06-Nov-88]
	push	si			; save it for later use [06-Nov-88]
	mov	ax,CRT_TXT_SEG
	mov	ds,ax
	mov	cx,0800h
	rep	movsw
	pop	si			; remember source address [06-Nov-88]
	add	si,2000h		; attribute area
	mov	cx,0800h
	rep	movsw
;
	pop	es
	pop	ds
;
; clear mode line
;
	mov	al,vt_blkatr
	call	vt_stat_clr
;
	mov	ah,0Ch			; start dispay
	int	BIOS
;
	mov	ax,0
	call	set_cursor		; restore cursor attributes
;
	mov	si,offset gnrm_color
	call	set_gpalette
	call	gdisp_off
;
	pop	dx
	pop	cx
	pop	ax
;
	ret
VT100_SAVE	ENDP
 
;
; restore VT100 screen
;
VT100_RESTORE	PROC	NEAR
	push	ax
	push	bx
	push	cx
	push	dx
	push	ds
	push	es
;
	cld
;
	mov	ah,0Dh			; stop display
	int	BIOS
;
	mov	ax,CRT_TXT_SEG
	mov	es,ax			; destination sagment address
	mov	di,vram_line
	push	di
	mov	ax,vt_saveseg
	mov	ds,ax
	mov	si,0
	mov	cx,0800h
	rep	movsw
	pop	di
	add	di,2000h		; attribute area
	mov	cx,0800h
	rep	movsw
;
	mov	ah,0Ch			; start dispay
	int	BIOS
;
	pop	es
	pop	ds
;
	xor	ax,ax
	mov	al,vt100_cursr
	call	set_cursor		; set cursor attributes
;
	call	locate_cur
;
	call	set_gcolor
	call	gdisp_on
;
	pop	dx
	pop	cx
	pop	bx
	pop	ax
;
	ret
VT100_RESTORE	ENDP
 
set_termnam	proc	near
	push	ax
	push	cx
	push	si
	push	di
	push	es
;
	mov	ax,ds
	mov	es,ax
;  terminal type
	mov	cx,10			; length of terminal name
	mov	si,offset nam_vt52
	cmp	flags.vtflg,ttvt52
	je	set_termnam1
	mov	si,offset nam_vt100
	cmp	flags.vtflg,ttvt100
	je	set_termnam1
	mov	si,offset nam_tek
	cmp	flags.vtflg,tttek
	je	set_termnam1
	mov	si,offset nam_none
set_termnam1:
	mov	di,offset mode_trm
	rep	movsb
;
	pop	es
	pop	di
	pop	si
	pop	cx
	pop	ax
	ret
set_termnam	endp
;
set_prnstat	proc
	push	ax
	push	cx
	push	si
	push	di
	push	es
;
	mov	ax,ds
	mov	es,ax
;
;  printer status
;
	mov	cx,4
	mov	si,offset nam_nprn
	test	vt100_pflag,(AUTOPRINT_BIT+PRINTCTRL_BIT)
	jz	set_prnstat1
	mov	si,offset nam_prn
set_prnstat1:
	mov	di,offset mode_prn
	rep	movsb
	pop	es
	pop	di
	pop	si
	pop	cx
	pop	ax
	ret
set_prnstat	endp
;
SET_MODLIN	PROC	NEAR
; set the mode line buffer
;
	push	es
	mov	ax,ds
	mov	es,ax
;
	mov	al,' '
	mov	ah,trans.escchr
	cmp	ah,020h
	jge	set_modlin1
	mov	al,'^'
	or	ah,040h
set_modlin1:
	mov	word ptr mode_esc,ax
	mov	word ptr mode_hlp,ax
;
	mov	al,vt_ourarg.baudb
	mov	si,offset unkbaud	; Assume unknown baud.
	mov	cx,5			; length of baud space
	cmp	al,BAUDNSIZ		; too big?
	jnb	set_modlin2		; yes, use default
	mul	cl
	xor	ah,ah
	add	ax,offset baudname
	mov	si,ax
set_modlin2:
	mov	di,offset mode_spd
	rep	movsb
;
	mov	al,vt_ourarg.prt
	cmp	al,'A'
	jae	set_modlin3
	add	al,'0'			; convert to character
set_modlin3:
	mov	mode_prt,al
;
	mov	al,vt_ourarg.parity
	xor	ah,ah
	mov	cx,4
	imul	cl
	add	ax,offset parityname
	mov	si,ax
	mov	di,offset mode_pty
	rep	movsb
;
	mov	si,offset lclename
	test	vt_ourarg.flgs,lclecho
	jnz	set_modlin4
	mov	si,offset remename
set_modlin4:
	mov	cx,3
	mov	di,offset mode_ech
	rep	movsb
;
	call	set_termnam
	call	set_prnstat
;
	mov	mode_len,MODE_LINE_LENG
;
	pop	es
	ret
SET_MODLIN	ENDP
;
vt_stat_clr	proc	near
;
; clear status line with attribute in AL.
;
	push	bx
	push	es
	push	di
	push	si
;
	mov	bx,ax
	cld
	mov	ax,CRT_TXT_SEG
	mov	es,ax
	mov	di,vram_last_line
	mov	cx,80
	xor	ah,ah
	mov	al,' '
	rep	stosw
	mov	di,vram_last_line
	add	di,02000h
	mov	al,bl
	mov	cx,80
	rep	stosw
;
	mov	ax,bx
	pop	si
	pop	di
	pop	es
	pop	bx
	ret
vt_stat_clr	endp
;
VT100_MODLIN	PROC	NEAR
;
; Mode line display control
;
; Inputs:
;	dx	offset address of the mode line buffer;
;		The 1st byte of the mode line buffer must contain the
;		the number of characters in the buffer. If it is zero,
;		the mode line is cleared.
;
	push	ax
	push	cx
	cmp	vt_stat_type,0		; clear status buffer ?
	jne	vt100_modlin1		; ne=no.
	mov	al,vt_blkatr		; attribute
	call	vt_stat_clr		; clear the status line
	jmp	vt100_modlin_ex		; and return
;
vt100_modlin1:
	cmp	vt_stat_type,1		; Kermit mode line control ?
	jne	vt100_modlin2		; ne=no.
	test	vt_ourarg.flgs,modoff	; mode line off ?
	jz	vt100_modlin1_1		; z=no.
	mov	al,vt_blkatr
	call	vt_stat_clr
	jmp	vt100_modlin_ex
;
;  display kermit mode line
;
vt100_modlin1_1:
	mov	al,vt_modatr
	call	vt_stat_clr
;
	push	es
	push	di
	push	si
;
	cld
	xor	ch,ch
	mov	cl,mode_len
	mov	si,offset mode_ker
	mov	ax,CRT_TXT_SEG
	mov	es,ax
	mov	di,vram_last_line
	xor	ah,ah
vt100_modlin1_2:
	mov	al,[si]
	mov	es:[di],ax
	inc	si
	add	di,2
	loop	vt100_modlin1_2
;
	pop	si
	pop	di
	pop	es
	jmp	vt100_modlin_ex
;
vt100_modlin2:
;@@	mov	al,vt_modatr
;@@	call	vt_stat_clr
;
vt100_modlin_ex:
	call	locate_cur
;
	pop	cx
	pop	ax
	ret
VT100_MODLIN	ENDP
 
VT100_COLOR	PROC	NEAR
;
; Change color to the value specified in [si].
;	[si]	color index for foreground
;	[si+1]	color index for background
;	[si+2]	color index for highlight
;	[si+3]	color index for modeline
;
	push	ax
	push	cx
;
	mov	al,[si]
	and	vt_nrmatr,1Fh		; mask color attributes
	and	vt_chratr,1Fh
	and	vt_blkatr,1Fh
	mov	cl,5
	shl	al,cl
	or	vt_nrmatr,al
	or	vt_chratr,al
	or	vt_blkatr,al
;
	push	di
	push	si
	mov	al,[si+1]
	xor	ah,ah
	mov	si,offset gnrm_color
	add	si,ax
	add	si,ax
	add	si,ax
	mov	di,offset gbck_color
	mov	cx,16
vt100_color1:
	mov	al,[si]
	mov	[di],al
	inc	di
	mov	al,[si+1]
	mov	[di],al
	inc	di
	mov	al,[si+2]
	mov	[di],al
	inc	di
	loop	vt100_color1
	pop	si
	pop	di
;
	mov	al,[si+2]
	and	vt_hglatr,1Fh		; mask color attributes
	mov	cl,5
	shl	al,cl
	or	vt_hglatr,al
;
	mov	al,[si+3]
	and	vt_modatr,1Fh		; mask color attributes
	mov	cl,5
	shl	al,cl
	or	vt_modatr,al
;
	pop	cx
	pop	ax
	ret
VT100_COLOR	ENDP
 
mrsave		proc	near
;
; save n lines (given by CL) in roll-up buffer (circular).
;
	push	ax
	push	cx
	push	si
	push	di
	push	ds
	push	es
;
	xor	ch,ch		; clear high byte of CX
	mov	si,vram_line
mrsave1:
	cmp	cx,0
	jle	mrsave3
	push	cx
	push	ds
	mov	ax,vt_rollcur	; current roll-buffer segment
	mov	es,ax		; destination segment address
	mov	di,0		; destination offset address
	mov	ax,CRT_TXT_SEG
	mov	ds,ax		; source segment address
	push	si		; save the source offset address
	mov	cx,80		; words per line
	rep	movsw		; save the text area
	pop	si
	add	si,2000h	; offset address of the attribute area
	mov	cx,80
	rep	movsw		; save the attribute area
	sub	si,2000h	; return to text area
	pop	ds
	pop	cx
	dec	cx
	inc	vt_rollcln	; update lines
	add	vt_rollcur,20	; update segment address. 20 parag. per line
	mov	ax,vt_rollfil
	cmp	ax,vt_rollmxl
	jge	mrsave2
	inc	vt_rollfil
mrsave2:
	mov	ax,vt_rollcln
	cmp	ax,vt_rollmxl	; exceed maximum lines ?
	jl	mrsave1
	mov	ax,vt_rollseg
	mov	vt_rollcur,ax
	mov	vt_rollcln,0
	jmp	mrsave1
mrsave3:
	pop	es
	pop	ds
	pop	di
	pop	si
	pop	cx
	pop	ax
	ret
mrsave		endp
 
prn_chk	proc	near
;
; Check the printer port
; carry on  -- printer not ready
;
	push	ax
	mov	ah,ioctl
	mov	al,7			; get output status of printer
	push	bx
	mov	bx,4			; file handle for system printer
	int	dos
	pop	bx
 	jc	prn_chk1		; c = printer not ready
 	cmp	al,0ffh			; Ready status?
	je	prn_chk2		; e = Ready
prn_chk1:
	call	vt_bell
	stc
prn_chk2:
	pop	ax
	ret
prn_chk	endp
 
 
VT100_RUPN	proc	near
;
; roll-up n lines (n is given in cx)
; cx will be broken when return.
; 1) copy the last line of the screen to the current save area
; 2) decrement the save area pointer
; 3) scroll down the screen by one line
; 4) copy the current save area to the top of screen
; 5) increment the number of moved lines
;
	push	ax
	push	dx
	push	si
	push	di
	push	es
;
vt100_rupn_1:
	cmp	cx,0
	jg	vt100_rupn_2
	jmp	vt100_rupn_ex
vt100_rupn_2:
	mov	ax,vt_rollnum
	inc	ax
	cmp	ax,vt_rollfil
	jl	vt100_rupn_3
	jmp	vt100_rupn_ex
;
vt100_rupn_3:
	push	cx			; save counter
	mov	ax,vt_rollcur
	mov	es,ax
	mov	di,0
;
	push	ds
;
	mov	ax,CRT_TXT_SEG
	mov	si,vram_botm_line
	push	si
	mov	cx,80
	mov	ds,ax
	cld
	rep	movsw
	pop	si
	add	si,2000h		; attribute area
	mov	cx,80
	rep	movsw			; save attributes
;
	pop	ds
;
	mov	cx,20			; one line (display + attributes)
	cmp	vt_rollcln,0
	jg	vt100_rupn_4
	mov	ax,vt_rollmxl
	mov	vt_rollcln,ax
	mov	ax,vt_rollmxs
	mov	vt_rollcur,ax
vt100_rupn_4:
	dec	vt_rollcln
	mov	ax,vt_rollcln
	sub	vt_rollcur,cx
;
	mov	cx,vram_botm_line
	sub	cx,vram_line
	mov	di,vram_last_line
	dec	di
	mov	si,vram_botm_line
	dec	si
	std
	mov	ax,CRT_TXT_SEG
;
	push	ds
;
	push	cx
	push	di
	push	si
	mov	ds,ax
	mov	es,ax
	std
	rep	movsb
	pop	si
	pop	di
	pop	cx
	add	si,2000h
	add	di,2000h
	rep	movsb
;
	pop	ds
	cld
;
	mov	di,vram_line
	mov	si,0
	mov	ax,CRT_TXT_SEG
	mov	es,ax
	mov	ax,vt_rollcur
;
	push	ds
;
	mov	ds,ax
	mov	cx,80
	push	di
	rep	movsw
	pop	di
	add	di,2000h
	mov	cx,80
	rep	movsw
;
	pop	ds
;
	inc	vt_rollnum
	pop	cx			; restore line counter
	dec	cx
	jmp	vt100_rupn_1
;
vt100_rupn_ex:
	pop	es
	pop	di
	pop	si
	pop	dx
	pop	ax
	ret
VT100_RUPN	endp
 
VT100_RDNN	proc	near
;
; roll-down n lines (n is given in CX).
; CX will be broken when return.
; 1) copy the top of the screen to the current save area
; 2) increment the save area pointer
; 3) screen scroll up one line
; 4) copy the current save area to the bottom of the screen
; 5) decrement the number of moved lines
;
	push	ax
	push	dx
	push	si
	push	di
	push	es
;
vt100_rdnn_1:
	cmp	cx,0
	jg	vt100_rdnn_2
	jmp	vt100_rdnn_ex
vt100_rdnn_2:
	mov	ax,vt_rollnum
	cmp	ax,0
	jg	vt100_rdnn_3
	jmp	vt100_rdnn_ex
;
vt100_rdnn_3:
	push	cx			; save line counter
	mov	ax,vt_rollcur
	mov	es,ax
	mov	di,0
;
	push	ds
;
	mov	ax,CRT_TXT_SEG
	mov	si,vram_line
	push	si
	mov	cx,80
	mov	ds,ax
	cld
	rep	movsw
	pop	si
	add	si,2000h		; attribute area
	mov	cx,80
	rep	movsw			; save attributes
;
	pop	ds
;  increment save-area pointer
	mov	cx,20			; one line (display + attributes)
	inc	vt_rollcln
	add	vt_rollcur,cx
	mov	ax,vt_rollcln
	cmp	ax,vt_rollmxl
	jl	vt100_rdnn_4
	mov	vt_rollcln,0
	mov	ax,vt_rollseg
	mov	vt_rollcur,ax
vt100_rdnn_4:
;
	mov	cx,vram_botm_line
	sub	cx,vram_line
	mov	di,vram_line
	mov	si,di
	add	si,160
	mov	ax,CRT_TXT_SEG
;
	push	ds
;
	push	cx
	push	di
	push	si
	mov	ds,ax
	mov	es,ax
	rep	movsb
	pop	si
	pop	di
	pop	cx
	add	si,2000h
	add	di,2000h
	rep	movsb
;
	pop	ds
;
	mov	di,vram_botm_line
	mov	si,0
	mov	ax,CRT_TXT_SEG
	mov	es,ax
	mov	ax,vt_rollcur
;
	push	ds
;
	mov	ds,ax
	mov	cx,80
	push	di
	rep	movsw
	pop	di
	add	di,2000h
	mov	cx,80
	rep	movsw
;
	pop	ds
;
	dec	vt_rollnum
	pop	cx			; restore line counter
	dec	cx
	jmp	vt100_rdnn_1
;
vt100_rdnn_ex:
	pop	es
	pop	di
	pop	si
	pop	dx
	pop	ax
	ret
VT100_RDNN	endp
 
scrn_mode	proc	near
;
; set screen mode to normal(AL=0)/reverse(AL=1)
; [NOTE]
;	registers AX and BX are broken when return
;
	push	cx
	push	di
	push	es
;
	mov	bx,ax
	mov	ax,CRT_TXT_SEG
	mov	es,ax
	mov	di,vram_line
	add	di,2000h
	mov	cx,1920			; 1920 = 80 x 24
	cmp	bl,0
	je	scrn_mode0
scrn_mode1:
;  light background dark text.
	test	vt_nrmatr,CHR_REV
	jz	scrn_mode1L
	jmp	scrn_mode3
scrn_mode1L:
	xor	BYTE PTR es:[di],CHR_REV
	add	di,2
	loop	scrn_mode1L
	or	vt_nrmatr,CHR_REV
	or	vt_chratr,CHR_REV
	or	vt_blkatr,CHR_REV
	jmp	scrn_mode3
scrn_mode0:
;  dark background light text.
	test	vt_nrmatr,CHR_REV
	jnz	scrn_mode0L
	jmp	scrn_mode3
scrn_mode0L:
	xor	BYTE PTR es:[di],CHR_REV
	add	di,2
	loop	scrn_mode0L
	and	vt_nrmatr,NOT CHR_REV
	and	vt_chratr,NOT CHR_REV
	and	vt_blkatr,NOT CHR_REV
scrn_mode3:
	pop	es
	pop	di
	pop	cx
	ret
scrn_mode	endp
 
 
locate_cur	proc	near
;
; locate cursor at (cur_row,cur_col)
;
; [NOTE]
;	Registers ax, bx and dx are to be broken when return.
;
 
	mov	dh,cur_row
	mov	dl,cur_col
	call	move_cur
	mov	vt_wrap,0		; new position clears wrap req. flag
	ret
locate_cur	endp
;
move_cur	proc	near
;
;  Move cursor at (dh:row,dl:col)
;  Registers ax, bx and dx are broken when return.
;
	call	vram_ofs		; get VRAM address in BX
	shr	bx,1
	cli
move_cur1:
	in	al,60h
	test	al,04h			; test GDC status
	jz	move_cur1		; z=not ready
	mov	al,49h
	out	62h,al
	mov	al,bl
	out	60h,al
	mov	al,bh
	out	60h,al
	sti
	ret
move_cur	endp
;
disp_char	proc	near
;
; Display character in AX on the screen.
; Cursor moves to the next character position.
; AX:will be broken when return.
;
	cmp	ax,00060h		; backquote special treatment
	jne	disp_char_mod1
	mov	ax,06009h		; for backquote
	jmp	disp_char_modx
disp_char_mod1:
;@@	cmp	ax,0005Ch		; backslash
;@@	jne	disp_char_mod2
;@@	mov	ax,000EFh
disp_char_mod2:
disp_char_modx:
;
	push	es			; save segment reg.
	mov	dx,CRT_TXT_SEG		; set vram segment address
	mov	es,dx
	cmp	vt_wrap,0		; wrap requested ?
	je	disp_char_nowrap	; e = no.
;
	mov	cur_col,0		; return to left margin
	mov	bl,cur_row
	cmp	bl,vt_bottom		; exceed bottom margin ?
	jl	disp_char_wrap1		; l = No.
	je	disp_char_wrap2
	inc	cur_row
	mov	bl,cur_row
	cmp	bl,vt_phys_bottom
	jle	disp_char_nowrap
	mov	bl,vt_phys_bottom
	mov	cur_row,bl
	jmp	disp_char_nowrap
disp_char_wrap1:
	inc	cur_row
	jmp	disp_char_nowrap
disp_char_wrap2:
	push	ax
	mov	al,vt_top
	mov	ah,vt_bottom
	mov	cx,1
	call	scroll_up
	pop	ax
disp_char_nowrap:
	mov	dh,cur_row		; get current cursor position
	mov	dl,cur_col
	call	vram_ofs		; get vram offset address in bx
	mov	di,bx			; set destination
	test	vt100_flags,INSERT_BIT	; insert mode ?
	jz	disp_char_noins		; z = no
	cmp	cur_col,79		; at left margin ?
	jge	disp_char_noins		; ge = Yes. No characters shifted
	mov	cx,79
	sub	cl,cur_col		; get num. of chars. to be shifted
	mov	dh,cur_row
	mov	dl,79
	call	vram_ofs		; get destination offset address
	mov	di,bx			; set destination reg
	mov	si,bx
	sub	si,2			; source offset address
	push	ds			; save data-seg. reg.
	mov	dx,CRT_TXT_SEG
	mov	ds,dx
	std				; inverse direction
	rep	movsw			; shift the characters
	cld				; reset direction flag
	pop	ds			; restore data-seg. reg.
disp_char_noins:
	mov	es:[di],ax		; put the character
	xor	ah,ah			; clear higher bit
	mov	al,vt_chratr		; load attribute
	add	di,02000h		; attribute offset address
	stosw				; put attribute and increment address
	pop	es			; restore segment
	inc	cur_col			; update cursor position
	mov	al,cur_col
	cmp	al,79			; exceed right margin ?
	jbe	disp_char_loc		; be = No.
	mov	cur_col,79		; stay at right margin
	test	vt100_flags,AUTOWRAP_BIT	; Autowrap enable ?
	jz	disp_char_ex		; z = No. NoWrap
	mov	vt_wrap,1		; wrap request
	jmp	disp_char_ex		; all done.
disp_char_loc:
	call	locate_cur
disp_char_ex:
	ret
disp_char	endp
 
save_cursor	proc	near
; saves
; 1) cursor position
	mov	al,cur_row
	mov	cur_save_row,al
	mov	al,cur_col
	mov	cur_save_col,al
; 2) graphic rendition
	mov	al,vt_graph
	mov	save_graph,al
	mov	al,vt_chrset
	mov	save_chrset,al
	mov	al,vt_chratr
	mov	save_chratr,al
	mov	al,vt_blkatr
	mov	save_blkatr,al
;
	mov	ax,char_SS
	mov	char_save_SS,ax
	mov	ax,char_GL
	mov	char_save_GL,ax
	mov	ax,char_GR
	mov	char_save_GR,ax
;
	mov	al,char_G0
	mov	char_save_G0,al
	mov	al,char_G1
	mov	char_save_G1,al
	mov	al,char_G2
	mov	char_save_G2,al
	mov	al,char_G3
	mov	char_save_G3,al
; 3) state of wrap flag
; 4) state of origin mode
	mov	al,vt100_flags
	mov	save_flags,al
; 5) state of selective erase
	ret
save_cursor	endp
 
restore_cursor	proc	near
; 1) state of selective erase
; 2) state of origin mode
	and	vt100_flags,(not ORIGIN_BIT)
	mov	al,save_flags
	and	al,ORIGIN_BIT
	or	vt100_flags,al
; 3) state of wrap flag
	and	vt100_flags,(not AUTOWRAP_BIT)
	mov	al,save_flags
	and	al,AUTOWRAP_BIT
	or	vt100_flags,al
; 4) graphic rendition
	mov	al,save_graph
	mov	vt_graph,al
	mov	al,save_chrset
	mov	vt_chrset,al
	mov	al,save_chratr
	mov	vt_chratr,al
	mov	al,save_blkatr
	mov	vt_blkatr,al
;
	mov	ax,char_save_SS
	mov	char_SS,ax
	mov	ax,char_save_GL
	mov	char_GL,ax
	mov	ax,char_save_GR
	mov	char_GR,ax
;
	mov	al,char_save_G0
	mov	char_G0,al
	mov	al,char_save_G1
	mov	char_G1,al
	mov	al,char_save_G2
	mov	char_G2,al
	mov	al,char_save_G3
	mov	char_G3,al
; 5) cursor position
	mov	al,cur_save_row
	mov	cur_row,al
	mov	al,cur_save_col
	mov	cur_col,al
	call	locate_cur
	ret
restore_cursor	endp
 
vt_dump	proc	near
;
; copy the one line image from es:[si] to dump buffer.
; input
;   ES:SI
; outputs
;   CX		contains number of characters.
;   ES:SI	will be updated (points to the next line).
;
	push	ax
	push	di
;
	mov	dump_mode,0
	mov	di,offset dump_buffer
	mov	dump_pntr,di
	mov	cx,80
;
vt_dump1:
	mov	ax,es:[si]
	cmp	ah,0			; 1 byte code ?
	je	vt_dump3		; e = yes.
	cmp	al,09h			; ANK ?
	jne	vt_dump11		; ne = no.
	mov	al,ah
	mov	ah,0
	jmp	vt_dump3
vt_dump11:
	cmp	dump_mode,0
	je	vt_dump12
	mov	byte ptr [di],ESCAPE
	mov	word ptr [di+1],'0)'
	add	di,3
	mov	dump_pntr,di
	mov	dump_mode,0
vt_dump12:
	add	ax,20h			; convert to jis
	and	ax,7F7Fh		; mask 8th bit
	call	jis2s			; convert to shift jis
	mov	[di],al
	mov	[di+1],ah
	add	di,2
	add	si,4
	dec	cx
	mov	dump_pntr,di
	jmp	vt_dump2
vt_dump3:
; check graphic code. It is overrap over the shift-JIS kanji code.
; In that case, we should put the ESC seq to change the character set.
	cmp	al,80h
	jbe	vt_dump6
	cmp	al,0FCh
	ja	vt_dump6
	cmp	al,09Fh
	jbe	vt_dump5
	cmp	al,0E0h
	jb	vt_dump6
vt_dump5:
	cmp	dump_mode,0
	jne	vt_dump4
	mov	byte ptr [di],ESCAPE
	mov	word ptr [di+1],'3)'
	add	di,3
	mov	dump_pntr,di
	mov	dump_mode,1
	jmp	vt_dump4
vt_dump6:
	cmp	dump_mode,0
	je	vt_dump4
	mov	byte ptr [di],ESCAPE
	mov	word ptr [di+1],'0)'
	add	di,3
	mov	dump_pntr,di
	mov	dump_mode,0
vt_dump4:
	mov	[di],al			; remove Kanji flag etc in ah.
	inc	di
	add	si,2
	cmp	al,' '			; Is it blank ?
	je	vt_dump2		; e = yes.
	mov	dump_pntr,di
vt_dump2:
	dec	cx
	jcxz	vt_dump7
	jmp	vt_dump1
;
vt_dump7:
	mov	di,dump_pntr
	cmp	dump_mode,0
	je	vt_dump8
	mov	byte ptr [di],ESCAPE
	mov	word ptr [di+1],'0)'
	add	di,3
vt_dump8:
	mov	ax,0A0Dh		; add CR/LF
	mov	[di],ax
	add	di,2
	mov	cx,di
	sub	cx,offset dump_buffer
;
	pop	di
	pop	ax
	ret
vt_dump	endp
 
 
vt_prn	proc	near
;
; copy the one line image from es:[si] to dump buffer as a printer
; image.
;
; input
;   ES:SI
; outputs
;   CX		contains number of characters.
;   ES:SI	will be updated (points to the next line).
;
	push	ax
	push	di
;
	mov	dump_mode,0
	mov	di,offset dump_buffer
	mov	dump_pntr,di
	mov	cx,80
;
vt_prn1:
	mov	ax,es:[si]
	cmp	ah,0			; 1 byte code ?
	je	vt_prn3			; e = yes.
vt_prn11:
	cmp	dump_mode,0		; in 2 byte mode ?
	jne	vt_prn12		; ne = yes.
	mov	byte ptr [di],ESCAPE
	mov	byte ptr [di+1],'K'	; Kanji mode.
	add	di,2
	mov	dump_pntr,di
	mov	dump_mode,1
vt_prn12:
	add	ax,20h			; convert to jis
	and	ax,7F7Fh		; mask 8th bit
	mov	[di],al
	mov	[di+1],ah
	add	di,2
	add	si,4
	dec	cx
	mov	dump_pntr,di
	jmp	vt_prn2
vt_prn3:
	cmp	dump_mode,0		; in 1 byte mode ?
	je	vt_prn4			; e = yes.
	mov	byte ptr [di],ESCAPE
	mov	byte ptr [di+1],'H'	; High density pica mode.
	add	di,2
	mov	dump_pntr,di
	mov	dump_mode,0
vt_prn4:
	mov	[di],al			; remove Kanji flag etc in ah.
	inc	di
	add	si,2
	cmp	al,' '			; Is it blank ?
	je	vt_prn2			; e = yes.
	mov	dump_pntr,di
vt_prn2:
	dec	cx
	jcxz	vt_prn7
	jmp	vt_prn1
;
vt_prn7:
	mov	di,dump_pntr
	cmp	dump_mode,0
	je	vt_prn8
	mov	byte ptr [di],ESCAPE
	mov	byte ptr [di+1],'H'
	add	di,2
vt_prn8:
	mov	ax,0A0Dh		; add CR/LF
	mov	[di],ax
	add	di,2
	mov	cx,di
	sub	cx,offset dump_buffer
;
	pop	di
	pop	ax
	ret
vt_prn	endp
 
vt_bell	proc	near
	push	ax
	push	cx
;
	mov	al,06h
	out	37h,al
	mov	cx,0D000h
vt_bell1:
	loop	vt_bell1
	mov	al,07h
	out	37h,al
;
	pop	cx
	pop	ax
vt_bell	endp

;---------------------------
VT100_DUMP	PROC	NEAR
;---------------------------
; Dump screen. This procedure dump the VT100 screen on the disk using
; MS-DOS function 40H (int 21H).
;
; Inputs
;   BX	file handle
;
; Outputs
;   None
;
	push	cx
	push	dx
	push	es
	push	si
	push	di
 
	mov	ax,CRT_TXT_SEG
	mov	es,ax
	mov	si,vram_line
	mov	cx,24
vt100_dump0:
	push	cx
	call	vt_dump
	mov	ah,WRITE2		; write function
	mov	dx,offset dump_buffer
	int	DOS
;
	pop	cx
	loop	vt100_dump0
;
	pop	di
	pop	si
	pop	es
	pop	dx
	pop	cx
	ret
VT100_DUMP	ENDP
 
;------------------------------------------------------------------------------
VT100_PRNC	PROC	NEAR
;
;  Printer control (Transparent printing).
;  - Watches the control seunce CSI 4 i (turns off printer controller mode).
;    If this sequence is found, control returns to normal terminal mode.
;  - Until CSI 4 i sequnce is found, all the received characters are sent to
;    the printer without displaying them on the screen except NUL, XON, XOFF,
;    CSI 5 i and CSI 4 i.
;
	mov	di,offset watch_buf	; get buffer pointer
	add	di,watch_pnd		; adjust pointer
	mov	[di],al			; save the character
	inc	watch_pnd		; increment the pointer
;
	cmp	watch_lvl,0		; normal sequnce ?
	jne	vt100_prnc_n0		; ne = no.
	jmp	vt100_prnc_L0
vt100_prnc_n0:
	cmp	watch_lvl,1		; next ESC ?
	jne	vt100_prnc_n1		; ne = no.
	jmp	vt100_prnc_L1
vt100_prnc_n1:
	cmp	watch_lvl,2		; after CSI ?
	jne	vt100_prnc_n2		; ne = no.
	jmp	vt100_prnc_L2
vt100_prnc_n2:
	cmp	watch_lvl,3		; final character ?
	jne	vt100_prnc_n3		; ne = no.
	jmp	vt100_prnc_L3
vt100_prnc_n3:				; *** if come here, PROGRAM ERROR ***
	mov	watch_lvl,0
	mov	watch_pnd,0
	jmp	vt100_prnc_OUT
;
vt100_prnc_L0:
	mov	watch_lvl,1		; assume ESC
	cmp	al,ESCAPE		; ESC ?
	je	vt100_prnc_L0_1		; e = yes.
	mov	watch_lvl,2		; assume CSI
	cmp	al,CSI			; CSI ?
	je	vt100_prnc_L0_1		; e = yes.
	jmp	vt100_prnc_OUT
;
vt100_prnc_L0_1:
	mov	di,offset watch_buf
	mov	watch_pnd,0
	mov	[di],al
	inc	watch_pnd
	jmp	vt100_prnc_ex
;
vt100_prnc_L1:
	cmp	al,'['
	je	vt100_prnc_L1_1
	jmp	vt100_prnc_OUT
vt100_prnc_L1_1:
	mov	watch_lvl,2
	jmp	vt100_prnc_ex
;
vt100_prnc_L2:
	mov	watch_mod,al
	cmp	al,'5'
	je	vt100_prnc_L2_1
	cmp	al,'4'
	je	vt100_prnc_L2_1
	jmp	vt100_prnc_OUT
vt100_prnc_L2_1:
	mov	watch_lvl,3
	jmp	vt100_prnc_ex
;
vt100_prnc_L3:
	cmp	al,'i'
	jne	vt100_prnc_OUT
	mov	watch_pnd,0		; clear pending buffer
	cmp	watch_mod,'4'		; off the printer control ?
	jne	vt100_prnc_L3_1		; ne = no.
	and	vt100_pflag,(not PRINTCTRL_BIT)
vt100_prnc_L3_1:
	jmp	vt100_prnc_ex
;
vt100_prnc_OUT:
	mov	di,offset watch_buf
	mov	cx,watch_pnd
vt100_prnc_OUT1:
	mov	ah,LSTOUT
	mov	dl,[di]
	int	DOS
	jc	vt100_prnc_OUT2
	inc	di
	loop	vt100_prnc_OUT1
	mov	watch_pnd,0
	jmp	vt100_prnc_ex
;
vt100_prnc_OUT2:
	call	vt_bell
	and	vt100_pflag,(not (AUTOPRINT_BIT+PRINTCTRL_BIT))
	mov	watch_pnd,0
;
vt100_prnc_ex:
	xor	ah,ah
	xor	cx,cx
	ret
VT100_PRNC	ENDP
 
;------------------------------------------------------------------------------
VT100_PRNL	PROC	NEAR
;
;  Print the current line on the printer
;
	push	dx
;
	push	bx
	mov	dh,cur_row
	mov	dl,0
	call	vram_ofs
	mov	si,bx
	pop	bx
;
	push	es
	mov	ax,CRT_TXT_SEG
	mov	es,ax
	call	vt_prn
	pop	es
;
	mov	di,offset dump_buffer
vt100_prnl1:
	mov	al,[di]
	call	pntchr
	jc	vt100_prnl2
	inc	di
	loop	vt100_prnl1
	jmp	vt100_prnl3
;
vt100_prnl2:
	call	vt_bell
	and	vt100_pflag,(not (AUTOPRINT_BIT+PRINTCTRL_BIT))
;
vt100_prnl3:
;
	pop	dx
	ret
VT100_PRNL	ENDP
 
;------------------------------------------------------------------------------
VT100_PRNS	PROC	NEAR
;
;  Print the current screen on the printer.
;  Similar to dump.
;
	push	cx
	push	dx
	push	es
	push	si
	push	di
;
	test	vt100_pflag,AUTOPRINT_BIT	; printer off?
	jnz	vt100_prns1		; nz = no not. it is on.
	call	prn_chk			; check the printer port
	jnc	vt100_prns1		; nc = ready.
	jmp	vt100_prns5
;
vt100_prns1:
	mov	ax,CRT_TXT_SEG
	mov	es,ax
	mov	si,vram_line
	mov	cx,24
	test	vt100_pflag,PRINTEXT_BIT	; full screen printing?
	jnz	vt100_prns2		; nz = yes.
	mov	al,vt_top		; determine start address
	xor	ah,ah
	mov	cx,ax
	shl	ax,1
	mov	si,offset vram_line
	add	si,ax
	mov	si,[si]
	mov	al,vt_bottom
	xor	ah,ah
	xchg	ax,cx
	sub	cx,ax
	inc	cx
vt100_prns2:
	push	cx
	call	vt_prn
	mov	di,offset dump_buffer
;
vt100_prns3:
	mov	al,[di]
	call	pntchr
	jc	vt100_prns4
	inc	di
	loop	vt100_prns3
;
	pop	cx
	loop	vt100_prns2
;
	test	vt100_pflag,PRINTFF_BIT	; must print FF ?
	jz	vt100_prns5	; z = no.
	mov	al,FF
	call	pntchr
	jc	vt100_prns4
	jmp	vt100_prns5
;
vt100_prns4:
	call	vt_bell
	and	vt100_pflag,(not (AUTOPRINT_BIT+PRINTCTRL_BIT))
;
vt100_prns5:
	pop	di
	pop	si
	pop	es
	pop	dx
	pop	cx
	ret
VT100_PRNS	ENDP
 
;------------------------------------------------------------------------------
VT100		PROC	NEAR
;
;  The main program for VT100 emulator
;  Inputs:
;       AL  character code
;  Outputs:
;       AH  results
;           0:Normal, in this case,
;       CX  number of characters to be sent to communication port
;    DS:SI  character string to be sent
;
;       AH  non zero means 'change to the tek4010 emulation mode'
;           1:only change the mode. do not pass any character.
;           2:change the mode and send the character in AL.
;           3:change the mode and send the characters in DH and DL.
;       DX  character pair to be sent to tek4010 emulator if AH=3.
;    
;------------------------------------------------------------------------------
;
; Character display routine in VT-100 mode
;
vt_disp:
	mov	vt_rollnum,0
;
	cmp	spec_mode,0		; in special mode ?
	je	vt_disp_NRM		; e = No. go to normal process.
	cmp	spec_mode,IN_ESC_MODE	; in ESC sequence ?
	jne	vt_disp_01		; ne = No. check other sequnce.
	jmp	vt_disp_inESC		; go to ESC sequence procedure.
vt_disp_01:
	cmp	spec_mode,IN_CSI_MODE	; in CSI sequence ?
	jne	vt_disp_02		; ne = No. check other sequnce.
	jmp	vt_disp_inCSI		; go to CSI sequence procedure.
vt_disp_02:
	cmp	spec_mode,IN_DCS_MODE	; in DCS sequence ?
	jne	vt_disp_03		; ne = No.
	jmp	vt_disp_inDCS		; go to DCS sequence procedure.
vt_disp_03:
	mov	spec_mode,0		; May be my program error. treate as
					; normal character.
;
vt_disp_NRM:
	cmp	al,080h			; C0/GL character ?
	jae	vt_disp_C1GR		; ae = No.
;
; C0/D0 character
;
	cmp	al,020h			; C0 code ?
	jae	vt_disp_GL		; ae = No. This is GL code.
	jmp	vt_disp_C0		; do C0 control.
vt_disp_GL:
	cmp	al,07Fh			; DEL code ?
	je	vt_disp_ex		; e = Yes. Ignore this character.
	cmp	char_SS,0		; single shift in progress ?
	je	vt_disp_GL2		; e = No.
	mov	bx,char_SS		; single shift
	jmp	disp_out		; display character
vt_disp_GL2:
	mov	bx,char_GL		; GL character
	jmp	disp_out		; display character
vt_disp_ex:
	mov	ah,0			; continue vt emulation
	mov	cx,0
	ret
;
; C1/GR character
;
vt_disp_C1GR:
	cmp	al,0A0h			; C1 code ?
	jae	vt_disp_GR		; ae = No. This is GR code
	jmp	vt_disp_C1		; do C1 control
vt_disp_GR:
	cmp	al,0FFh			; 8 bit DEL code ?
	je	vt_disp_ex		; e = Yes. Ignore this character
	and	al,07Fh
	cmp	char_SS,0		; Single shift in progress ?
	je	vt_disp_GR2		; e = No.
	mov	bx,char_SS		; set single shift
	jmp	disp_out
vt_disp_GR2:
	mov	bx,char_GR		; GR character
;-----------------------------------
; Display the character code.
; Inputs:
;   AL: Character code
;   BX: Address of the character set
;-----------------------------------
disp_out:
	cmp	vt_knjmode,0		; multi-byte code in progress ?
	jne	disp_Kanji		; ne = Yes.
	jmp	disp_out0		; 1st byte character code.
;
disp_Kanji:
	mov	vt_kanji2,al		; save Kanji 2nd byte
;
;       test logging
;
	cmp	vt100_lflag,(LOGCOOK_BIT+LOGENAB_BIT) ; log enabled and cooked
	jne	disp_Kanji_1            ; ne = No.
	mov	ah,vt_kanji2
	mov	al,vt_kanji1
	call	jis2s			; convert to shift JIS
	call	outcapt                 ; log 1st byte
	xchg	ah,al
	call	outcapt			; log 2nd byte
disp_Kanji_1:
;
;       Display Kanji
;
	mov	ah,vt_kanji2		; restore Kanji 2nd byte
	mov	al,vt_kanji1		; restore Kanji 1st byte
	sub	ax,020h
	push	ax
	call	disp_char
	pop	ax
	or	ax,8000h
	call	disp_char
	mov	vt_knjmode,0
	mov	char_SS,0		; reset single shift
	jmp	vt_disp_ex
;
disp_out0:
	mov	ah,[bx]			; Get character set number
	mov	vt_graph,ah
	xor	ah,ah
	cmp	vt_graph,CSET_JISROMAN	; JIS roman character set ?
	jne	disp_out1
	jmp	disp_outit
disp_out1:
	cmp	vt_graph,CSET_DECGRAPH	; DEC special graphics character set ?
	jne	disp_out2
	jmp	disp_DECGRAPH
disp_out2:
	cmp	vt_graph,CSET_JISC6226	; JIS 2-byte Kanji code ?
	jne	disp_out3
	jmp	disp_JISC6226
disp_out3:
	cmp	vt_graph,CSET_JISKATAKANA
	jne	disp_out4
	jmp	disp_JISKATAKANA
disp_out4:
	jmp	disp_outit
;---------------------------------------
disp_DECGRAPH:
	cmp	ax,060h
	jge	disp_DECGRAPH1
	jmp	disp_outit
disp_DECGRAPH1:
	sub	ax,060h
	mov	bx,offset vt_gset
	add	bx,ax
	mov	al,[bx]
	jmp	disp_outit
disp_JISC6226:
	mov	vt_kanji1,al
	mov	vt_knjmode,1
	jmp	vt_disp_ex
disp_JISKATAKANA:
	or	al,080h
disp_outit:
	cmp	vt100_lflag,(LOGCOOK_BIT+LOGENAB_BIT)
	jne	disp_outit_1
	call	outcapt
disp_outit_1:
	call	disp_char
	mov	char_SS,0		; reset single shift
	jmp	vt_disp_ex
;
;-------------------------------------------------
; C0 control characters
; Note that only CAN and SUB clear ESC, CSI stage.
;-------------------------------------------------
vt_disp_C0:
	push	ax
	mov	bx,offset C0_func_tab	; jump table address
	xor	ah,ah
	shl	ax,1
	add	bx,ax
	pop	ax
	jmp	[bx]
;
; No action
;
vt_disp_none:
	jmp	vt_disp_ex
;
; BEL
;
vt_disp_BEL:
	mov	al,06h
	out	37h,al
	mov	cx,0D000h
bell_loop:
	loop	bell_loop
	mov	al,07h
	out	37h,al
	jmp	vt_disp_ex
;
; BS
;
vt_disp_BS:
	mov	vt_knjmode,0		; clear multi-byte flag
	cmp	cur_col,0
	jg	vt_disp_BS_1
	jmp	vt_disp_ex
vt_disp_BS_1:
	dec	cur_col
	call	locate_cur
	jmp	vt_disp_ex
;
; HT
;
vt_disp_HT:
	mov	vt_knjmode,0		; clear multi-byte flag
	cmp	vt100_lflag,(LOGCOOK_BIT+LOGENAB_BIT)
	jne	vt_disp_HT0
	call	outcapt
vt_disp_HT0:
	push	bx			; save BX register
	mov	bx,offset tabstops	; set address of tabstops
	mov	al,cur_col		; get current cursor position
	xor	ah,ah			; clear higher byte
	add	bx,ax			; tab table pointer
vt_disp_HT1:
	cmp	al,79			; right margin ?
	jge	vt_disp_HT2		; ge = Yes. do not move any more
	inc	al			; move position
	inc	bx			; update table pointer
	cmp	byte ptr [bx],0		; TAB stop position ?
	je	vt_disp_HT1		; e = No. increment pointer and cont.
;
vt_disp_HT2:
	pop	bx
	mov	cur_col,al		; save the new cursor position
	call	locate_cur		; and move the cursor
	jmp	vt_disp_ex
;
; LF
;
vt_disp_LF:
	mov	vt_knjmode,0		; clear multi-byte flag
	cmp	vt100_lflag,(LOGCOOK_BIT+LOGENAB_BIT)
	jne	vt_disp_LF0
	call	outcapt
vt_disp_LF0:
	test	vt100_pflag,AUTOPRINT_BIT	; auto-print requested ?
	jz	vt_disp_LF5	; z = no.
	call	vt100_prnl	; print the current line
vt_disp_LF5:
	mov	bl,vt_bottom	; get bottom margin
	cmp	cur_row,bl
	jl	vt_disp_LF2	; above boundary
	je	vt_disp_LF1	; on the boundary
	inc	cur_row
	mov	bl,vt_phys_bottom
	cmp	cur_row,bl	; screen boundary
	jle	vt_disp_LF3
	mov	cur_row,bl
	jmp	vt_disp_LF3
vt_disp_LF1:
	mov	cur_row,bl
	mov	al,vt_top
	mov	ah,vt_bottom
	mov	cx,1
	call	scroll_up
	jmp	vt_disp_LF3
vt_disp_LF2:
	inc	cur_row
vt_disp_LF3:
	test	vt100_flags,NEWLINE_BIT	; newline enabled ?
	jz	vt_disp_LF4	; z = no.
	mov	cur_col,0
vt_disp_LF4:
	call	locate_cur
	jmp	vt_disp_ex
;
; CR
;
vt_disp_CR:
	mov	vt_knjmode,0		; clear multi-byte flag
	cmp	vt100_lflag,(LOGCOOK_BIT+LOGENAB_BIT)
	jne	vt_disp_CR0
	call	outcapt
vt_disp_CR0:
	mov	cur_col,0
	call	locate_cur
	jmp	vt_disp_ex
;
; SO
;
vt_disp_SO:
	mov	vt_knjmode,0		; clear multi-byte flag
	mov	char_GL,offset char_G1
	jmp	vt_disp_ex
;
; SI
;
vt_disp_SI:
	mov	vt_knjmode,0		; clear multi-byte flag
	mov	char_GL,offset char_G0
	jmp	vt_disp_ex
;
; CAN
;
vt_disp_CAN:
	mov	vt_knjmode,0		; clear multi-byte flag
	mov	spec_mode,0		; clear ESC/CSI seq.
	jmp	vt_disp_ex
;
; SUB
;
vt_disp_SUB:
	mov	vt_knjmode,0		; clear multi-byte flag
	mov	spec_mode,0		; clear ESC/CSI seq.
	mov	ax,001Ah
	jmp	disp_outit		; and display it.
;
vt_disp_ESC:
	mov	vt_knjmode,0		; clear multi-byte flag
	mov	spec_mode,in_ESC_MODE	; enter in ESC mode
	mov	spec_stage,0		; show that just entered
	mov	I_pnt,0
	mov	bx,offset I_buf
	mov	word ptr [bx],0
	jmp	vt_disp_ex
;
; GS  Enter tektronix mode if tek4010 enabled
;
vt_disp_GS:
	test	vt100_flags,AUTOTEK_BIT
	jnz	vt_disp_GS_01
	jmp	vt_disp_ex
vt_disp_GS_01:
	mov	vt_knjmode,0		; clear multi-byte flag
	mov	spec_mode,0
	mov	ah,2			; pass character in AL
	mov	cx,0
	ret
;
;----------------------
; C1 control characters
;----------------------
vt_disp_C1:
	mov	vt_knjmode,0		; clear multi-byte flag
	cmp	al,084h			; IND
	jne	vt_disp_C1_n84
	jmp	vt_C1_IND
vt_disp_C1_n84:
	cmp	al,085h			; NEL
	jne	vt_disp_C1_n85
	jmp	vt_C1_NEL
vt_disp_C1_n85:
	cmp	al,088h			; HTS
	jne	vt_disp_C1_n88
	jmp	vt_C1_HTS
vt_disp_C1_n88:
	cmp	al,08Dh			; RI
	jne	vt_disp_C1_n8D
	jmp	vt_C1_RI
vt_disp_C1_n8D:
	cmp	al,08Eh			; SS2
	jne	vt_disp_C1_n8E
	jmp	vt_C1_SS2
vt_disp_C1_n8E:
	cmp	al,08Fh			; SS3
	jne	vt_disp_C1_n8F
	jmp	vt_C1_SS3
vt_disp_C1_n8F:
	cmp	al,090h			; DCS
	jne	vt_disp_C1_n90
	jmp	vt_C1_DCS
vt_disp_C1_n90:
	cmp	al,09Bh			; CSI
	jne	vt_disp_C1_n9B
	jmp	vt_C1_CSI
vt_disp_C1_n9B:
	cmp	al,09Ch			; ST
	jne	vt_disp_C1_n9C
	jmp	vt_C1_ST
vt_disp_C1_n9C:
	jmp	vt_disp_ex
;--------------------------------------------
vt_disp_vt52ESC:
	cmp	al,'A'
	jb	vt_disp_vt52ESC_nD
	cmp	al,'D'
	ja	vt_disp_vt52ESC_nD
	mov	WORD PTR P_buf,1
	jmp	vt_CSI_ABCD
vt_disp_vt52ESC_nD:
	cmp	al,'H'
	jne	vt_disp_vt52ESC_nH
	mov	cur_col,0
	mov	cur_row,0
	call	locate_cur
	jmp	vt_esc_done
vt_disp_vt52ESC_nH:
	cmp	al,'I'
	jne	vt_disp_vt52ESC_nI
	jmp	vt_C1_RI
vt_disp_vt52ESC_nI:
	cmp	al,'J'
	jne	vt_disp_vt52ESC_nJ
	mov	WORD PTR P_buf,0
	jmp	vt_CSI_J
vt_disp_vt52ESC_nJ:
	cmp	al,'K'
	jne	vt_disp_vt52ESC_nK
	mov	WORD PTR P_buf,0
	jmp	vt_CSI_K
vt_disp_vt52ESC_nK:
	cmp	al,'Y'
	jne	vt_disp_vt52ESC_nY
	mov	spec_stage,VT52_DCA_L
vt_disp_vt52ESC_nY:
	cmp	al,'F'			; enter graphics mode ?
	jne	vt_disp_vt52ESC_nF
	jmp	vt_esc_done
vt_disp_vt52ESC_nF:
	cmp	al,'G'			; leave graphics mode ?
	jne	vt_disp_vt52ESC_nG
	jmp	vt_esc_done
vt_disp_vt52ESC_nG:
	cmp	al,'W'			; enter printer control mode ?
	jne	vt_disp_vt52ESC_nW
	jmp	vt_esc_done
vt_disp_vt52ESC_nW:
	cmp	al,'X'			; leave printer control mode ?
	jne	vt_disp_vt52ESC_nX
	jmp	vt_esc_done
vt_disp_vt52ESC_nX:
	cmp	al,'V'			; print cursor line ?
	jne	vt_disp_vt52ESC_nV
	jmp	vt_esc_done
vt_disp_vt52ESC_nV:
;
; Non VT52 sequence is interpreted as VT100 sequence.
;
	add	al,040h		; convert to C1
	jmp	vt_disp_c1
;
vt_disp_vt52ESC_YL:
	xor	ah,ah
	sub	ax,32
	mov	P_buf,ax
	mov	spec_stage,VT52_DCA_C
	jmp	vt_disp_ex
;
vt_disp_vt52ESC_YC:
	push	ax
	xor	ah,ah
	sub	ax,32
	mov	cur_col,al
	mov	ax,P_buf
	mov	cur_row,al
	call	locate_cur
	pop	ax
	jmp	vt_esc_done
;------------------------------------------------------------------------------
; ESC sequence analysis
; Note that VT100 allows many C0 characters in ESC-seq.

vt_disp_inESC:
	cmp	al,07Eh			; check the allowed range
	ja	vt_disp_inESCe		; error.
	cmp	al,020h			; normal GL character ?
	jae	vt_disp_inESC1		; ae = yes.
; C0 control character
	cmp	spec_stage,0		; 1st character in ESC seq.?
	je	vt_disp_inESC0		; e = Yes. Need check ESC FF.
	jmp	vt_disp_C0
vt_disp_inESC0:
	cmp	al,0Ch			; FF ?
	je	vt_disp_ESC_FF		; e = Yes. Need special treatment.
	jmp	vt_disp_C0
;
; ESC FF:Enter tektronix mode if tek4010 enabled
;
vt_disp_ESC_FF:
	test	vt100_flags,AUTOTEK_BIT	; AutoTek enabled ?
	jnz	vt_disp_ESC_FF_do	; nz = Yes.
	jmp	vt_disp_C0
vt_disp_ESC_FF_do:
	mov	spec_mode,0		; ESC sequnce done. [25-Jun-1990]
	mov	ah,3			; pass character in DX
	mov	dh,ESCAPE
	mov	dl,al
	mov	cx,0
	ret
;--------------
vt_disp_inESC1:
	cmp	spec_stage,0		; 1st character in ESC seq.?
	jne	vt_disp_inESC2		; ne = no, check the sequnce type
	jmp	vt_esc_1
vt_disp_inESC2:
	cmp	spec_stage,1		; ESC with I sequence ?
	jne	vt_disp_inESC3
	jmp	vt_esc_2
vt_disp_inESC3:
	cmp	flags.vtflg,ttvt52
	jne	vt_disp_inESCe
;
	cmp	spec_stage,VT52_DCA_L
	jne	vt_disp_inESC4
	jmp	vt_disp_VT52ESC_YL
vt_disp_inESC4:
	cmp	spec_stage,VT52_DCA_C
	jne	vt_disp_inESCe
	jmp	vt_disp_VT52ESC_YC
vt_disp_inESCe:
	mov	spec_mode,0		; Sequence error. Clear flags and
	jmp	vt_disp_NRM		; treat as normal case.
;--------------------------------
; 1st byte just after the ESC
; AL is in 2/0 - 7/E
vt_esc_1:
	cmp	al,02Fh
	ja	vt_esc_10		; char is in 3/0 - 7/14, i.e., single
	mov	spec_stage,1		; set mutibyte flag
	jmp	vt_esc_I		; and goto I-seq.
vt_esc_10:
	cmp	al,05Fh
	ja	vt_esc_do_s		; char is in 6/0 - 7/14, i.e., single
	cmp	al,040h
	jb	vt_esc_do_s		; char is in 3/0 - 3/15, i.e., single
;  now AL is in 4/0 - 5/15, i.e., C1 except for a few cases
	cmp	al,'Z'			; DECDA ?
	jne	vt_esc_11
	jmp	vt_CSI_DA
vt_esc_11:
	cmp	flags.vtflg,ttvt52	; vt52 mode ?
	jne	vt_esc_12		; ne = no.
	jmp	vt_disp_vt52ESC
vt_esc_12:
	add	al,040h			; convert to C1
	jmp	vt_disp_c1		; display the C1 character
;--------------------------------
; in multi-byte ESC seq.
; AL is 2/0 - 7/E
vt_esc_2:
	cmp	al,02Fh
	jbe	vt_esc_I		; char is in 2/0 - 2/15, i.e., I
	jmp	vt_esc_do_m		; char is in 3/0 - 7/14, i.e., final
vt_esc_I:
	mov	bx,offset I_buf
	add	bx,I_pnt
	mov	byte ptr [bx],al
	inc	I_pnt
	jmp	vt_disp_ex
;
vt_esc_done:
vt_CSI_done:
	mov	spec_mode,0
	jmp	vt_disp_ex
;
; Found the final character of the ESC sequence
;
; Single-byte ESC seq.
; 3/0 - 3/15  private seq.
; 6/0 - 7/14  standard seq.
vt_esc_do_s:
	cmp	al,6Eh
	jne	vt_esc_do_n6E
	mov	char_GL,offset char_G2
	jmp	vt_esc_done
vt_esc_do_n6E:
	cmp	al,6Fh
	jne	vt_esc_do_n6F
	mov	char_GL,offset char_G3
	jmp	vt_esc_done
vt_esc_do_n6F:
	cmp	al,7Ch
	jne	vt_esc_do_n7C
	mov	char_GR,offset char_G3
	jmp	vt_esc_done
vt_esc_do_n7C:
	cmp	al,7Dh
	jne	vt_esc_do_n7D
	mov	char_GR,offset char_G2
	jmp	vt_esc_done
vt_esc_do_n7D:
	cmp	al,7Eh
	jne	vt_esc_do_n7E
	mov	char_GR,offset char_G1
	jmp	vt_esc_done
vt_esc_do_n7E:
	cmp	al,63h			; ESC c
	jne	vt_esc_do_n63
	call	vt100_reset
	jmp	vt_esc_done
vt_esc_do_n63:
	cmp	al,3Dh			; ESC =
	jne	vt_esc_do_n3D
	mov	keypad_mode,1
	jmp	vt_esc_done
vt_esc_do_n3D:
	cmp	al,3Eh			; ESC >
	jne	vt_esc_do_n3E
	mov	keypad_mode,0
	jmp	vt_esc_done
vt_esc_do_n3E:
	cmp	al,37h			; ESC 7
	jne	vt_esc_do_n37
	call	save_cursor
	jmp	vt_esc_done
vt_esc_do_n37:
	cmp	al,38h			; ESC 8
	jne	vt_esc_do_n38
	call	restore_cursor
	jmp	vt_esc_done
vt_esc_do_n38:
	cmp	al,3Ch			; ESC < VT52 -> ANSI mode ?
	jne	vt_esc_do_n3C
	mov	flags.vtflg,ttvt100
	call	set_termnam
	call	vt100_modlin
	jmp	vt_esc_done
vt_esc_do_n3C:
	jmp	vt_esc_done
;
; Multi-byte ESC seq.
; 3/0 - 3/15  Private seq.
; 4/0 - 7/14  Standard seq.
vt_esc_do_m:
vt_esc_do32:
	mov	bx,offset I_buf
	mov	ah,byte ptr [bx]
	cmp	ah,24h			; multibyte designation code ?
	jne	vt_esc_do34
	jmp	vt_desig_m
vt_esc_do34:
	cmp	ah,28h			; singlebyte desig. code (2/8-2/15)?
	jb	vt_esc_do36		; b = no.
	cmp	ah,2Fh			;
	ja	vt_esc_do36		; a = no.
	jmp	vt_desig_s
vt_esc_do36:
	cmp	al,'0'			; Possible Select Tek mode ?
	jne	vt_esc_do37		; ne = no
	cmp	I_pnt,2
	jne	vt_esc_do37
	cmp	ah,'%'			; Tek4105 Select code 1st byte ?
	jne	vt_esc_do37		; ne = no
	inc	bx			; next int. char.
	mov	ah,byte ptr [bx]
	cmp	ah,'!'			; Tek4105 Select code 2nd byte ?
	jne	vt_esc_do37
	mov	vt100_gflag,5		; Tek41xx screen color
	mov	ah,1			; enter Tek mode
	mov	cx,0
	mov	spec_mode,0		; clear ESC/CSI seq.
	ret
vt_esc_do37:
	jmp	vt_esc_done		; unknown
;-------------------------------------
; designate single byte character set
;
vt_desig_s:
	and	ah,3
	mov	bx,offset char_G0
	add	bl,ah
	mov	ah,CSET_JISROMAN
	cmp	al,49h
	jne	vt_desig_s1
	mov	ah,CSET_JISKATAKANA
	jmp	vt_desig_s2
vt_desig_s1:
	cmp	al,30h
	jne	vt_desig_s2
	mov	ah,CSET_DECGRAPH
vt_desig_s2:
	mov	byte ptr [bx],ah
	jmp	vt_esc_done
;
; designate multi-byte character set.
;
vt_desig_m:
	mov	ah,0
	cmp	I_pnt,1
	jbe	vt_desig_m1
	add	bx,1
	mov	ah,byte ptr [bx]
	and	ah,3
vt_desig_m1:
	mov	bx,offset char_G0
	add	bl,ah
	mov	ah,CSET_JISC6226
	mov	byte ptr [bx],ah
	jmp	vt_esc_done
;----------------------------------------------------
; Control seuence analysis
; Note that VT100 allows C0 characters in CSI seq.
vt_disp_inCSI:
	cmp	al,07Eh			; check the range
	ja	vt_disp_inCSIe		; error.
	cmp	al,020h			; C0 character ?
	jae	vt_disp_inCSI1		; ae = no. It is GL.
	jmp	vt_disp_C0
vt_disp_inCSI1:
	cmp	spec_stage,0		; 1st character in CSI ?
	jne	vt_disp_inCSI2		; ne = No.
	jmp	vt_CSI_1		; CSI with Parameters
vt_disp_inCSI2:
	cmp	spec_stage,1		; in intermediates ?
	jne	vt_disp_inCSI3
	jmp	vt_CSI_2		; CSI with Intermediates
vt_disp_inCSI3:
vt_disp_inCSIe:
	mov	spec_mode,0		; clear flags and treat as normal
	jmp	vt_disp_NRM
;
vt_disp_inCSIx:
	mov	spec_mode,0
	jmp	vt_disp_ex
;-----------------------------------------------------
; DCS analysis
;-----------------------------------------------------
vt_disp_inDCS:
	cmp	al,07Fh			; check the range
	jae	vt_disp_inDCSe		; sequence error.
	cmp	al,08h
	jb	vt_disp_inDCSe
	cmp	al,0Dh
	jbe	vt_disp_inDCS1
	cmp	al,020h
	jb	vt_disp_inDCSe
vt_disp_inDCS1:
	cmp	spec_stage,IN_SIXEL
	jne	vt_disp_inDCS2
	call	sixel
	jmp	vt_disp_ex
vt_disp_inDCS2:
	jmp	vt_DCS_1
vt_disp_inDCSe:
	mov	spec_mode,0		; sequence error.
	jmp	vt_disp_NRM
;--------------------------
vt_DCS_do:
	cmp	al,'q'			; sixel ?
	jne	vt_DCS_do_nq
	mov	spec_stage,IN_SIXEL
	call	sixel_in
	mov	vt100_gflag,2
	mov	sixel_disp_on,1
vt_DCS_do_nq:
	jmp	vt_disp_ex
;----------------------------------------------------------
; CSI & DCS sequence analysys
;----------------------------------------------------------
vt_DCS_1:
vt_CSI_1:
	cmp	al,030h			; Parameter (3/0-3/15) ?
	jb	vt_CSI_2
	cmp	al,03Fh
	jbe	vt_CSI_Para
	mov	spec_stage,1
vt_CSI_2:
	cmp	al,020h			; Intermediate (2/0-2/15) ?
	jb	vt_CSI_3
	cmp	al,02Fh
	jbe	vt_CSI_Intr
	cmp	al,040h			; Terminator (4/0-7/14) ?
	jb	vt_CSI_3
	cmp	spec_mode,IN_CSI_MODE
	jne	vt_CSI_2_1
	jmp	vt_CSI_do
vt_CSI_2_1:
	jmp	vt_DCS_do
vt_CSI_3:
	jmp	vt_CSI_done
;
; Parameter (3/0-3/15)
;
vt_CSI_Para:
	cmp	al,03ah
	jae	vt_CSI_Para1
	mov	bx,offset P_buf
	add	bx,P_pnt
	mov	cx,[bx]			; cx = previous value
	and	cx,7FFFh		; mask private parameter flag
	mov	dx,cx
	shl	dx,1
	shl	dx,1
	add	dx,cx			; dx = cx*5
	shl	dx,1			; dx = (previous value)*10
	xor	ah,ah
	sub	ax,030h
	add	ax,dx			; ax is (previous value)*10 + new
	or	ax,priv_pflg		; set private parameter flag
	mov	[bx],ax			; save it
	jmp	vt_disp_ex
vt_CSI_Para1:
	cmp	al,'?'			; Private parameter ? (3/15)
	jne	vt_CSI_Para11
	mov	priv_pflg,PRIVP_FLG
	jmp	vt_disp_ex
vt_CSI_Para11:
	add	P_pnt,2			; separator
	mov	bx,offset P_buf
	add	bx,P_pnt
	mov	word ptr [bx],0		; clear for next parameter
	jmp	vt_disp_ex
;
; Intermediate (2/0-2/15)
;
vt_CSI_Intr:
	mov	bx,offset I_buf
	add	bx,I_pnt
	mov	byte ptr [bx],al
	inc	I_pnt
	jmp	vt_disp_ex
 
;------------------------
; Do the control sequence
;------------------------
vt_CSI_do:
	cmp	al,'K'
	jne	vt_CSI_do_10
	jmp	vt_CSI_K
vt_CSI_do_10:
	cmp	al,'J'
	jne	vt_CSI_do_20
	jmp	vt_CSI_J
vt_CSI_do_20:
	cmp	al,'H'
	jne	vt_CSI_do_25
	jmp	vt_CSI_H
vt_CSI_do_25:
	cmp	al,'f'
	jne	vt_CSI_do_30
	jmp	vt_CSI_H
vt_CSI_do_30:
	cmp	al,'A'
	jb	vt_CSI_do_40
	cmp	al,'D'
	ja	vt_CSI_do_40
	jmp	vt_CSI_ABCD
vt_CSI_do_40:
	cmp	al,'r'
	jne	vt_CSI_do_50
	jmp	vt_CSI_SCR
vt_CSI_do_50:
	cmp	al,'L'
	jne	vt_CSI_do_60
	jmp	vt_CSI_L
vt_CSI_do_60:
	cmp	al,'M'
	jne	vt_CSI_do_70
	jmp	vt_CSI_M
vt_CSI_do_70:
	cmp	al,'m'
	jne	vt_CSI_do_80
	jmp	vt_CSI_CATR
vt_CSI_do_80:
	cmp	al,'c'
	jne	vt_CSI_do_90
	jmp	vt_CSI_DA
vt_CSI_do_90:
	cmp	al,'h'
	jne	vt_CSI_do_100
	jmp	vt_CSI_SET_M
vt_CSI_do_100:
	cmp	al,'l'
	jne	vt_CSI_do_110
	jmp	vt_CSI_RESET_M
vt_CSI_do_110:
	cmp	al,'n'
	jne	vt_CSI_do_120
	jmp	vt_CSI_DSR
vt_CSI_do_120:
	cmp	al,'q'
	jne	vt_CSI_do_130
	jmp	vt_CSI_LED
vt_CSI_do_130:
	cmp	al,'P'
	jne	vt_CSI_do_140
	jmp	vt_CSI_DCH
vt_CSI_do_140:
	cmp	al,'@'
	jne	vt_CSI_do_150
	jmp	vt_CSI_ICH
vt_CSI_do_150:
	cmp	al,'X'
	jne	vt_CSI_do_160
	jmp	vt_CSI_ECH
vt_CSI_do_160:
	cmp	al,'g'
	jne	vt_CSI_do_170
	jmp	vt_CSI_TBC
vt_CSI_do_170:
	cmp	al,'i'
	jne	vt_CSI_do_180
	jmp	vt_CSI_PRN
vt_CSI_do_180:
	cmp	al,'}'
	jne	vt_CSI_do_190
	jmp	vt_CSI_DECSASD
vt_CSI_do_190:
	cmp	al,'~'
	jne	vt_CSI_do_200
	jmp	vt_CSI_DECSSDT
vt_CSI_do_200:
vt_CSI_do_ex:
	jmp	vt_CSI_done
;
vt_CSI_DA:
; Device attributes
	mov	si,offset I_am_vt52
	cmp	flags.vtflg,ttvt52
	je	vt_CSI_DA_1
	mov	si,offset I_am_vt102
vt_CSI_DA_1:
	xor	cx,cx
	mov	cl,[si]
	inc	si
	mov	spec_mode,0			; done the sequence
	mov	ah,0
	ret
;
vt_CSI_DSR:
;
; Device status report
;     Host to VT             VT returns
;      CSI 5 n                CSI 0 n      no mulfunction
;                             CSI 3 n      mulfunction
;
;      CSI 6 n                CSI Pr;Pc R  cursor position is Pr(row)
;                                          Pc (column)
;
	mov	spec_mode,0		; done the sequence
	mov	si,offset P_buf		; get param. buff address
	mov	bx,[si]			; get parameter value
	cmp	bx,5
	je	vt_CSI_DSR5
	cmp	bx,6
	je	vt_CSI_DSR6
	jmp	vt_CSI_do_ex
;
vt_CSI_DSR5:
	mov	si,offset I_am_fine
	xor	cx,cx
	mov	cl,[si]
	inc	si
	mov	ah,0
	ret
vt_CSI_DSR6:
	mov	si,offset My_cursor_is
	add	si,2
	mov	cx,2
;
	xor	ax,ax
	mov	al,cur_row
	inc	ax
	cmp	ax,100
	jb	vt_CSI_DSR61
	mov	bx,100
	div	bl
	or	al,30h
	mov	byte ptr [si],al
	inc	si
	inc	cx
	mov	al,ah
	xor	ah,ah
	jmp	vt_CSI_DSR62
vt_CSI_DSR61:
	cmp	ax,10
	jb	vt_CSI_DSR63
vt_CSI_DSR62:
	mov	bx,10
	div	bl
	or	al,30h
	mov	byte ptr [si],al
	inc	si
	inc	cx
	mov	al,ah
	xor	ah,ah
vt_CSI_DSR63:
	or	al,30h
	mov	byte ptr [si],al
	inc	si
	inc	cx
;
	mov	byte ptr [si],';'
	inc	si
	inc	cx
;
	xor	ax,ax
	mov	al,cur_col
	inc	ax
	cmp	ax,100
	jb	vt_CSI_DSR64
	mov	bx,100
	div	bl
	or	al,30h
	mov	byte ptr [si],al
	inc	si
	inc	cx
	mov	al,ah
	xor	ah,ah
	jmp	vt_CSI_DSR65
vt_CSI_DSR64:
	cmp	ax,10
	jb	vt_CSI_DSR66
vt_CSI_DSR65:
	mov	bx,10
	div	bl
	or	al,30h
	mov	byte ptr [si],al
	inc	si
	inc	cx
	mov	al,ah
	xor	ah,ah
vt_CSI_DSR66:
	or	al,30h
	mov	byte ptr [si],al
	inc	si
	inc	cx
;
	mov	byte ptr [si],'R'
	inc	si
	inc	cx
;
	mov	si,offset My_cursor_is
	mov	ah,0
	ret
;
; Character attributes
;    0  All off
;    1  Bold (Highlight)
;    4  Underscored
;    5  Blinking
;    7  Reverse
;   22  Normal intensity
;   24  Not underlined
;   25  Not blinking
;   27  Positive image
; 30-37 Foreground color = 30 + colors (colors: 1=red, 2=green, 4=blue)
;
vt_CSI_CATR:
	push	cx
	push	si
 
	mov	si,offset P_buf
	mov	cx,P_pnt
	shr	cx,1
	inc	cx
vt_CSI_CATR1:
	mov	bx,[si]
	cmp	bx,0
	jne	vt_CSI_CATR2
	push	si
	mov	si,offset def_color	; reset to default color
	call	set_cur_color
	call	vt100_color
	pop	si
	call	set_gcolor
	mov	al,vt_nrmatr
	mov	vt_chratr,al
	jmp	vt_CSI_CATRX
vt_CSI_CATR2:
	cmp	bx,1
	jne	vt_CSI_CATR3
	mov	al,vt_chratr			; Bold
	and	al,01Fh
	or	al,vt_hglatr
	mov	vt_chratr,al
	jmp	vt_CSI_CATRX
vt_CSI_CATR3:
	cmp	bx,4
	jne	vt_CSI_CATR5
	or	vt_chratr,8			; Underscored
	jmp	vt_CSI_CATRX
vt_CSI_CATR5:
	cmp	bx,5
	jne	vt_CSI_CATR7
	or	vt_chratr,2			; Blinking
	jmp	vt_CSI_CATRX
vt_CSI_CATR7:
	cmp	bx,7
	jne	vt_CSI_CATR22
	test	vt_nrmatr,CHR_REV
	jz	vt_CSI_CATR7_1
	and	vt_chratr,(not CHR_REV)
	jmp	vt_CSI_CATRX
vt_CSI_CATR7_1:
	or	vt_chratr,CHR_REV
	jmp	vt_CSI_CATRX
vt_CSI_CATR22:
	cmp	bx,22
	jne	vt_CSI_CATR24
	jmp	vt_CSI_CATRX
vt_CSI_CATR24:
	cmp	bx,24
	jne	vt_CSI_CATR25
	and	vt_chratr,0F7h			; not Underscored
	jmp	vt_CSI_CATRX
vt_CSI_CATR25:
	cmp	bx,25
	jne	vt_CSI_CATR27
	and	vt_chratr,0FDh			; not blinking
	jmp	vt_CSI_CATRX
vt_CSI_CATR27:
	cmp	bx,27
	jne	vt_CSI_CATR30
	test	vt_nrmatr,CHR_REV
	jz	vt_CSI_CATR27_1
	or	vt_chratr,CHR_REV
	jmp	vt_CSI_CATRX
vt_CSI_CATR27_1:
	and	vt_chratr,(not CHR_REV)		; positive image
	jmp	vt_CSI_CATRX
vt_CSI_CATR30:
	cmp	bx,30
	jb	vt_CSI_CATR40
	cmp	bx,37
	ja	vt_CSI_CATR40
	mov	ax,bx
	sub	ax,30
	mov	bx,offset color_index_table
	add	bx,ax
	mov	al,[bx]
	push	si
	mov	si,offset scn_color
	mov	[si],al
	call	vt100_color			; set color
	pop	si
	jmp	vt_CSI_CATRX
vt_CSI_CATR40:
	cmp	bx,40
	jb	vt_CSI_CATRX
	cmp	bx,47
	ja	vt_CSI_CATRX
	mov	ax,bx
	sub	ax,40
	mov	bx,offset color_index_table
	add	bx,ax
	mov	al,[bx]
	push	si
	mov	si,offset scn_color
	mov	[si+1],al
	call	vt100_color
	pop	si
	call	set_gcolor
;
vt_CSI_CATRX:
	add	si,2
	dec	cx
	jcxz	vt_CSI_CATRXX
	jmp	vt_CSI_CATR1
vt_CSI_CATRXX:
	pop	si
	pop	cx
	jmp	vt_CSI_do_ex
 
; LED control
vt_CSI_LED:
	push	cx
	push	si
 
	mov	si,offset P_buf
	mov	cx,P_pnt
	shr	cx,1
	inc	cx
vt_CSI_LED1:
	mov	bx,[si]
	cmp	bx,0
	jb	vt_CSI_LEDX
	jne	vt_CSI_LED2
	mov	ax,'..'
	mov	bx,offset LED_buff
	mov	[bx],ax
	mov	[bx+2],ax
	jmp	vt_CSI_LED3
vt_CSI_LED2:
	cmp	bx,4
	ja	vt_CSI_LEDX
	mov	ax,bx
	dec	bx
	add	bx,offset LED_buff
	add	al,'0'
	mov	[bx],al
vt_CSI_LED3:
vt_CSI_LEDX:
	add	si,2
	loop	vt_CSI_LED1
	call	set_termnam
	call	vt100_modlin
	pop	si
	pop	cx
	jmp	vt_CSI_do_ex
 
;
; Set mode
;   2  Keyboard locked
;   4  Insert mode
;  12  Send-Receive off
;  20  LF is newline
;  ?1  Cursor Key is application
;  ?3  132 column
;  ?4  Smooth scroll
;  ?5  Reverse screen
;  ?6  Origin mode relative
;  ?7  Auto Wrap on
;  ?8  Auto repeate on
; ?18  Print form feed on
; ?19  Print extent is full screen
; ?25  Text cursor enable on
; ?38  Tektronix graphic mode
;
vt_CSI_SET_M:
	push	cx
	push	si
 
	mov	si,offset P_buf
	mov	cx,P_pnt
	shr	cx,1
	inc	cx
vt_CSI_SET_M0:
	mov	bx,[si]
vt_CSI_SET_M4:
	cmp	bx,4			; 4 = Insert mode ?
	jne	vt_CSI_SET_M5		; ne = no
	or	vt100_flags,INSERT_BIT
	jmp	vt_CSI_SET_MX
vt_CSI_SET_M5:
vt_CSI_SET_M20:
	cmp	bx,20			; 20 = Newline mode ?
	jne	vt_CSI_SET_M21		; ne = no
	or	vt100_flags,NEWLINE_BIT
	jmp	vt_CSI_SET_MX
vt_CSI_SET_M21:
;
; Private sequence
;
vt_CSI_SET_MP1:
	cmp	bx,1+PRIVP_FLG		; ?1 = Cursor key application ?
	jne	vt_CSI_SET_MP2		; ne = no
	mov	curkey_mode,1
	jmp	vt_CSI_SET_MX
vt_CSI_SET_MP2:
vt_CSI_SET_MP3:
	cmp	bx,3+PRIVP_FLG		; ?3 = 132 Column ?
	jne	vt_CSI_SET_MP4
	jmp	vt_CSI_SET_MX
vt_CSI_SET_MP4:
vt_CSI_SET_MP5:
	cmp	bx,5+PRIVP_FLG		; ?5 = reverse screen ?
	jne	vt_CSI_SET_MP6
	mov	ax,1
	call	scrn_mode
	jmp	vt_CSI_SET_MX
vt_CSI_SET_MP6:
	cmp	bx,6+PRIVP_FLG		; ?6 = Origin relative mode ?
	jne	vt_CSI_SET_MP7
	or	vt100_flags,ORIGIN_BIT
	mov	al,vt_top
	mov	cur_row,al
	mov	cur_col,0
	call	locate_cur
	jmp	vt_CSI_SET_MX
vt_CSI_SET_MP7:
	cmp	bx,7+PRIVP_FLG		; ?7 = AutoWrap ?
	jne	vt_CSI_SET_MP8
	or	vt100_flags,AUTOWRAP_BIT
	jmp	vt_CSI_SET_MX
vt_CSI_SET_MP8:
	cmp	bx,18+PRIVP_FLG		; ?18 = Print form feed
	jne	vt_CSI_SET_MP19
	or	vt100_pflag,PRINTFF_BIT
	jmp	vt_CSI_SET_MX
vt_CSI_SET_MP19:
	cmp	bx,19+PRIVP_FLG		; ?19 = Print Extent
	jne	vt_CSI_SET_MP20
	or	vt100_pflag,PRINTEXT_BIT
	jmp	vt_CSI_SET_MX
vt_CSI_SET_MP20:
vt_CSI_SET_MP38:
	cmp	bx,38+PRIVP_FLG		; ?38 = Tektronix mode
	jne	vt_CSI_SET_MP39
	pop	si
	pop	cx
	mov	spec_mode,0		; done the sequence.
	mov	vt100_gflag,4		; Tek40xx color
	mov	ah,1			; do not pass the character
	mov	al,0
	mov	cx,0
	ret
vt_CSI_SET_MP39:
vt_CSI_SET_MX:
	add	si,2
	dec	cx
	jcxz	vt_CSI_SET_MX0
	jmp	vt_CSI_SET_M0
vt_CSI_SET_MX0:
	pop	si
	pop	cx
	jmp	vt_CSI_do_ex
;
; Reset mode
;   2  Keyboard Unlocked
;   4  Replace mode
;  12  Send-Receive on
;  20  LF is line feed
;  ?1  Normal cursor key
;  ?2  Enter VT52 mode
;  ?3  80 column
;  ?4  Jump scroll
;  ?5  Normal screen
;  ?6  Orgin mode is absolute
;  ?7  Auto wrap off
;  ?8  Auto repeat off
; ?18  Print form feed off
; ?19  Print extent is scroll region
; ?25  Text cursor enable off
;
vt_CSI_RESET_M:
	push	cx
	push	si
 
	mov	si,offset P_buf
	mov	cx,P_pnt
	shr	cx,1
	inc	cx
vt_CSI_RESET_M0:
	mov	bx,[si]
vt_CSI_RESET_M4:
	cmp	bx,4			; 4 = Replace mode ?
	jne	vt_CSI_RESET_M5		; ne = no.
	and	vt100_flags,(not INSERT_BIT)
	jmp	vt_CSI_RESET_MX
vt_CSI_RESET_M5:
vt_CSI_RESET_M20:
	cmp	bx,20			; 20 = Linefeed mode ?
	jne	vt_CSI_RESET_M21	; ne = no.
	and	vt100_flags,(not NEWLINE_BIT)
	jmp	vt_CSI_RESET_MX
vt_CSI_RESET_M21:
;
; Private sequence
;
vt_CSI_RESET_MP1:
	cmp	bx,1+PRIVP_FLG		; ?1 = Normal cursor key ?
	jne	vt_CSI_RESET_MP2
	mov	curkey_mode,0
	jmp	vt_CSI_RESET_MX
vt_CSI_RESET_MP2:
	cmp	bx,2+PRIVP_FLG		; ?2 = Enter VT52 mode ?
	jne	vt_CSI_RESET_MP3
	mov	flags.vtflg,ttvt52
	call	set_termnam		; set terminal name
	call	vt100_modlin		; re-display mode line
	jmp	vt_CSI_RESET_MX
vt_CSI_RESET_MP3:
vt_CSI_RESET_MP5:
	cmp	bx,5+PRIVP_FLG		; ?5 = normal screen ?
	jne	vt_CSI_RESET_MP6
	mov	ax,0
	call	scrn_mode
	jmp	vt_CSI_RESET_MX
vt_CSI_RESET_MP6:
	cmp	bx,6+PRIVP_FLG		; ?6 = Origin absolute mode ?
	jne	vt_CSI_RESET_MP7
	and	vt100_flags,(not ORIGIN_BIT)
	mov	cur_row,0
	mov	cur_col,0
	call	locate_cur
	jmp	vt_CSI_RESET_MX
vt_CSI_RESET_MP7:
	cmp	bx,7+PRIVP_FLG
	jne	vt_CSI_RESET_MP8
	and	vt100_flags,(not AUTOWRAP_BIT)
	jmp	vt_CSI_RESET_MX
vt_CSI_RESET_MP8:
	cmp	bx,18+PRIVP_FLG
	jne	vt_CSI_RESET_MP19
	and	vt100_pflag,(not PRINTFF_BIT)
	jmp	vt_CSI_RESET_MX
vt_CSI_RESET_MP19:
	cmp	bx,19+PRIVP_FLG
	jne	vt_CSI_RESET_MP20
	and	vt100_pflag,(not PRINTEXT_BIT)
	jmp	vt_CSI_RESET_MX
vt_CSI_RESET_MP20:
vt_CSI_RESET_MX:
	add	si,2
	dec	cx
	jcxz	vt_CSI_RESET_MX0
	jmp	vt_CSI_RESET_M0
vt_CSI_RESET_MX0:
	pop	si
	pop	cx
	jmp	vt_CSI_do_ex
;
vt_CSI_ABCD:
	mov	bx,offset P_buf
	mov	bx,[bx]
	cmp	bx,1
	jae	vt_CSI_ABCD1
	mov	bx,1
vt_CSI_ABCD1:
	cmp	al,'B'
	je	vt_CSI_CUD
	cmp	al,'C'
	je	vt_CSI_CUR
	cmp	al,'D'
	je	vt_CSI_CUL
vt_CSI_CUU:
	xor	ah,ah
	mov	al,cur_row
	sub	ax,bx
	xor	bh,bh
	mov	bl,vt_top
	cmp	ax,bx
	jge	vt_CSI_CUU1
	mov	ax,bx
vt_CSI_CUU1:
	mov	cur_row,al
	jmp	vt_CSI_ABCD_ex
vt_CSI_CUD:
	xor	ah,ah
	mov	al,cur_row
	add	ax,bx
	cmp	al,vt_bottom
	jle	vt_CSI_CUD1
	mov	al,vt_bottom
vt_CSI_CUD1:
	mov	cur_row,al
	jmp	vt_CSI_ABCD_ex
vt_CSI_CUR:
	xor	ah,ah
	mov	al,cur_col
	add	ax,bx
	cmp	ax,79
	jle	vt_CSI_CUR1
	mov	ax,79
vt_CSI_CUR1:
	mov	cur_col,al
	jmp	vt_CSI_ABCD_ex
vt_CSI_CUL:
	xor	ah,ah
	mov	al,cur_col
	sub	ax,bx
	cmp	ax,0
	jge	vt_CSI_CUL1
	mov	ax,0
vt_CSI_CUL1:
	mov	cur_col,al
vt_CSI_ABCD_ex:
	call	locate_cur
	jmp	vt_CSI_do_ex
;
vt_CSI_K:
	mov	bx,offset P_buf
	mov	ax,[bx]
	cmp	ax,0
	jne	vt_CSI_K1
	mov	dh,cur_row
	mov	dl,cur_col
	call	vram_ofs
	mov	ax,bx
	mov	dh,cur_row
	mov	dl,79
	jmp	vt_CSI_KX
vt_CSI_K1:
	cmp	ax,1
	jne	vt_CSI_K2
	mov	dh,cur_row
	mov	dl,0
	call	vram_ofs
	mov	ax,bx
	mov	dh,cur_row
	mov	dl,cur_col
	jmp	vt_CSI_KX
vt_CSI_K2:
	cmp	ax,2
	jne	vt_CSI_K3
	mov	dh,cur_row
	mov	dl,0
	call	vram_ofs
	mov	ax,bx
	mov	dh,cur_row
	mov	dl,79
	jmp	vt_CSI_KX
vt_CSI_K3:
	jmp	vt_CSI_do_ex
vt_CSI_KX:
	call	vram_ofs
	call	vt_erase
	jmp	vt_CSI_do_ex
;
vt_CSI_L:
	mov	al,cur_row
	cmp	al,vt_top
	jge	vt_CSI_L01
	jmp	vt_CSI_do_ex
vt_CSI_L01:
	cmp	al,vt_bottom
	jle	vt_CSI_L02
	jmp	vt_CSI_do_ex
vt_CSI_L02:
	mov	bx,offset P_buf
	mov	cx,[bx]
	cmp	cx,0
	jg	vt_CSI_L1
	mov	cx,1
vt_CSI_L1:
	mov	ah,vt_bottom
	call	scroll_down
	mov	cur_col,0
	call	locate_cur
	jmp	vt_CSI_do_ex
 
vt_CSI_M:
	mov	al,cur_row
	cmp	al,vt_top
	jge	vt_CSI_M01
	jmp	vt_CSI_do_ex
vt_CSI_M01:
	cmp	al,vt_bottom
	jle	vt_CSI_M02
	jmp	vt_CSI_do_ex
vt_CSI_M02:
	mov	bx,offset P_buf
	mov	cx,[bx]
	cmp	cx,0
	jg	vt_CSI_M1
	mov	cx,1
vt_CSI_M1:
	mov	ah,vt_bottom
	call	scroll_up
	mov	cur_col,0
	call	locate_cur
	jmp	vt_CSI_do_ex
 
vt_CSI_J:
	mov	bx,offset P_buf
	mov	ax,[bx]
	cmp	ax,0
	jg	vt_CSI_J1
	mov	dh,cur_row
	mov	dl,cur_col
	call	vram_ofs
	mov	ax,bx
	mov	dh,vt_phys_bottom
	mov	dl,79
	call	vram_ofs
	jmp	vt_CSI_JX
vt_CSI_J1:
	cmp	ax,1
	jg	vt_CSI_J2
	mov	dh,0
	mov	dl,0
	call	vram_ofs
	mov	ax,bx
	mov	dh,cur_row
	mov	dl,cur_col
	call	vram_ofs
	jmp	vt_CSI_JX
vt_CSI_J2:
	cmp	sixel_disp_on,1
	jne	vt_CSI_J2_1
	call	sixel_clear
	mov	vt100_gflag,1
	mov	sixel_disp_on,0
vt_CSI_J2_1:
	mov	dh,0
	mov	dl,0
	call	vram_ofs
	mov	ax,bx
	mov	dh,vt_phys_bottom
	mov	dl,79
	call	vram_ofs
vt_CSI_JX:
	call	vt_erase
	jmp	vt_CSI_do_ex
;
; Cursor Position CUP    CSI Pl ; Pc H
;
vt_CSI_H:
	mov	bx,offset P_buf
	mov	ax,[bx]
	cmp	ax,1
	jae	vt_CSI_H1
	mov	ax,1
vt_CSI_H1:
	test	vt100_flags,ORIGIN_BIT	; relative mode ?
	jz	vt_CSI_H2		; z = no.
	add	al,vt_top		; convert to absolute
	cmp	al,vt_bottom
	jbe	vt_CSI_H3
	mov	al,vt_bottom
	jmp	vt_CSI_H31
vt_CSI_H2:
	cmp	ax,24
	jbe	vt_CSI_H3
	mov	ax,24
vt_CSI_H3:
	dec	ax
vt_CSI_H31:
	mov	cur_row,al
	xor	ax,ax
	cmp	P_pnt,2
	jb	vt_CSI_H6
	mov	ax,[bx+2]
	cmp	ax,1
	jae	vt_CSI_H4
	mov	ax,1
vt_CSI_H4:
	cmp	ax,80
	jbe	vt_CSI_H5
	mov	ax,80
vt_CSI_H5:
	dec	ax
vt_CSI_H6:
	mov	cur_col,al
;
;	put the CR/LF for the cooked log.
;
	cmp	vt100_lflag,(LOGCOOK_BIT+LOGENAB_BIT)
	jne	vt_CSI_H61
;@@	cmp	al,0
;@@	jne	vt_CSI_H61
	mov	al,0Dh		; put CR
	call	outcapt
	mov	al,0Ah		; put LF
	call	outcapt
vt_CSI_H61:
;
	call	locate_cur
	jmp	vt_CSI_do_ex
 
;
; Chracter editing functions
;   CSI Pn @     ICH           Inserts Pn blank characters
;   CSI Pn P     DCH           Deletes Pn characters
;   CSI Pn X     ECH           Erases Pn characters
; In each function, action starts from current cursor position
; and the cursor does not move.
;
 
; Insert characters (ICH) -- CSI Pn @
 
vt_CSI_ICH:
vt_CSI_ICH1:
	mov	bx,offset P_buf		; get the address of the parameter
	mov	cx,[bx]			; get the parameter value
	cmp	cx,0
	jg	vt_CSI_ICH2
	mov	cx,1			; use default
vt_CSI_ICH2:
	std				; backward direction
	mov	dl,79			; set destination (row,col)
	mov	dh,cur_row
	call	vram_ofs
	mov	di,bx			; set destination address
	xor	ax,ax
	mov	al,cur_col
	mov	bx,ax			; save column position
	add	ax,cx			; ax = cur_col + Pn
	cmp	ax,79			; inside the right margin ?
	jle	vt_CSI_ICH3		; le = Yes.
	mov	cx,80
	sub	cx,bx			; cx = 80 - cur_col
	jmp	vt_CSI_ICH4
vt_CSI_ICH3:
	push	cx			; save Pn
	mov	dx,79
	sub	dx,cx			; dx = 79 - Pn
	mov	dh,cur_row
	call	vram_ofs		; get VRAM offset address
	mov	si,bx			; set source address
	mov	cx,80
	sub	cx,ax			; cx = 80 - cur_col - Pn
	mov	ax,CRT_TXT_SEG
	push	es			; save segment registers
	push	ds
	mov	es,ax			; set segment registers
	mov	ds,ax
	push	si
	push	di
	push	cx
	rep	movsw			; move the characters
	pop	cx
	pop	di
	pop	si
	add	di,2000h		; attribute area
	add	si,2000h
	rep	movsw			; move the attributes
	sub	di,2000h
	pop	ds
	pop	es
	pop	cx			; restore Pn
vt_CSI_ICH4:
	push	es
	push	cx
	push	di
	mov	ax,CRT_TXT_SEG
	mov	es,ax
	mov	ax,20h			; set blank code
	rep	stosw
	pop	di
	pop	cx
	add	di,2000h		; attribute area
	mov	al,vt_nrmatr		; set normal attributes
	rep	stosw
	pop	es
	cld				; reset direction flag
	jmp	vt_CSI_do_ex
 
 
; Delete characters (DCH) -- CSI Pn P
 
vt_CSI_DCH:
vt_CSI_DCH1:
	mov	bx,offset P_buf		; get the address of the parameter
	mov	cx,[bx]			; get the parameter value
	cmp	cx,0
	jg	vt_CSI_DCH2
	mov	cx,1			; use default
vt_CSI_DCH2:
	cld
	xor	ax,ax
	mov	al,cur_col
	mov	dh,cur_row
	mov	dl,cur_col
	call	vram_ofs		; get the destination address
	mov	di,bx			; set the destination address
	mov	bx,ax			; save column position
	add	ax,cx			; ax = cur_col + Pn
	cmp	ax,79			; inside the right margin ?
	jle	vt_CSI_DCH3		; le = Yes.
	mov	cx,80
	sub	cx,bx			; cx = 80 - cur_col
	jmp	vt_CSI_DCH4
vt_CSI_DCH3:
	push	cx
	mov	cx,80
	sub	cx,ax			; cx = 80 - cur_col - Pn
	mov	dh,cur_row		; set curosr pointer
	mov	dl,al
	call	vram_ofs		; get VRAM offset address
	mov	si,bx			; set the source address
	mov	ax,CRT_TXT_SEG
	push	es			; save segment registers
	push	ds
	mov	es,ax			; set segment registers
	mov	ds,ax
	push	si
	push	di
	push	cx
	rep	movsw			; move the characters
	pop	cx
	pop	di
	pop	si
	add	di,2000h
	add	si,2000h
	rep	movsw			; move the attributes
	sub	di,2000h
	pop	ds
	pop	es
	pop	cx
vt_CSI_DCH4:
	push	es
	push	cx
	push	di
	mov	ax,CRT_TXT_SEG
	mov	es,ax
	mov	ax,20h			; set blank code
	rep	stosw
	pop	di
	pop	cx
	add	di,2000h
	mov	al,vt_blkatr		; set blank attributes
	rep	stosw
	pop	es
	jmp	vt_CSI_do_ex
 
 
; Erase characters (ECH) -- CSI Pn X
 
vt_CSI_ECH:
vt_CSI_ECH1:
	mov	bx,offset P_buf		; get the address of the parameter
	mov	cx,[bx]			; get the parameter value
	cmp	cx,0
	jg	vt_CSI_ECH2
	mov	cx,1			; use default
vt_CSI_ECH2:
	cld
	xor	ax,ax
	mov	al,cur_col
	mov	dh,cur_row
	mov	dl,cur_col
	call	vram_ofs		; get the destination address
	mov	di,bx			; set the destination address
	mov	bx,ax			; save column position
	add	ax,cx			; ax = cur_col + Pn
	cmp	ax,79			; inside the right margin ?
	jle	vt_CSI_ECH3		; le = Yes.
	mov	cx,80
	sub	cx,bx			; cx = 80 - cur_col
vt_CSI_ECH3:
	push	es
	push	cx
	push	di
	mov	ax,CRT_TXT_SEG
	mov	es,ax
	mov	ax,20h			; set blank code
	rep	stosw
	pop	di
	pop	cx
	add	di,2000h
	mov	al,vt_nrmatr		; set normal attributes
	rep	stosw
	pop	es
	jmp	vt_CSI_do_ex
 
;  Tabulation Clear (TBC)
;    CSI g
;    CSI 0 g	Clears a horizontal tab stop at cursor position
;    CSI 3 g	Clears all horizontal tab stops

vt_CSI_TBC:
	mov	bx,offset P_buf
	mov	ax,[bx]			; get the parameter value
	cmp	ax,0			; zero ?
	je	vt_CSI_TBC0		; e = yes.
	cmp	ax,3			; 3 ?
	je	vt_CSI_TBC3		; e = yes.
	jmp	vt_CSI_do_ex		; not supported
;
vt_CSI_TBC0:
	xor	ax,ax
	mov	al,cur_col		; get current cursor position
	mov	bx,offset tabstops
	add	bx,ax
	mov	byte ptr [bx],0		; clear the tab
	jmp	vt_CSI_do_ex
;
vt_CSI_TBC3:
	push	es
	push	di
	mov	ax,ds
	mov	es,ax			; set destination segment
	mov	di,offset tabstops	; set destination offset
	mov	cx,80			; number of bytes
	mov	ax,0			; data = 0
	cld
	rep	stosb			; store it
	pop	di
	pop	es
	jmp	vt_CSI_do_ex
 
;  Printer control
;    * not implemented yet
;    CSI i	Prints the screen (full/scroll region) display.
;    CSI 0 i	Same as above.
;  * CSI 4 i	Turns off printer controller mode.
;  * CSI 5 i	Turns on printer controller mode (transparent printing).
;    CSI ? 1 i	Prints the display line containing the cursor.
;    CSI ? 4 i	Turns off auto print mode.
;    CSI ? 5 i	Turns on auto print mode.
;

vt_CSI_PRN:
	mov	bx,offset P_buf
	mov	ax,[bx]			; get the parameter value
	cmp	ax,0			; 0
	je	vt_CSI_PRN_S0		; e = yes.
	cmp	ax,1+PRIVP_FLG		; ?1
	je	vt_CSI_PRN_P1		; e = yes.
	cmp	ax,4+PRIVP_FLG		; ?4
	je	vt_CSI_PRN_P4		; e = yes.
	cmp	ax,5+PRIVP_FLG		; ?5 ?
	je	vt_CSI_PRN_P5		; e = yes.
	jmp	vt_CSI_do_ex		; not supported
;
vt_CSI_PRN_S0:
	call	vt100_prns
	jmp	vt_CSI_do_ex
;
vt_CSI_PRN_P1:
	test	vt100_pflag,AUTOPRINT_BIT	; printer off?
	jnz	vt_CSI_PRN_P1_1		; nz = no not. it is on.
	call	prn_chk			; check the printer port
	jc	vt_CSI_PRN_P1_2		; c = not ready.
vt_CSI_PRN_P1_1:
	call	vt100_prnl
vt_CSI_PRN_P1_2:
	jmp	vt_CSI_do_ex
;
vt_CSI_PRN_P4:
	and	vt100_pflag,(not AUTOPRINT_BIT)	; turns off the printer
	call	set_prnstat		; show printer status
	call	vt100_modlin		; re-display mode line
	jmp	vt_CSI_do_ex
;
vt_CSI_PRN_P5:
	test	vt100_pflag,AUTOPRINT_BIT	; printer off?
	jnz	vt_CSI_PRN_P5_1		; nz = no not. do nothing.
	call	prn_chk			; check the printer port
	jc	vt_CSI_PRN_P5_1		; c = not ready.
	or	vt100_pflag,AUTOPRINT_BIT	; turns on auto print
	call	set_prnstat			; show printer status
	call	vt100_modlin		; re-display mode line
vt_CSI_PRN_P5_1:
	jmp	vt_CSI_do_ex
 
;  Set scroll region.
;  It is NOT clear that this command affects the cursor position
;  or not.  In my experence, cursor moves to the left-top corner of the
;  entire screen (i.e., same as <ESC>[1;1H ).
;  - The above statement was wrong. In ORIGIN mode, the cursor goes to
;    left-top corner of the scroll region. Thanx for VTTEST. [01-Oct-88].
;  - Bugs for funny scroll region are fixed. Thanx for VTTEST. [01-Oct-88].
;  - Bug for ESC[;r is fixed. [03-Dec-88].
 
vt_CSI_SCR:
	mov	bx,offset P_buf
	cmp	P_pnt,2			; have good number of parameters ?
	je	vt_CSI_SCR1		; e = yes.
	ja	vt_CSI_SCR7		; a = too many. Ignore. [03-Dec-88].
	mov	ax,[bx]
	mov	bx,24			; set to default
	jmp	vt_CSI_SCR2
vt_CSI_SCR1:
	mov	ax,[bx]
	mov	bx,[bx+2]
vt_CSI_SCR2:
	cmp	ax,1
	jae	vt_CSI_SCR3
	mov	ax,1
vt_CSI_SCR3:
	cmp	bx,0			; Pb = 0? [03-Dec-88]
	ja	vt_CSI_SCR31		; a = no. [03-Dec-88]
	mov	bx,24			; set to default. [03-Dec-88].
	jmp	vt_CSI_SCR4		; [03-Dec-88].
vt_CSI_SCR31:				; [03-Dec-88].
	cmp	bx,24
	jbe	vt_CSI_SCR4
	mov	bx,24
vt_CSI_SCR4:
	cmp	ax,bx			; Pt < Pb ?
	jae	vt_CSI_SCR7		; ae = no. Do nothing.
vt_CSI_SCR5:
	dec	ax
	dec	bx
	mov	vt_top,al
	mov	vt_bottom,bl
	test	vt100_flags,ORIGIN_BIT	; origin relative mode ?
	jnz	vt_CSI_SCR6		; nz = Yes. Use vt_top.
	mov	ax,0
vt_CSI_SCR6:
	mov	cur_row,al
	mov	cur_col,0
	call	locate_cur
vt_CSI_SCR7:
	jmp	vt_CSI_do_ex
;
vt_CSI_DECSASD:
	cmp	I_pnt,1			; requires 1 intermediate char.
	je	vt_CSI_DECSASD_1	; e=yes, we have.
	jmp	vt_CSI_do_ex
vt_CSI_DECSASD_1:
	cmp	I_buf,'$'		; required character ?
	je	vt_CSI_DECSASD_2	; e=yes, we have.
	jmp	vt_CSI_do_ex
vt_CSI_DECSASD_2:
	mov	ax,P_buf		; P_buf always has at least 0.
	cmp	ax,0
	je	vt_CSI_DECSASD_3
	jmp	vt_CSI_DECSASD_5
;
vt_CSI_DECSASD_3:
	cmp	vt_in_stat,0		; already in main screen ?
	jne	vt_CSI_DECSASD_4
	jmp	vt_CSI_do_ex
vt_CSI_DECSASD_4:
	mov	vt_in_stat,0
	mov	al,cur_row
	mov	stat_row,al
	mov	al,cur_col
	mov	stat_col,al
	mov	al,text_row
	mov	cur_row,al
	mov	al,text_col
	mov	cur_col,al
	mov	al,text_top
	mov	vt_top,al
	mov	al,text_bottom
	mov	vt_bottom,al
	call	locate_cur
	jmp	vt_CSI_do_ex
;
vt_CSI_DECSASD_5:
	cmp	vt_in_stat,1		; already in status line ?
	jne	vt_CSI_DECSASD_6
	jmp	vt_CSI_do_ex
vt_CSI_DECSASD_6:
	cmp	vt_stat_type,2		; host writable status line ?
	je	vt_CSI_DECSASD_7	; e=yes.
	jmp	vt_CSI_do_ex
vt_CSI_DECSASD_7:
	mov	vt_in_stat,1
	mov	al,cur_row
	mov	text_row,al
	mov	al,cur_col
	mov	text_col,al
	mov	al,vt_top
	mov	text_top,al
	mov	al,vt_bottom
	mov	text_bottom,al
;
	mov	al,stat_col
	mov	cur_col,al
	mov	al,stat_row
	mov	cur_row,al
	mov	vt_top,al
	mov	vt_bottom,al
	call	locate_cur
	jmp	vt_CSI_do_ex
;
vt_CSI_DECSSDT:
	cmp	I_pnt,1			; requires 1 intermediate char.
	je	vt_CSI_DECSSDT_1	; e=yes, we have.
	jmp	vt_CSI_do_ex
vt_CSI_DECSSDT_1:
	cmp	I_buf,'$'		; required character ?
	je	vt_CSI_DECSSDT_2	; e=yes, we have.
	jmp	vt_CSI_do_ex
vt_CSI_DECSSDT_2:
	mov	ax,P_buf		; P_buf always has at least 1 param.
	cmp	ax,2			; allowed parameter?
	jbe	vt_CSI_DECSSDT_3	; be=yes.
	jmp	vt_CSI_do_ex
vt_CSI_DECSSDT_3:
	cmp	al,vt_stat_type		; same type?
	jne	vt_CSI_DECSSDT_4	; ne=no.
	jmp	vt_CSI_do_ex
vt_CSI_DECSSDT_4:
	cmp	ax,2			; host writable ?
	jne	vt_CSI_DECSSDT_5	; ne=no.
	push	ax
	mov	al,vt_blkatr
	call	vt_stat_clr		; clear status line
	pop	ax
	mov	stat_col,0		; cursor move to left margin
vt_CSI_DECSSDT_5:
	mov	vt_stat_type,al
	call	vt100_modlin
	jmp	vt_CSI_do_ex
;
; Erase from VRAM address AX to BX
;
vt_erase:
	cld
	push	es
	mov	cx,bx
	sub	cx,ax
	shr	cx,1
	inc	cx
	mov	di,ax
	push	cx
	push	di
	mov	ax,CRT_TXT_SEG
	mov	es,ax
	mov	ax,0020h
	rep	stosw
	pop	di
	add	di,2000h
	pop	cx
	xor	ah,ah
	mov	al,vt_blkatr
	rep	stosw
	pop	es
	ret
 
;-------------
; Scroll-down
;-------------
; scroll down n-lines in the region [Pt,Pb].  The cursor does not move.
;
; Input paramters:
;	al: top row position Pt
;	ah: bottom row position Pb
;	cl: number of lines n (must be > 0)
; Registers:
;	ax, bx, cx, dx, si, di are broken
 
scroll_down:
	mov	bl,ah
	sub	bl,al
	cmp	cl,bl			; n <= bottom - top ?
	jle	scroll_down_2		; yes, text remains.
	jmp	scroll_down_3		; no text remains.
scroll_down_2:
	mov	dh,ah
	sub	dh,cl
	mov	dl,79
	call	vram_ofs
	mov	si,bx			; si is VRAM(bottom-n,79)
	mov	dh,al
	xor	dl,dl
	call	vram_ofs
	mov	cx,si
	sub	cx,bx
	shr	cx,1			; byte counts -> word counts
	inc	cx			; number of words to be moved
	mov	dh,ah
	mov	dl,79
	call	vram_ofs
	mov	di,bx			; di is VRAM(bottom,79)
	push	es
	push	ds
	mov	ax,CRT_TXT_SEG
	mov	bl,vt_blkatr		; save attribute before ds cahnge
	mov	es,ax
	mov	ds,ax
	push	cx			; save word count
	push	di			; save destination address
	push	si			; save source address
	std
	rep	movsw			; move the text codes
	mov	cx,di
	sub	cx,si
	shr	cx,1
	mov	ax,0020h		; fill blank
	rep	stosw
;
	pop	si
	pop	di
	pop	cx			; cx, si, di are restored
	add	di,2000h		; attribute block
	add	si,2000h
	rep	movsw			; move the attributes
	mov	cx,di
	sub	cx,si
	shr	cx,1
	mov	al,bl			; fill attributes
	xor	ah,ah
	rep	stosw
;
	cld
	pop	ds
	pop	es
	jmp	scroll_down_ex
scroll_down_3:
	mov	dh,al
	xor	dl,dl
	call	vram_ofs
	mov	cx,bx
	mov	dh,ah
	mov	dl,79
	call	vram_ofs
	mov	ax,cx
	call	vt_erase
scroll_down_ex:
	ret
;
;-----------
; Scroll-up
;-----------
; scroll up n-lines in the region [Pt,Pb].  The cursor does not move.
;
; Input paramters:
;	al: top row position Pt
;	ah: bottom row position Pb (ah must be > al)
;	cl: number of lines n (must be > 0)
; Registers:
;	ax, bx, cx, dx, si, di are broken
 
scroll_up:
	cmp	al,0
	jne	scroll_up_1
	call	mrsave			; save into roll buffer
scroll_up_1:
	mov	bl,ah
	sub	bl,al
	cmp	cl,bl			; n <= bottom - top ?
	jle	scroll_up_2		; yes, text remains.
	jmp	scroll_up_3		; no text remains.
scroll_up_2:
	mov	dh,al
	add	dh,cl
	xor	dl,dl
	call	vram_ofs
	mov	si,bx			; si is VRAM(top+n,0)
	mov	dh,ah
	xor	dl,79
	call	vram_ofs
	mov	cx,bx
	sub	cx,si
	shr	cx,1			; byte counts -> word counts
	inc	cx			; number of words to be moved
	mov	dh,al
	xor	dl,dl
	call	vram_ofs
	mov	di,bx			; di is VRAM(top,0)
	push	es
	push	ds
	mov	ax,CRT_TXT_SEG
	mov	bl,vt_blkatr		; save attribute before ds cahnge
	mov	es,ax
	mov	ds,ax
	push	cx			; save word count
	push	di			; save destination address
	push	si			; save source address
	cld
	rep	movsw			; move the text codes
	mov	cx,si
	sub	cx,di
	shr	cx,1
	mov	ax,0020h		; fill blank
	rep	stosw
;
	pop	si
	pop	di
	pop	cx			; cx, si, di are restored
	add	di,2000h		; attribute block
	add	si,2000h
	rep	movsw			; move the attributes
	mov	cx,si
	sub	cx,di
	shr	cx,1
	mov	al,bl			; fill attributes
	xor	ah,ah
	rep	stosw
;
	cld
	pop	ds
	pop	es
	jmp	scroll_up_ex
scroll_up_3:
	mov	dh,al
	xor	dl,dl
	call	vram_ofs
	mov	cx,bx
	mov	dh,ah
	mov	dl,79
	call	vram_ofs
	mov	ax,cx
	call	vt_erase
scroll_up_ex:
	ret
 
;
; Calculate VRAM offset address from (col,row)
; Inputs:
;   dh: row (0-vt_phys_bottom)
;   dl: col (0-79)
; Output:
;   bx: VRAM offset address
;
; dx is broken when return
 
vram_ofs:
	xor	bx,bx
	mov	bl,dh
	shl	bx,1
	add	bx,offset vram_line
	mov	bx,[bx]
	xor	dh,dh
	shl	dl,1
	add	bx,dx
	ret
 
; C1 8-bit control character
 
;-----------------------------
; Single shift 2 (8/14); ESC N
;-----------------------------
; Temporarily invokes G2 character set into GL for the next graphic
; character.

vt_c1_SS2:
	mov	char_SS,offset char_G2
	jmp	vt_esc_done

;-----------------------------
; Single shift 3 (8/15); ESC O
;-----------------------------
; Temporarily invokes G3 character set into GL for the next graphic
; character.

vt_c1_SS3:
	mov	char_SS,offset char_G3
	jmp	vt_esc_done

;----------------------
; Index ( 8/4 ); ESC D
;----------------------
; Moves the cursor down one line in the same column.  If the cursor
; is at the bottom margin, the screen perform a scroll-up.
 
vt_c1_IND:
	mov	ah,cur_row
	cmp	ah,vt_bottom
	jl	vt_c1_IND_1
	je	vt_c1_IND_2
	jmp	vt_esc_done
vt_c1_IND_1:
	inc	ah
	mov	cur_row,ah
	call	locate_cur
	jmp	vt_esc_done
vt_c1_IND_2:
	mov	al,vt_top
	mov	cx,1
	call	scroll_up
	jmp	vt_esc_done
 
;-------------------------------
; Reverse index ( 8/13 ); ESC M
;-------------------------------
; Moves the cursor up one line in the same column.  If the cursor is
; at the top margin, the screen performs a scroll-down.
 
vt_c1_RI:
	mov	al,cur_row
	cmp	al,vt_top
	jg	vt_c1_RI_1
	je	vt_c1_RI_2		; [04-Aug-1989]
	cmp	al,0			; [04-Aug-1989]
	jg	vt_c1_RI_1		; [04-Aug-1989]
	jmp	vt_esc_done		; [04-Aug-1989]
vt_c1_RI_1:
	dec	al
	jmp	vt_c1_RI_3
vt_c1_RI_2:
	mov	al,vt_top
	mov	ah,vt_bottom
	mov	cx,1
	call	scroll_down
	mov	al,vt_top
vt_c1_RI_3:
	mov	cur_row,al
	call	locate_cur
	jmp	vt_esc_done
 
;--------------------------
; Next line ( 8/5 ); ESC E
;--------------------------
; Moves the cursor to the first position on the next line.
; If the cursor is at the bottom margin, the screen performs a
; scroll-up.
 
vt_c1_NEL:
	mov	ah,cur_row
	cmp	ah,vt_bottom
	jl	vt_c1_NEL_1
	je	vt_c1_NEL_2
	cmp	ah,vt_phys_bottom	; [04-Aug-1989]
	jl	vt_c1_NEL_1		; [04-Aug-1989]
	jmp	vt_esc_done
vt_c1_NEL_1:
	inc	ah
	mov	cur_row,ah
	mov	cur_col,0
	call	locate_cur
	jmp	vt_esc_done
vt_c1_NEL_2:
	mov	al,vt_top
	mov	cx,1
	call	scroll_up
	mov	cur_col,0
	call	locate_cur
	jmp	vt_esc_done
 
;----------------------------------
; Horizontal tab set (8/08); ESC H
;----------------------------------
vt_c1_HTS:
	xor	ax,ax
	mov	al,cur_col
	mov	bx,offset tabstops
	add	bx,ax			; tab pointer
	mov	byte ptr [bx],1
	jmp	vt_esc_done
;
;-------------------------------------------
; Device Control String (9/0); ESC P
;-------------------------------------------
vt_c1_DCS:
	mov	spec_mode,in_DCS_MODE
	mov	P_pnt,0
	mov	bx,offset P_buf
	mov	word ptr [bx],0
	mov	I_pnt,0
	mov	bx,offset I_buf
	mov	byte ptr [bx],0
	mov	priv_pflg,0
	jmp	vt_disp_ex
;
;-------------------------------------------
; Control Sequence Introducer (9/11); ESC [
;-------------------------------------------
vt_c1_CSI:
	mov	spec_mode,in_CSI_MODE
	mov	P_pnt,0
	mov	bx,offset P_buf
	mov	word ptr [bx],0
	mov	I_pnt,0
	mov	bx,offset I_buf
	mov	byte ptr [bx],0
	mov	priv_pflg,0
	jmp	vt_disp_ex
;
;-------------------------------------------
; String Terminator (9/12); ESC \
;-------------------------------------------
vt_c1_ST:
	mov	spec_mode,0
	jmp	vt_disp_ex
;
VT100	ENDP
 
code	ends
	end
