home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Columbia Kermit
/
kermit.zip
/
archives
/
msr313src.tar.gz
/
msr313src.tar
/
msxgri.asm
< prev
next >
Wrap
Assembly Source File
|
1991-03-18
|
54KB
|
1,918 lines
name msxgri
; File MSXGRI.ASM
include mssdef.h
; Copyright (C) 1982,1991, Trustees of Columbia University in the
; City of New York. Permission is granted to any individual or
; institution to use, copy, or redistribute this software as long as
; it is not sold for profit and this copyright notice is retained.
; Grid Compass dependent file for MS-DOS Kermit
; Use with msugri.asm keyboard translator file.
; Edit history
; 2 March 1991 version 3.10
; Last edit:
; 2 March 1991
; Dec. 7, 1990. Put modem in verbose mode at startup.
; Change machnm from GRID to GRiD.
; Nov. 27, 1990. Add call to getbaud in serini.
; Nov. 24, 1990. Remove reference to prserr to make link happy.
; Nov. 21, 1990. Fix so both serial and modem drivers need not be loaded
; if they are not used. [jan]
; October 1990. Cosmetic fixes.
; August 1990. Select tek enable/ disable in termtb
; 22 february 1990 Fix up baud setting and and string parsing
; procedurs [jan]
; 23 January 1990. Version 3. Fix up comnd calls. Chance PRTCHR so
; clc for character, stc for no character. clc in OUTPRT. Include
; baud table and portval. Add BAUDST from MSXIBM.ASM. Zap DODISK. [jan]
; 3 February 1989.
; Call "call cmblnk" call call to tekcls so tek screen is cleared
; even if it's not initialized
; Take out II in machnm since this also works on 1101 [jan]
; 5 January 1989. Fix up SERINT, SERINI, SERRST, and SENDBR.
; Implement GETMODEM and SERHNG. Send 'ATE1' to modem in LCLINI. [jan]
; 13 Dec 1988 Move screen clear and terminal type toggling to this file.
; Do other small cleanups. [jrd]
;
; John Nyenhuis Purdue University School of Electrical Engineering
; West Lafayette IN 47907 (317)494-3524 nyenhuis@ecn.purdue.edu
; November 1988
; Fix up for Tektronix emulation
; User can specify screen size by set term 112x or set term 113x
; Call sbrk to get memory for Tektronix and ascii screen saves
; enable automatic entry into Tektronix emulator
; Most characters are now written to screen through bios rather than with DOS
; keyboard is checked once each 8 read of serial port for added speed
; Xon/Xoff flow control enabled
; vt52 terminal emulation taken out (all it did was to not restore the cursor)
;
; 1 July 1988 Version 2.31
; 12 June 1988 Add error recovery if serial port fails to initialize, reduce
; serial port buffer to 1000 bytes. [jrd]
; 11 Jan 1988 Add 2.30 features. [jrd]
; 1 Jan 1988 version 2.30
;
; Jim Noble
; Planning Research Corporation
; 1500 Planning Research Drive
; Mail Stop 5S3
; McLean, VA 22102
; May, 1985
; Add global entry point vtstat for use by Status in mssset.
; Added register save/restore in procedure getbaud.
; Joe R. Doupnik 12 March 1986
; Add global procedures ihosts and ihostr to handle host initialization
; when packets are to be sent or received by us,resp. 24 March 1986
; Add global procedure dtrlow (without worker serhng) to force DTR & RTS low
; in support of Kermit command Hangup. Says Not Yet Implemented. [jrd]
; Add global procedure Dumpscr, called by Ter in file msster, to dump screen
; to a file. Just does a beep for now. 13 April 1986 [jrd]
; In proc Outchr add override of xon from chkxon sending routine.
; This makes a hand typed Xoff supress the xon flow control character sent
; automatically as the receiver buffer empties. 20 April 1986 [jrd]
saveregs macro
push ax
push bx
push cx
push dx
push es
push di
push si
push ds
pushf
endm
restoreregs macro
popf
pop ds
pop si
pop di
pop es
pop dx
pop cx
pop bx
pop ax
endm
;; below 40 publics are the minimum necessary
public baudst,ihostr,bdtab,getbaud,chrout
public pcwait,putmod,serrst,trnprs,prtchr
public poscur,outchr,dtrlow,vts,puthlp
public vtstat,coms,cquery,ctlu,shomodem
public portval,getmodem,term,dumpscr,cmblnk
public cquit,locate,clearl,machnam,lclini
public sendbl,comptab,sendbr,clrmod,cstatus
public termtb,serhng,clrbuf,beep, serini
;;additional system dependent publics
public klogon,kdos,snull,klogof
public bigscreen ; bigscreen=1 if it's big [jan]
public termtog ; toggle terminal types [jan]
public kclrscn, getflgs, setchtab
cmcfm equ cmeol ; equates to account for 3.0
cmtxt equ cmline ; names changes in
cmfile equ cmword ; mssdef.h
baudsiz equ 18 ; entries in baud table
false equ 0
true equ 1
print_out equ 05h ; dos function to print to printer
prtscr equ 80h ; print screen pressed
gbuflen equ 1000 ; max bytes grid internal buffer holds
mntrgh equ gbuflen/2 ; High point = 1/2 of buffer full.
mntrgl equ gbuflen/4 ; Low point = 1/4 buffer full. [jrd]
CLK_INT equ 1ch*4 ; clock interrupt
gserial equ 81h ; grid serial port interrupt
gmodem equ 82h ; grid modem port interrupt
ginit equ 0 ; function 0 - initialize port
gread equ 1 ; function 1 - read data
gwrite equ 2 ; function 2 - write data
gwcmd equ 4 ; function 4 - write command
grstat equ 5 ; function 5 - read status
gflush equ 6 ; function 6 - buffer flush
ggbaud equ 7 ; function 7 - get baud
gsbaud equ 8 ; function 8 - set baud
gspar equ 9 ; function 9 - set parity
gsdata equ 10 ; function 10 - set data bits
gssbit equ 11 ; function 11 - set stop bits
gbufass equ 12 ; function 12 - buffer assign
gcharto equ 13 ; function 13 - set character timeout
gcts equ 19 ; function 19 - clear to send timeout
gbrkon equ 0effH ; function 14 - set break on
gbrkoff equ 0e00H ; function 14 - set break off
scnstrt equ 400h ; starting address of screen area (page 0)
maxscnwrds equ 256*32 ; max number of words in screen memory area
tekonnum equ 18 ; enable tek auto entry
tekoffnum equ 19
ttbig equ 12 ;big screen
ttsmall equ 23 ;small screen
data segment public 'data'
extrn flags:byte, trans:byte
extrn dmpname:byte
extrn kbdflg:byte, rxtable:byte
extrn tekflg:byte ; used in msggri [jan]
extrn denyflg:word ; controls tek autoentry etc
extrn dosnum:word
extrn repflg:byte, diskio:byte ; for replay feature
extrn kbdflg:byte ; in telnet
; structure for status information table sttab.
stent struc
sttyp dw ? ; type (actually routine to call)
msg dw ? ; message to print
val2 dw ? ; needed value: another message, or tbl addr
tstcel dw ? ; address of cell to test, in data segment
basval dw 0 ; base value, if non-zero
stent ends
; table with datacomm status for the status command
vtstbl stent <srchkw,tekstatustxt,termtb,tekbyte> ; tell tek able/disable
stent <srchkw,screenstatustxt,termtb,screenbyte> ; tell screen size
dw 0 ; end of table
tekstatustxt db 'Tek Auto Entry: $'
tekbyte db tekonnum ; tek auto entry code
screenstatustxt db 'Screen Size: $'
screenbyte db ttsmall
prtrdy db true ; when false, exit connect mode
machnam db 'GRiD_COMPASS$'
msmsg1 db cr,lf,' Modem is not ready: DSR is off$'
msmsg2 db cr,lf,' Modem is ready: DSR is on$'
msmsg3 db cr,lf,' no Carrier Detect: CD is off$'
msmsg4 db cr,lf,' Carrier Detect: CD is on$'
msmsg5 db cr,lf,' no Clear To Send: CTS is off$'
msmsg6 db cr,lf,' Clear To Send: CTS is on$'
msmsg7 db cr,lf,' Modem is not used by the Network$'
mdmhand db 0 ;used by showmodem
mdmstr db 'ATE1Q0V1S7=25,',cr,lf ;init modem string
mdmstrlen equ $-mdmstr ;length of modem string
;;new stuff to scan escape sequences from comm port [jan]
stringtab dw tekst1,tekst2 ; strings for matching
numstrings equ 2 ; number of strings to match
disptab dw toteknoplay,totekplay ; dispatch table
tekst1 db escape,'[?38h',0 ;1st string to get into tek mode [jan]
tekst2 db escape,FF,0 ;2nd string to get into tek mode [jan]
stringchekbuff db 16 dup (0)
stringchekcnt dw 0 ;characters already in buffer
matchsofar dw false ; no match yet
match dw 0
playem db false ;don't play back switch characters
; end of data for string scanning
scnwrds dw 240*20 ;words in small screen [jan]
scrsavseg dw ? ;segment for screen save [jan]
bigscreen db 0 ;=1 for big [jan]
prevport db 86 ;port number on previous connect
portbusy db 0 ;serial port not yet busy
save_ax dw ? ;temp location to save ax
save_ds dw ? ;temp location to save ds
curini db 0 ; [gaw@prc]
cursav db ESCAPE,'[s','$' ; [gaw@prc]
curres db ESCAPE,'[u','$' ; [gaw@prc]
curon db ESCAPE,'[3;3z','$' ; [gaw@prc]
curoff db ESCAPE,'[3;4z','$' ; [gaw@prc]
erms20 db cr,lf,'?Warning: System has no disk drives$'
erms40 db cr,lf,'?Warning: Unrecognized baud rate$'
badbd db cr,lf,'Unimplemented baud rate$'
crlf db cr,lf,'$'
comphlp db cr,lf,'1 (SERIAL) 2 (MODEM)$' ; [19b] [gaw@prc]
hngmsg db cr,lf,' The phone should have hungup.',cr,lf,'$'
hnghlp db cr,lf,' The modem control lines DTR and RTS for the current'
db ' port are forced low (off)'
db cr,lf,' to hangup the phone. Normally, Kermit leaves them'
db ' high (on) when it exits.'
db cr,lf,'$'
rdbuf db 80 dup (?) ; temp buf
noimp db cr,lf,'?Not implemented.$'
delstr db BS,' ',BS,'$' ; Delete string
clrlin db cr,ESCAPE,'[0K','$'
portin db 0 ; has clock int vector been initialized?
xofsnt db 0 ; Say if we sent an XOFF.
xofrcv db 0 ; Say if we received an XOFF.
insrvc db false ; Say if in service on XON/XOFF interrupt
parmsk db ? ; parity mask, 0ffh for no parity, 07f with.
flowoff db ? ; flow-off char, Xoff or null (if no flow)
flowon db ? ; flow-on char, Xon or null
captrtn dw ? ; routine to call for captured output
invseq db ESCAPE,'[7m$' ; Reverse video.
nrmseq db ESCAPE,'[0m$' ; Normal mode.
ivlseq db 79 dup (' '),cr,'$' ; Make a line inverse video
tmp db ?,'$'
temp dw 0
temp1 dw ? ; Temporary storage.
temp2 dw ? ; Temporary storage.
fncerr db cr,lf,'Error on function '
fnctype db 'X with a status return of '
fncstat db 'Y$'
argadr dw ? ; address of arg blk
; key redefinitions
setktab db 0
setkhlp db 0
; Entries for choosing communications port.
comptab db 2 ; number of entries
mkeyw 'Serial',1
mkeyw 'Modem',2
setchtab db 1; set file character-set table
mkeyw 'CP437',437
termtb db 6
mkeyw '112x',ttsmall
mkeyw '113x',ttbig
mkeyw 'ANSI',ttgenrc
mkeyw 'Tek4010',tttek
mkeyw 'EnableTek',tekonnum
mkeyw 'DisableTek', tekoffnum
defbaud equ 7 ; defauld baud rate is 1200
port1 prtinfo <defbaud,0,defpar,1,0,defhand,floxon,0>
port2 prtinfo <defbaud,0,defpar,1,0,defhand,floxon,0>
portval dw port1 ; Default is to use port 1
bdtab db 16 ; Baud rate table
mkeyw '50',0
mkeyw '75',1
mkeyw '110',2
mkeyw '134',3
mkeyw '150',4
mkeyw '300',5
mkeyw '600',6
mkeyw '1200',7
mkeyw '1800',8
mkeyw '2000',9
mkeyw '2400',10
mkeyw '3600',11
mkeyw '4800',12
mkeyw '7200',13
mkeyw '9600',14
mkeyw '19200',15
modbdtab db 2 ; baud entries legal for modem
mkeyw '300',5
mkeyw '1200',7
; variables for serial interrupt handler
gbuffer db gbuflen DUP(?) ; large internal buffer for grid [gaw@prc]
source db bufsiz DUP(?) ; Buffer for data from port
bufout dw 0 ; buffer removal ptr
count dw 0 ; Number of chars in int buffer
bufin dw 0 ; buffer insertion ptr
telflg db 0 ; Are we acting as a terminal
clreol db ESCAPE,'[0K$'
blank db ESCAPE,'[2J$'
movcur db ESCAPE,'['
colno db 20 dup (?)
ten db 10
ourarg termarg <>
keydelay dw 0 ;for periodically checking the keyboard
clkdelay dw 0 ;check flow control every 4th tick
serclk db false ;clock interrupt resets-for xon/xoff
charout dd ? ; pointer to direct screen write [jan]
savclko dw ? ; save clock tick interrupt vector offset
savclks dw ? ; save clock tick interrupt vector segment
data ends
code segment public 'code'
extrn comnd:near, dopar:near, defkey:near
extrn sleep:near, msuinit:near, keybd:near
extrn tekcls:near
extrn tekemu:near ; entry point to msggri [jan]
extrn sbrk:near ; memory allocator in mssker [jan]
extrn srchkw:near, statc:near
assume cs:code,ds:data
; local initialization
lclini proc near
mov dosnum,200h ; force dosnum to 2.00 so replay proc works
mov prtrdy,true ; port is ready
push es ;first set up for direct screen writing [jan]
push bx ; See page A1 of the GRiD DOS Manual
mov ax,0
mov es,ax
les bx,es:[200h] ; look in Bios for address of charout
mov ax,es:[bx+20h] ; offset of charout in ax
mov bx,es:[bx+22h] ; seg of charout routine in bx
; now store addr in a pointer that is used
; for indirect calls to charout
mov word ptr charout,ax
mov word ptr charout+2,bx
pop bx ; restore the registers
pop es
;we're all set up for direct screen write [jan]
mov tekflg,0 ;tek emulator not initialized [jan]
mov portin,0 ; serial port not yet initialized
mov flags.vtflg,0 ; turn off terminal emulation [gaw@prc]
call msuinit ; init keyboard translator
call scrsavinit ;set up screen memory
; call serini ; initialize serial port
ret
lclini endp
;scrsavinit sets up memory block for saving tektronix and
; alpha screens two pages of screen memory are requested
; first page is for alpha, second is for tektronix
scrsavinit proc near ;set up memory block to save [jan]
push ax
push cx
push es
push di
mov ax,maxscnwrds*4+100 ; want 4*maxscnwrds bytes
call sbrk ; ax will have the segment
mov scrsavseg,ax ; put it in our data segment
xor ax,ax ; ax=0--clear screen buffer
mov di,ax ; di=0
mov cx,2*maxscnwrds+6 ; number of words to be 0
mov es,scrsavseg ; es points to memory segment
rep stosw ; zero memory location [jrd]
pop di
pop es
pop cx
pop ax
ret
scrsavinit endp
; Clear the input buffer before sending a packet.
CLRBUF PROC NEAR
cmp repflg,0 ; doing replay?
je clrb0 ; e => no replay
ret ; don't clear if replaying
clrb0:
push ax ;need to save for CROSHAIR in msggri
cli
mov ax,offset source
mov bufin,ax
mov bufout,ax
mov count,0
sti
clrb1: call prtchr ; get a character
jnc clrb1 ; until there aren't any more
pop ax
clc
ret
CLRBUF ENDP
; Common routine to clear to end-of-line
CLEARL PROC NEAR
mov dx,offset clreol
mov ah,prstr
int dos
ret
CLEARL ENDP
; SHOW MODEM, displays current status of lines DSR, CD, and CTS.
; Uses byte mdmhand, the modem line status register. [jrd]
shomodem proc near
mov ah,cmcfm ; get a confirm
call comnd
jnc shomod0
ret ; get out if error
shomod0:
mov dx,offset msmsg7 ; no modem status for network
call getmodem ; get modem status
mov mdmhand,al
mov ah,prstr
mov dx,offset msmsg1 ; modem ready msg
test mdmhand,20h ; is DSR asserted?
jz shomd1 ; z = no
mov dx,offset msmsg2 ; say not asserted
shomd1: int dos
mov dx,offset msmsg3 ; CD asserted msg
test mdmhand,80h ; CD asserted?
jz shomd2 ; z = no
mov dx,offset msmsg4 ; say not asserted
shomd2: int dos
mov dx,offset msmsg5 ; CTS asserted msg
test mdmhand,40h ; CTS asserted?
jz shomd3 ; z = no
mov dx,offset msmsg6 ; say not asserted
shomd3: mov ah,prstr
int dos
stc
ret ; carry set upon failure
shomodem endp
; Get modem status and set global byte mdmhand. Preserve all registers.
; status in al ; ax not preserved [jan]
getmodem proc near
push bx ;need to save everybody
push cx
push dx
pushf
mov ah,5 ;grid status call
call grdfnc
mov al,ah ;ah contains status if no error
popf
pop dx
pop cx
pop bx
clc ; carry clear upon success
ret
getmodem endp
; Do a grid function call to the correct com port and return
GRDFNC PROC NEAR
or portbusy,1 ;so we know port is busy
push es ; save es reg
push ds ; then mov ds to es
pop es
push ax ; save function call and value in al
add ah,"0" ; make function code printable
mov fnctype,ah ; and save in error message
pop ax ; restore ax
cmp flags.comflg,1 ; serial port or modem? [gaw@prc]
jne grdfnc1 ; if modem, do other int [gaw@prc]
int gserial ; else do serial port function call [gaw@prc]
jmp short grdfnc2 ; skip other int [gaw@prc]
grdfnc1:int gmodem ; do modem port function call [gaw@prc]
grdfnc2:jnc grdfnc3 ; skip error msg if carry not set
add al,"0" ; make error code printable
mov fncstat,al ; and put in error message
mov ah,prstr
push dx
mov dx,offset fncerr ; Give an error message
int dos
pop dx
grdfnc3:pop es ; restore es
and portbusy,0feH ; clear bit 0
ret
GRDFNC ENDP
; Set the baud rate for the current port, based on the value
; in the portinfo structure. Returns carry clear.
BAUDST PROC NEAR
saveregs
mov dx,offset bdtab ; baud rate table for serial
mov si,portval
mov ax, offset port2 ; structure for modem
cmp ax,si ; using the modem
jne baudst1 ; ne= > yes, using modem
mov dx, offset modbdtab
baudst1:xor bx,bx ; help is the table itself
mov ah,cmkey ; get keyword
call comnd
jc baudst2 ; c = failure
push bx ; save result
mov ah,cmeol ; get confirmation
call comnd
pop bx
jc baudst2 ; c = failure
mov si,portval ; get address of baud structure
mov ax,[si].baud ; remember original value
mov [si].baud,bx ; set the baud rate
call dobaud ; use common code
clc
baudst2:restoreregs
ret
BAUDST ENDP
; Set the baud rate for the current port, based on the value
; in the portinfo structure. Returns normally.
; illegal rate not checked; baudst does this
DOBAUD PROC NEAR
saveregs
mov bx,portval
mov ax,[bx].baud ; ax has baud rate from bdtab
mov ah,gsbaud ; set up to set the port baudrate
call grdfnc ; do a grid function call to a com port
restoreregs
ret
DOBAUD ENDP
; Send a break out the current serial port. Returns normally.
sendbr proc near
push ax
mov ax,250 ;250 milliseconds long
call sendbrt ;do a timed break
pop ax ;restore ax
ret
sendbr endp
; Send a long break out the current serial port. Returns normally.
sendbl proc near
push ax
mov ax,1400 ;1400 milliseconds long
call sendbrt ;do a timed break
pop ax ;restore ax
ret
sendbl endp
;send timed break. ax has length in milliseconds.
sendbrt proc near
mov portbusy,2 ; port is occupied
push cx ; save cx
push ax ; save length of break
mov ax,gbrkon ; setup to do break on [gaw@prc]
call grdfnc ; do break on
pop ax ; get time to delay
call pcwait ; wait awhile
mov ax,gbrkoff ; setup to do break off [gaw@prc]
call grdfnc ; do break off
mov ax,50
call pcwait ; wait awhile
pop cx ; restore
mov portbusy,0 ; port no longer busy
clc
ret ; And return
sendbrt endp
; Send char in ah out the serial port. Checks flow control.
; clc if success
OUTCHR PROC NEAR
push cx
push bx
cmp portin,0 ; port initialized?
jne outchr0 ; ne=> not initialized
call serini ; initialize port
outchr0:
mov bx,portval
cmp [bx].floflg,0 ; Are we doing flow control
pop bx
je outch2 ; No, just continue
xor cx,cx ; clear counter
cmp ah,flowoff ; sending xoff?
jne outch1 ; ne = no
mov xofsnt,false ; supress xon from chkxon buffer routine
outch1: cmp xofrcv,true ; Are we being held?
jne outch2 ; No - it's OK to go on
loop outch1 ; held, try for a while
mov xofrcv,false ; timed out, force it off and fall thru
outch2:
mov al,ah ; parity routine expects character in al
call dopar ; do the parity [jan ]
mov byte ptr temp,al ; put character in buffer
push di ; Save register
mov cx,1 ; set up to write one char to a grid port
mov di,offset temp
mov ah,gwrite
call grdfnc ; go write a character
pop di ; restore saved registers
pop cx
clc
ret ; clc means success
OUTCHR ENDP
; This routine blanks the screen.
CMBLNK PROC NEAR
push ax
push dx
mov ah,prstr
mov dx,offset blank
int dos
pop dx
pop ax
clc ; stay in connect mode
ret
CMBLNK ENDP
LOCATE PROC NEAR
mov dx,0 ; Go to top left corner of screen.
jmp poscur ; callret...
LOCATE ENDP
; Get the current baud rate from the serial card and set it
; in the portinfo structure for the current port. Returns normally.
; This is used during initialization.
GETBAUD PROC NEAR
push ax ; save some regs
push bx
push cx
push dx
mov ah,ggbaud ; set up to get port baud rate
call grdfnc ; and go get it
mov al,ah ; mov baudrate into al
mov ah,0 ; and zero upper part of ax
mov bx,portval
mov [bx].baud,ax ; Set baud rate
pop dx ; restore regs
pop cx
pop bx
pop ax
clc ; msxibm does this
ret
GETBAUD ENDP
; Returns with char in al, # of chars in buffer in dx and carry clear.
; Carry set means no character available.
PRTCHR PROC NEAR
cmp repflg,0 ; doing replay?
je prtch0a ; e => not doing replay
jmp getrepchr ; get replay character if in replay
prtch0a: cmp portin,0 ; port not initialized
jne prtch0b ; 0=> not initialized
call serini
prtch0b:
cmp serclk,true ; should we check flow control? [jan][jrd]
jne prtch0 ;ne = no
call flowchek ;checkout flow control
prtch0: push si
cmp count,0 ; any characters?
jne prtch2 ; ne = yes, get from buffer
prtch1:
push di
push bx
push cx
mov cx,bufsiz ; set up to read from grid port buffer
mov di,offset source
mov ah,gread
call grdfnc
pop cx ; restore saved registers
pop bx
pop di
mov count,ax ; reset count
or ax,ax
jz prtch4 ; still no chars
mov bufout,offset source ; this is output ptr
prtch2:
dec count
mov dx,count ; return count in dx
mov si,bufout
cld
lodsb ; get character
mov bufout,si ; update ptr
pop si
clc ; clc means a character
ret
prtch4: pop si
stc ; stc means no characters
ret
PRTCHR ENDP
;FLOWCHEK --Check to see if we need to do flow control
;this gets called in connect mode each 4 ticks of the clock
;both SERINT and PRTCHR call this. SERINT will not call FLOWCHEK
;if the port is busy
;
;
FLOWCHEK PROC NEAR
or portbusy,2 ;bit 1 set if in flowchek
; code below largely taken from old SERINT
push ax
push bx
push cx
push dx
push di
cld
mov bx,portval
cmp [bx].floflg,0 ; Doing flow control?
je intdone ; No, just leave.
mov ah,grstat ; get the buffer count
call grdfnc
cmp xofsnt,true ; Have we sent an XOFF?
je flowchek1 ; Yes.
cmp cx,mntrgh ; Past the high trigger point?
jbe intdone ; No, we're within our limit
mov ah,flowoff ; Get the XOFF
or ah,ah ; null (no flow control)?
jz intdone ; z = yes, do nothing
mov byte ptr temp,ah ; put character in buffer
mov cx,1 ; set up to write one char to a grid port
mov di,offset temp
mov ah,gwrite
call grdfnc ; go write a character
mov xofsnt,true ; Remember we sent it
jmp intdone
flowchek1:
cmp cx,mntrgl ; below the low trigger point?
ja intdone ; no, don't send XON
mov ah,flowon ; get the XON
or ah,ah ; null?
jz intdone ; z = yes, do nothing
mov byte ptr temp,ah ; put character in buffer
mov cx,1 ; set up to write one char to a grid port
mov di,offset temp
mov ah,gwrite
call grdfnc ; go write a character
mov xofsnt,false ; remember we sent it
intdone:pop di
pop dx
pop cx
pop bx
pop ax
mov serclk,false
mov portbusy,0 ;port no longer busy
ret
FLOWCHEK ENDP
; IHOSTS - Initialize the host by sending XON, or equivalent, and enter the
; cycle of clear input buffer, wait 1 second, test if buffer empty then exit
; else repeat cycle. Requires that the port be initialized before hand.
; Ihosts is used by the local send-file routine just after initializing
; the serial port.
; 22 March 1986 [jrd]
IHOSTS PROC NEAR
push ax ; save the registers
push bx
push cx
push dx
mov bx,portval ; port indicator
mov ax,[bx].flowc ; put Go-ahead flow control char in ah
or ah,ah ; don't send null if flow = none
jz ihosts1 ; z = null
call outchr ; send it (release Host's output queue)
nop ; outchr can do skip return
nop
nop
ihosts1:call clrbuf ; clear out interrupt buffer
pop dx ; empty buffer. we are done here
pop cx
pop bx
pop ax
ret
IHOSTS ENDP
; IHOSTR - initialize the remote host for our reception of a file by
; sending the flow-on character (XON typically) to release any held
; data. Called by receive-file code just after initializing the serial
; port. 22 March 1986 [jrd]
IHOSTR PROC NEAR
push ax ; save regs
push bx
push cx
mov bx,portval ; port indicator
mov ax,[bx].flowc ; put Go-ahead flow control char in ah
or ah,ah ; don't send null if flow = none
jz ihostr1 ; z = null
call outchr ; send it (release Host's output queue)
nop ; outchr can do skip return
nop
nop
ihostr1:pop cx
pop bx
pop ax
ret
IHOSTR ENDP
DTRLOW PROC NEAR ; Global proc to Hangup the Phone by making
; DTR and RTS low.
mov ah,cmtxt ; allow text to be able to display help
mov bx,offset rdbuf ; dummy buffer
mov dx,offset hnghlp ; help message
call comnd ; get a confirm
jnc dtrlow1
ret ; get out if error
dtrlow1:
call serhng ; drop DTR and RTS
mov ah,prstr ; give a nice message
mov dx,offset hngmsg
int dos
clc
ret ; clear carry for success
DTRLOW ENDP
; Hang up the Phone. Similar to SERRST except it just forces DTR and RTS low
; to terminate the connection. 29 March 1986 [jrd]
; Calling this twice without intervening calls to serini should be harmless.
; Returns normally.
SERHNG PROC NEAR ;[jan]
or portbusy,2 ;port is occupied
mov ax,150
call pcwait ;wait for next tick of clock
cmp flags.comflg,1 ;serial(1) or modem(<>1)
jne serhngm ;jne means we are using modem
mov ax,01000H ;turn off rts with function 16
call grdfnc
mov ax,100
call pcwait ;wait 100 mx
mov ax,01100H ;turn off dtr with function 17
call grdfnc
mov ax,500 ;wait 1/2 second
call pcwait
mov ax,010ffH ;turn on rts with function 16
call grdfnc
mov ax,100
call pcwait
mov ax,011ffH ;turn on dtr with function 17
call grdfnc
jmp serhng1
serhngm: ;hang up modem
mov ah,ginit
call grdfnc ;hangup and initialize modem
mov ax,500
call pcwait ;let relay settle down
mov prevport,86 ;fake so serini will initialize
call serini ;this reinitialzes modem
serhng1:mov ax,300 ;wait to let things settle
call pcwait
mov portbusy,0 ;port is no longer occupied
clc ; success
ret
SERHNG ENDP
MODEMSTR PROC NEAR ;send initializing string to modem [jan]
cmp flags.comflg,2 ; using modem
je modemstr0a ; yes
ret ; get out if serial
modemstr0a:
push ax ;save ax
mov ax,200
call pcwait ;delay 200 ms before doing something
push es ;save es and di
push di
push ds
pop es ;es now points to our data segment
mov di,offset mdmstr ;string to send to modem
mov cx,mdmstrlen ;length of the string
modemstr0: push cx ;save cx
cmp byte ptr es:[di],',' ;delay 0.5 second on comma
jne modemstr2
mov ax,500 ;delay for the comma
call pcwait
jmp modemstr3 ;onto next character
modemstr2:
mov ax,50 ;send out port
call pcwait ;50 ms between characters
mov cx,1 ;1 byte at a time
mov ah,2 ;grid write call
call grdfnc ;write it to modem
modemstr3: inc di ;point to next byte
pop cx ;get the count
loop modemstr0 ;do the next byte if cx<>0
pop di ;restore di and es
pop es
pop ax
ret
MODEMSTR ENDP
; Wait for the # of milliseconds in ax, for non-IBM compatibles.
; Based on 4.77 Mhz 8088 processor speeds.
; Thanks to Bernie Eiben for this one.
pcwait proc near
mov cx,240 ; inner loop counter for 1 millisecond
pcwai1: sub cx,1 ; inner loop takes 20 clock cycles
jnz pcwai1
dec ax ; outer loop counter
jnz pcwait ; wait another millisecond
ret
pcwait endp
; Position the cursor according to contents of DX.
POSCUR PROC NEAR
push ax ; save regs
push dx
push es
push di
mov ax,ds
mov es,ax ; address data segment!!!
cld
mov di,offset colno
mov al,dh ; row
inc al ; adjust offset from 1 instead of 0
mov ah,0 ; zero up half of reg containing number
call nout
mov al,';'
stosb
mov al,dl ; column
inc al ; adjust offset from 1 instead of 0
mov ah,0 ; zero up half of reg containing number
call nout
mov al,'H'
stosb
mov al,'$'
stosb
mov dx,offset movcur
mov ah,prstr
int dos ; print the sequence
pop di
pop es
pop dx
pop ax
ret
POSCUR ENDP
; put the number in ax into the buffer pointed to by di. Di is updated
nout proc near
push dx ; save registers
push bx
push ax
cld
mov dx,0 ; high order is always 0
mov bx,10
div bx ; divide to get digit
push dx ; save remainder digit
or ax,ax ; test quotient
jz nout1 ; zero, no more of number
call nout ; else call for rest of number
nout1: pop ax ; get digit back
add al,'0' ; make printable
stosb ; drop it off
pop ax ; restore all registers
pop bx
pop dx
ret
nout endp
; Write a line in inverse video at the bottom of the screen...
; the line is passed in dx, terminated by a $. Returns normally.
putmod proc near
push dx ; preserve message
mov dx,26 * 100H ; line 26
call poscur
mov dx,offset invseq ; put into inverse video
mov ah,prstr
int dos
pop dx
int dos
mov dx,offset nrmseq ; normal videw
int dos
ret ; and return
putmod endp
; Clear the mode line written by putmod. Returns normally.
clrmod proc near
mov dx,26 * 100H
call poscur
call clearl
ret
clrmod endp
; Put a help message one the screen in reverse video. Pass
; the message in AX, terminated by a null. Returns normally.
; The message is put wherever the cursor currently is located.
puthlp proc near
push ax
mov ah,prstr ; Leave some room before the message
mov dx,offset crlf
int dos
pop si ; Put message address here
puth0: mov ah,prstr
mov dx,offset invseq ; Put into reverse video
int dos
mov ah,prstr
mov dx,offset ivlseq ; Make line inverse video
int dos
cld
puth1: lodsb
cmp al,0 ; Terminated with a null
je puth2
mov dl,al
mov ah,conout
int dos
cmp al,lf ; Line feed?
je puth0 ; Yes, clear the next line
jmp puth1 ; Else, just keep on writing
puth2: mov dx,offset crlf
mov ah,prstr
int dos
mov dx,offset nrmseq ; Normal video
int dos
clc
ret
puthlp endp
; Perform a delete.
DODEL PROC NEAR
push ax
push dx
mov ah,prstr
mov dx,offset delstr ; Erase character
int dos
pop dx
pop ax
ret
DODEL ENDP
; Perform a Control-U.
CTLU PROC NEAR
push ax
push dx
mov ah,prstr
mov dx,offset clrlin
int dos
pop dx
pop ax
ret
CTLU ENDP
;; set the current port
COMS PROC NEAR
mov dx,offset comptab
xor bx,bx ; help is the table itself
mov ah,cmkey
call comnd
jnc coms00
ret ; get out if error
coms00: push bx
mov ah,cmcfm
call comnd ; Get a confirm.
jc comx ; carry set = failure
pop bx
mov flags.comflg,bl ; Set the comm port flag
cmp flags.comflg,1 ; Using Com 1?
jne coms0 ; ne = no
mov portval,offset port1
clc ; carry clear for success
ret
coms0: mov portval,offset port2
clc ; carry clear for success
ret
comx: pop bx
stc ; carry set for failure
ret
COMS ENDP
; Set heath emulation on/off.
VTS PROC NEAR
mov dx,offset termtb
mov bx,0
mov ah,cmkey
call comnd
jnc vts0
ret ; get out if error
vts0:
push bx
mov ah,cmcfm
call comnd ; Get a confirm
jc vt0 ; carry => didn't get a confirm
pop bx
cmp bl,ttbig ; using big screen?
jne vt1 ;ne means its not big
mov bigscreen,1 ; so we know screen is big
mov screenbyte, bl ; for status
mov scnwrds, 256*32 ; words in big screen
mov tekflg,0 ; tek needs reinitialization
clc
ret
vt1: cmp bl,ttsmall ;ne means its not small
jne vt1a
mov tekflg,0 ; tek needs reinitialization
mov scnwrds, 240*20 ;words in small screen
mov bigscreen,0 ;screen is not big, i.e. it's small
mov screenbyte, bl ; for status
clc
ret
vt1a: cmp bl,tekonnum ; enable tek?
jne vt1b ; ne = no, don't enable
and denyflg,not tekxflg ; clear tekx bit
mov tekbyte,bl ; for status display
clc
ret
vt1b: cmp bl,tekoffnum ; disable tek
jne vt2 ; ne => don't disable
or denyflg,tekxflg ; set tek deny bit
mov tekbyte,bl ; for status display
clc
ret
vt2: mov flags.vtflg,bl ; Set the Tektronix emulation flag [jan]
mov tekflg,0 ; need to re-initialize tek emulator [jan]
clc ; carry clear for success
vt3: ret
vt0: pop bx
stc ; carry set for failure
ret
VTS ENDP
VTSTAT PROC NEAR ; For Status display [jrd]
mov bx, offset vtstbl ; table of things to show
jmp statc ; common status code
;;; ret ; no emulator status to display
VTSTAT ENDP
termtog proc near ; toggle terminal type [jan]
call savescr ; save present screen
xor flags.vtflg,tttek ;toggle terminal type
mov tekflg,0 ; we need to re-initialize tek emulator
call restscr ; restore the previous screen
clc ; do not exit Connect mode [jrd]
ret
termtog endp
kclrscn proc near ; clear screen in text or Tek mode [jrd]
cmp flags.vtflg,tttek ; doing Tek emulation?
jne kclrsc1 ; ne = no
call cmblnk ; blank for good measure [jan]
call tekcls ; blank and some more
clc ; stay in Connect mode
ret
kclrsc1:call cmblnk ; blank screen
clc ; stay in Connect mode
ret
kclrscn endp
; Save the screen to a buffer and then append buffer to a disk file. [jrd]
; Default filename is Kermit.scn; actual file can be a device too. Filename
; is determined by mssset and is passed as pointer dmpname.
DUMPSCR PROC NEAR ; Dumps screen contents to a file. Just Beeps here
call beep ; [jrd]
clc
ret
DUMPSCR ENDP
; show the definition of a key. The terminal argument block (which contains
; the address and length of the definition tables) is passed in ax.
; Returns a string to print in AX, length of same in CX.
; Returns normally.
showkey proc near
ret ; and return
showkey endp
; Common initialization for using serial port.
SERINI PROC NEAR
mov portbusy,2 ;port is occupied-don't check flow
mov clkdelay,0 ; restart flow check clock
push es
cmp portin,0 ; Did we initialize interrupt already?
je serin0 ; No, skip exit
jmp serin1 ; Yes, so just leave
serin0:
cli ; Disable interrupts
cld ; Do increments in string operations
xor ax,ax ;ax=0
mov es,ax ;es=0
mov bx,CLK_INT ;clock vector
mov ax,es:[bx] ;get offset
mov savclko,ax ;save clock int offset
mov ax,es:[bx+2] ;get segment
mov savclks,ax ;save clock int segment
mov ax,offset serint
mov es:[bx],ax ; and load with offset of serint
mov ax,cs
mov es:[bx+2],ax ; and load with code segement address
;clk vector now reset
mov portin,1 ; Remember interrupt has been initialized
sti ; turn interrupts back on
serin1: call getbaud ; get existing baud rate
call dobaud ; and reset it
push bx
mov bx,portval ; get port
mov parmsk,0ffh ; parity mask, assume parity is None
cmp [bx].parflg,parnon ; is it None?
je serin2 ; e = yes
mov parmsk,07fh ; no, pass lower 7 bits as data
serin2: mov bx,[bx].flowc ; get flow control chars
mov flowoff,bl ; xoff or null
mov flowon,bh ; xon or null
pop bx
mov ah,flags.comflg ;get new com port
cmp ah,prevport ;port changed?
je serin3 ;no change so don't reinitialize
mov prevport,ah ;remember we have changed
xor ax,ax
mov ah,gspar ; parity = none
call grdfnc
mov al,1 ; stopbit = 1
mov ah,gssbit
call grdfnc
mov al,8 ; data bits = 8
mov ah,gsdata
call grdfnc
mov dx,1 ; timeout on char read wait = 1ms
mov ah,gcharto
call grdfnc
call modemstr ; init modem if on
cmp flags.comflg,1 ; Using Com 1?
jne skipcts ; Nope.
mov dx,0 ; timeout on cts = 0
mov ah,gcts
call grdfnc
skipcts:mov ax,ds ; point to large buffer
mov es,ax
mov di,offset gbuffer
mov cx,gbuflen
mov ah,gbufass
call grdfnc
mov ah,gflush ; flush grid input buffer
call grdfnc
;; call clrbuf ; Clear input buffer
serin3: pop es
mov portbusy,0 ;now able to do flow checking
clc ; carry clear for success
ret
SERINI ENDP
SERRST PROC NEAR ; reset the clock interrupt vector
cmp portin,0 ; Did we initialize interrupt already?
je serrst0 ; No, skip resetting clock vector
cli ; Disable interrupts
push es ; restore vector of clock tick int at 1CH
xor ax,ax ; point to segment part of vector
mov es,ax ; es=0
mov bx,CLK_INT ; clock interrupt =1ch*4
mov ax,savclko ; replace with original value
mov es:[bx],ax ; restore offset
mov ax,savclks
mov es:[bx+2],ax ; restore segment
pop es ; and clean up stack
mov portin,0 ; Remember interrupt has been reset.
sti ; turn interrupts back on
serrst0:
ret ; All done
SERRST ENDP
; Comm port interrupt service routine to prevent grid buffer overflow
; Calls flowchek which sends Xoff if necessary if activated
;flow control is checked every 4 clock ticks, about 80 ms
; Modified by [jan] with helpful suggestions from [jrd]
SERINT PROC FAR
push ax ;all registers must be saved by SERINT
push ds ;here, we put some words on the stack
mov ax,data ;first we let the clock interrupt get called
mov ds,ax ;then (maybe) come back to check flow control
pop save_ds ;save ds
pop save_ax ;save ax
pushf ;save since they're changed by and instr.
inc clkdelay ;just do flow control check
mov ax,clkdelay ;once each 4 ticks of the clock
and ax,3 ;for improved performance
jnz serint0 ;nz means don't check this tick
popf
pushf ;restore flags and return to stack
mov ax,cs ;put segment of return address on stack
push ax ;clock will return here
mov ax,offset serint1 ;offset of return address
push ax ;is placed on stack
pushf ;this will come off
serint0:popf ;remove extra flags from stack
mov ax,savclks ;put address of clock routine
push ax ;on top of stack
mov ax,savclko
push ax
mov ax,save_ax ;restore ax and ds
mov ds,save_ds
ret ;go to the clock routine
;we come back at serint1
;once each 4 ticks
;;Clock interrupt returns here if (clkdelay and 3)=0
serint1: ;; entry point after clock routine
push ax
push bx
push cx
push dx
push ds
mov ax,data
mov ds,ax
mov serclk,true ;check out flow control at least once/4 tick
cmp insrvc,true ; are we already doing interrupt service?
je retint ; yes, then skip service until this one done
mov insrvc,true ; nope, set in service flag
cmp portbusy,0 ;is serial port available?
jne serint5 ;don't stack calls
;grdfnc is non-reentrant
sti ; flag set enable interrupts
call flowchek ;do flow control checking
mov serclk,false ;don't check until next tick
serint5: mov insrvc,false ; set in service flag to false
retint: pop ds
pop dx
pop cx
pop bx
pop ax
iret ;iret since we have to remove flags
SERINT ENDP
; Generate a short beep.
BEEP PROC NEAR
mov dl,bell
mov ah,conout
int dos
ret
BEEP ENDP
;check string to see if we need to do something special
stringchek proc near
cmp stringchekcnt,0 ; nobody in yet?
jne stringchek1 ; ne => already have characters
cmp al,escape ; is this escape?
je stringchek1 ; it is escape, so go and process
cmp al,escape+80h ; in case parity is odd
je stringchek1 ; process the escape
stc ; display the character
ret ; return quickly if nothing to do
stringchek1: ; here is escape already in
saveregs
and al,07fh ;strip high bit
mov bx,stringchekcnt
mov stringchekbuff[bx],al ;put character in buffer
inc stringchekcnt ;one more character in buffer
call stringtest ; does the string in stringchekbuff match?
cmp match,0 ; 0 means no match
je stringchek2
mov si,match ; here means we have a match
shl si,1 ; multiply by 2
dec si
dec si ; 1=0, 2=1 etc
call disptab[si] ; call appropriate function
call stringbuffplay ; play back the buffer
clc ; don't display
jmp stringchek3 ; return and don't display character
stringchek2:
clc ; don not display
cmp matchsofar,true ; do we have a match so far
je stringchek3 ; e=true , get out
mov playem,true
call stringbuffplay ; clean out the buffer
clc ; don't display character
stringchek3:
restoreregs
ret
stringchek endp
;test to see if input string is a match to toggle terminal [jan]
; stringtab gives addresses of 0 terminated strings
; teststring in stringchekbuff
;numstrings is the number to checked
; matchsofar will have be true if there is a possilbe match
; match will be non-zero 1, 2, 3 indicating number of match if a match
; if no match yet, match will be 0
; severaal registers get destroyed
stringtest proc near
mov matchsofar, false ; assume no match
mov match,0 ; no match
xor si,si ; pointer to string tab
dec si
dec si ; step back 1 item
mov cx,0 ; cx points to number of string
strtst1:
inc cx ; strings number
cmp cx,numstrings ; done parsing table?
ja strtst5 ; we're done, get out of here
mov di, offset stringchekbuff
inc si
inc si ; point to next item
mov bx,stringtab[si] ; offset of string
strtst2:
mov al,[di] ; stringchekbuff in al
mov ah,[bx] ; string element to test in ah
cmp al,0 ; end of stringchekbuff
jne strtst2a ; ne=> not at end of buffer
mov matchsofar,true ; we have a match so far
jmp strtst5 ; return to caller
strtst2a:
cmp ah,0 ; at end of string?
je strtst1 ; failure, go to next string
cmp ah,al ; match?
jne strtst1 ; no match, on to next string
; here if match
mov ah,[bx+1] ; next byte from string
cmp ah,0 ; are we done with string?
je strtst3 ; e => yes, a match
inc bx ; next element in string
inc di ; next character in stringchekbuff
jmp strtst2 ; check next item in string
strtst3: ; here if we have a match
mov match,cx ;
mov matchsofar,true ;
strtst5:
ret
stringtest endp
;play back characters in string buffer ..called by stringchek
stringbuffplay proc near
xor bx,bx ;bx=0
mov cx,stringchekcnt
stringbuffplay1:
mov al,stringchekbuff[bx]
cmp playem,true ;playback characters?
jne stringbuffplay2 ;ne = no don't play back
push bx ; save index
push cx ; save count
call outtty ; print the character
pop cx ; restore count
pop bx ; restore index
stringbuffplay2:
mov stringchekbuff[bx],0 ;set to 0
inc bx ;point to next character
loop stringbuffplay1 ;repeat until buffer is empty
mov stringchekcnt,0 ;now no characters in buffer
ret
stringbuffplay endp
ignoretek proc near ; ignore this escape sequence in tek mode
mov playem,false
cmp flags.vtflg,tttek ; are in in tek emulation
je ignoretek1 ; e=yes do not play back
mov playem,true
ignoretek1:
ret
ignoretek endp
ignoreall proc near ; always ignore this escape sequence
mov playem,false
call beep
ret
ignoreall endp
totekplay proc near ; turn on tektronix
mov playem,true ; play back characters
jmp totek
totekplay endp
toteknoplay proc near
mov playem,false
jmp totek
toteknoplay endp
totek proc near ; turn on tektronix
test denyflg,tekxflg ;tek auto entry enabled?
jz totek1
mov playem,true ; play back characters
ret
totek1:
cmp flags.vtflg,tttek ; already doing tek
je totek2
call termtog ; toggle to tektronix
totek2:
ret
totek endp
; put the character in al to the screen, do capture and printing,
; does translation for Set Input command.
; Adapted from msyibm.asm [jrd]
outtty proc near
cmp flags.vtflg,tttek ; doing tektronix emulation?
jne outtty1 ; ne= not doing tek emulation
jmp tekemu ; do tekemu and return
outtty1:cmp repflg,0 ; replaying?
je outtty2 ; e=> no replay
; mov ah,conout ; dostty screen mode
; mov dl,al ; write without intervention.
; int dos ; else let dos display char
; ret ; get out
outtty2:
test flags.remflg,d8bit ; keep 8 bits for displays?
jnz outnp8 ; nz = yes, 8 bits if possible
and al,7fh ; remove high bit
outnp8: cmp rxtable+256,0 ; is translation off?
je outnp7 ; e = yes, off
push bx ; Translate incoming char [jrd]
mov bx,offset rxtable ; address of translate table [jrd]
xlatb ; new char is in al
pop bx
outnp7:
test ourarg.flgs, capt ; capture flag on?
jz outnoc ; no, forget this part
push ax ; save char
call captrtn ; give it captured character
pop ax ; restore character and keep going
outnoc: test ourarg.flgs,prtscr ; should we be printing?
jz outnop ; no, keep going
push ax
mov ah,print_out ; write to system printer device
mov dl,al
int dos
pop ax
jnc outnop ; nc = successful print
push ax
call beep ; else make a noise and
call trnprs ; turn off printing
pop ax
outnop: cmp flags.vtflg,0 ; emulating a terminal?
jnz outnop1 ; nz = yup, go do something smart
test ourarg.flgs,trnctl ; debug? if so use dos tty mode
jz outnp5 ; z = no
mov ah,conout
cmp al,7fh ; Ascii Del char or greater?
jb outnp1 ; b = no
je outnp0 ; e = Del char
push ax ; save the char
mov dl,7eh ; output a tilde for 8th bit
int dos
pop ax ; restore char
and al,7fh ; strip high bit
outnp0: cmp al,7fh ; is char now a DEL?
jne outnp1 ; ne = no
and al,3fH ; strip next highest bit (Del --> '?')
jmp outnp2 ; send, preceded by caret
outnp1: cmp al,' ' ; control char?
jae outnp3 ; ae = no
add al,'A'-1 ; make visible
outnp2: push ax ; save char
mov dl,5eh ; caret
int dos ; display it
pop ax ; recover the non-printable char
outnp3: mov dl,al
int dos
ret
;outnp4: ;cmp al,bell ; bell (Control G)? [jrd]
;jne outnp5 ; ne = no
; jmp beep ; use short beep, avoid char loss.
outnop1:
outnp5:
call charout ;tell grid bios to write character[jan]
; mov ah,conout ; dostty screen mode
; mov dl,al ; write without intervention.
; int dos ; else let dos display char
outnp6: ret ; and return
outtty endp
; send the character in al out to the serial port
; handle echoing also...
outprt proc near
; test flags,lclecho ; echoing?
test ourarg.flgs,lclecho ; echoing?
jz outpr1 ; no, forget it
push ax ; save char
call outtty ; print it
pop ax ; restore
outpr1: mov ah,al ; this is where outchr expects it
call outchr ; output to the port
nop
nop
nop ; skip returns
ret
outprt endp
; Get a char from the serial port manager
; returns with carry on if a character is available
portchr proc near
call prtchr ; character at port?
jnc portc1 ; nc => character at port
portc0: clc ; no carry -> no character
ret ; and return
portc1: and al,parmsk ; apply 8/7 bit parity mask
stc ; have a character
ret ; and return
portchr endp
argini proc near ; read passed arguments
mov bx,argadr ; base of argument block
mov ax,[bx].captr
mov captrtn,ax ; buffer capture routine
mov parmsk,0ffh ; parity mask, assume parity = None
cmp [bx].parity,parnon ; is parity None?
je argin2 ; e = yes, keep all 8 bits
mov parmsk,07fh ; else keep lower 7 bits
argin2: call serini ; initialize port if necessary
ret ; that's it
argini endp
getflgs proc near
mov al,ourarg.flgs ;supply flags for msggri [jan]
ret
getflgs endp
term proc near
mov argadr,ax ; save argument ptr
push es
mov si,ax ; this is source
mov di,offset ourarg ; place to store arguments
push ds
pop es ; address destination segment
mov cx,size termarg
cld
rep movsb ; copy into our arg blk
pop es
call argini ; init options from arg address
cmp curini,0 ; have we been in here before[gaw@prc]
je term1 ; if not skip restoring cursor[gaw@prc]
call restscr ; restore screen
term1: cmp prtrdy,false ; ready to read port
je term5 ; get out
call portchr ; read char from serial port
jnc term3 ; nc = no char, go on
cmp flags.vtflg,tttek ; doing tek emulation?
je term1a ; e=yes, already doing tek
call stringchek ; ESC FF will turn on tek [jan]
jnc term3
term1a: call outtty ; display and capture char [jrd]
term3: inc keydelay ; just check keyboard once
mov ax,keydelay ; each eight reads of the port
and ax,7 ; should speed things up
jnz term1 ; at higher baud rates [jan]
call keybd ; call keyboard xlator, send results
jnc term1 ; nc = stay in Connect mode
term5: ; [gaw@prc]
call savescr ; save screen [gaw@prc]
cmp prtrdy,true ; need to set kbdflg if wierd exit
je term6
mov kbdflg,'C' ; so we exit connect mode
mov prtrdy,true
term6: ret
term endp
getrepchr proc near ; get replay character for file
mov ah,readf2 ; read from replay file
mov bx,diskio.handle
mov cx,1 ; read 1 character
mov dx,offset rdbuf ; to this buffer
int dos
jc getrepchr1 ; c => failure
cmp ax,cx ; read the byte?
jne getrepchr1
mov al,rdbuf ; al has character
clc ; character available in al
clc
ret
getrepchr1:
call beep ; announce file is done
call beep
call getkey ; wait for a key to be pressed
mov prtrdy,false ; so we exit connect mode
stc
ret ; no character available
getrepchr endp
repchrout proc near ; process key in al while replaying
and al,7fh ; strip parity
repchrout1:
cmp al,'C'-40h ; Control C?(to exit playback mode)
je repchrout3 ; e=> yes, return failure
cmp al,XOFF ; user wants to stop?
jne repchrout2 ; ne => ok to continue
call getkey ; wait and get a key
jmp repchrout1 ; now process this key
repchrout2:
clc ; return success
ret
repchrout3:
mov prtrdy,false ; exit terminal
stc ; exit connect mode
ret
repchrout endp
getkey proc near ; wait for a key to be typed
mov ah,7
int dos
ret
getkey endp
savescr proc near
push es ; move ds base address to es
push di
push ax
push dx
xor ax,ax
mov di,maxscnwrds*2 ;tek page by default
cmp flags.vtflg,tttek
je savsc1
mov di,0 ;point to 1st page for text
mov ah,prstr ; send '<esc>[s' to ansi.sys[gaw@prc]
mov dx,offset cursav ; [gaw@prc]
int dos ; [gaw@prc]
mov byte ptr curini,1 ; now we've saved the cursor[gaw@prc]
mov dx,offset curoff ; turn off cursor
mov ah,prstr
int dos
savsc1: mov ax,scrsavseg
mov es,ax ;es points to screen save segment
mov si,scnstrt ; point to screen memory area
mov cx,scnwrds ; setup word count
push ds
xor ax,ax ; point to base page with ds
mov ds,ax
cld
rep movsw ; transfer image to save area
pop ds ; restore registers and return
mov dx,offset curon ; turn on cursor
mov ah,prstr
int dos
pop dx
pop ax
pop di
pop es
ret
savescr endp
restscr proc near
mov dx,offset curoff ; turn off cursor
mov ah,prstr
int dos
mov dx,offset blank ; clear screen to get rid of cursor
mov ah,prstr
int dos
push es ; point to base page with es
xor ax,ax ; restore screen
mov es,ax
xor ax,ax
mov si,ax ;si=0 by default
cmp flags.vtflg,tttek
jne ressc1 ;ne means not tek
mov si,maxscnwrds*2 ;point to second page if tek
ressc1: mov di,scnstrt ; point to screen memory area
mov cx,scnwrds ; setup word count
mov ax,scrsavseg
push ds
mov ds,ax ;ds points to screen save area
cld
rep movsw ; transfer image to screen
pop ds
pop es
cmp flags.vtflg,0 ; are we in emulation mode[gaw@prc]
jne ressc2 ; to skip restoring cursor[gaw@prc]
mov ah,prstr ; send '<esc>[u' to ansi.sys[gaw@prc]
mov dx,offset curres ; [gaw@prc]
int dos ; [gaw@prc]
mov dx,offset curon ; turn on cursor
mov ah,prstr
int dos
ressc2: ret
restscr endp
; msu calls this to send keystroke in al out the port
chrout proc near
cmp repflg,0 ; in replay mode?
je chrout1 ; e=> not doing replay
jmp repchrout ; display the replay character
chrout1:call outprt ; put char in al to serial port
clc ; stay in Connect mode
ret
chrout endp
trnprs: push ax ; toggle Copy screen to printer
test ourarg.flgs,prtscr ; are we currently printing?
jnz trnpr2 ; nz = yes, its on and going off
mov ah,ioctl
mov al,7 ; get output status of printer
push bx
mov bx,4 ; file handle for system printer
int dos
pop bx
jc trnpr1 ; c = printer not ready
cmp al,0ffh ; Ready status?
je trnpr2 ; e = Ready
trnpr1: call beep ; Not Ready, complain
jmp trnpr3 ; and ignore request
trnpr2: xor ourarg.flgs,prtscr ; flip the flag
trnpr3: pop ax
clc
ret
klogon proc near ; resume logging (if any)
test flags.capflg,logses ; session logging enabled?
jz klogn ; z = no, forget it
or ourarg.flgs,capt ; turn on capture flag
push bx ; tell kermit we resume logging
mov bx, offset argadr
or [bx].flgs, capt
pop bx
klogn: clc
ret
klogon endp
klogof proc near ; suspend logging (if any)
and ourarg.flgs, not capt
push bx
mov bx, offset argadr
and [bx].flgs, not capt ; turn off kermit's capture flag
pop bx
klogo: clc
ret
klogof endp
snull: mov ah,0 ; send a null
call outchr ; send without echo or logging
clc
ret
kdos: mov al,'P' ; Push to DOS
jmp short cmdcom
cstatus:mov al,'S' ; these commands exit Connect mode
jmp short cmdcom
cquit: mov al,'C'
jmp short cmdcom
cquery: mov al,'?'
jmp short cmdcom
cmdcom: mov kbdflg,al ; pass char to msster.asm via kbdflg
stc ; say exit Connect mode
ret
code ends
end