home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Columbia Kermit
/
kermit.zip
/
archives
/
msvp98b1.lzh
/
MSXP98.ASM
< prev
next >
Wrap
Assembly Source File
|
1993-05-18
|
113KB
|
4,456 lines
name msxp98
; File MSXP98.ASM
; NEC PC-9801 MS DOS Kermit module.
;
; Last edit: 01 Dec 1991
; 18 May 1993 KEK v2.00/Beta added TCP/IP port (from MSXIBM.ASM)
; 01 Dec 1991 KEK v1.29
; support 20 line mode
; RTS/CTS handshake
; 02 Jul 1991 Test version for Color sixel mode -> KEK v1.26
; 24 May 1991 Bug fixed for CSI (in MSYP98.ASM) -> KEK v1.25
; 13 May 1991 Bug fixed for serhng (in MSXP98.ASM) -> KEK v1.24
; 10 May 1991 Bug fixed for script file (in MSXP98.ASM)
; vt_ourarg.prt is replaced by flags.comflg . -> KEK v1.23
; 17 Apr 1991 Joe Doupnik's modifications are added. -> KEK v1.22
; 05 Apr 1991 KEK v1.21 for MS-Kermit v3.10
; correct flow control mismatch.
; added pcwtst for correct pcwait.
; 25 Jul 1990 KEK v1.20 for MS-Kermit v3.02
; 24 Sep 1989 KEK v1.16 (added VT52 mode).
; 04 Aug 1989 Fixed wrong ESC M (Reverse index) behavior (in MSYP98.ASM).
; 30 May 1989 ESC [ 0 m resets to color to default (color in command mode).
; 25 Apr 1989 KEK v1.15 .
; 24 Apr 1989 Fixed bug of cooked log for dumb terminal emulator.
; 21 Apr 1989 Raw mode logging is moved to outside the terminal emulator.
; 16 Apr 1989 Cooked log in VT100 mode is installed.
; 01 Mar 1989 Bug on JIS-7 input when local echo is on.
; 24 Feb 1989 start test of the device port. v1.15 alpha
; 13 Feb 1989 domode is called when really necessary.
; graphic display on when exit.
; 08 Feb 1989 Call getbaud in lclini.
; 04 Feb 1989 Bug report from Yoro@Kyoto.Univ. SHOW MODEM becomes mad
; when modem is not ready. This was bug in getmodem.
; 28 Jan 1989 KEK v1.14, + MS-Kermit 2.23/A
; 17 Dec 1988 AUTOTEK feature is completely removed. Use eneble/disable Tek.
; 08 Sep 1988 JIS-7 code for 'Kanji-send' is installed.
; The original idea and its code is due to Ogawa, NTT software-lab.
; Thanx for cooperation !
; 16 Jul 1988 Keyboard kanji translation comes into chrout to work with
; SET KEY command.
; 14 Jul 1988 V2.31
; old global variable PCNET is now local variable
; local termination pointer NETDONE is renamed LCLEXIT
; GETMODEM is added as a dummy routine (from MSXGEN.ASM)
; Ungermann-Bass port name is UB-NETCI
; 25 Jun 1988 Ungermann-Bass PC-NIU N98 support in NETCI mode
; 15 Jun 1988 V1.00
; 06 Jun 1988 show modem is installed
; 23 May 1988 added KEYCLICK, AUTOTEK features
; 19 May 1988 become v2.27(A) level (TEK4014, VT100)
; 18 May 1988 Keyboard routine for VT100 is installed.
; 16 May 1988 Works with v2.27(A) VT100 output routine.
; 15 May 1988 Fixed bug in SERINI.
; 14 May 1988 Works with dumb terminal emulator !
; 12 May 1988 start coding based on MSXGEN.ASM by H.Fujii
public serini, serrst, clrbuf, outchr, coms, vtstat
public ctlu, cmblnk, locate, lclini, prtchr, clearl
public baudst, getbaud, beep, trnprs
public setchtab
public count, xofsnt, puthlp, putmod, clrmod, poscur
public sendbr, sendbl, term, machnam, setktab, setkhlp, showkey
public ihosts, ihostr, dtrlow, serhng, dumpscr
public bdtab, comptab, portval
public chrout, cstatus, cquit, cquery, chang ; kbd action verbs
public snull, kdos, klogof, klogon
public trnmod
public shomodem, getmodem, mdmhand
public pf1, pf2, pf3, pf4
public kp0, kp1, kp2, kp3, kp4, kp5, kp6, kp7, kp8, kp9
public decf6, decf7, decf8, decf9, decf10, decf11, decf12, decf13
public decf14, dechelp, decdo, decf17, decf18, decf19, decf20
public decfind, decinsert, decremove, decselect
public decprev, decnext
public kpmins, kpcoma, kpentr, kpdot
public uparrw, dnarrw, lfarrw, rtarrw
public keyinchg
public vtchg, vtreset, vtrmac, vtsmac
public upone, dnone, upscn, dnscn
public gupone, gdnone
public prtscn
public outcapt
public set_cur_color
public cpu_clock, vtgrph_flg, vttest_flg
public curkey_mode, keypad_mode, display_mode
public kanji_rmode, kanji_smode
public kanji_rcode, kanji_scode
public keyin_dos, vt100_cursr
public vt100_flags, vt100_pflag, vt100_lflag, vt100_gflag
public yflags, vt_ourarg
public scn_color, def_color, scrn_lines
public extmacro, vtmacname, vtmaclen
include mssdef.h
include msxp98.h
CHR_GS equ 1Dh
CHR_CAN equ 18h
false equ 0
true equ 1
off equ 0
bufon equ 1 ; buffer level xon/xoff on-state control flag
usron equ 2 ; user level xon/xoff on-state contrl flag
instat equ 6
prtscr equ 80h ; print screen pressed
;
; SIAM Interface Section (by Kenji Rikitake 30-DEC-1991)
; from SIAM.INC in SIAM distribution kit
; modified for MS-Kermit to avoid conflict of symbols
; ----- INT 2FH entry check -----
MAGIC equ 08347h
MAGIC2 equ 04783h
AP_NO_SIAM equ 0
MAX_PORT equ 8
FN_NO_SIAM equ 0
; ----- Function definition -----
_siam_getVerSI equ 1
_siam_releaseSI equ 2
_siam_initSI equ 3
_siam_restoreSI equ 4
_siam_getBaud equ 5
_siam_setBaud equ 6
_siam_getParam equ 7
_siam_setParam equ 8
_siam_rQClear equ 9
_siam_sQClear equ 10
_siam_rQcnt equ 11
_siam_sQcnt equ 12
_siam_getSI equ 13
_siam_putSI equ 14
_siam_getCH equ 15
_siam_putCH equ 16
_siam_getDR equ 17
_siam_getCS equ 18
_siam_getCD equ 19
_siam_getCI equ 20
_siam_lockRS equ 21
_siam_unlockRS equ 22
_siam_setRS equ 23
_siam_setER equ 24
_siam_sndBRK equ 25
_siam_errReset equ 26
_siam_openSI equ 27
_siam_closeSI equ 28
def_func macro func_name, param
func_name macro param
push es
mov es, data:siam_seg
ifnb <param>
ifdifi <param>, <ax>
mov ax, param
endif
push ax
endif
call dword ptr es:[_&func_name*4]
ifnb <param>
add sp, 2
endif
pop es
endm
endm
def_func siam_getVerSI
def_func siam_releaseSI
def_func siam_initSI
def_func siam_restoreSI
def_func siam_getBaud
def_func siam_setBaud baud
def_func siam_getParam
def_func siam_setParam param
def_func siam_rQClear
def_func siam_sQClear
def_func siam_rQcnt
def_func siam_sQcnt
def_func siam_getSI
def_func siam_putSI word
def_func siam_getCH
def_func siam_putCH word
def_func siam_getDR
def_func siam_getCS
def_func siam_getCD
def_func siam_getCI
def_func siam_lockRS
def_func siam_unlockRS
def_func siam_setRS on_off
def_func siam_setER on_off
def_func siam_sndBRK on_off
def_func siam_errReset
def_func siam_openSI id
def_func siam_closeSI id
; ----- DOS Function definition -----
GETPSP equ 51h
; ------------------------------
; End of SIAM Interface Section
;
; Ungermann-Bass PC-NIU N98 command interpreter interface
; CALL AH -- Function number
; AL -- Port number relative to 0
; CX -- may be a counter, CL is used as a subfunction for control
; ES:BX -- may be a buffer address
NETCI_PORT equ 0 ; NETCI port number
NETCI_INT equ 06Bh ; Software interrupt vector# for NETCI
NETCI_OPEN equ 2 ; NETCI open function
NETCI_CLOSE equ 3 ; NETCI close function
NETCI_READ equ 1 ; NETCI read function
NETCI_WRITE equ 0 ; NETCI write function
NETCI_CNTL equ 6 ; NETCI control function
NETCI_STATUS equ 7 ; NETCI status function
NETCI_RBRK equ 8 ; NETCI read break function
NETCI_BRK equ 2 ; NETCI control function, BREAK
NETCI_DIS equ 4 ; NETCI control function, DISCONNECT
NETCI_HLD equ 6 ; NETCI control function, HOLD
TCPIP_READ equ 0A5h
TCPIP_WRITE equ 0A4h
NASI_READ equ 019h ; Novell NASI read function
NASI_WRITE equ 018h ; Novell NASI write function
; Buffer size for Network transfer
NETBUFLEN equ 256
; port assignments for 8251 serial controllers
;
;== PORT 1 ==
mndata equ 30h
mnst1a equ 32h
mncmda equ 32h
mnmska equ 35h ; mask set
mnrdsa equ 33h ; read signal
;== PORT 2 ==
mndatb equ 0B1h
mnst1b equ 0B3h
mncmdb equ 0B3h
mnmskb equ 0B0h
mnrdsb equ 0B0h ; read signal
;== PORT 3 ==
mndatc equ 0B9h
mnst1c equ 0BBh
mncmdc equ 0BBh
mnmskc equ 0B2h ; mask set
mnrdsc equ 0B2h ; read signal
; Status bits from austt
txrdy equ 01h
rxrdy equ 02h
; Command values for mncmd
; Command
; 7 6 5 4 3 2 1 0
; +-----+-----+-----+-----+-----+-----+-----+-----+
; | HUNT|RESET| RTS | ERR | SBRK| RxE | DTR | TxE |
; +-----+-----+-----+-----+-----+-----+-----+-----+
ccmd equ 37H ; RTS & DTR high, RX & TX enabled, ERR reset
cmdrtslow equ 17H ; RTS low, DTR high,
cbrk equ 08H ; break enabled
chng equ 10H ; RTS & DTR low, RX & TX disabled, ERR reset
cmode equ 40H ; enable mode reset
mmode equ 4EH ; 16x rate, 8 data, no parity, 1 stop
; Mask values for mnmsk
txmsk equ 04H ; disables transmit ready interrupt
rxmsk equ 01H ; disables receive ready interrupt
tbemsk equ 02H ; disables transmit buffer empty interrupt
; port assignments for 8253 timers
; Standard interface
tmdata equ 75H ; data port
tmcmda equ 77H ; command port (Was 27H Ian 10/27/84)
; values for tmcmd which select timer channel and mode
tmsela equ 0B6H ; Channel 2, mode 3 (standard port)
; Baudrate
B9600 equ 13
; Modem information
mdminfo struc
mddat dw 0 ; data port
mdstat dw 0 ; status port
mdcom dw 0 ; command port
mdmsk dw 0 ; interrupt mask port
mdsig dw 0 ; signal read port
mdminfo ends
; Timer information for current port selection
tmrinfo struc
tmdat dw 0 ; data port
tmcmd dw 0 ; command port
tmsel db 0 ; byte which selects channel and mode
tmrinfo ends
; Modem information for current port selection
; port assignments for 8259 interrupt controllers
; Standard interface
intcmda equ 00H ; Command port (master controller)
intmska equ 02H ; Mask port
ictmsk equ 01H ; Timer interrupt mask (to master)
icsmska equ 10H ; Standard serial interrupt mask (to master)
icsvcta equ 0CH ;Interrupt vector for standard interface
icEOI equ 20H ; generic end of interrupt for intcmd
; miscellaneous constants
mntrgh equ bufsiz*3/4 ; High XON/XOFF trigger = 3/4 of buffer full.
mntrgl equ bufsiz/4 ; Low point = 1/4 buffer full
_TEXT segment
extrn ktcpstart:far, ktcpstop:far, ktcpcom:far
_TEXT ends
; external variables used:
; flags - global flags as per flginfo structure defined in pcdefs
; trans - global transmission parameters, trinfo struct defined in pcdefs
; portval - pointer to current portinfo structure (currently either port1
; or port2)
; port1, port2 - portinfo structures for the corresponding ports
; global variables defined in this module:
; xofsnt, xofrcv - tell whether we saw or sent an xoff.
data segment
extrn denyflg:word, rdbuf:byte
extrn flags:byte, trans:byte, ttyact:byte
extrn repflg:byte, diskio:byte, filtst:byte
extrn lclsusp:word, lclrest:word, lclexit:word
extrn taklev:byte, takadr:word
extrn comand:byte, dmpname:byte, prnhand:word
extrn kbdflg:byte, rxtable:byte, mcctab:byte
extrn decbuf:byte
extrn tcpdata:word, tcphost:byte
;------------------------
cpu_clock db 0
curkey_mode db 0
keypad_mode db 0
display_mode db 0
;
kanji_7smode db 0
kanji_7rmode db 0
kanji_smode db 0 ; Kanji 1st/2nd byte indicator
kanji_rmode db 0
kanji_scode db 0
kanji_rcode db 0
;
keyin_dos db 0
yflags db 0 ; flags for lclecho, capt, modoff, ...
vt100_cursr dw 0 ; cursor lines and attributes
vt100_flags db 0
vt100_lflag db 0
vt100_pflag db 0 ; printer control
vt100_gflag db 0
;------------------------
vtgrph_flg db 0
vttest_flg db 0
replay_hold db 0
db 0 ; adjustment for word boundary
;------------------------
net_wbuflen dw 0
net_rbuflen dw 0
net_port db 0
net_write db 0
net_read db 0
db 0
;------------------------
scrn_lines dw 25 ; number of lines of the screen (25 or 20)
;
portval dw 1
;
; previous baud rate for serial port 1
pbaud_1 dw 0FFFFh ; set unknown baud rate
;
; color for Foreground, Background, Highlight and Modeline
;
def_color db 07h, 00h, 06h, 07h
scn_color db 07h, 00h, 06h, 07h
;------------------------
fairness dw 0
KI_len dw 0
KI_ofs dw 0
KO_len dw 0
KO_ofs dw 0
pcnet db 0 ; 2.30 global --> 2.31 local
kanjis1 db 0 ; storage for Kanji 1st byte (Keyboard)
kanjis2 db 0
kanjir1 db 0 ; storage for Shift-JIS kanji code
kanjir2 db 0
kanjio1 db 0 ; storage for DEC Kanji code
kanjio2 db 0
mdstreg db ? ; modem status register
machnam db 'NEC PC-9801(KEK v2.00/Beta(01))$'
erms20 db cr,lf,'?Warning: System has no disk drives$'
erms40 db cr,lf,'?Warning: Unrecognized baud rate$'
erms41 db cr,lf,'?Warning: Cannot open com port$'
erms50 db cr,lf,'Error reading from device$'
hnd1 db cr,lf,'Enter a file handle. Check your DOS manual if you are '
db cr,lf,'not certain what value to supply (generally 3).$'
hnd2 db cr,lf,'Handle: $'
hnderr db cr,lf,'Warning: Handle not known.'
deverr db cr,lf,'Any routine using the communications port will'
db cr,lf,'probably not work.$'
nasier1 db cr,lf,'NASI: Cannot initialize NASI port.$'
nasier2 db cr,lf,'NASI: Query Name fail.$'
nasier3 db cr,lf,'NASI: Cannot initialize NASI circuit.$'
pntmsg db 'Printer not ready, printing request skipped$'
hndhlp db cr,lf,'A one to four digit file handle $'
dev1 db cr,lf,'Device: $'
devhlp db cr,lf,'Name for your systems auxiliary port $'
badbd db cr,lf,'Unimplemented baud rate$'
noimp db cr,lf,'Command not implemented.$'
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,'$'
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$'
vtrname db 'TERMINALR' ; a macro name, must be Upper Case
vtrlen equ $-vtrname
vtsname db 'TERMINALS' ; a macro name, must be Upper Case
vtslen equ $-vtsname
prodname db 'PRODUCT'
vtplen equ $-prodname
vtmacname dw vtrname ; pointer to selected macro name
vtmaclen db vtrlen
oldsp dw 0
tmpbuf db 80 DUP (?)
;playback_hndl dw ?
;playback_fnam db 80 dup (?)
;playback_defnam db 'KERMIT.LOG',0
;playback_hlp db cr,lf,'Filename to playback$'
prthnd dw 0 ; Port handle.
prtnam db 80 dup (0) ; Name of auxiliary device
prtdef db 'AUX',0 ; default device name
prtdev db ? ; device flag (device=1,file=0)
prthld db ? ; hold port
prthlp db cr,lf,'specify device/file name (default AUX)$'
shkmsg db 'Not implemented.'
shklen equ $-shkmsg
setktab db 0
setkhlp db 0
crlf db cr,lf,'$'
delstr db BS,BS,' ',BS,BS,'$' ; Delete string
fulscr db ESCAPE,'[>1h$'
nrmscr db ESCAPE,'[>1l$'
delscr db ESCAPE,'[2J$' ; Delete screen
retscr db ESCAPE,'[>1h'
db ESCAPE,'[25;1H',ESCAPE,'[0J'
db cr,'$'
; If delete code moves cursor then BS over code, BS over bad char, space
; over both to erase from screen, BS twice to restore cursor position.
clrlin db cr,'$' ; Clear line (just the cr part).
clreol db ESCAPE,'[K$' ; Clear to end of line.
telflg db 0 ; non-zero if we're a terminal.
argadr dw ? ; address of arg blk from msster.asm
captrtn dw ? ; routine to call for captured output
dupflg db 0 ; 0 = full duplex, 1 = half
portin db -1 ; Has comm port been initialized, -1=not used
xofsnt db 0 ; Say if we sent an XOFF
xofrcv db 0 ; Say if we received an XOFF
parmsk db 0ffh ; parity mask, 0ffh for no parity, 07fh with
flowoff db 0 ; flow-off char, Xoff or null (if no flow)
flowon db 0 ; flow-on char, Xon or null
flowcnt db 0 ; holds flowc (!= 0 using any flow control)
temp dw 0
temp1 dw ? ; Temporary storage.
temp2 dw ? ; Temporary storage.
; Entries for choosing communications port
comptab db 12 ; Number of options
mkeyw '1',1
mkeyw '2',2
mkeyw '3',3
mkeyw 'COM1',1
mkeyw 'COM2',2
mkeyw 'COM3',3
mkeyw 'Device','D'
mkeyw 'File','D'
mkeyw 'NASI(Novell)','W'
mkeyw 'SIAM','S' ; SIAM driver
mkeyw 'TCP/IP','t' ; Telnet, internal
mkeyw 'UB-NETCI','N'
mkeyw ' ',0 ; port is not present, for Status
vt_ourarg termarg <>
modem mdminfo <mndata,mnst1a,mncmda,mnmska,mnrdsa>
timer tmrinfo <tmdata,tmcmda,tmsela>
;++ The following structure must be initialized as in MSSKER
;
port1 prtinfo <0FFFFh,0,defpar,1,0,defhand,floxon,0>
port2 prtinfo <0FFFFh,0,defpar,1,0,defhand,floxon,0>
portd prtinfo <0FFFFh,0,defpar,1,0,defhand,floxon,0>
portf prtinfo <0FFFFh,0,defpar,1,0,defhand,floxon,0>
portn prtinfo <0FFFFh,0,defpar,1,0,defhand,floxon,0>
ports prtinfo <0FFFFh,0,defpar,1,0,defhand,floxon,0>
setchtab db 1
mkeyw 'CP932 Shift-JIS',932
; this table is indexed by the baud rate definitions given in
; pcdefs. Unsupported baud rates should contain FF.
bdtab db 17
mkeyw '45.5',0
mkeyw '50',1
mkeyw '75',2
mkeyw '110',3
mkeyw '134.5',4
mkeyw '150',5
mkeyw '300',6
mkeyw '600',7
mkeyw '1200',8
mkeyw '1800',9
mkeyw '2000',10
mkeyw '2400',11
mkeyw '4800',12
mkeyw '9600',13
mkeyw '19200',14
mkeyw '38400',15
mkeyw 'Unknown',-1
; Baudrate clock count table for 5/10 MHz CPU
even
bddat5 label word ; AHS 29-MAY-86
dw 00D30H ; 45.5 baud
dw 00C00H ; 50 baud
dw 00800H ; 75 baud
dw 00574H ; 110 baud
dw 00476H ; 134.5 baud
dw 00400H ; 150 baud
dw 00200H ; 300 baud
dw 00100H ; 600 baud
dw 00080H ; 1200 baud
dw 00055H ; 1800 baud
dw 0004DH ; 2000 baud
dw 00040H ; 2400 baud
dw 00020H ; 4800 baud
dw 00010H ; 9600 baud
dw 00008H ; 19200 baud
dw 00004H ; 38400 baud
dw 0FFFFH
dw 0FFFFH
dw 0FFFFH
; Baud rate clock count table for 8 MHz CPU
bddat8 label word ; AHS 29-MAY-86
dw 0FFFFH ; 45.5 baud
dw 0FFFFH ; 50 baud
dw 00680H ; 75 baud
dw 0FFFFH ; 110 baud
dw 0FFFFH ; 134.5 baud
dw 00340H ; 150 baud
dw 001A0H ; 300 baud
dw 000D0H ; 600 baud
dw 00068H ; 1200 baud
dw 0004EH ; 1800 baud
dw 0FFFFH ; 2000 baud
dw 00034H ; 2400 baud
dw 0001AH ; 4800 baud
dw 0000DH ; 9600 baud
dw 00006H ; 19200 baud (not acculate - may not work)
dw 00003H ; 38400 baud (not acculate - may not work)
dw 0FFFFH
dw 0FFFFH
dw 0FFFFH
baudlen equ ($-bddat8)/2 ; number of entries above
; SIAM Interface Section (by Kenji Rikitake -- 30/Dec/1991)
siam_seg dw 0 ; SIAM routine address table
processID dw 0 ; PSP segment value (for openSI)
siammsg_nosiam db cr,lf,'Error: SIAM does not exist$'
siammsg_in_use db cr,lf,'Error: SIAM is used by another application$'
; Baud rate table for
; internal baud table index -> siam_getBaud/setBaud value
even
siam_bauddat label word ; KR 29-DEC-1991
dw 0FFFFH ; 45.5 baud
dw 0FFFFH ; 50 baud
dw 1 ; 75 baud
dw 0FFFFH ; 110 baud
dw 0FFFFH ; 134.5 baud
dw 2 ; 150 baud
dw 3 ; 300 baud
dw 4 ; 600 baud
dw 5 ; 1200 baud
dw 0FFFFH ; 1800 baud
dw 0FFFFH ; 2000 baud
dw 6 ; 2400 baud
dw 7 ; 4800 baud
dw 8 ; 9600 baud
dw 9 ; 19200 baud (not acculate - may not work)
dw 10 ; 38400 baud (not acculate - may not work)
dw 0FFFFH
dw 0FFFFH
dw 0FFFFH
siam_bauddat_len equ ($-siam_bauddat)/2 ; number of entries above
; Baud rate table for
; siam_getBaud/setBaud value -> internal baud table index
siam_datbaud label word
dw 0FFFFH ; unknown
dw 2 ; 75bps
dw 5 ; 150bps
dw 6 ; 300bps
dw 7 ; 600bps
dw 8 ; 1200bps
dw 11 ; 2400bps
dw 12 ; 4800bps
dw 13 ; 9600bps
dw 14 ; 19200bps
dw 15 ; 38400bps
siam_datbaud_len equ ($-siam_datbaud)/2 ; number of entries above
SIAM_B9600 equ 8
; End of SIAM section
axsave dw ?
portinia dw 0
dmphand dw ? ; file handle for dump file
oldsera_ofs dw ?
oldsera_sgm dw ?
oldmska db ?
oldmsdat db ?
; variables for serial interrupt handler
even
source db bufsiz DUP (?) ; Buffer for data from port.
db 2 DUP (?) ; guard for source.
srcpnt dw 0 ; Pointer in buffer (DI).
count dw 0 ; Number of chars in int buffer.
rcvpnt dw 0 ; Save SI register here.
mdmhand db 0 ; modem status register, current
; buffer for network
xmtbuf db NETBUFLEN DUP (0) ; Buffer for Network xfer.
db 2 DUP (0) ; guard
xmtpnt dw 0
xmtcnt dw 0
;
even
dw 80 DUP (?) ; local stack for interrupt processing
mnstk dw ?
mnsp dw ? ; remote stack info
mnsseg dw ?
baud_set db 0
onmsg db 'off'
db 'on '
applmsg db 'normal '
db 'application'
colmsg db 'black '
db 'blue '
db 'red '
db 'magenta'
db 'green '
db 'cyan '
db 'yellow '
db 'white '
knjmsg db 'none '
db 'DEC-code '
db 'Shift-JIS'
db 'JIS-7 '
keyinmsg db 'BIOS '
db 'CON '
db 'DOS '
insrepmsg db 'Replace'
db 'Insert '
originmsg db 'Absolute'
db 'Relative'
lfnlmsg db 'Line-feed'
db 'New-line '
clkmsg db '5/10 MHz'
db '8 MHz '
dspmsg db 'Digital '
db 'Analogue'
vstmsg db '<Terminal status> clock '
vstmsg_clk db ' '
db ' Diaplay: '
vstmsg_dsp db ' '
db cr,lf,' Keyclick: '
vstmsg_key db ' '
db ' Keyinput: '
vstmsg_keyin db ' '
db ' Cursorkey: '
vstmsg_curmod db ' '
db ' Keypad: '
vstmsg_kpdmod db ' '
db cr,lf,' Color: Fore:'
vstmsg_colf db ' '
db ' Back:'
vstmsg_colb db ' '
db ' Highlight:'
vstmsg_colh db ' '
db ' Modeline:'
vstmsg_colm db ' '
db cr,lf,' Kanji-send: '
vstmsg_sknj db ' '
db ' Kanji-receive: '
vstmsg_rknj db ' '
db cr,lf,' Ins/Rep: '
vstmsg_insrep db ' '
db ' LF/NL: '
vstmsg_lfnl db ' '
db ' Orgin: '
vstmsg_origin db ' '
db ' Wrap: '
vstmsg_autow db ' '
db cr,lf,' Cooked-log: '
vstmsg_logcook db ' '
db '$'
tcpnet equ 0100h ; TCP/IP
nettype dw 0 ; kind of local area net (vendor bit field)
nsbrk dw 0 ; net can send Break
naskpmt db cr,lf,' A network session is active.',cr,lf
db ' Enter RESUME to resume it or NEW to start a new session:',0
nettab db 2
mkeyw 'New',0
mkeyw 'Resume',1
tcpadrst db cr,lf,' tcp/ip address: $' ; TCP/IP status msgs
tcpsubst db cr,lf,' tcp/ip subnetmask: $'
tcpdomst db cr,lf,' tcp/ip domain: $'
tcpgatest db cr,lf,' tcp/ip gateway: $'
tcppnsst db cr,lf,' tcp/ip primary-nameserver: $'
tcpsnsst db cr,lf,' tcp/ip secondary-nameserver: $'
tcpbcstst db cr,lf,' tcp/ip broadcast: $'
tcphostst db cr,lf,' tcp/ip host: $'
tcpportst db cr,lf,' tcp/ip port: $'
tcppdintst db ', Packet-Driver-interrupt: \x$'
tcppdnul db ' (search for it)$'
tcpttyst db cr,lf,' tcp/ip telnet-term-type: $'
tcpttynul db '(report real terminal type)',0 ; ASCIIZ
tcphlp db cr,lf,' Host Internet name machine.domain or'
db ' Internet address nnn.nnn.nnn.nnn'
db cr,lf,' or * to become a Telnet server.'
db cr,lf,' Optional TCP port number may follow the host name.$'
tcpporthlp db cr,lf,' TCP port on host, 23 is Telnet.$'
badport db cr,lf,'?Port 25 is forbidden, sorry. Use 23 for Telnet.$'
lastchar db 0 ; previous char sent, for NVT
tcponptr dw ktcpstart,seg _TEXT ; far pointers to TCP start
tcpoffptr dw ktcpstop,seg _TEXT ; and stop procedures
data ends
code2 segment
extrn tekstat:far
code2 ends
code segment
extrn comnd:near, dopar:near, atoi:near, prompt:near
extrn isfile:near, strlen:near, strcpy:near
extrn prtasz:near
extrn sleep:near, msuinit:near, keybd:near
extrn kbdlini:near, kbdlend:near
extrn ans_keystr:near
extrn pntchr:near, pntflsh:near
extrn decout:near, valout:near
extrn katoi:near
extrn vt100:near, vt100_ini:near, vt100_reset:near
extrn vt100_save:near, vt100_restore:near, vt100_modlin:near
extrn vt100_dump:near, vt100_color:near
extrn vt100_rupn:near, vt100_rdnn:near
extrn vt100_prnl:near, vt100_prns:near
extrn prn_chk:near ; in MSYP98.ASM
extrn set_modlin:near ; in MSYP98.ASM
extrn gdisp_on:near ; in MSGP98.ASM
extrn set_gcolor:near ; in MSGP98.ASM
extrn text_scrn:near ; in MSZP98.ASM
extrn pc98_bell:near ; in MSZP98.ASM
extrn pc98_tstrt:near ; in MSZP98.ASM
extrn pc98_tend:near ; in MSZP98.ASM
extrn pcwait:near ; in MSZP98.ASM
extrn pcwtst:near ; in MSZP98.ASM
extrn tek4014:near, tek4014_ini:near, tek4014_reset:near
extrn tek4014_save:near, tek4014_restore:near, tek4014_modlin:near
extrn tek4014_color:near
extrn sixel_rollup:near, sixel_rolldown:near
extrn sense_sftkey:near
extrn set_keydef:near, reset_keydef:near
extrn is_kanji1:near, s2jis:near, jis2s:near
assume cs:code,ds:data,es:nothing
;-----------------
; Utility Package
;-----------------
fprtasz proc far
call prtasz
ret
fprtasz endp
fdecout proc far
call decout
ret
fdecout endp
fvalout proc far
call valout
ret
fvalout endp
NOUT PROC NEAR
; Copy numeric value from AX to ASCII buffer indicated by DI.
; DI is updated.
mov dx,0
mov bx,10
div bx
push dx ; save remainder digit
or ax,ax ; anything left?
jz nout1 ; no, start output phase
call nout
nout1: pop ax ; retrieve a digit
add al,'0' ; make it ASCII
stosb ; put it in buffer
ret
NOUT ENDP
ENT_VT PROC NEAR
;@@ call vt100_restore
and vt100_gflag,7Fh ; mask text screen control
call set_gcolor
call set_modlin
call vt100_modlin
mov kanji_rmode,0 ; clear all kanji pending flags
mov kanji_smode,0
ret
ENT_VT ENDP
ENT_TK PROC NEAR
;@@ call cmblnk
;@@ call tek4014_restore
and vt100_gflag,7Fh
cmp vt100_gflag,4 ; TeK screen ?
jge ent_tk_1 ; ge = yes
mov vt100_gflag,4
ent_tk_1:
or vt100_gflag,80h ; set text screen cotrol bit
call set_gcolor
call set_modlin
call tek4014_modlin
mov kanji_rmode,0
mov kanji_smode,0
ret
ENT_TK ENDP
SET_CUR_COLOR PROC NEAR
;
; Set the current color. The color table is given in [si] - [si+3]
;
push ax
push di
mov di,offset scn_color ; copy color to current buffer
mov ax,[si] ; fore & back
mov [di],ax
mov ax,[si+2] ; highlight & modeline
mov [di+2],ax
pop di
pop ax
ret
SET_CUR_COLOR ENDP
;---------------------------------------------------------------------------
; Clear the input buffer. This throws away all the characters in the
; serial interrupt buffer. This is particularly important when
; talking to servers, since NAKs can accumulate in the buffer.
CLRBUF PROC NEAR
cli
mov srcpnt,offset source ; receive circular buffer
mov count,0
sti
cmp repflg,0 ; in replay mode ?
jne clrbf2 ; ne=yes. do not read any character.
clrbf1:
call prtchr ; empty any intermediate buffers
jnc clrbf1 ; got a char, clear again
clrbf2:
cli
push ax
mov ax,offset source ; reset pointers
mov rcvpnt,ax
mov srcpnt,ax
mov count,0
pop ax
sti
ret
CLRBUF ENDP
; Clear to the end of the current line. Returns normally.
CLEARL PROC NEAR
push ax
push dx
mov ah,prstr
mov dx,offset clreol
int dos
pop dx
pop ax
ret
CLEARL ENDP
code ends
code1 segment
assume cs:code1
ftcpstats proc far ; TCP/IP status display
mov ah,prstr
mov dx,offset tcpadrst
int dos
mov dx,tcpdata[0] ; offset of tcpaddress string
call fprtasz
mov dx,offset tcpsubst
int dos
mov dx,tcpdata[2] ; offset of tcp subnetmask string
call fprtasz
mov dx,offset tcpdomst
int dos
mov dx,tcpdata[4] ; offset of tcp domain string
call fprtasz
mov dx,offset tcpgatest
int dos
mov dx,tcpdata[6] ; offset of tcp gateway string
call fprtasz
mov dx,offset tcppnsst
int dos
mov dx,tcpdata[8] ; offset of tcp primary nameserver
call fprtasz
mov dx,offset tcpsnsst
int dos
mov dx,tcpdata[10] ; offset of tcp secondary nameserver
call fprtasz
mov dx,offset tcpbcstst
int dos
mov dx,tcpdata[14] ; offset of tcp broadcast address
call fprtasz
mov dx,offset tcpportst
int dos
push ax
push bx
push cx
mov bx,tcpdata[16] ; offset of tcp port
mov ax,[bx]
call fdecout
mov ah,prstr
mov dx,offset tcppdintst
int dos
mov bx,tcpdata[18] ; offset of Packet Driver interrupt
mov ax,[bx]
mov cx,16
push ax
call fvalout ; show value as hex
pop ax
or ax,ax ; null?
jnz ftcpst1 ; nz = no, just show value
mov ah,prstr
mov dx,offset tcppdnul ; show search msg
int dos
ftcpst1:pop cx
pop bx
pop ax
mov dx,offset tcpttyst
int dos
mov dx,tcpdata[20] ; offset of tcp term-type override
push bx
mov bx,dx
cmp byte ptr [bx],0
jne ftcpst2
mov dx,offset tcpttynul ; alternate msg
ftcpst2:pop bx
call fprtasz
mov dx,offset tcphostst
int dos
mov dx,tcpdata[12] ; offset of tcp host ident string
call fprtasz
ret
ftcpstats endp
code1 ends
code segment
assume cs:code
; SHOW MODEM, displays current status of lines DSR, CD, and CTS.
; Uses byte mdmhand, the modem line status register.
shomodem proc near
mov ah,cmeol ; get a confirm
call comnd
jnc shomd1a ; nc = success
ret ; no confirm
shomd1a: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 not ready msg
test mdmhand,moddsr ; is DSR asserted?
jz shomd1 ; z = no
mov dx,offset msmsg2 ; say asserted
shomd1: int dos
mov dx,offset msmsg3 ; CD not asserted msg
test mdmhand,modcd ; CD asserted?
jz shomd2 ; z = no
mov dx,offset msmsg4 ; say asserted
shomd2: int dos
mov dx,offset msmsg5 ; CTS asserted msg
test mdmhand,modcts ; CTS asserted?
jz shomd3 ; z = no
mov dx,offset msmsg6 ; say asserted
shomd3: mov ah,prstr
int dos
shomd3c:call ftcpstats ; call TCP/IP FAR worker
clc
ret
shomodem endp
;
; returns modem status in AL.
;
getmodem proc near
push bx
push dx
mov dx,modem.mdstat ; read status of port
in al,dx
and al,80h ; set only DR bit
mov bl,al ; save it
mov dx,modem.mdsig ; read signal
in al,dx
and al,60h ; set CS and CD only
or bl,al
;
mov al,0
test bl,80h ; is DSR asserted?
jz getmd1 ; z = no
or al,moddsr ; set DSR bit
getmd1:
test bl,20h ; CD asserted?
jnz getmd2 ; nz = no
or al,modcd ; set CD bit
getmd2:
test bl,40h ; CTS asserted?
jnz getmd3 ; nz = no
or al,modcts ; set CTS bit
getmd3:
pop dx
pop bx
ret
getmodem endp
; Put the char in AH to the serial port, assumimg the port is active.
; Returns carry clear if success, else carry set.
OUTCHR PROC NEAR
cmp repflg,0 ; in REPLAY mode?
je outch0 ; e=no
cmp ah,03h ; CTRL-C ?
je outch0_1 ; e=yes
xor replay_hold,1 ; toggle replay_hold flag
clc
jmp outch0_2
outch0_1:
stc
outch0_2:
ret
outch0:
test flowcnt,1 ; doing XON/XOFF flow control?
jz outch2 ; z = no, just continue
cmp ah,flowoff ; sending xoff?
jne outch1 ; ne = no
mov xofsnt,usron ; indicate user level xoff being sent
jmp short outch1b
outch1: and xofsnt,not usron ; cancel user level xoff
cmp ah,flowon ; user sending xon?
jne outch1b ; ne = no
mov xofsnt,off ; say an xon has been sent (cancels xoff)
outch1b:cmp xofrcv,off ; Are we being held (xoff received)?
je outch2 ; e = no - it's OK to go on
push cx ; save reg
mov ch,15 ; 15 sec timeout interval
xor cl,cl ; convert to 4 millsec increments
outch1a:cmp xofrcv,off ; are we being held (xoff received)?
je outch1c ; e = no - it's OK to go on
push ax
mov ax,4 ; 4 millisec wait loop
call pcwait
pop ax
loop outch1a ; and try it again
mov xofrcv,off ; timed out, force it off
outch1c:pop cx ; end of XON/XOFF control section
OUTCH2: mov al,ah ; Parity routine works on AL.
call dopar ; Set parity appropriately
mov ah,al ; Don't overwrite character with status
outch3eb:cmp flags.comflg,'S' ; SIAM? (speed is critical)
jne outch3 ; ne = no.
jmp outchs
outch3: cmp flags.comflg,'N' ; Network port ?
jne outch3e ; ne = no.
jmp outchn ; yes
outch3e:cmp flags.comflg,'t' ; TCP/IP Telnet?
jne outch3ea
jmp outchn
outch3ea:cmp flags.comflg,'W' ; Novell NASI ?
jne outch3ec
jmp outchn
outch3ec:cmp flags.comflg,'D' ; DOS device ?
jne outch3a ; ne = no.
jmp outchd
outch3a:push cx
push dx ; Save register.
cmp dupflg,0 ; full duplex?
jne outch3b ; ne = no, half
test flowcnt,2 ; using RTS tp cpmtrp; omcoming chars ?
jz outch3d ; z = no
mov cx,8000 ; ~10 seconds worth of wating on CTS
jmp short outch3c ; do CTS test/waiting
outch3b:mov dx,modem.mdcom ; modem command reg.
mov al,ccmd ; assert RTS for for hardware transmit
out dx,al
jmp $+2
jmp $+2
mov dx,modem.mdstat ; modem status reg.
in al,dx
test al,80h ; ignore CTS if DSR is not asserted
jz outch3d ; z = DSR not asserted
mov cx,8000 ; ~10 seconds worth of wating on CTS
; wait on CTS (ah has output char)
outch3c:mov dx,modem.mdsig ; modem signal reg.
in al,dx ; wait on CTS (ah has output char)
test al,40h ; is CTS asseerted?
jz outch3d ; z = yes
push ax ; preserve char in ah
mov ax,1 ; wait one millisec
call pcwait
pop ax
loop outch3c
; timeout, make non-fatal
outch3d:
outch3f:xor cx,cx
mov dx,modem.mdstat ; get port status
outch3g:in al,dx
test al,txrdy ; Transmitter ready ?
jnz outch4 ; nz = yes
jmp $+2 ; use time, prevent overdriving UART
jmp $+2
loop outch3g
jmp short outch5 ; Timeout
outch4: mov al,ah ; Now send it out
mov dx,modem.mddat
out dx,al
cmp dupflg,0 ; full duplex?
je outch4a ; e = yes
cmp al,trans.seol ; End of line char?
jne outch4a ; ne = no
xor cx,cx
outch4b:
outch4a:pop dx ; exit success
pop cx
clc
ret
outch5: pop dx ; exit failure
pop cx
stc
ret
;
outchn:
push bx
mov bx,offset xmtbuf ; set xfer address
add bx,xmtcnt ; count of chars in buffer
mov [bx],ah ; put char in buffer
pop bx
inc xmtcnt ; count of items in this buffer
cmp xmtcnt,NETBUFLEN ; is buffer full now?
jae outchn1 ; ae = buffer is full, send it now.
cmp ah,trans.seol ; end of packet?
je outchn1 ; e = yes, send buffer.
cmp ah,flowon ; flow control?
je outchn1 ; e = yes, always expedite
cmp ah,flowoff ; ditto for flow off
je outchn1
cmp ttyact,0 ; are we in Connect mode?
je outchn2 ; e = no, wait for more before sending
outchn1:
call send ; network send routine
jc outchn3 ; c = error
outchn2:
clc ; good exit
outchn3:
ret ; bad exit
outchd:
cmp prthnd,0 ; Got a handle yet?
jne outchd3 ; Yup just go on
call opnprt ; Else 'open' the port
outchd3:
cmp prtdev,1 ; device ?
je outchd5 ; e = yes.
xor prthld,1 ; flip-flop
jmp outch5
outchd5:
push bx
push cx
push dx
mov temp,ax ; store the character in the buffer
mov bx,prthnd ; port handle
mov cx,1 ; one byte to write
mov dx,offset temp ; place where data will be found
mov ah,write2 ; dos 2 write to file/device
int dos
pop dx
pop cx
pop bx ; end of revised routine
ret
; SIAM section by Kenji Rikitake (30/Dec/1991)
outchs:
push dx
mov al,ah ; set char to AX
xor ah,ah ; clear AH
siam_PUTSI ax ; send it out
shl ah,1 ; if AH == 0FFH then failed
pop dx ; else AH == 0 and succeeded
ret
OUTCHR ENDP
SEND PROC NEAR
push ax
push bx
push cx
push es
;
push ds
pop es ; ES = DS
mov bx,offset xmtbuf ; xfer start address
mov ah,net_write ; set function
mov al,net_port ; set port
;
send0:
mov cx,xmtcnt ; packet length
jcxz send1
test nettype,tcpnet ; TCP/IP Telnet?
jz send0a ; z = no
call ktcpcom
jmp short send0b
send0a: int NETCI_INT ; send packet
send0b: cmp cx,xmtcnt ; all done ?
jae send1 ; e = yes.
pop ax
mov bx,offset xmtbuf
add bx,cx ; update xfer address
sub xmtcnt,cx
jmp send0
;
send1:
mov xmtcnt,0
pop es
pop cx
pop bx
pop ax
clc
ret
SEND ENDP
; This routine blanks the screen. Returns normally.
CMBLNK PROC NEAR
push ax ; save some registers
push dx
mov ah,prstr
mov dx,offset delscr ; delete screen.
int dos
pop dx
pop ax
ret
CMBLNK ENDP
; Homes the cursor. Returns normally.
LOCATE PROC NEAR
mov dx,0 ; Go to top left corner of screen.
jmp poscur
LOCATE ENDP
; Write a line 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,1800h ; now address line 24
call poscur
pop dx ; get message back
mov ah,prstr
int dos ; write it out
ret ; and return
putmod endp
; clear the mode line written by putmod. Returns normally.
clrmod proc near
mov dx,1800h
call poscur ; Go to bottom row.
call clearl ; Clear to end of line.
ret
clrmod endp
; Put a help message on the screen.
; Pass the message in ax, terminated by a null. Returns normally.
puthlp proc near
push dx ; save regs
push si
push ax ; preserve this
;@@ call cmblnk
;@@ call locate
mov ah,prstr ;@@
mov dx,offset retscr ;@@
int dos ;@@
mov ah,prstr
mov dx,offset crlf
int dos
pop si ; point to string again
cld
puthl3: lodsb ; get a byte
cmp al,0 ; end of string?
je puthl4 ; yes, stop
mov dl,al
mov ah,dconio
int dos ; else write to screen
jmp puthl3 ; and keep going
puthl4: mov ah,prstr
mov dx,offset crlf
int dos
pop si
pop dx
ret
puthlp endp
; Set the baud rate for the current port, based on the value
; in the portinfo structure. Returns normally.
BAUDST PROC NEAR
mov dx,offset bdtab ; baud rate table, ascii
xor bx,bx ; help is the table itself
mov ah,cmkey ; get keyword
call comnd
jc baudst1 ; c = failure
push bx ; save result
mov ah,cmeol ; get confirmation
call comnd
pop bx
jc baudst1 ; c = failure
mov si,portval
mov ax,[si].baud ; remember original value
mov [si].baud,bx ; set the baud rate
call dobaud ; use common code
clc
baudst1:ret
BAUDST ENDP
;
DOBAUD PROC NEAR
cmp flags.comflg,'S' ; SIAM?
je dobauds ; e = SIAM, do SIAM things
push ax
push bx
push dx
;
mov axsave,ax
mov bx,portval
mov ax,[bx].baud
shl ax,1
;
cmp cpu_clock,CPU_5M_CLOCK
je c5mhz
c8mhz:
mov bx,offset bddat8
jmp dobd0
c5mhz:
mov bx,offset bddat5
dobd0:
add bx,ax
cmp word ptr [bx],0FFFFh
jne dobd1
mov ah,prstr
mov dx,offset badbd
int dos
jmp dobd_ex
dobd1:
mov ax,[bx]
cmp pbaud_1,ax ; same as previous baud rate ?
jne dobd2
jmp dobd_ex
dobd2:
call domode ; reset RS-232C chip
mov dx,timer.tmcmd
mov al,timer.tmsel
out dx,al
mov ax,[bx]
mov pbaud_1,ax ; store baud rate
mov dx,timer.tmdat
out dx,al
mov al,ah
out dx,al
mov baud_set,1
dobd_ex:
pop dx
pop bx
pop ax
clc
ret ; Must be set before starting Kermit.
; for SIAM
dobauds:
push ax
push bx
push cx
push dx
;
mov axsave,ax
mov bx,portval
mov ax,[bx].baud
shl ax,1
mov bx,offset siam_bauddat
add bx,ax
cmp word ptr [bx],0FFFFh
jne dobauds1
mov ah,prstr
mov dx,offset badbd
int dos
jmp dobauds_ex
dobauds1:
mov ax,[bx] ; ax = value for siam_setBaud
cmp pbaud_1,ax ; same as previous baud rate ?
jne dobauds2
jmp dobauds_ex
dobauds2:
mov pbaud_1,ax ; store baud rate
siam_setBaud ax ; set SIAM baudrate
siam_setParam 00011000b ; 8-bit, no-parity, 1-stopbit
siam_initSI ; init SIAM
mov baud_set,1
dobauds_ex:
pop dx
pop cx
pop bx
pop ax
clc
ret ; Must be set before starting Kermit.
DOBAUD 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
cmp flags.comflg,'A' ; controlable ?
jae gbaud1 ; ae = No.
push bx
cmp baud_set,1 ; Did we already set baud rate?
je gbaud0 ; yes, so just leave
mov bx,portval
mov [bx].baud,B9600
mov baud_set,1
gbaud0:
pop bx
gbaud2:
ret
gbaud1:
cmp flags.comflg, 'S' ; SIAM?
jne gbaud2 ; ne = No, do nothing
push bx
push cx
push dx
cmp baud_set, 1 ; Did we already set baud rate?
je gbaud3 ; yes, so just leave
siam_getBaud ; get current SIAM baudrate
mov cx, ax ; cx = SIAM baudrate value
shl ax, 1
mov bx, offset siam_datbaud
add bx, ax
mov ax, [bx] ; ax = internal table index
cmp ax, 0FFFFH ; unknown?
jne gbaud4 ; ne = SIAM baudrate already set
mov ax, B9600 ; default = 9600bps
mov cx, SIAM_B9600
gbaud4:
mov bx,portval
mov [bx].baud, ax ; set portval baudrate data
siam_setBaud cx ; set SIAM baudrate
mov baud_set,1
siam_setParam 00011000b ; 8-bit, no-parity, 1-stopbit
gbaud3:
pop dx
pop cx
pop bx
ret
GETBAUD ENDP
; Set the mode for the current port. This is part of the serial
; initialization routine.
DOMODE PROC NEAR
push ax
push cx
push dx
;
mov dx,modem.mdcom ;send 3 zeros to command port to reset chip
mov al,0
out dx,al
mov al,0
out dx,al
mov al,0
out dx,al
mov al,cmode ;enable mode setting
out dx,al
mov cx,100 ;allow chip time to reset
mode1: loop mode1
mov al,mmode ;mode: 16x rate, 8 data, no parity, 1 stop
out dx,al
mov cx,100
mode2: loop mode2
mov al,ccmd ;RTS & DTR high, RX & TX enabled, reset errors
out dx,al
;
pop dx
pop cx
pop ax
ret
DOMODE ENDP
; Get Char from serial port buffer.
; returns carry set if no character available at port, otherwise
; returns carry clear with char in al, # of chars in buffer in dx.
PRTCHR PROC NEAR
cmp repflg,0 ; in replay mode ?
je prtch3a ; e=no.
jmp prtchf
prtch3a:
cmp flags.comflg,'S' ; SIAM? (speed is critical)
jne prtch0
jmp prtchs
prtch0:
cmp flags.comflg,'D'
jne prtch4
jmp prtchd
prtch4:
;@@ call chkxon
cmp flags.comflg,'N'
jne prtch3
mov net_rbuflen,bufsiz
jmp prtchn
prtch3:
cmp flags.comflg,'t'
jne prtch3b
mov net_rbuflen,bufsiz
jmp prtchn
prtch3b:
cmp flags.comflg,'W'
jne prtch3c
mov net_rbuflen,128
jmp prtchn
prtch3c:
cmp count,0
jnz prtch2
xor dx,dx ; No data in buffer
xor al,al
stc ; No data in AL.
ret
prtch2:
pushf
cli ; disable interrupts while manipulating pointers
push si ; save SI (uses in rpack)
mov si,rcvpnt
lodsb ; get a byte
cmp si,offset source + bufsiz ; bigger than buffer?
jb prtch1 ; no, keep going
mov si,offset source ; yes wrap around
prtch1:
dec count
mov rcvpnt,si
mov dx,count
pop si ; restore SI
popf
clc ; we have data in AL
ret
;
; Read from replay file
;
prtchf:
cmp repflg,1 ; nomral state ?
jne prtchf0 ; ne=no
cmp replay_hold,0 ; holding?
je prtchf1 ; e=no
prtchf0:
xor dx,dx ; no char at all.
xor al,al ; with NUL
stc ; no char is available
ret
prtchf1:
push bx
push cx
mov ah,readf2
mov bx,diskio.handle ; file handle
mov cx,1 ; read one char
mov dx,offset rdbuf ; to this buffer
int dos
jc prtchf2 ; c=read failure
cmp ax,cx ; read the byte?
jne prtchf2 ; ne=no
mov al,rdbuf
mov dx,1
clc
jmp prtchf3
prtchf2:
call pc98_bell ; notify that we cannot read.
mov repflg,2
xor dx,dx
xor al,al
stc
prtchf3:
pop cx
pop bx
ret
;
; Read from file/device
;
prtchd:
cmp prthld,0 ; hold ?
je prtchd2 ; e = no
stc
ret
prtchd2:
push bx
push cx
cmp prthnd,0 ; Got a handle yet?
jne prtchd0 ; Yup just go on
call opnprt ; Else 'open' the port
prtchd0:
call chkxon
mov bx,prthnd
mov al,instat ; input status command
mov ah,ioctl ; see note above
int dos
jc prtchd4 ; c = call failed, device not ready
or al,al
jz prtchd4 ; not ready
mov bx,prthnd ; the file handle
mov ah,readf2 ; read file/device
mov cx,1 ; want just one character
mov dx,offset rdbuf ; where to store it
int dos
jnc prtchd1 ; nc = no error
cmp al,5 ; Error condition
je prt3dx
cmp al,6 ; Error condition
je prt3dx
jmp prtchd4 ; else report no char present
prtchd1:;;;mov count,0 ; update count (always 0 for one char reads)
mov dx,0 ; needed to obey rules
or ax,ax ; reading from end of file?
jz prtchd4 ; z = yes
mov al,rdbuf ; recover char
prtchd3:
pop cx
pop bx
ret ; return success (char is in al)
prt3dx: mov ah,prstr
mov dx,offset erms50
int dos
prtchd4:
pop cx
pop bx
xor dx,dx
xor al,al
stc
ret
prtchn:
cmp count,0 ; Data in buffer?
je prtchn0 ; e = No. Get them from port.
jmp prtchn2
prtchn0:
cmp pcnet,1 ; session active?
jbe prtchn0b ; be = no, not active
push ax
push bx
push cx
push es
mov ax,offset source
mov rcvpnt,ax
mov srcpnt,ax
;
mov ah,net_read
mov al,net_port
mov bx,offset source
mov cx,net_rbuflen
push ds
pop es
xor dh,dh ;@@ for tcp/ip
test nettype,tcpnet ; TCP/IP Telnet?
jz prtchn0c ; z = no
call ktcpcom
cmp ah,3 ;@@ for tcp/ip
jb prtchn0a ;@@ for tcp/ip
call nethangup ;@@ for tcp/ip
xor cx,cx ;@@ for tcp/ip
jmp short prtchn0a
prtchn0c:int NETCI_INT
prtchn0a:
mov count,cx
add srcpnt,cx
pop es
pop cx
pop bx
pop ax
cmp count,0
jnz prtchn2
prtchn0b:
xor dx,dx ; no data in buffer
xor al,al
stc ; no data in AL.
ret
prtchn2:
pushf
cli ; disable interrupts while manipulating pointers
push si ; save SI
mov si,rcvpnt
lodsb ; get a byte
dec count
mov rcvpnt,si
;
; I'm not sure the floowings are necesary or not.
; The handshake should be done at network level.
;
; check the data
;
;@@ push bx
;@@ or al,al
;@@ jz prtchn5 ; Ignore nulls.
;@@ mov ah,al ; copy the character in AH
;@@ and ah,parmsk ; apply parity mask
;@@ mov bx,portval
;@@ cmp [bx].floflg,0 ; Doing flow control?
;@@ je prtchn4 ; Nope.
;@@ mov bx,[bx].flowc ; Flow control character (BH=XON, BL=XOFF).
;@@ cmp ah,bl ; Is it an XOFF?
;@@ jne prtchn3 ; Nope, go on.
;@@ mov xofrcv,true ; Set the flag.
;@@ jmp short prtchn5
prtchn3:
;@@ cmp ah,bh ; Get an XON?
;@@ jne prtchn4 ; No, go on.
;@@ mov xofrcv,false ; Clear our flag.
;@@ jmp short prtchn5
;
prtchn4:
;@@ pop bx
mov dx,count ; number of characters in buffer
pop si ; restore SI
popf
clc ; we have data in AL.
ret
prtchn5:
;@@ pop bx
;@@ popf
;@@ jmp prtchn
;
; Read from SIAM
;
prtchs:
call chkxon
siam_getSI ; get a char from SIAM
xor dx,dx ; no data in buffer anyway
shl ah,1 ; if AX == 0FFFFH then AL is invalid
ret ; else AX should be < 7FFFH and AL is valid
PRTCHR ENDP
; local routine to see if we have to transmit an xon
chkxon proc near
cmp flowcnt,0 ; doing flow control?
je chkxo1 ; no, skip all this
test xofsnt,usron ; did user send an xoff?
jnz chkxo1 ; nz = yes, don't contradict it here
test xofsnt,bufon ; have we sent a buffer level xoff?
jz chkxo1 ; z = no, forget it
cmp count,mntrgl ; below (low water mark) trigger?
jae chkxo1 ; no, forget it
test flowcnt,2 ; using RTS/CTS kind?
jz chkxo2 ; z = no
cmp flags.comflg,4 ; using uart?
ja chkxo1 ; a = no, ignore situation
push ax
push dx
mov al,ccmd ; assert RTS for flow-on
mov dx,modem.mdcom ; serial port command port
out dx,al
and xofsnt,off ; remember we've sent the "xon"
pop dx
pop ax
; do software flow control too
chkxo2: test flowcnt,1 ; using XON/XOFF kind?
jz chkxo1 ; z = no
mov ah,flowon ; ah gets xon
and xofsnt,off ; remember we've sent the xon
call outch2 ; send via non-flow controlled entry point
chkxo1: ret
chkxon endp
; IHOSTS - Initialize the host by sending XOFF, or equivalent.
; Requires that the port be initialized before hand.
; Do not send flow control if doing half duplex.
IHOSTS PROC NEAR
push ax ; save the registers
push bx
push cx
push dx
mov xofrcv,off ; clear old xoff received flag
mov xofsnt,off ; and old xoff sent flag
cmp portin,0 ; is a comms port active?
jle ihosts1 ; le = no
mov bx,portval ; port indicator
mov ah,byte ptr [bx].flowc ; put wait flow control char in ah
or ah,ah ; check for null char
jz ihosts1 ; z = null, don't send it
cmp dupflg,0 ; full duplex?
jne ihosts1 ; ne = no, half
call outchr ; send it
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. Do not send flow control if doing half duplex.
IHOSTR PROC NEAR
push ax ; save regs
push bx
push cx
mov xofrcv,off ; clear old xoff received flag
mov xofsnt,off ; and old xoff sent flag
cmp portin,0 ; is a comms port active?
jle ihostr1 ; le = no
mov bx,portval ; port indicator
mov ah,byte ptr [bx].flowc+1; put Go-ahead flow control char in ah
or ah,ah ; check for null char
jz ihostr1 ; z = null
cmp dupflg,0 ; full duplex?
jne ihostr1 ; ne = no, half
call outchr ; send it (release Host's output queue)
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,cmline ; 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
dtrlow1:
call serhng ; drop DTR and RTS
mov ah,prstr ; give a nice message
mov dx,offset hngmsg
int dos
ret
DTRLOW ENDP
; Test version for NEC PC-9801 (03-Sep-1988)
; 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
call serini ; init port, if not done already
mov al,flags.comflg ; get kind of port
cmp al,'A'
jb serhng3
cmp al,'S'
je serhngs
cmp al,'W'
jne serhng1
jmp serhngw
serhng1:
clc ; no hangup
ret
serhng3:
call serrst ; reset port so can be opened again
cli ; disable interrupt
push ax
push dx
mov dx,modem.mdcom ; set command port
mov al,chng ; hangup command
out dx,al
sti
mov ax,500 ; 500 millisec, for pcwait
call pcwait
mov pbaud_1,0FFFFh ; reset previous baud rate
pop dx
pop ax
clc
ret
; when using SIAM, only DTR turns low,
; since SIAM assumes RTS is dedicated for
; flow control.
serhngs:
call serrst ; reset port so can be opened again
push ax
push dx
siam_setER 0 ; turn DTR low
mov ax,500 ; 500 millisec, for pcwait
call pcwait
mov pbaud_1,0FFFFh ; reset previous baud rate
pop dx
pop ax
clc
ret
serhngw:
call serrst
push ax
push cx
mov ah,NETCI_CNTL
mov al,0
mov cx,NETCI_DIS
int NETCI_INT
pop cx
pop ax
clc
ret
SERHNG ENDP
; Send a break out the current serial port. Returns normally.
SENDBR PROC NEAR ; Normal Break
cmp flags.comflg,'N'
je ub_sendbr
cmp flags.comflg,'S'
je siam_sendbr
mov dx,modem.mdcom ; set command port
mov al,cbrk+ccmd ; add break to normal command
out dx,al
mov ax,275 ; wait for 275 milliseconds
call pcwait
mov al,ccmd ; restore normal command
out dx,al
ret
ub_sendbr:
push ax
push cx
mov ah,NETCI_CNTL ; control function
mov al,NETCI_PORT
mov cl,NETCI_BRK ; request break [ohl]
int NETCI_INT ; Net/One command interface int. (6Bh) [ohl]
pop cx
pop ax
ret ; [ohl] ---
siam_sendbr:
siam_sndBRK 1 ; break on
mov ax,275 ; wait for 275 milliseconds
call pcwait
siam_sndBRK 0 ; break off
ret
SENDBR ENDP
SENDBL PROC NEAR ; Long Break
cmp flags.comflg,'N'
je ub_sendbl
cmp flags.comflg,'S'
je siam_sendbl
mov dx,modem.mdcom ; set command port
mov al,cbrk+ccmd ; add break to normal command
out dx,al
mov ax,1800 ; 1.8 second long break
call pcwait
mov al,ccmd
out dx,al ; restore normal command
ret
ub_sendbl:
push ax
push cx
mov ah,NETCI_CNTL ; control function
mov al,NETCI_PORT
mov cl,NETCI_HLD ; request hold
int NETCI_INT ; Net/One command interface int. (6Bh) [ohl]
pop cx
pop ax
ret ; [ohl] ---
siam_sendbl:
siam_sndBRK 1 ; break on
mov ax,1800 ; 1.8 second long break
call pcwait
siam_sndBRK 0 ; break off
ret
SENDBL ENDP
; Position the cursor according to contents of DX:
; DH contains row, DL contains column. Returns normally.
POSCUR PROC NEAR
push di
mov di,offset tmpbuf
mov byte ptr [di],ESCAPE
mov byte ptr [di+1],'['
add di,2
mov al,dh
xor ah,ah
inc ax
push dx
call nout
mov byte ptr [di],';'
inc di
pop dx
mov al,dl
xor ah,ah
inc ax
call nout
mov byte ptr [di],'H'
mov byte ptr [di+1],'$'
mov dx,offset tmpbuf
mov ah,prstr
int dos
pop di
ret
POSCUR ENDP
; Move the cursor to the left margin, then clear to end of line.
; Returns normally.
CTLU PROC NEAR
mov ah,prstr
mov dx,offset clrlin
int dos
call clearl
ret
CTLU ENDP
NETHANGUP PROC NEAR
mov al,flags.comflg ; get type of port
cmp al,'N'
jne nethang5
mov ah,NETCI_CLOSE ; UB-NETCI close command
mov al,net_port
int NETCI_INT
jmp nethang7
nethang5:
cmp al,'W' ; Novell NASI ?
jne nethang6 ; ne = no
mov ah,NETCI_CNTL
mov al,NETCI_DIS
int NETCI_INT
clc
ret
nethang6:test nettype,tcpnet ; TCP Telnet?
jz nethang7 ; z = no
call tcpclose ; close the system
nethang7:
mov portn.portrdy,0 ; say the comms port is not ready
mov pcnet,1 ; say network but no session
call serrst ; reset the serial port for reiniting
clc
ret
NETHANGUP ENDP
NETCLOSE PROC NEAR
call nethangup
mov pcnet,0 ; say no network
mov portn.portrdy,0 ; say comms port is not ready
clc
ret
NETCLOSE ENDP
; Called only when Kermit exits. Program pointer passed to mssker
; in word 'lclexit'.
; This is used as a local end routine.
finexit proc near
push ax
call netclose
call clsprt ; close device if opened.
test vtgrph_flg,EXITG_BIT
jz finexit2
call gdisp_on ; graphic display on
finexit2:
call reset_keydef ; reset key definition table
call kbdlend ; local reset keyboard routine
call pc98_tend ; reset tick-timer
mov ah,prstr ;@@
mov dx,offset nrmscr ;@@
int dos ;@@
pop ax
ret
finexit endp
; Call these routines when suspending Kermit to go to DOS
suspend proc near
; set keyboard to DOS
cmp flags.comflg,'t' ; doing TCP?
je suspen1 ; e = yes, don't touch port
cmp flags.comflg,'W'
je suspen1
call ihosts ; suspend the host
mov ax,20 ; wait 20 millisec for port to finish
call pcwait
call serrst
suspen1:ret
suspend endp
; Call these routines when returning to Kermit from DOS
restore proc near
; restore keyboard setting
cmp flags.comflg,'t' ; doing TCP?
je restor1 ; e = yes, don't touch port
cmp flags.comflg,'W'
je restor1
call serini ; reinit serial port
call ihostr ; resume the host
restor1:ret
restore endp
; Start a TCP/IP Telnet session. Set nettype if successful.
tcpstart proc near
mov net_port,0
mov net_read,TCPIP_READ
mov net_write,TCPIP_WRITE
mov bx,offset tcpdata ; pass near pointer to msntni.asm
call dword ptr tcponptr ; call ktcpstart
cmp ax,2 ; successful?
je tcpstart1 ; e = yes
call tcpclose
stc ; fail
ret
tcpstart1:mov pcnet,2
or nettype,tcpnet ; say a session is active
clc
ret
tcpstart endp
; Close/shutdown/terminate a TCP/IP Telnet session
tcpclose proc near
call dword ptr tcpoffptr ; call ktcpstop
and nettype,not tcpnet ; clear activity flag
mov portn.portrdy,0 ; say the comms port is not ready
mov pcnet,0 ; say no network
call serrst ; reset the serial port for reiniting
;@@ mov portin,-1 ; need port re-initialization
cmp ax,1 ; successful?
je tcpclo2 ; e = yes
tcpclo1:stc ; fail
ret
tcpclo2:
clc
ret
tcpclose endp
; Start a Novell NASI session. Set nettype if successful.
nasistart proc near
mov count,0
mov xmtcnt,0
mov net_port,0
mov net_read,NETCI_READ
mov net_write,NETCI_WRITE
;
;@@ mov net_read,NASI_READ
;@@ mov net_write,NASI_WRITE
;@@ mov ah,11h ; NASI alloc circuit
;@@ mov al,0
;@@ int NETCI_INT ; NASI int = NETCI int
;@@ jnc nasistart1 ; nc = no error
;@@ mov ax,offset nasier1 ; set error message
;@@ jmp nasisterr ; error return
nasistart1:
;@@ mov net_port,al ; save circuit number
;@@ push ds
;@@ pop es ; ES = DS
;@@ mov bx,offset nasi_port ; port information
;@@ mov ah,21h ; Query name
;@@ mov cx,0 ; sets service name
;@@ int NETCI_INT
;@@ jnc nasistart2 ; nc = no error
;@@ mov ax,offset nasier2 ; set error message
;@@ jmp nasisterr ; error return
nasistart2:
;@@ mov al,net_port
;@@ mov bx,offset nasi_port
;@@ xor bx,bx
;@@ xor cx,cx
;@@ mov ah,16h ; init virtual circuit
;@@ int NETCI_INT
;@@ jnc nasistart3 ; nc = no error
;@@@ mov ax,offset nasier3 ; set error message
;@@@ jmp nasisterr ; error return
;@@ jmp nasistart2 ; try again
nasistart3:
and nettype,not tcpnet
mov pcnet,2
clc ; success
ret
nasisterr:
push dx
mov dx,ax
mov ah,prstr
int DOS
pop dx
stc
ret
nasistart endp
; Close/shutdown/terminate a Novell NASI session
nasiclose proc near
;@@ mov al,net_port
;@@ mov ah,17h ; disconnect
;@@ int NETCI_INT
;@@ mov portn.portrdy,0 ; say the comms port is not ready
mov ah,NETCI_CNTL
mov al,NETCI_PORT
mov cx,NETCI_DIS
int NETCI_INT
mov pcnet,0 ; say no network
call serrst ; reset the serial port for reiniting
;@@ mov portin,-1 ; need port re-initialization
;@@ cmp ax,1 ; successful?
;@@ je nasiclo2 ; e = yes
;@@nasiclo1:stc ; fail
;@@ ret
nasiclo2:
clc
ret
nasiclose endp
; Open NETCI port
ubstart proc near
cmp pcnet,0 ; netport is closed ?
jne ubstartx
push ax
push bx
push cx
push es
;
call clrbuf
mov xmtcnt,0
push ds
pop es
mov bx,offset source
mov cx,bufsiz
mov ah,NETCI_OPEN
mov al,NETCI_PORT
mov net_port,al
mov net_write,NETCI_WRITE
mov net_read,NETCI_READ
int NETCI_INT
mov pcnet,2
;
pop es
pop cx
pop bx
pop ax
ubstartx:
clc
ret
ubstart endp
chknet proc near
clc
ret
chknet endp
; Get a file handle for the communications port. Use DOS call to get the
; next available handle. If it fails, ask user what value to use (there
; should be a predefined handle for the port, generally 3). The open
; will fail if the system uses names other than "COM1" or "COM2".
opnprt proc near
mov dx,offset prtnam ; port name
mov ah,open2 ; open file/device
mov al,2 ; for reading/writing
int dos
jnc opnpr2 ; nc = no error so far
stc ; set carry for failure
ret
opnpr2: mov prthnd,ax ; Call succeeded
mov prtdev,1 ; device is assumed
mov ah,ioctl
mov al,00h ; get device info
xor dx,dx
mov bx,prthnd ; port's handle
int dos
test dl,80h ; is device ?
jnz opnpr3 ; nz = yes.
mov prtdev,0 ; say this is a file
ret
opnpr3:
or dl,20h ; set raw mode in device info
mov dh,0
mov ah,ioctl
mov al,01h ; set device info
int dos
ret ; carry clear for success
opnprt endp
clsprt proc near
cmp prthnd,0 ; already closed ?
je clsprt1 ; e = yes. Do nothing.
push ax
push bx
mov ah,close2
mov bx,prthnd
int dos
mov prthnd,0
pop bx
pop ax
clsprt1:
ret
clsprt endp
chknew proc near
mov dx,offset naskpmt ; prompt for New or Resume
call prompt
mov dx,offset nettab ; table of answers
xor bx,bx ; help for the question
mov ah,cmkey ; get answer keyword
mov comand.cmcr,1 ; allow bare CR's
call comnd
mov comand.cmcr,0 ; dis-allow bare CR's
jc chknew1 ; c = failure, means Resume
push bx
mov ah,cmeol ; get a confirm
call comnd
pop bx
jc chknew1 ; c = failure, resume session
or bx,bx ; 0 for new?
je chknew1 ; set carry for resume
stc
chknew1:ret
chknew endp
;
; Set the current port.
;
COMS PROC NEAR
mov dx,offset comptab ; table of legal comms ports
xor bx,bx ; no extra help text
mov ah,cmkey ; parse key word
call comnd
jnc coms0a ; nc = success
ret ; failure
coms0a: cmp bl,'3' ; networks?
ja comstrt ; a = yes
mov ah,cmeol ; non-network
push bx
call comnd ; get a confirm
pop bx
jnc comstrt ; nc = success
ret ; failure
COMSTRT:mov temp,bx ; port ident is in BL
cmp bl,'N' ; Network ?
jne comst1 ; ne = no
jmp comsn ; Yes, setup for networks
comst1:
cmp bl,'D' ; Device ?
jne comst2
jmp comsd ; Yes, setup for device
comst2:
cmp bl,'t' ; Telnet, internal?
jne comst2a
jmp comstn
comst2a:
cmp bl,'W' ; Novell NASI
jne comst3
jmp comsn
comst3:
cmp bl,'S' ; SIAM?
jne comst4
jmp comss
comst4:
mov bx,temp ; get port number/letter
mov flags.comflg,bl ; remember port number
xor bh,bh ; clear high byte
mov bl,flags.comflg ; get COMx number (1-3)
push bx
pop bx
mov ax,offset port1
mov portval,ax
call inita
clc
ret
comsn:
mov temp,bx
mov ah,cmeol
call comnd ; Get a confirm
jnc comsn0
ret ; Didn't get a confirm
comsn0:
call serrst ; reset serial port
mov bx,temp
call chknet ; check network status
jnc comsn4 ; nc = OK
ret ; return failure
comsn4:
mov bx,temp
mov portval,offset portn ; set netowrk port data
mov flags.comflg,bl ; set the comm port flag.
clc ; return sucess
ret
;
comsd:
; Set device name. Taken from 'setdmp' in MSSSET.ASM
; Puts device name in global string prtnam.
mov dx,offset rdbuf ; work area
mov rdbuf,0 ; clear it
mov bx,offset prthlp ; help message
mov ah,cmword ; allow paths
call comnd
jnc comsd0
ret
comsd0:
mov ah,cmeol
call comnd
jnc comsd1
ret
comsd1:
mov dx,offset rdbuf ; assume we will use this text
call strlen ; filename given?
push si
push di
mov si,dx ; for strcpy
cmp cx,0 ; length of user's filename
jg comsd2 ; g = filename is given
mov si,offset prtdef ; no name, use default instead
comsd2:
mov di,offset prtnam ; copy to globally available loc
call strcpy
pop di
pop si
call serrst ; reset serial port
call clsprt ; close previous device if exists.
call opnprt ; open device
jnc comsd3
stc
ret
comsd3:
mov portval,offset portd ; set device port data
mov flags.comflg,'D'
clc
ret
; TCP/IP Telnet
comstn: mov ah,cmword ; get a word (remote node name)
mov comand.cmblen,60 ; set 60 byte limit plus null
mov dx,offset decbuf ; work buffer
mov word ptr decbuf,0 ; insert terminator
mov bx,offset tcphlp ; help message
call comnd ; get the name
jc comstnx
mov ah,cmword ; get optional Port number
mov comand.cmblen,5 ; set 5 byte limit plus null
mov dx,offset decbuf+81 ; far from real node names
mov decbuf+80,'\' ; \number prefix, just in case
mov word ptr decbuf+81,0 ; clear entry
mov bx,offset tcpporthlp
call comnd
jc comstnx
mov ah,cmeol
call comnd ; get a confirm
jnc comstn1 ; nc = ok so far
comstnx:ret ; did not get a confirm
comstn1:cmp decbuf,0 ; anything new given?
jnz comstn2 ; nz = yes, copy it
cmp tcphost,0 ; have a name already?
jnz comstn3 ; nz = yes
stc ; return failure (no host name)
ret
comstn2:test nettype,tcpnet ; is there an active tcp session?
jz comstn2a ; z = no
call chknew ; ask about new/old connection
jc comstn3 ; c = resume old
call tcpclose ; end old session
comstn2a:mov si,offset decbuf
mov di,offset tcphost
call strcpy ; copy new host name
mov si,offset decbuf+81 ; optional port number
cmp byte ptr [si],0 ; any port specified?
je comstn2c ; e = no, use default
cmp byte ptr [si],'\' ; user specified leading backslash?
je comstn2b ; e = yes
dec si ; then use ours
comstn2b:call katoi ; convert si to number in ax
cmp ax,25 ; this one?
je comstn4 ; e = yes
or ax,ax ; this one?
jnz comstn2d ; nz = no
comstn2c:mov ax,23 ; use official Telnet port
comstn2d:mov bx,tcpdata+16 ; holds offset of tcpport
mov [bx],ax ; copy new port
comstn3:call serrst ; close current port
mov portval,offset portn ; set Network port data structure address
push bx
mov bx,portval
;@@ mov [bx].sndproc,offset ubsend
;@@ mov [bx].rcvproc,offset ubrecv
pop bx
mov flags.comflg,'t' ; what we want, may not have yet
mov nsbrk,1 ; network BREAK supported
mov portin,0
clc
ret
comstn4:mov ah,prstr
mov dx,offset badport ; say bad port number
int dos
stc
ret
; SIAM interface section
comss:
mov temp,bx
mov ah,cmeol
call comnd ; Get a confirm
jnc comss0
ret ; Didn't get a confirm
comss0:
call serrst ; reset serial port
call siam_setseg ; check if SIAM exists
jnc comss1 ; nc = successful
mov ah, prstr
mov dx, offset siammsg_nosiam ; SIAM does not exist
int dos
stc ; failed
ret
comss1:
mov ah, GETPSP ; get process ID
int 21H
mov processID, bx
siam_openSI processID ; check if SIAM is already used
cmp ax, processID
je comss2 ; kermit can use SIAM
mov ah, prstr
mov dx, offset siammsg_in_use ; SIAM has been used
int dos
stc ; failed
ret
comss2:
mov portval,offset ports ; set network port data structure address
mov flags.comflg,'S' ; set the comm port flag.
siam_closeSI processID ; close SIAM immediately
siam_errReset ; reset errors in SIAM
call getbaud ; set baudrate and word length
siam_initSI ; initialize SIAM
clc ; return sucess
ret
;
COMS ENDP
; SIAM Interface section
; check SIAM is resident and
; if resident clear carry flag and
; set siam_seg to the segment address (in AX)
; (assigns the first SIAM driver found)
; if not resident set carry flag
SIAM_SETSEG PROC NEAR
mov bh, AP_NO_SIAM
siam_setseg1: push bx
mov ax, MAGIC
mov bl, FN_NO_SIAM
int 2FH
cmp bx, MAGIC2
pop bx
jz siam_found ; Found
inc bh
cmp bh, (MAX_PORT - 1)
jbe siam_setseg1
stc ; Not found
ret
siam_found: mov siam_seg, ax ; Found
clc
ret
SIAM_SETSEG ENDP
; Set heath emulation on/off.
VTSTAT PROC NEAR ; For Status display [jrd]
push ax
push bx
push cx
push dx
push si
push di
push es
;
push ds
pop es
cld
; CPU clock
mov si,offset clkmsg
mov cx,8
cmp cpu_clock,CPU_5M_CLOCK
je vtstat0
add si,cx
vtstat0:
mov di,offset vstmsg_clk
rep movsb
; Display
mov si,offset dspmsg
mov cx,8
cmp display_mode,0
je vtstat0_1
add si,cx
vtstat0_1:
mov di,offset vstmsg_dsp
rep movsb
; Keyclick
mov si,offset onmsg
mov cx,3
test vt100_flags,KEYCLICK_BIT
jz vtstat1
add si,cx
vtstat1:
mov di,offset vstmsg_key
rep movsb
; Log-cooked
mov si,offset onmsg
mov cx,3
test vt100_lflag,LOGCOOK_BIT
jz vtstat2
add si,cx
vtstat2:
mov di,offset vstmsg_logcook
rep movsb
; Autowrap
mov si,offset onmsg
mov cx,3
test vt100_flags,AUTOWRAP_BIT
jz vtstat3
add si,cx
vtstat3:
mov di,offset vstmsg_autow
rep movsb
; Cursor key mode
mov si,offset applmsg
mov cx,11
mov di,offset vstmsg_curmod
cmp curkey_mode,0
je vtstat5
add si,cx
vtstat5:
rep movsb
; Keypad mode
mov si,offset applmsg
mov cx,11
mov di,offset vstmsg_kpdmod
cmp keypad_mode,0
je vtstat7
add si,cx
vtstat7:
rep movsb
; Foreground
mov si,offset colmsg
mov di,offset def_color
mov al,[di]
mov ah,0
mov cx,7
imul cl
add si,ax
mov di,offset vstmsg_colf
rep movsb
; Background
mov si,offset colmsg
mov di,offset def_color
mov al,[di+1]
mov ah,0
mov cx,7
imul cl
add si,ax
mov di,offset vstmsg_colb
rep movsb
; Highlight
mov si,offset colmsg
mov di,offset def_color
mov al,[di+2]
mov ah,0
mov cx,7
imul cl
add si,ax
mov di,offset vstmsg_colh
rep movsb
; Modeline
mov si,offset colmsg
mov di,offset def_color
mov al,[di+3]
mov ah,0
mov cx,7
imul cl
add si,ax
mov di,offset vstmsg_colm
rep movsb
; Kanji-code send
mov si,offset knjmsg
mov ah,0
mov al,kanji_scode
mov cx,9
imul cl
add si,ax
mov di,offset vstmsg_sknj
rep movsb
; Kanji-code receive
mov si,offset knjmsg
mov ah,0
mov al,kanji_rcode
mov cx,9
imul cl
add si,ax
mov di,offset vstmsg_rknj
rep movsb
; Keyinput
mov si,offset keyinmsg
mov ah,0
mov al,keyin_dos
mov cx,6
imul cl
add si,ax
mov di,offset vstmsg_keyin
rep movsb
; Insert/Replace
mov si,offset insrepmsg
mov cx,7 ; message length
test vt100_flags,INSERT_BIT
jz vtstat10
add si,cx
vtstat10:
mov di,offset vstmsg_insrep
rep movsb
; Origin-mode
mov si,offset originmsg
mov cx,8
test vt100_flags,ORIGIN_BIT
jz vtstat11
add si,cx
vtstat11:
mov di,offset vstmsg_origin
rep movsb
; Line-feed/New-line
mov si,offset lfnlmsg
mov cx,9
test vt100_flags,NEWLINE_BIT
jz vtstat12
add si,cx
vtstat12:
mov di,offset vstmsg_lfnl
rep movsb
;
mov ah,prstr
mov dx,offset vstmsg
int dos
;
call tekstat
mov dx,si
mov ah,prstr
int dos
;
pop es
pop di
pop si
pop dx
pop cx
pop bx
pop ax
ret ; no emulator status to display
VTSTAT 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
push ax
push bx
push cx
push dx
mov dmphand,-1 ; preset illegal handle
mov dx,offset dmpname ; name of disk file, from mssset
mov ax,dx ; where isfile wants name ptr
call isfile ; what kind of file is this?
jc dmp5 ; c = no such file, create it
test byte ptr filtst.dta+21,1fh ; file attributes, ok to write?
jnz dmp0 ; nz = no.
mov al,1 ; writing
mov ah,open2 ; open existing file
int dos
jc dmp0 ; c = failure
mov dmphand,ax ; save file handle
mov bx,ax ; need handle here
mov cx,0ffffh ; setup file pointer
mov dx,-1 ; and offset
mov al,2 ; move to eof minus one byte
mov ah,lseek ; seek the end
int dos
jmp dmp1
dmp5: test filtst.fstat,80h ; access problem?
jnz dmp0 ; nz = yes
mov ah,creat2 ; file did not exist
mov cx,20h ; attributes, archive bit
int dos
mov dmphand,ax ; save file handle
jnc dmp1 ; nc = ok
dmp0: call beep
pop dx
pop cx
pop bx
pop ax
clc
ret
dmp1: mov ah,ioctl ; is destination ready for output?
mov al,7 ; test output status
mov bx,dmphand ; handle
int dos
jc dmp0 ; c = error
cmp al,0ffh ; ready?
jne dmp0 ; ne = not ready.
;
cmp flags.vtflg,tttek
jne dmp_v1
call ent_vt
dmp_v1:
mov bx,dmphand ; need file handle
call vt100_dump
;
mov bx,offset tmpbuf
mov byte ptr [bx],CTLZ ; put EOF mark
mov dx,bx
mov bx,dmphand
mov cx,1
mov ah,write2
int dos ; write EOF
;
mov ah,close2 ; close the file now
int dos
;
pop dx
pop cx
pop bx
pop ax
clc
ret
DUMPSCR ENDP
; Initialize variables to values used by this routine.
lclini:
call detclck ; determine CPU clock
call pcwtst ; adjust wait counter
call pc98_tstrt ; start pc98 tick-timer
call scrncheck ; check the screen
mov prthnd,0 ; No handle yet
mov portval,offset port1 ; default portval
mov pbaud_1,0FFFFh ; previous baud rate is unknown
mov flags.comflg,1 ; Communication port 1
mov flags.chrset,932 ; force to CP932(Shift-JIS)
mov flags.vtflg,ttvt102 ; override default terminal type
call getbaud ; Put the baud rate in portval [08-Feb-89]
mov curkey_mode,0 ; cursor key is ANSI normal
mov keypad_mode,0 ; keypad is normal
mov vt100_flags,AUTOTEK_BIT ; set flags
mov vt100_lflag,LOGCOOK_BIT ; log mode is cooked
mov vt100_gflag,0
mov kanji_scode,KNJCODE_DEC ; DEC kanji code
mov kanji_rcode,KNJCODE_DEC
mov kanji_smode,0 ; 1st character must be Kanji 1st byte.
mov kanji_rmode,0
mov xmtcnt,0 ; clear counter for xfer
or flags.remflg,d8bit ; display 8-bit
call set_keydef
mov lclsusp,offset suspend ; call this when suspending to DOS
mov lclrest,offset restore ; call this when returning from DOS
mov lclexit,offset finexit ; call this when exiting Kermit
call msuinit ; declare keyboard translator present
call kbdlini ; keyboard local initialize
call vt100_ini ; initialize VT100 terminal emulator
call tek4014_ini ; initialize TEK4014 terminal emulator
push si
mov si,offset def_color
call set_cur_color
call vt100_color ; setup color index table
call tek4014_color ; same for Tek4014
pop si
mov ah,prstr ;@@
mov dx,offset fulscr ;@@
int dos ;@@
clc
ret
showkey:
mov ax,offset shkmsg
mov cx,shklen
ret
scrncheck proc near
push ax
mov ah,0bh ; sense CRT mode
int BIOS
test al,1 ; 25 line mode ?
jz scrncheck1 ; z = yes
mov scrn_lines,20
mov ah,19 ; lines/row - 1
jmp scrncheck2
scrncheck1:
mov scrn_lines,25
mov ah,15 ; lines/row - 1
scrncheck2:
mov al,0
mov vt100_cursr,ax
pop ax
ret
scrncheck endp
detclck proc near
;
; determine CPU clock
;
mov cpu_clock,CPU_5M_CLOCK
push ax
in al,042h
test al,0C0h
jz detclck1
test al,020h
jz detclck1
mov cpu_clock,CPU_8M_CLOCK
detclck1:
pop ax
ret
detclck endp
; serial port interrupt routine. This is not accessible outside this
; module, handles serial port receiver interrupts.
SERINT PROC NEAR
push ds ; save these on remote stack
push ax
mov ax,seg data ; get our own data segment
mov ds,ax
mov mnsp,sp ; save remote stack information
mov mnsseg,ss
mov sp,offset mnstk ; switch to local stack
mov ss,ax
push es ; and save remaining registers
push bp
push di
push si
push dx
push cx
push bx
mov es,ax
call mnproc ; process the interrupt
mov al,icEOI
mov dx,intcmda
out dx,al
pop bx ; restore registers from stack
pop cx
pop dx
pop si
pop di
pop bp
pop es
mov ax,mnsseg ; switch back to remote stack
mov ss,ax
mov ax,mnsp
mov sp,ax
pop ax
pop ds
iret
; handler for serial input
mnproc: cld
mov dx,modem.mdstat ; is data available?
in al,dx
test al,rxrdy
jnz mnpro0b ; nz = yes
jmp mnpror
mnpro0b:
mov dx,modem.mddat
in al,dx ; read the received character into al
test flowcnt,1 ; XON/XOFF flow control active?
jz mnpro2 ; z = no
mov dh,al ; dh = working copy. Check flow ctrl
and dh,parmsk ; strip parity temporarily, if any
cmp dh,flowoff ; acting on Xoff?
jne mnpro1 ; ne = no, go on
cmp xofsnt,0 ; have we sent an outstanding XOFF?
jne mnpro4e ; ne = yes, ignore (possible echo)
mov xofrcv,bufon ; set the flag saying XOFF received
jmp short mnpro4e ; and continue the loop
mnpro1: cmp dh,flowon ; acting Xon?
jne mnpro2 ; ne = no, go on
mov xofrcv,off ; clear the XOFF received flag
jmp short mnpro4e ; and continue the loop
mnpro2: push bx
mnpro2a:mov bx,srcpnt ; address of buffer storage slot
mov byte ptr [bx],al ; store the new char in buffer "source"
inc srcpnt ; point to the next slot
inc bx
cmp bx,offset source + bufsiz ; beyond end of buffer?
jb mnpro3 ; not past end...
mov srcpnt,offset source ; wrap buffer around
mnpro3: cmp count,bufsiz ; filled already?
jae mnpro4 ; ae = yes
inc count ; no, add a char
mnpro4:
mnpro4a:pop bx
mnpro4e:
cmp count,mntrgh ; past the high trigger point?
jbe mnpror ; be = no, we're within our limit.
test xofsnt,bufon ; has an XOFF been sent by buffer control?
jnz mnpror ; nz = Yes
test flowcnt,2 ; using RTS/CTS flow control?
jz mnpro4b ; z = no
mov dx,modem.mdcom ; modem command port
mov al,cmdrtslow ; drop RTS
out dx,al ; tell the UART to drop RTS
mov xofsnt,bufon ; remember RTS reset at buffer level
jmp short mnpror
mnpro4b:mov al,flowoff ; get the flow off char (XOFF or null)
or al,al ; do not send null chars
jz mnpror ; z = null, nothing to send
call dopar ; set parity appropriately
mov ah,al ; don't overwrite character with status
push cx ; save reg
xor cx,cx ; loop counter
mnpro5: mov dx,modem.mdstat
in al,dx
test al,txrdy ; transmitter ready?
jnz mnpro6 ; nz = yes
jmp $+2 ; use time, prevent overdriving UART
jmp $+2
loop mnpro5
jmp short mnpro7 ; timeout
mnpro6: mov al,ah ; now send out the flow control char
mov dx,modem.mddat
jmp $+2
out dx,al
mov xofsnt,bufon ; remember we sent an XOFF at buffer level
mnpro7: pop cx ; restore reg
mnpror: ret
SERINT ENDP
; Initialization for using serial port. Returns normally.
SERINI PROC NEAR
cmp portin,0 ; did we initialize port already?
je serin5 ; e = yes
jl serin0 ; l = no, not yet
jmp serin4 ; yes, update flow and leave
serin0: mov bl,flags.comflg ; pass current port ident
mov portin,0 ; say have been here once
call comstrt ; do SET PORT now
jnc serin5 ; nc = success
ret ; failed, exit now
serin5: push bx
mov bx,portval
mov bl,[bx].duplex ; get full/half duplex flag, local cpy
mov dupflg,bl
pop bx
cmp flags.comflg,4 ; UART?
jbe serin2 ; be = yes, real thing
jmp serin3
serin2:
call inita
call clrbuf ; Clear input buffer.
jmp serin4
serin3:
serin3d:cmp flags.comflg,'N' ; UB-NETCI ?
jne serin3e ; ne = no
call ubstart
jnc serin4
call nethangup
stc
ret
serin3e:cmp flags.comflg,'W' ; Novell NASI ?
jne serin3f ; ne = no
call nasistart ; start NASI session
jnc serin4
call nethangup
stc
ret
serin3f:cmp flags.comflg,'t' ; TCP/IP ?
jne serin4 ; ne = no
call tcpstart ; start TCP connection
jnc serin4
call nethangup
stc
ret
serin4: push bx
mov bx,portval ; get port data structure
mov [bx].portrdy,1 ; say the comms port is ready
mov parmsk,0ffh ; parity mask, assume parity is None
cmp [bx].parflg,parnon ; is it None?
je serin1 ; e = yes
mov parmsk,07fh ; no pass lower 7 bits as data
serin1: xor ax,ax
mov al,[bx].floflg ; flow control kind
mov flowcnt,al ; save here for active use
mov ax,[bx].flowc ; get flow control chars
serin1a:mov flowoff,al ; xoff or null
mov flowon,ah ; xon or null
mov xofrcv,off ; clear xoff received flag
pop bx
;@@ mov quechar,0 ; clear outchr queued flow control
mov portin,1 ; say initialized
clc ; carry clear for success
ret
SERINI ENDP
; Reset the serial port. This is the opposite of serini. Calling
; this twice without intervening calls to serini should be harmless.
; Returns normally.
SERRST PROC NEAR
cmp portin,0 ; Reset already?
jg srst3 ; g = no
clc
ret
srst3: cmp flags.comflg,'0' ; Bios or networks?
jb srst4 ; b = no, real UART
jmp srst1 ; nz = yes (Bios or Net)
srst4:
cmp portinia,0 ; Did we reset port already?
je rsta0 ; Yes, so just leave.
push es
cli ; Disable interrupts
xor ax,ax ; Address low memory
mov es,ax
mov ax,oldsera_ofs ; Restore interrupt vector
mov es:[4*icsvcta],ax
mov ax,oldsera_sgm
mov es:[4*icsvcta+2],ax
mov dx,intmska ; restore old master controller mask
mov al,oldmska
out dx,al
mov dx,mnmska ; disable serial interrupts at port
; mov al,txmsk+rxmsk+tbemsk
mov al,oldmsdat
out dx,al
mov portinia,0 ; Remember port has been reset
sti ; Allow interrupts
pop es
rsta0: jmp short srst8
srst1:
srst8: mov portin,0 ; reset flag
push bx
mov bx,portval ; port data structure
mov [bx].portrdy,0 ; say port is not ready
pop bx
;@@ mov quechar,0 ; clear any outchr queued char
clc
ret
SERRST ENDP
; Local routine to initialize the standard serial port
INITA PROC NEAR
cmp portinia,1 ; Did we initialize port already ?
je inita0 ; Yes, so just leave.
;
cli ; Disable interrupts
push ax
push dx
push es
;
mov ax,offset port1
mov portval,ax
xor ax,ax
mov es,ax
mov ax,es:[4*icsvcta] ; save interrupt vector for port1
mov oldsera_ofs,ax
mov ax,es:[4*icsvcta+2]
mov oldsera_sgm,ax
mov ax,offset serint ; pointer to our routine
mov es:[4*icsvcta],ax ; set interrupt routine offset
mov es:[4*icsvcta+2],cs ; and segment
mov dx,intmska
in al,dx
mov oldmska,al ; save old master controller mask
;
and al,not icsmska ; enable serial interrupt at master
out dx,al
mov dx,mnmska
in al,dx
mov oldmsdat,al
and al,0f8h
or al,rxmsk
out dx,al
mov modem.mddat,mndata
mov modem.mdstat,mnst1a
mov modem.mdcom,mncmda
mov modem.mdmsk,mnmska
mov modem.mdsig,mnrdsa
mov timer.tmdat,tmdata
mov timer.tmcmd,tmcmda
mov timer.tmsel,tmsela
call dobaud
mov portinia,1
call clrbuf
;
pop es
pop dx
pop ax
sti
inita0: ret
INITA ENDP
;
; Produce a short beep. The PC DOS bell is long enough to cause a loss
; of data at the port. Returns normally.
BEEP PROC NEAR
mov dl,bell
mov ah,dconio
int dos
ret
BEEP ENDP
;
; Terminal emulator.
;
term proc near
mov oldsp,sp ; remember stack for i/o failure
mov argadr,ax ; save argument ptr
mov prthld,0 ; clear port hold flag at the beginning
mov replay_hold,0
mov bx,portval
mov bl,[bx].floflg
mov flowcnt,bl
mov bx,portval
mov bx,[bx].flowc ; get flow control character
mov flowoff,bl
mov flowon,bh
or vt100_flags,AUTOTEK_BIT
test denyflg,tekxflg
jz term_01
and vt100_flags,(not AUTOTEK_BIT)
term_01:
and vt100_lflag,(not LOGENAB_BIT)
test flags.capflg,logses ; session logging enabled?
jz term_02 ; z = no.
or vt100_lflag,LOGENAB_BIT
term_02:
cmp flags.vtflg,ttgenrc ; no terminal emulation?
je term_02a ; e = no emulation
call vt100_restore
call tek4014_restore
term_02a:
mov fairness,0
mov kanji_smode,0 ; clear Kanji pending flag
mov kanji_rmode,0
mov kanji_7smode,0
mov kanji_7rmode,0
mov si,argadr ; this is source
mov di,offset vt_ourarg ; place to store arguments
mov ax,ds
mov es,ax ; address destination segment
mov cx,size termarg
cld
rep movsb ; copy into our arg blk
mov bx,argadr ; get the address of argument
mov al,[bx].flgs ; get the flags
mov yflags,al ; set yflags
;@@ and vt_ourarg.flgs,not (prtscr) ; no screen printing at startup
;@@ mov vt100_pflag,0
mov ax,vt_ourarg.captr
mov captrtn,ax ; buffer capture routine
test vt_ourarg.flgs,modoff ; mode line off?
jnz term_1
call set_modlin ; setup mode line
term_1:
mov parmsk,0ffh ; parity mask, assume parity = None
cmp vt_ourarg.parity,parnon ; is parity None?
je term_2 ; e = yes, keep all 8 bits
mov parmsk,07fh ; else keep lower 7 bits
term_2:
mov ax,KI_code
call ans_keystr
mov KI_len,cx
mov KI_ofs,bx
mov ax,KO_code
call ans_keystr
mov KO_len,cx
mov KO_ofs,bx
;
cmp flags.vtflg,tttek ; Tek4014 emulation ?
je term_tk ; e = yes.
cmp flags.vtflg,ttgenrc ; no emulation
jne term_vt ; ne = yes, VT emulation
jmp term0 ; non supported terminal
;
; vt100/vt52 emulation
term_vt:
call ent_vt
jmp term0
;
; tek4014 emulation
term_tk:
call ent_tk
;
term0:
; test vt100_flags,LOOPTEST_BIT
; je term1
; jmp term_tst1
term1: call portchr ; get char from port, apply parity mask
jnc short term1a ; nc = char at port
push bx
mov bx,portval
cmp [bx].portrdy,0 ; is port ready for business?
pop bx
jne term1b
mov kbdflg,'C' ; report 'C' to TERM's caller
mov sp,oldsp ; recover startup stack pointer
jmp quit
term1a:
call outtty ; display and capture char
term1b:
inc fairness
cmp fairness,10
jb term1 ; do quick loop back for more
term2: mov fairness,0
;@@ call pntflsh ; flush printer buffer
;@@ jnc term2a ; nc = success
;@@ call pntdead ; call bad printer notifier
term2a: call keybd ; keyboard translator to read and send text
jnc term1 ; nc = do not exit Connect mode
quit: call pntflsh ; flush printer buffer
cmp flags.vtflg,ttgenrc ; no emulation ?
je term3
call vt100_save
call tek4014_save
term3: mov al,1
call text_scrn ; ON the text screen
xor al,al
mov ah,prstr
mov dx,offset retscr
int dos
ret
;term_tst1:
; mov ax,3D00h ; open file (read only)
; mov dx,offset playback_fnam
; int dos
; jc term_tstz ; if error, then normal operation
; mov playback_hndl,ax
;term_tst2:
;@@ call portchr
;@@ jnc short term_tst3
;@@ call outtty
;@@ jmp term_tst2
;term_tst3:
; mov ah,3Fh ; read file/device
; mov dx,offset tmpbuf
; mov bx,playback_hndl
;@@ mov cx,8
; mov cx,72 ;@@
; int dos
; jc term_tstx
; mov cx,ax
; jcxz term_tstx
; mov si,offset tmpbuf
;term_tst4:
; push cx
; push si
;@@ mov ah,[si]
;@@ call outchr
;@@ nop
;@@ nop
;@@ nop
; mov al,[si] ;@@
; call outtty ;@@
; pop si
; pop cx
; inc si
;
; check the keyboard by using direct console i/o
; Any key can be used for toggle of screen output.
;
; push dx
; mov ah,dconio ; direct console i/o
; mov dl,0ffh ; read
; int dos
; jz term_tst5
;term_tst6:
; mov ah,dconio
; mov dl,0ffh
; int dos
; jz term_tst6
; cmp al,CR
; jne term_tst5
; pop dx
; jmp term_tstx
;term_tst5:
; pop dx
;
; loop term_tst4
; jmp term_tst2
;term_tstx:
; mov ah,3Eh
; mov bx,playback_hndl
; int dos
;term_tstz:
; and vt100_flags,NOT LOOPTEST_BIT
; clc
; jmp term1
term endp
;; keyboard translator action routines, system dependent, called from msugen.
; These are invoked by a jump instruction. Return carry clear for normal
; processing, return carry set exit Connect mode (kbdflg has transfer char).
; kanji_shiftin sends designation codes for G0 to JIS-C6226.
; kanji_shiftout sends designation codes for G0 to JIS-roman.
; These routines are called in chrout when JIS-7 is specified.
kanji_shiftin proc near
push ax ; save ax
push cx
push si
mov cx,KI_len
jcxz kanji_shiftin2
mov si,KI_ofs
kanji_shiftin1:
mov al,[si]
push si ; save si and cx.
push cx ; these are broken when local echo is on
call outprt
pop cx
pop si
inc si
loop kanji_shiftin1
kanji_shiftin2:
mov kanji_7smode,1
pop si
pop cx
pop ax
ret
kanji_shiftin endp
kanji_shiftout proc near
push ax ; save ax
push cx
push si
mov cx,KO_len
jcxz kanji_shiftout2
mov si,KO_ofs
kanji_shiftout1:
mov al,[si]
push si ; save si and cx.
push cx ; these are broken when local echo is on
call outprt
pop cx
pop si
inc si
loop kanji_shiftout1
kanji_shiftout2:
mov kanji_7smode,0
pop si
pop cx
pop ax
ret
kanji_shiftout endp
; chrout is called from KEYBD after key definition translation.
; the character is in AL.
chrout:
cmp kanji_scode,KNJCODE_NONE ; if kanji is not used,
je chroutx2 ; no translation
cmp kanji_scode,KNJCODE_SJIS ; if shift-JIS is used,
je chroutx2 ; no translation
cmp kanji_smode,0 ; 1st byte ?
je chrout_1 ; e = yes,
jmp chrout_knj2
chrout_1:
call is_kanji1 ; Kanji code 1st byte ?
jnc chroutx ; nc = no. ASCII character
mov kanjis1,al
mov kanji_smode,1
jmp chroutxx
chroutx:
cmp kanji_scode,KNJCODE_JIS7 ; JIS-7 used ?
jne chroutx2 ; ne = no
cmp kanji_7smode,0 ; roman-mode ?
je chroutx2 ; e = yes.
cmp al,DEL ; BS and DEL can be used in Kanji mode
je chroutx2
cmp al,BS
je chroutx2
call kanji_shiftout
chroutx2:
test vt100_flags,NEWLINE_BIT ; newline mode ?
jz chroutx1 ; z = no
cmp al,0Dh ; CR ?
jne chroutx1 ; ne = no
call outprt ; send it
mov al,0Ah ; send LF
chroutx1:
call outprt ; put char in al to serial port
mov kanji_smode,0
chroutxx:
clc ; stay in Connect mode
ret
chrout_knj2:
mov ah,al
mov al,kanjis1
call s2jis
cmp kanji_scode,KNJCODE_JIS7 ; JIS-7 used ?
je chrout_knj21 ; e = yes.
or ax,8080h ; convert to DEC code
jmp chrout_knj22
chrout_knj21:
cmp kanji_7smode,0 ; roman-mode ?
jne chrout_knj22 ; ne = no.
call kanji_shiftin
chrout_knj22:
mov kanjis1,ah
mov ah,0
call outprt
mov al,kanjis1
jmp chroutx1
trnprs: push ax ; toggle Copy screen to printer
test vt100_pflag,(AUTOPRINT_BIT+PRINTCTRL_BIT)
; are we currently printing?
jz trnpr0 ; z = no, check the printer status
and vt100_pflag,(not (AUTOPRINT_BIT+PRINTCTRL_BIT))
; clear printer flag
jmp trnpr1 ; and going off
trnpr0:
push bx
mov bx,prnhand ; file handle for system printer
mov ah,ioctl
mov al,7 ; get output status of printer
int dos
pop bx
jc trnpr1 ; c = printer not ready
cmp al,0ffh ; Ready status
jne trnpr3 ; ne = not-Ready
or vt100_pflag,AUTOPRINT_BIT ; set the autoprint flag
trnpr1: call set_modlin
call vt100_modlin
trnpr3: pop ax
clc ; return carry clear (don't quit)
ret
prtscn: call vt100_prns
clc
ret
klogon proc near ; resume logging (if any)
test flags.capflg,logses ; session logging enabled?
jz klogn ; z = no, forget it
or vt_ourarg.flgs,capt ; turn on capture flag
klogn: clc
ret
klogon endp
klogof proc near ; suspend logging (if any)
and argadr.flgs,not capt ; stop capturing
klogo: clc
ret
klogof endp
uparrw: mov al,'A'
jmp short comarr
dnarrw: mov al,'B'
jmp short comarr
rtarrw: mov al,'C'
jmp short comarr
lfarrw: mov al,'D'
comarr: push ax
mov al,ESCAPE ; [06-July-1990]
call outprt ; [06-July-1990]
cmp flags.vtflg,ttvt52
je comar2
mov al,'[' ; [06-July-1990]
cmp curkey_mode,0
je comar1
mov al,'O' ; [06-July-1990]
comar1: call outprt ; [06-July-1990]
comar2:
pop ax
call outprt ; [06-July-1990]
clc
ret
pf1: mov al,'P'
jmp short compf
pf2: mov al,'Q'
jmp short compf
pf3: mov al,'R'
jmp short compf
pf4: mov al,'S'
compf: push ax
mov al,ESCAPE ; [06-July-1990]
call outprt ; [06-July-1990]
cmp flags.vtflg,ttvt52
je compf1
mov al,'O'
call outprt ; [06-July-1990]
compf1:
pop ax
call outprt ; [06-July-1990]
clc
ret
kp0: mov al,'p'
jmp short comkp
kp1: mov al,'q'
jmp short comkp
kp2: mov al,'r'
jmp short comkp
kp3: mov al,'s'
jmp short comkp
kp4: mov al,'t'
jmp short comkp
kp5: mov al,'u'
jmp short comkp
kp6: mov al,'v'
jmp short comkp
kp7: mov al,'w'
jmp short comkp
kp8: mov al,'x'
jmp short comkp
kp9: mov al,'y'
jmp short comkp
kpmins: mov al,'m'
jmp short comkp
kpcoma: mov al,'l'
jmp short comkp
kpentr: mov al,'M'
jmp short comkp
kpdot: mov al,'n'
jmp short comkp
comkp: cmp keypad_mode,0
je comkp1
push ax
mov al,ESCAPE ; [06-July-1990]
call outprt ; [06-July-1990]
mov al,'O' ; [06-July-1990]
cmp flags.vtflg,ttvt52
jne comkp0
mov al,'?' ; [06-July-1990]
comkp0:
call outprt ; [06-July-1990]
pop ax
jmp short comkp2
comkp1: sub al,40h
comkp2:
call outprt ; [06-July-1990]
clc
ret
decf6:
decf7:
decf8:
decf9:
decf10:
decf11:
decf12:
decf13:
decf14:
dechelp:
decdo:
decf17:
decf18:
decf19:
decf20:
jmp comdec1
decfind:
mov ah,'1'
jmp comdec
decinsert:
mov ah,'2'
jmp comdec
decremove:
mov ah,'3'
jmp comdec
decselect:
mov ah,'4'
jmp comdec
decprev:
mov ah,'5'
jmp comdec
decnext:
mov ah,'6'
comdec:
push ax
mov ah,ESCAPE
call outchr
mov ah,'['
call outchr
pop ax
call outchr
mov ah,'~'
call outchr
comdec1:
clc
ret
snull: mov ah,0 ; send a null
call outchr ; send without echo or logging
nop
nop
nop
clc
ret
keyinchg:
xor keyin_dos,1
clc
ret
; change terminal emulator
;
vtchg:
cmp flags.vtflg,ttgenrc ; no emulation mode?
je vtchg1
cmp flags.vtflg,tttek ; tek emulation mode?
je vtchgt
call vt100_save
jmp vtchg1
vtchgt:
call tek4014_save
vtchg1:
cmp flags.vtflg,ttgenrc
jne vtchg2
call ent_vt
mov flags.vtflg,ttvt52
jmp vtchgx
vtchg2:
cmp flags.vtflg,ttvt52
jne vtchg3
mov flags.vtflg,ttvt100
jmp vtchgx
vtchg3:
cmp flags.vtflg,ttvt100
jne vtchg4
mov flags.vtflg,ttvt102
jmp vtchgx
vtchg4:
cmp flags.vtflg,ttvt102
jne vtchg5
call ent_tk
mov flags.vtflg,tttek
jmp vtchgx
vtchg5:
cmp flags.vtflg,tttek
jne vtchg6
call ent_vt
mov flags.vtflg,ttgenrc
vtchg6:
mov flags.vtflg,ttgenrc
vtchgx:
call set_modlin
call vt100_modlin
clc ; stay in connect mode
ret
;
; reset terminal
vtreset:
cmp flags.vtflg,ttgenrc
je vtreset2
cmp flags.vtflg,tttek
je vtreset1
call vt100_reset
jmp vtresetx
vtreset1:
call tek4014_reset
jmp vtresetx
vtreset2:
vtresetx:
clc
ret
upone:
push ax
push cx
call sense_sftkey
test al,08h ; GRPH is pressed ?
jz upone_1 ; z=no
mov cx,6
call sixel_rollup
jmp upone_2
upone_1:
mov cx,1
call vt100_rupn
upone_2:
pop cx
pop ax
clc
ret
dnone:
push ax
push cx
call sense_sftkey
test al,08h ; GRPH is pressed ?
jz dnone_1
mov cx,6
call sixel_rolldown
jmp dnone_2
dnone_1:
mov cx,1
call vt100_rdnn
dnone_2:
pop cx
pop ax
clc
ret
upscn:
push cx
mov cx,24
call vt100_rupn
pop cx
clc
ret
dnscn:
push cx
mov cx,24
call vt100_rdnn
pop cx
clc
ret
gupone:
push cx
mov cx,6
call sixel_rollup
pop cx
clc
ret
gdnone:
push cx
mov cx,6
call sixel_rolldown
pop cx
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
chang: mov al,'H' ; Hangup, drop DTR & RTS
jmp short cmdcom
trnmod: mov al,'M'
jmp short cmdcom
cmdcom: mov kbdflg,al ; pass char to msster.asm via kbdflg
stc ; say exit Connect mode
ret
;; end of action routines
;
; capture routine.
; If capture flag is ON, put the character in AL to the file.
;
outcapt proc near
push bx
mov bx,argadr ; args from msster directly
test [bx].flgs,capt ; capturing output? Can be shut off
pop bx ; if out dev becomes not ready
jz outcapt1 ; no, forget this part
push ax ; save char
call captrtn ; give it captured character
pop ax ; restore character and keep going
outcapt1:
ret
outcapt endp
;
; Dumb terminal emulator. AL is the character to be displayed.
; Taken from MSXGEN.ASM .
;
dumbterm proc near
cmp vt100_lflag,(LOGCOOK_BIT+LOGENAB_BIT) ; is cooked logging ?
jne dumbterm1 ; ne = no.
call outcapt
dumbterm1:
test vt100_pflag,AUTOPRINT_BIT ; should we be printing?
jz dumbterm2 ; no, keep going
push ax
mov ah,LSTOUT ; write to system printer device
mov dl,al
int dos
pop ax
jnc dumbterm2 ; nc = successful print
push ax
call beep ; else make a noise and
call trnprs ; turn off printing
pop ax
dumbterm2:
test vt_ourarg.flgs,trnctl ; debug? if so use dos tty mode
jz dumbterm8 ; z = no
mov ah,conout
cmp al,7fh ; Ascii Del char or greater?
jb dumbterm4 ; b = no
je dumbterm3 ; 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
dumbterm3:
cmp al,7fh ; is char now a DEL?
jne dumbterm4 ; ne = no
and al,3fH ; strip next highest bit (Del --> '?')
jmp dumbterm5 ; send, preceded by caret
dumbterm4:
cmp al,' ' ; control char?
jae dumbterm6 ; ae = no
add al,'A'-1 ; make visible
dumbterm5:
push ax ; save char
mov dl,5eh ; caret
int dos ; display it
pop ax ; recover the non-printable char
dumbterm6:
mov dl,al
int dos
ret
dumbterm7:
test flags.remflg,d8bit ; keep 8 bits for displays?
jnz dumbterm8 ; nz = yes, 8 bits if possible
and al,7fh ; remove high bit
dumbterm8:
mov ah,conout ; dostty screen mode
mov dl,al ; write without intervention
int dos ; else let dos display char
ret ; and return
dumbterm 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
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 vt100_lflag,LOGENAB_BIT ; raw mode logging ?
jne outtty_lg1 ; ne = no.
call outcapt ; log it
outtty_lg1:
cmp rxtable+256,0 ; is translation off?
je outtty_knj0 ; e = yes, off
push bx ; Translate incoming char
mov bx,offset rxtable ; address of translate table
xlatb ; new char is in al
pop bx
;
; Kanji test. If kanji is used for receiving characters,
; do translation for capture file, printer and display.
; The capture file and printer use shift-JIS. On the other hand,
; VT100 emulator ueses DEC (extended UNIX - JIS-8) code.
;
outtty_knj0:
cmp kanji_rcode,KNJCODE_NONE ; Kanji code used ?
je outtty_knj2 ; e = no, no translation
cmp kanji_rcode,KNJCODE_DEC ; DEC (EUC) code ?
jne outtty_knj1 ; ne = no
jmp outtty_dknj0 ; jump to DEC kanji processor
outtty_knj1:
cmp kanji_rcode,KNJCODE_SJIS ; Shift-JIS code ?
jne outtty_knj2 ; ne = no
jmp outtty_sknj0 ; jump to Shift-JIS process
outtty_knj2:
jmp outtty_trm
;
outtty_dknj0:
cmp flags.vtflg,0 ; dumb terminal ?
je outtty_dknj1 ; e = Yes. Needs code conversion.
jmp outtty_trm1
outtty_dknj1:
cmp kanji_rmode,0 ; 2-byte code in progress ?
je outtty_dknj2 ; e = No, not in progress.
mov kanjir2,al ; put 2nd byte
mov ah,al ; prepare to conversion
mov al,kanjir1 ; put 1st byte
cmp al,08Eh ; SS2 ?
jne outtty_dknj5 ; ne = No.
mov al,kanjir2 ; get 2nd byte
jmp outtty_dknj3
outtty_dknj5:
and ax,7f7fh ; mask 8-th bits
call jis2s ; convert to Shift-JIS
xchg kanjir1,al ; save the 2byte code
xchg kanjir2,ah
mov kanjio1,ah
mov al,kanjir1
call dumbterm
mov al,kanjir2
jmp outtty_dknj3
outtty_dknj2:
cmp al,08Eh ; SS2 ?
je outtty_dknj4 ; e = Yes.
cmp al,0A0h ; is Kanji ?
jbe outtty_dknj3 ; z = No.
outtty_dknj4:
mov kanji_rmode,1 ; set multi-byte flag
mov kanjio1,al ; save 1st byte
mov kanjir1,al
ret
outtty_dknj3:
call dumbterm
mov kanji_rmode,0
ret
;
outtty_sknj0:
outtty_sknj2:
cmp flags.vtflg,0 ; emulating a terminal?
jnz outtty_sknj3 ; nz = yup, go do something smart
call dumbterm ; dumb terminal emulation
ret
outtty_sknj3:
cmp kanji_rmode,0 ; is it 1st byte character?
je outtty_sknj4 ; e = yes.
mov kanjio2,al ; put 2nd byte
mov ah,al ; prepare to conversion
mov al,kanjio1 ; put 1st byte
call s2jis ; convert to JIS
or ax,8080h ; use GR set
xchg kanjio1,al ; save the 2byte code
xchg kanjio2,ah
mov kanjir1,ah
jmp outtty_trm1
outtty_sknj4:
call is_kanji1 ; check if kanji
jc outtty_sknj6 ; c = Yes.
test al,80h ; katakana ?
jz outtty_sknj5 ; z = No.
mov kanji_rmode,1 ; set multi-byte flag
mov kanjio1,08Eh ; SS2 code
mov kanjio2,al ; extended UNIX convention
outtty_sknj5:
jmp outtty_trm1
outtty_sknj6:
mov kanji_rmode,1
mov kanjir1,al
mov kanjio1,al
ret
;
outtty_trm:
cmp flags.vtflg,0
jne outtty_trm1
call dumbterm
ret
outtty_trm1:
cmp flags.vtflg,tttek
je outtty_tk
;
outtty_vt:
outtty_vt1:
cmp kanji_rmode,0
je outtty_vt3
outtty_vt2:
mov al,kanjio1
call vt100
mov al,kanjio2
outtty_vt3:
call vt100
;
cmp ah,0
jne outtty_vt4
jmp outtty_snd
outtty_vt4:
push ax
push dx
;;@@ call vt100_save
mov flags.vtflg,tttek
call ent_tk
pop dx
pop ax
cmp ah,2
je outtty_tk3
cmp ah,3
jne outtty_vt5
mov kanjio1,dh
mov kanjio2,dl
jmp outtty_tk2
outtty_vt5:
jmp outtty_snd_ex
outtty_tk:
outtty_tk1:
cmp kanji_rmode,0
je outtty_tk3
outtty_tk2:
mov al,kanjio1
call tek4014
jnc outtty_tk2_2
jcxz outtty_tk2_2
outtty_tk2_1:
lodsb
push cx
push si
call vt100
pop si
pop cx
loop outtty_tk2_1
outtty_tk2_2:
mov al,kanjio2
outtty_tk3:
call tek4014
jnc outtty_tk3_2
jcxz outtty_tk3_2
outtty_tk3_1:
lodsb
push cx
push si
call vt100
pop si
pop cx
loop outtty_tk3_1
outtty_tk3_2:
;
cmp ah,0
jne outtty_tk4
jmp outtty_snd
outtty_tk4:
push ax
push dx
;;@@ call tek4014_save
mov flags.vtflg,ttvt102
call ent_vt
pop dx
pop ax
cmp ah,2
je outtty_vt3
cmp ah,3
jne outtty_tk5
mov kanjio1,dh
mov kanjio2,dl
jmp outtty_vt2
outtty_tk5:
jmp outtty_snd_ex
;
outtty_snd:
mov kanji_rmode,0
jcxz outtty_snd_ex ; If there is no answer-back, return
outtty_snd1:
mov ah,[si]
call outchr ; send character without echo
nop
nop
nop
inc si
loop outtty_snd1
outtty_snd_ex:
ret
outtty endp
; send the character in al out to the serial port; handle echoing.
; Can send an 8 bit char while displaying only 7 bits locally.
outprt proc near
test yflags,lclecho ; echoing?
jz outpr1 ; z = 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
ret
outprt endp
pntdead proc near ; display printer is inoperative msg
push ax
test vt_ourarg.flgs,modoff ; mode line off?
jnz pntdea1 ; nz = off, skip msg
push bx
mov dx,offset pntmsg ; say printer not ready
call putmod ; write on mode line
pop bx
pntdea1:pop ax
stc ; say printer not ready
ret
pntdead endp
; Get a char from the serial port manager
; returns with carry clear if a character is available
portchr proc near
call prtchr ; character at port?
jc portc2 ; no character
and al,parmsk ; apply 8/7 bit parity mask
or al,al ; catch nulls
jnz portc2 ; nz = non null
stc ; ignore null
portc2: ret
portchr endp
; Jump here to exit Connect mode and execute macros 'TERMINALR' (vtrmac) or
; 'TERMINALS' (vtsmac). Does nothing if macro does not exist.
; Preserves registers except ax. Returns to TELNET caller with 'C' in kbdflg.
vtrmac proc near ; RESET macro
mov vtmacname,offset vtrname ; select macro name
mov vtmaclen,vtrlen ; and its length
jmp vtmacro
vtrmac endp
vtsmac proc near ; SET macro
mov vtmacname,offset vtsname
mov vtmaclen,vtslen
jmp vtmacro
vtsmac endp
; Invoked by keyboard translator when an unknown keyboard verb is used as
; a string definition, such as {\ktest}. Enter with vtmacname pointing to
; uppercased verb name, asciiz, and vtmaclen set to its length.
extmacro proc near
jmp vtmacro
extmacro endp
;
; Reference Macro structure for db number of entries (mac names)
; is file table mcctab |-> db length of macroname, excl '$'
; mssset.asm each entry |-> db 'macroname','$'
; where these |-> dw segment:0 of definition string
; are stored. (offset part is always 0)
; Definition string in db length of <string with null>
; buffer macbuf db 'string with trailing null'
;
vtmacro proc far ; common code for macros vtsmac,vtrmac
push bx ; and Product
push cx
push si
push di
push es
mov ax,ds
mov es,ax
mov di,offset rdbuf+1 ; macro def buffer starts here
mov si,vtmacname ; pointer to macro name
mov cl,vtmaclen ; length of macro name<sp/null>text
xor ch,ch
mov [di-1],cl ; counted string field
cld
rep movsb ; copy to rdbuf
mov byte ptr [di],0 ; null terminator
mov si,offset rdbuf+1 ; look for name-text separator
mov cl,vtmaclen
xor ch,ch
vtmac1: lodsb
cmp al,' ' ; space separator?
je vtmac1a ; e = yes, stop here
or al,al ; null terminator?
jz vtmac1a ; e = yes, stop here
loop vtmac1
inc si ; to do null lenght correctly
vtmac1a:sub si,offset rdbuf+1+1 ; compute length of macro name
mov cx,si
mov vtmaclen,cl ; save a macro name length
; check for existence of macro
mov bx,offset mcctab ; table of macro names
mov cl,[bx] ; number of names in table
xor ch,ch
jcxz vtmacx ; z = empty table, do nothing
inc bx ; point to length of first name
vtmac2: mov al,[bx] ; length of this name
xor ah,ah
cmp al,vtmaclen ; length same as desired keyword?
jne vtmac3 ; ne = no, search again
mov si,bx
inc si ; point at first char of name
push cx ; save name counter
push di ; save reg
mov cl,vtmaclen ; length of name, excluding '$'
xor ch,ch
mov di,vtmacname ; point at desired macro name
push es ; save reg
push ds
pop es ; make es use data segment
cld
repe cmpsb ; match strings
pop es ; need current si below
pop cx
pop di ; recover saved regs
je vtmac4 ; e = matched
vtmac3: add bx,ax ; step to next name, add name length
add bx,4 ; + count, dollar sign, def word ptr
loop vtmac2 ; try next name
vtmacx: pop es
pop di
pop si ; no macro, return to Connect mode
pop cx
pop bx
ret
vtmac4: cmp taklev,maxtak ; room in Take level?
jge vtmacx ; ge = no, exit with no action
inc taklev ; increment take level
add takadr,size takinfo ; make a new Take entry/macro
mov bx,takadr ; point to current macro structure
mov ax,ds ; segment of rdbuf
mov [bx].takbuf,ax ; segment of definition string struc
mov cl,rdbuf ; length of whole string
xor ch,ch
mov [bx].takcnt,cx ; number of chars in definition
mov [bx].takargc,0 ; our argument count
mov [bx].takptr,offset rdbuf+1 ; where to read next command char
mov [bx].taktyp,0ffh ; flag as a macro
pop es
pop di
pop si
pop cx
pop bx
jmp endcon ; exit Connect mode
vtmacro endp
; Error recovery routine used when outchr reports unable to send character
; or when vtmacro requests exiting Connect mode.
; Exit Connect mode cleanly, despite layers of intermediate calls.
endcon proc near
mov kbdflg,'C' ; report 'C' to TERM's caller
mov sp,oldsp ; recover startup stack pointer
; TERM caller's return address is now
; on the top of stack. A longjmp.
jmp quit ; exit Connect mode cleanly
endcon endp
code ends
end