Category : Alternate Operating Systems - Quarterdeck DesqView, CP/M, etc
Archive   : VMIXUTL.ZIP
Filename : VT.ASM

 
Output of file : VT.ASM contained in archive : VMIXUTL.ZIP
PAGE 57, 132
TITLE vt.asm
COMMENT #

*************** Copyright (C) 1985 - 1992 by J. Anthony Borras ***************

DATE: Apr. 24, 1991 02-16-91

NAME: VMiX 386 remote session communications program

USAGE:

FUNCTION:

C - CALL:
N/A

RETURNS:
N/A

*****************************************************************************#

.SALL ;Supress MACRO listings

SUBTITLE MACRO STRING ;Change the subtitle but
;don't display SUBTTL command
SUBTTL STRING
.LIST
PAGE
ENDM

PRINT MACRO STRING ;Print a string
MOV DX,offset STRING
MOV AH,09
INT 21h
ENDM

; external SYSGATE variables

BIOS_DATA_AREA SEGMENT at 0040h
EXTRN _io0b_activepg:byte ;active video RAM page
EXTRN _io0us_addr6845:word ;CRT controller port
EXTRN _io0ai_addrcomm:word ;comm port addresses
EXTRN bios_brkkey:byte ;bios break key state
EXTRN bios_ret_off:word ;bios re-entry pointer
EXTRN bios_ret_seg:word
EXTRN char_bytes:word ;bytes per character
EXTRN crtc_biosinfo:dword ;video parameters pointer
EXTRN _io0ui_crtcinfo:word ;video control states
EXTRN _io0b_crtpalett:byte ;color select register 0x3D9
EXTRN cursor_start:word
EXTRN _io0ui_extkbd:word ;extended kb state
EXTRN _io0ui_kbdstat:word ;current console kb state
EXTRN last_row:byte ;number of rows - 1
EXTRN mode_6845:byte
EXTRN _io0b_prtstat:byte ;PrtSc status
EXTRN _io0ui_regenbuf:word
EXTRN _io0ui_regenlen:word
EXTRN screen_width:word
EXTRN _ker0ui_stathw:word ;installed hardware
EXTRN _mem0ui_sysmsiz:word ;installed system memory
EXTRN _io0b_tcurx:byte ;current cursor position
EXTRN _io0b_tcury:byte
EXTRN _sch0ul_tmtick:dword ;time of day timer tick
EXTRN _io0b_vmode:byte ;last load to mode register
EXTRN _ker0us_xbioseg:word ;extended BIOS data segment
BIOS_DATA_AREA ends

; external SYSGATE functions

EXTRN _sys_version:far ;VMiX MEMORY API CALLS
EXTRN _sys_chanreq:far
EXTRN _sys_clrwindow:far
EXTRN _sys_getccb:far
EXTRN _sys_getpcb:far
EXTRN _sys_getpid:far
EXTRN _sys_getqkey:far
EXTRN _sys_getqueue:far
EXTRN _sys_memreq:far
EXTRN _sys_scrollwin:far
EXTRN _sys_setbwindow:far
EXTRN _sys_sysreq:far

; GENERAL DEFINES

eos EQU 0
false EQU 0
true EQU 01
bell EQU 07
bsp EQU 08
tab EQU 09
lf EQU 0Ah
cr EQU 0Dh
blank EQU 20h
eom EQU 24h
xsc EQU 1Bh
double_quote EQU 22h
single_quote EQU 27h
escbufsiz EQU 16

; VIRTUAL MACHINE DEFINES

clock EQU 08 ;clock 8259 IREQ0 INT 08
kbd_io EQU 09 ;keybd 8259 IREQ1 INT 09
com2_io EQU 0Bh ;COM2 8259 IREQ3 INT 0Bh
com1_io EQU 0Ch ;COM1 8259 IREQ4 INT 0Ch
prt2_io EQU 0DH ;printer2 IREQ5 INT 0Dh
fdsk_io EQU 0Eh ;floppydisk IREQ6 INT 0Eh
prt1_io EQU 0Fh ;printer1 IREQ7 INT 0Fh
video_io EQU 10h ;video BIOS Routine INT 10h
dsk_bufio EQU 13h ;disk BIOS Routine INT 13h
tty_bufio EQU 14h ;RS232 BIOS Routine INT 14h
system EQU 15h ;VMiX system service INT 15h
kbd_bufio EQU 16h ;keybd BIOS Routine INT 16h
prt_bufio EQU 17h ;printer BIOS RoutineINT 17h
break EQU 1Bh ;Ctrl Break Routine INT 1Bh
fdos EQU 21h ;MSDOS function call INT 21h

; PROTOCOL FUNCTION CODES

RECV_REPLY EQU 01
SEND_REPLY EQU 02

; VMiX DATA STRUCTURES

CCX struc ;full chan control block
DD ?
DD ?
DW 4 dup(?)
call_uid DW ?
DD ?
DW ?
irptr DD ?
CCX ends

IRX struc ;full I/O request packet
DD ?
DD ?
chan DW ?
DW ?
iosl DD ?
ocptr DD ?
calluid DW ?
DW 7 dup(?)
vcurx DB ?
vcury DB ?
DW 03 dup(?)
wintop DW ?
winbot DW ?
ihead DW ?
itail DW ?
ibuffer DD ?
ibuflen DW ?
DW 8 dup(?)
activpg DB ?
swappg DB ?
colorbg DB ?
colorwn DB ?
activmod DB ?
swapvmod DB ?
vpbufsiz DW ?
hvpbuf DW ?
callend DD ?
IRX ends

OCX struc ;partial object control block
DW 30 dup(?)
obj_putc DD ?
OCX ends

PCX struc ;partial process control block
pstate DW ?
prvlev DW ?
base_pprio DW ?
curr_pprio DW ?
psl DD ?
channel DW ?
altchan DW ?
DW 27 dup(?)
mcbhead DW ?
hvptab DW ?
currdta DD ?
currpsp DW ?
prevpsp1 DW ?
prevpsp2 DW ?
currdrv DW ?
currdir DD ?
DW 31 dup(?)
kbdevent DD ?
kbdbufio DD ?
PCX ends

TDB struc ;terminal description block
tty_hm DW 001Eh
DW 0
tty_clr DW 1B2Ah
DW 0
tty_eos DW 1B59h
DW 0
tty_eol DW 1B54h
DW 0
tty_pos DW 1B3Dh
DW 0
tty_win DW 0
DW 0
TDB ends


SUBTTL segments
PAGE

CSEG SEGMENT PARA PUBLIC 'CODE'

assume cs:CSEG,ds:DSEG,es:nothing

vt proc far ;entry point
PUSH DS
PUSH ES
MOV AX,DSEG
MOV DS,AX ;make our data addressable
MOV ES,AX
XOR DX,DX
CALL far ptr _sys_version

;VMiX not present
;exit the terminal emulator

CMP DX,1944
JZ vt1
PRINT BAD_DOS_MSG
JMP vt9

vt1: ;initialize
CALL get_biosdata ;get video data
PUSH DS
PUSH ES
CALL _sys_getpid ;get ourselves first

PUSH AX ;current PID
MOV currpid,AX
MOV CS:[pcktdata],AX
CALL _sys_getpcb ;our process block
ADD SP,02

MOV pptroff,AX
MOV pptrseg,DX
MOV BX,AX
MOV ES,DX
MOV AX,ES:[BX].channel
MOV schan,AX
PUSH AX ;stdio channel
CALL _sys_getccb ;our channel block
ADD SP,02

MOV cptroff,AX
MOV cptrseg,DX
MOV BX,AX
MOV ES,DX
MOV AX,word ptr ES:[BX].irptr
MOV DX,word ptr ES:[BX + 02].irptr
MOV irpoff,AX
MOV irpseg,DX
MOV BX,AX
MOV ES,DX
MOV AL,ES:[BX].colorbg ;current attribute
CMP vmode,04
JB @F
CMP vmode,07
JZ @F
MOV AL,55h
MOV ES:[BX].colorbg,AL ;current attribute
@@:
MOV attribute,AL
MOV AX,ES:[BX].winbot
CMP AH,24
JB @F
MOV AH,23
; MOV ES:[BX].winbot,AX
@@:
MOV screen_bot,AX
MOV CS:[pcktdata + 06],AX
INC AH
MOV byte ptr screen_rows,AH
INC AL
MOV byte ptr screen_cols,AL
MOV AX,ES:[BX].wintop
MOV screen_top,AX
MOV CS:[pcktdata + 04],AX

XOR AX,AX
PUSH AX ;UID of owner, system
MOV AX,512 ;memory size in bytes
PUSH AX
MOV AX,0
PUSH AX ;num of objs = 0, use bytelen
PUSH DS
MOV AL,'a' ;'a'ssign
MOV pcktbuf,AL
MOV AX,offset pcktbuf
PUSH AX
MOV AX,currpid
PUSH AX ;our PID
CALL far ptr _sys_memreq ;DX:AX pointer to pool mem
ADD SP,12
OR DX,DX
JZ no_memory
CLD ;string operations forward
MOV CX,xportlen + 01 ;copy our protocol functions
SHR CX,01 ;get word count
MOV DI,AX ;to address ES:DI
MOV ES,DX
MOV word ptr pfunc,AX
MOV word ptr pfunc + 02,ES
MOV SI,offset pcktproto ;from address DS:SI
PUSH CS
POP DS
REP MOVSW
POP ES
POP DS
JMP short @F
no_memory:
POP ES
POP DS
JMP vt5

assume cs:CSEG,ds:DSEG,es:DSEG

@@:
MOV AX,screen_top ;top of window
PUSH AX
MOV AX,schan ;the channel
PUSH AX
MOV AL,'p' ;'p'osition
MOV pcktbuf,AL
MOV AX,offset pcktbuf
PUSH DS
PUSH AX
MOV AX,currpid
PUSH AX ;our PID
CALL far ptr _sys_chanreq ;home the cursor
ADD SP,10
PRINT BANNER
PRINT SIGNON
CALL tty_init ;grab a COMM channel
JNC @F
JMP vt5
@@:
MOV AL,cr ;awake the host
MOV DX,pcomm
MOV AH,01 ;function 1 write
INT tty_bufio ;send character to COMM port
XOR CX,CX
ploop:
MOV DX,pcomm
MOV AH,03 ;function 3 status
INT tty_bufio ;get status and chk for errors
TEST AH,9Eh ;timeout, break, framing error
JZ @F ;no error detected

PUSHF
PUSH AX ;COMM error detected
MOV AL,bell
CALL putchar ;send a bell code
POP AX ;restore COMM status
POPF
@@:
LOOPZ ploop ;no error, loop
JZ @F
JMP vt5 ;error detected
@@:
TEST AH,01 ;NZ flag if character waiting
JNZ @F
JMP vt6 ;no response
@@:
CALL clear ;clear screen to colorbg
PRINT LWAIT
MOV AX,word ptr pfunc + 02 ;set-up for control packets
PUSH AX
MOV AX,word ptr pfunc ;our protocol sending function
PUSH AX
PUSH DS
MOV AL,'p' ;'p'rotocol
MOV pcktbuf,AL
MOV AX,offset pcktbuf
PUSH AX
MOV AX,currpid
PUSH AX ;our PID
CALL _sys_sysreq ;set protocol function
ADD SP,10

PUSH DS ;packet buffer
MOV SI,offset pcktbuf
PUSH SI
MOV AX,02 ;packet length
PUSH AX
MOV AX,cchan
PUSH AX
PUSH DS
MOV AL,'s' ;'s'end
MOV pcktbuf,AL
MOV AX,offset pcktbuf
PUSH AX
MOV AX,currpid
PUSH AX ;our PID
CALL _sys_chanreq ;send
ADD SP,14
XOR CX,CX ;wait awhile
@@:
NOP
LOOP short @B
vt3:
MOV AH,01 ;get kbd status
INT kbd_bufio ;check kbd character waiting
JZ vt4 ;no

MOV AH,0 ;read kbd
INT kbd_bufio
CMP AL,0
JNZ @F
CMP AH,2Ch ;is it Alt-Z ???
JZ vt7 ;yes, so exit
CALL kb_translate
JNZ @F ;send translated character
JMP short vt3
@@:
MOV DX,pcomm
MOV AH,01 ;function 1 write
INT tty_bufio ;send character to COMM port
vt4:
MOV DX,pcomm
MOV AH,03 ;function 3 status
INT tty_bufio ;get status, and check for errors
TEST AH,9Eh ;timeout, break, framing error
JNZ vt3 ;error detected
TEST AH,01 ;Z flag FALSE if
;character waiting
JZ vt3 ;no, loop

MOV DX,pcomm
MOV AH,02 ;function 2 read
INT tty_bufio ;to get COMM character
; CMP AL,xsc
; JNZ @F
; CMP esccnt,0
; JZ @F
; CALL flush_end
;@@:
CALL word ptr state_machine ;call the current state of
;the ANSI Esc sequence
JMP short vt3 ;now do it all over again

;COMM port in use
;exit the terminal emulator

vt5:
CALL clear
PRINT BAD_TTY_MSG
PRINT SIGNOFF
JMP short vt8

;HOST unavailable
;exit the terminal emulator

vt6:
CALL clear
PRINT BAD_HOST_MSG
PRINT SIGNOFF
JMP short vt8

;Alt-X key detected
;exit the terminal emulator

vt7:
CALL clear
PRINT SIGNOFF
vt8:
CALL tty_close
MOV AX,word ptr pfunc + 02
PUSH AX ;pointer to mem to release
MOV AX,word ptr pfunc
PUSH AX
PUSH DS
MOV AL,'d' ;'d'eassign
MOV pcktbuf,AL
MOV AX,offset pcktbuf
PUSH AX
MOV AX,currpid
PUSH AX ;our PID
CALL far ptr _sys_memreq ;deassign
ADD SP,10
vt9:
POP ES
POP DS
MOV AX,4C00h ;OK RETURN
INT fdos ;TERMINATE
vt endp


; Dynamic stack storage layout

dynst struc
syscmd DW ? ;command
oldbp DW ? ;save caller's BP
oldax DW ? ;save registers
olddx DW ?
oldsi DW ?
oldds DW ?
dynst ends

dynsz EQU 0


tty_init proc near
PUSH DS ;dynst stack frame
PUSH SI
PUSH DX
PUSH AX
PUSH BP
SUB SP,02
MOV BP,SP
MOV [BP].syscmd,'x' ;'x'port a COMM port
PUSH SS
PUSH BP
MOV AX,currpid
PUSH AX ;our PID
CALL _sys_sysreq ;xport
ADD SP,06

MOV pcomm,AX ;xported COMM port
MOV CS:[pcktdata + 02],AX
MOV DX,AX
PUSH DX ;save the port
MOV AX,01 ;SRCSINK
PUSH AX
MOV AX,03 ;'type' queue
PUSH AX
CALL _sys_getqueue
ADD SP,04

POP DX ;get the port
INC AX ;skip console object
ADD AX,DX ;UID of COMM port
PUSH AX
MOV AX,01 ;object queue
PUSH AX
CALL _sys_getqkey ;key is the COMM channel
ADD SP,04
MOV cchan,AX

assume cs:CSEG,ds:nothing,es:DSEG

PUSH AX ;need the channel
CALL _sys_getccb ;to get the control block

MOV SI,AX
MOV DS,DX
POP AX ;chan
CMP [SI].call_uid,0 ;owned by scheduler ???
JNZ no_init
MOV [BP].syscmd,'o' ;'o'pen
PUSH AX ;chan
PUSH SS
PUSH BP
MOV AX,ES:[currpid]
PUSH AX ;our PID
CALL _sys_chanreq ;open
ADD SP,06

POP AX ;chan
MOV SI,ES:[pptroff]
MOV DS,ES:[pptrseg]
MOV [SI].altchan,AX ;assign to PID as alternate
MOV [BP].syscmd,'i' ;'i'nts
MOV AX,true ;TRUE
PUSH AX
PUSH SS
PUSH BP
MOV AX,ES:[currpid]
PUSH AX ;our PID
CALL _sys_sysreq ;ints ON
ADD SP,08

MOV AX,0E3h ;init 9600,n,8,1
MOV DX,ES:[pcomm] ;ints are ON, so INT 14h
INT tty_bufio ;will open COMM for ints
CMP AX,-1
JZ @F
CLC
JMP short tt1
@@:
MOV AX,false ;FALSE
PUSH AX
PUSH SS
PUSH BP ;'i'nts
MOV AX,ES:[currpid]
PUSH AX ;our PID
CALL _sys_sysreq ;ints OFF
ADD SP,08
no_init:
STC
tt1:
ADD SP,02
POP BP
POP AX
POP DX
POP SI
POP DS
RET
tty_init endp

; CODE EXPORTED to AN ALWAYS RESIDENT SEGMENT BUFFER

assume cs:CSEG,ds:nothing,es:nothing

pcktproto proc far
CMP AH,RECV_REPLY
JZ @F
JMP chk_send
@@:
XOR AH,AH
CMP AL,06 ;ACK from host ???
JZ @F
JMP pp1
@@:
PUSH DS ;dynst stack frame
PUSH SI
PUSH DX
PUSH AX
PUSH BP
SUB SP,02
MOV BP,SP

MOV AX,true ;NON PREEMPTABLE CODE SECTION
PUSH AX
MOV [BP].syscmd,'b' ;'b'lock
PUSH SS
PUSH BP
MOV SI,packet
MOV AX,CS:[SI]
PUSH AX ;PID
CALL _sys_sysreq ;block scheduler
ADD SP,08
PUSH AX ;save original clkflg state

MOV AX,true ;abort send package
PUSH AX
MOV [BP].syscmd,'a' ;'a'bort
PUSH SS
PUSH BP
MOV SI,packet
MOV AX,CS:[SI]
PUSH AX ;PID
CALL _sys_sysreq ;abort
ADD SP,08

XOR AX,AX
PUSH AX ;NULL ptr
PUSH AX
MOV [BP].syscmd,'p' ;'p'rotocol
PUSH SS
PUSH BP
MOV AX,CS:[SI]
PUSH AX ;PID
CALL _sys_sysreq ;disable handshake
ADD SP,10

MOV AX,CS:[SI + 04]
MOV DX,CS:[SI + 02]
MOV AH,01 ;function 1 write
CALL delay
INT tty_bufio ;send character to COMM port

MOV AX,CS:[SI + 04]
MOV DX,CS:[SI + 02]
XCHG AH,AL
MOV AH,01 ;function 1 write
CALL delay
INT tty_bufio ;send character to COMM port

MOV AX,CS:[SI + 06]
MOV DX,CS:[SI + 02]
MOV AH,01 ;function 1 write
CALL delay
INT tty_bufio ;send character to COMM port

MOV AX,CS:[SI + 06]
MOV DX,CS:[SI + 02]
XCHG AH,AL
MOV AH,01 ;function 1 write
CALL delay
INT tty_bufio ;send character to COMM port

POP AX ;END OF CODE SECTION
CMP AX,0
JZ @F ;leave it as you found it
MOV AX,false ;unblock
PUSH AX
MOV [BP].syscmd,'b' ;'b'lock
PUSH SS
PUSH BP
MOV SI,packet
MOV AX,CS:[SI]
PUSH AX ;PID
CALL _sys_sysreq ;enable scheduler
ADD SP,08
@@:
ADD SP,02
POP BP
POP AX
POP DX
POP SI
POP DS
MOV AH,RECV_REPLY
RET
chk_send:
CMP AH,SEND_REPLY
JNZ pp1
XOR AH,AH
MOV AL,22 ;send a SYN to host
CALL delay
pp1:
RET
pcktproto endp


DB 90h ;ALIGN EVEN

delay proc near
PUSH DX
PUSH CX
MOV DX,05
del1:
XOR CX,CX
del2:
DEC CX
JNZ del2
DEC DX
JNZ del1
POP CX
POP DX
RET
delay endp

packet EQU $ - offset pcktproto
pcktdata DW 32 dup(0)
xportlen EQU $ - offset pcktproto

; END of EXPORTED CODE

assume cs:CSEG,ds:DSEG,es:DSEG

tty_close proc near
PUSH DS ;dynst stack frame
PUSH SI
PUSH DX
PUSH AX
PUSH BP
SUB SP,02
MOV BP,SP

MOV [BP].syscmd,'c' ;'c'lose COMM port
PUSH SS
PUSH BP
MOV AX,currpid
PUSH AX ;our PID
CALL _sys_sysreq ;close
ADD SP,06

MOV [BP].syscmd,'i' ;'i'nts
MOV AX,false ;FALSE
PUSH AX
PUSH SS
PUSH BP
MOV AX,currpid
PUSH AX ;our PID
CALL _sys_sysreq ;ints OFF
ADD SP,08

MOV AX,cchan ;the channel
PUSH AX
MOV [BP].syscmd,'o' ;'o'pen
PUSH SS
PUSH BP
XOR AX,AX
PUSH AX ;the scheduler PID
CALL far ptr _sys_chanreq ;free the channel by giving
ADD SP,08 ;it to the scheduler

MOV SI,pptroff ;get our process block
MOV DS,pptrseg
MOV AX,-1 ;EMPTY
MOV [SI].altchan,AX

ADD SP,02
POP BP
POP AX
POP DX
POP SI
POP DS
RET
tty_close endp


; ANSI state functions

esc_state:
MOV BX,offset bracket_state ;assume Esc char
CMP AL,xsc ;Esc? If yes, store
JZ store_state ;char and next state
JMP putchar ;else, normal char
bracket_state:
MOV BX,offset special_state ;assume left bracket
CMP AL,"[" ;bracket? If yes, store
JZ store_state
JMP short flush_buf ;else, flush buffer

;Must process [2J (CLS) regardless

special_state:
MOV BX,offset erase_state ;assume erase code
CMP AL,"2" ;is it the "2" ???
JZ store_state ;yes, to next state
MOV BX,offset params_state
CMP AL,"=" ;chk for set/reset mode characters
JZ store_state ;"=" and "?".
CMP AL,"?"
JZ store_state ;store
JMP short get_params ;else, check other codes
erase_state:
CMP AL,"J" ;second character of CLS ???
JNZ @F ;no, continue
CALL clear ;do clear procedure
JMP short flush_end ;reset buffer
@@:
MOV byte ptr numbuf,02 ;store the previous 2
get_params:
MOV state_machine,offset params_state
params_state:
CALL chk_quote ;single or double quotes ???
JZ store_state ;yes, store string state
CMP AL,";" ;delimiter ???
JNZ chk_num ;check number
INC numcnt ;else, increment number count
JMP short buffer_char ;buffer the semi-colon
get_cmds:
MOV DI,offset cmd_tbl ;get legal ANSI commands
MOV CX,cmdlen ;number of commands
REPNZ SCASB ;match ???
JNZ flush_end
; JNZ flush_buf ;no match, flush buffer
INC numcnt ;else, increment number count
MOV DI,offset lastcmd ;point to last command
SHL CX,01
SUB DI,CX
dispatch:
CALL DS:[DI] ;do command
JMP short flush_end ;reset buffer
quotes_state:
CMP AL,quote_style ;ending string quote ???
JNZ buffer_char ;no, store in buffer
MOV BX,offset params_state ;else, parameter parse
store_state:
MOV state_machine,BX ;redirect state machine
buffer_char:
MOV DI,esccnt ;buffer in case sequence illegal
CMP DI,escbufsiz
JAE flush_end
; JAE flush_buf ;buffer full
ADD DI,offset escbuf ;next buffer position
STOSB ;store character
INC esccnt ;up count
RET


flush_buf:
PUSH AX ;save the current character
MOV SI,offset escbuf ;point to the sequence buffer
MOV CX,esccnt ;buffered count
fnext:
LODSB ;get one
PUSH CX ;save counter and pointer
PUSH SI
CALL putchar ;write character
POP SI ;restore counter and pointer
POP CX
LOOP fnext ;flush all
POP AX ;retrieve last character
CALL putchar ;write character
flush_end:
MOV esccnt,0 ;reset counter and state
MOV state_machine,offset esc_state
MOV numcnt,0 ;reset parameter counter
MOV DI,offset numbuf ;zero out number buffer
MOV CX,escbufsiz SHR 1
XOR AX,AX
REP STOSW
RET


chk_num:
CMP AL,"0" ;below 0 ???
JB flush_end
; JB flush_buf ;yes, illegal; flush buffer
CMP AL,"9" ;is it above 9 ???
JA get_cmds ;yes, check for command
CALL build_decimal ;else it's a number; accumulate
JMP short buffer_char ;buffer it


putchar:
CMP AL,tab ;is character a TAB ???
JNZ tty_out ;if no, process normally
CALL get_tcur ;get cursor
MOV CX,DX ;else, expand TAB to
AND CX,07 ;appropriate space characters
NEG CX
ADD CX,08
tnext:
PUSH CX
MOV AL,blank
CALL tty_out
POP CX
LOOP tnext
RET

tty_out:
MOV AH,0Eh
INT video_io
RET


; SUPPORT ROUTINES

chk_quote:
MOV BX,offset quotes_state ;assume quote state
MOV AH,double_quote
CMP AL,AH ;double quote ???
JZ got_quote ;yes, string delimiter
MOV AH,single_quote ;single quote ???
CMP AL,AH ;yes, string delimiter
JNZ @F ;else, return Z flag TRUE
got_quote:
MOV quote_style,AH ;store as matching string end
@@:
RET


build_decimal:
PUSH AX ;save number character
SUB AL,"0" ;convert ASCII to binary
MOV CL,AL ;save binary
MOV AX,10 ;multiply previous count by 10
MOV BX,numcnt
MUL byte ptr numbuf[BX]
ADD AL,CL ;add in new number and save
MOV byte ptr numbuf[BX],AL
POP AX
RET


;Move BIOS video data into our data segment

assume cs:CSEG,ds:BIOS_DATA_AREA,es:DSEG

get_biosdata:
PUSH DS
MOV AX,BIOS_DATA_AREA
MOV DS,AX
MOV AL,_io0b_activepg ;get active page
MOV ES:[activepg],AL
MOV AL,_io0b_vmode ;get video mode
MOV ES:[vmode],AL
POP DS
RET


get_tcur:
PUSH DS
PUSH SI
MOV BX,BIOS_DATA_AREA
MOV DS,BX
MOV SI,offset _io0b_tcurx
MOV BL,_io0b_activepg ;use active page as index
XOR BH,BH ;of active cursor position
SHL BX,01
ADD SI,BX
MOV DX,[SI] ;return cursor position
POP SI
POP DS
RET


adv_tcur:
PUSH DS
PUSH SI
MOV BX,BIOS_DATA_AREA
MOV DS,BX
MOV SI,offset _io0b_tcurx
MOV BL,_io0b_activepg ;use active page as index
XOR BH,BH ;of active cursor position
SHL BX,01
ADD SI,BX
MOV DX,[SI]
INC DL
MOV AH,02
INT video_io
POP SI
POP DS
RET


;OUTPUT: BL = First parameter; BH = Second parameter

assume cs:CSEG,ds:DSEG,es:DSEG

adjust_num:
MOV BX,word ptr numbuf
OR BH,BH
JNZ @F
INC BH ;convert to base 1
@@:
OR BL,BL
JNZ @F
INC BL ;convert to base 1
@@:
RET


;INPUT: AX = number; BP = 0 if console output; BP = 1 if storage output

dec_output:
PUSH DX
MOV BX,10 ;divisor ten
XOR CX,CX ;counter
@@:
XOR DX,DX
DIV BX
ADD DL,"0" ;convert to ASCII
PUSH DX ;save
INC CX ;bump count
CMP AX,0 ;done ???
JNZ @B ;continue
OR BP,BP ;zero, output to screen
JNZ stor_output ;else, store in buffer
@@:
POP AX ;get digit
CALL putchar ;and display it
LOOP @B
POP DX
RET


stor_output:
CMP CX,02 ;num of digits ???
JAE @F
MOV AL,"0" ;else, store leading zero
STOSB
@@:
POP AX ;get digit
STOSB ;save it
LOOP @B
POP DX
RET


; ANSI command subset

clear:
MOV CX,screen_top ;from top
MOV DX,screen_bot ;to bottom
PUSH DX
PUSH CX
CALL _sys_clrwindow
ADD SP,04
MOV DX,CX
JMP short set_cur
position:
hvposition:
CALL adjust_num ;returns BL,BH = parameters
SUB BX,101h ;zero based
XCHG BH,BL
MOV DX,BX
set_cur:
MOV BH,activepg
MOV AH,02
INT video_io
position_end:
RET


currup:
CALL adjust_num
CALL get_tcur
OR DH,DH
JZ position_end ;if already at top, ignore
SUB DH,BL
JNC set_cur ;out of bounds ???
XOR DH,DH
JMP short set_cur
currdwn:
CALL adjust_num
CALL get_tcur
ADD DH,BL
JMP short set_cur
currfwd:
CALL adjust_num
CALL get_tcur
MOV BH,byte ptr screen_cols ;Retrieve displayable columns
DEC BH ;Adjust to zero base
CMP DL,BH ;out of bounds ???
JBE position_end
ADD DL,BL
CMP DL,BH ;at EOL ???
JNA set_cur
MOV DL,BH ;stay in bounds
JMP short set_cur
currbak:
CALL adjust_num
CALL get_tcur
OR DL,DL
JZ position_end
SUB DL,BL
JNC set_cur
XOR DL,DL
JMP short set_cur
currput:
MOV DX,savpos
JMP short set_cur
currsav:
CALL get_tcur
MOV savpos,DX
RET


scroll_win:
CALL adjust_num ;returns BL,BH = parameters
SUB BX,101h ;Zero based
MOV CX,screen_top
MOV DL,BH
SUB DL,BL
CMP BL,CH ;check the top
JB @F
MOV CH,BL ;use window top
@@:
CMP BH,CH
JA @F
MOV BH,BL
ADD BH,DL
; MOV BH,CH
@@:
MOV DX,screen_bot
CMP BH,DH
JA @F
MOV DH,BH
@@:
PUSH DX
PUSH CX
CALL _sys_scrollwin
ADD SP,04
@@:
RET


;Report cursor position via console; Format: ESC[#;#R

currstat:
MOV DI,offset parsebuf
MOV AL,xsc
STOSB
MOV AL,"[" ;store leading Esc, bracket
STOSB ;in video status buffer
CALL get_tcur
MOV AL,DH ;cursor row
XOR AH,AH
INC AX ;convert to base one
MOV BP,01 ;flag to store
CALL dec_output
MOV AL,";" ;store delimiter
STOSB
MOV AL,DL ;cursor column
XOR AH,AH
INC AX
CALL dec_output
MOV AL,"R" ;command character
STOSB
MOV AL,cr ;carriage return
STOSB
SUB DI,offset parsebuf ;setup for console out
MOV vparamcnt,DI
RET


erase_eol:
CALL get_tcur ;erase from the cursor to EOL
MOV CX,DX
MOV DL,byte ptr screen_cols
DEC DL
CMP CX,0
JNZ @F
INC CL
@@:
PUSH DX
PUSH CX
CALL _sys_clrwindow
ADD SP,04
RET


set_graphics:
MOV SI,offset numbuf
gnext:
LODSB ;get parameter
MOV DI,offset attr_tbl ;look up attribute in table
MOV CX,attrlen
REPNZ SCASB
JNZ gloop
MOV DI,offset lastattr
SHL CX,01
SUB DI,CX
MOV AX,[DI]
AND attribute,AL ;if match, AND with strip mask
OR attribute,AH ;and OR with add mask
gloop:
DEC numcnt ;loop for all parameters
JNZ gnext
RET


set_mode:
MOV AL,byte ptr numbuf ;get parameter
CMP AL,07 ;7 ???
JBE mode_end ;1 - 7 valid modes
CMP AL,13 ;13 - 19 valid modes
JB mode_end
CMP AL,19
JA mode_end ;above 19, illegal modes
@@:
XOR AH,AH ;set video mode
INT video_io
RET
mode_end:
RET


kb_translate:
PUSH BX
PUSH CX
XOR AL,AL ;in case no match
MOV BX,offset ttyxlat
INC BX ;match the high byte
MOV CX,word ptr ttyxcnt
scan_table:
CMP AH,[BX]
JZ matched
JB no_kbxlat
INC BX
INC BX
LOOP scan_table
JMP short no_kbxlat
matched:
DEC BX
MOV AL,[BX] ;our character
no_kbxlat:
OR AL,AL
POP CX
POP BX
RET
CSEG ends


DSEG SEGMENT PARA 'DATA'

pcomm DW 0
currpid DW 0
pptroff DW ?

pptrseg DW ?
cptroff DW ?
cptrseg DW ?
irpoff DW ?
irpseg DW ?

state_machine DW esc_state

attribute DB 07
quote_style DB ?
DB ?
savpos DW 0
esccnt DW 0
numcnt DW 0

schan DW 0
cchan DW 0
activepg DB 0
vmode DB 3
screen_cols DW ?
screen_rows DW ?
screen_top DW ?
screen_bot DW ?

vparamcnt DW 0


cmd_tbl LABEL byte
DB "H", "r", "K", "A", "B", "C", "D", "J", "f", "n", "s", "u", "m", "h", "l"
cmdlen EQU $ - cmd_tbl

DW position, scroll_win, erase_eol, currup, currdwn
DW currfwd, currbak, clear, hvposition, currstat
DW currsav, currput, set_graphics, set_mode, set_mode
lastcmd EQU $ - 2

attr_tbl LABEL byte
DB 00,01,04,05,07,08,30,31,32,33,34,35,36,37,40,41,42,43,44,45,46,47
attrlen EQU $ - attr_tbl

; Attribute AND/OR masks

DB 000H,07H, 0FFH,08H, 0F8H,01H, 0FFH,80H, 0F8H,70H, 088H,00H
DB 0F8H,00H, 0F8H,04H, 0F8H,02H, 0F8H,06H, 0F8H,01H, 0F8H,05H
DB 0F8H,03H, 0F8H,07H, 08FH,00H, 08FH,40H, 08FH,20H, 08FH,60H
DB 08FH,10H, 08FH,50H, 08FH,30H, 08FH,70H
lastattr EQU $ - 2

ttyxcnt DW 39h ;number of table entries
;scan code byte, ASCII byte
;sorted by AL character
ttyxlat DW 1051h ; Alt-Q
DW 1157h ; Alt-W
DW 1245h ; Alt-E
DW 1352h ; Alt-R
DW 1454h ; Alt-T
DW 1559h ; Alt-Y
DW 1655h ; Alt-U
DW 1749h ; Alt-I
DW 184Fh ; Alt-O
DW 1950h ; Alt-P
DW 1E41h ; Alt-A
DW 1F53h ; Alt-S
DW 2044h ; Alt-D
DW 2146h ; Alt-F
DW 2247h ; Alt-G
DW 2348h ; Alt-H
DW 244Ah ; Alt-J
DW 254Bh ; Alt-K
DW 264Ch ; Alt-L
DW 2C5Ah ; Alt-Z
DW 2D58h ; Alt-X
DW 2E43h ; Alt-C
DW 2F56h ; Alt-V
DW 3042h ; Alt-B
DW 314Eh ; Alt-N
DW 324Dh ; Alt-M
DW 3B31h ; F1
DW 3C32h ; F2
DW 3D33h ; F3
DW 3E34h ; F4
DW 3F35h ; F5
DW 4036h ; F6
DW 4137h ; F7
DW 4238h ; F8
DW 4339h ; F9
DW 4430h ; F10
DW 471Eh ; Home
DW 480Bh ; cursor up
DW 492Dh ; PgUp
DW 4B08h ; cursor left
DW 4D0Ch ; cursor right
DW 4F05h ;CTRL-E End
DW 500Ah ; cursor down
DW 512Bh ; PgDn
DW 5209h ;CTRL-I Ins
DW 5304h ;CTRL-D Del
DW 607Eh ; Ctl-F3
DW 6821h ; Alt-F1
DW 6940h ; Alt-F2
DW 6A23h ; Alt-F3
DW 6B24h ; Alt-F4
DW 6C25h ; Alt-F5
DW 6D5Eh ; Alt-F6
DW 6E26h ; Alt-F7
DW 6F2Ah ; Alt-F8
DW 7028h ; Alt-F9
DW 7129h ; Alt-F10
DW 0 ;end of table

BAD_DOS_MSG DB cr,lf,'VT requires VMiX 2.6X or above'
DB cr,lf,eom
BAD_TTY_MSG DB cr,lf,'Remote channel unavailable'
DB cr,lf,eom
BAD_HOST_MSG DB cr,lf,'Remote host did not respond'
DB cr,lf,eom
LWAIT DB cr,lf,'Wait...'
DB cr,eom
SIGNON DB cr,lf,'Negotiating remote session ...'
DB cr,lf,eom
SIGNOFF DB cr,lf,lf,'Goodbye ...'
DB cr,lf,eom
BANNER DB ' VMiX 386 Remote Session '
DB ' (Alt-Z Exits)'
DB cr,lf,eom

ALIGN 4

; Buffer areas

pfunc DD ?
escbuf = $
numbuf = escbuf + escbufsiz
parsebuf = numbuf + escbufsiz

DB 256 dup(0)
pcktbuf DB 64 dup(0)
DSEG ends

stack SEGMENT PARA STACK 'STACK'
DW 1024 dup(?)
stack ends
end vt



  3 Responses to “Category : Alternate Operating Systems - Quarterdeck DesqView, CP/M, etc
Archive   : VMIXUTL.ZIP
Filename : VT.ASM

  1. Very nice! Thank you for this wonderful archive. I wonder why I found it only now. Long live the BBS file archives!

  2. This is so awesome! 😀 I’d be cool if you could download an entire archive of this at once, though.

  3. But one thing that puzzles me is the “mtswslnkmcjklsdlsbdmMICROSOFT” string. There is an article about it here. It is definitely worth a read: http://www.os2museum.com/wp/mtswslnk/