name msxp98 ; File MSXP98.ASM ; NEC PC-9801 MS DOS Kermit module. ; ; Last edit: 17 Apr 1991 ; 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, termtb 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 vt_ourarg public scn_color, def_color public extmacro, vtmacname, vtmaclen include mssdef.h include msxp98.h CHR_GS equ 1Dh CHR_CAN equ 18h false equ 0 true equ 1 instat equ 6 prtscr equ 80h ; print screen pressed ; ; 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 ; 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 ccmd equ 37H ; RTS & DTR high, RX & TX enabled, reset ERR cbrk equ 08H ; break enabled chng equ 10H ; RTS & DTR low, RX & TX disabled, reset ERR 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 mdstat dw 0 mdcom dw 0 mden db 0 mddis db 0 mdmeoi db 0 mdintv dw 0 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. ; 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 public 'data' extrn denyflg:word, rdbuf:byte extrn flags:byte, trans:byte, ttyact:byte extrn repflg:byte, diskio:byte, filtst:byte extrn lclexit:word, taklev:byte, takadr:word extrn comand:byte, dmpname:byte, prnhand:word extrn kbdflg:byte, rxtable:byte, mcctab: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 vt100_cursr db 0 ; cursor 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 ;------------------------ ; 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 v1.22 17-APR-1991)$' 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.$' 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$' 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 parmsk db ? ; 8/7 bit parity mask, for reception flowoff db ? ; flow-off char, Xoff or null (if no flow) flowon db ? ; flow-on char, Xon or null captrtn dw ? ; routine to call for captured output xofsnt db 0 ; Say if we sent an XOFF. xofrcv db 0 ; Say if we received an XOFF. temp dw 0 temp1 dw ? ; Temporary storage. temp2 dw ? ; Temporary storage. ; Entries for choosing communications port comptab db 9 ; 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 'UB-NETCI','N' mkeyw ' ',0 ; port is not present, for Status vt_ourarg termarg <> modem mdminfo timer tmrinfo ;++ The following structure must be initialized as in MSSKER ; port1 prtinfo <0FFFFh,0,defpar,1,0,defhand,floxon> port2 prtinfo <0FFFFh,0,defpar,1,0,defhand,floxon> portd prtinfo <0FFFFh,0,defpar,1,0,defhand,floxon> portf prtinfo <0FFFFh,0,defpar,1,0,defhand,floxon> portn prtinfo <0FFFFh,0,defpar,1,0,defhand,floxon> termtb db tttypes ; entries for Status, not Set mkeyw 'Heath-19',ttheath mkeyw 'none',ttgenrc mkeyw 'Tek4014',tttek mkeyw 'VT102',ttvt100 mkeyw 'VT52',ttvt52 setchtab db 3 mkeyw 'EUC',1 mkeyw 'JIS7',2 mkeyw 'MS-Kanji',0 ; 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 (not tested - may not work) 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 0FFFFH ; 19200 baud dw 0FFFFH ; 38400 baud (not tested - may not work) dw 0FFFFH dw 0FFFFH dw 0FFFFH baudlen equ ($-bddat8)/2 ; number of entries above 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 ' 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 '$' data ends code segment public 'code' extrn comnd:near, dopar:near, atoi:near, prompt:near extrn isfile:near, strlen:near, strcpy:near extrn sleep:near, msuinit:near, keybd:near extrn kbdlini:near, kbdlend:near extrn ans_keystr:near extrn pntchr:near, pntflsh: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 tekstat: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 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 ;----------------- 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 shomodem proc near mov ah,cmeol ; get a confirm call comnd jnc shomd0 ret ; no confirm shomd0: ; call serini ; activate port to get status call serrst ; turn off port again ; call getmodem ; get modem status in al mov mdstreg,al ; mov ah,prstr mov dx,offset msmsg1 ; modem not ready msg test mdstreg,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 mdstreg,modcd ; CD asserted? jz shomd2 ; z = no mov dx,offset msmsg4 ; say asserted shomd2: int dos mov dx,offset msmsg5 ; CTS asserted msg test mdstreg,modcts ; CTS asserted? jz shomd3 ; z = no mov dx,offset msmsg6 ; say asserted shomd3: int dos clc ret shomodem endp ; ; returns modem status in AL. Needs more work. Current version ; returns only valid for PORT 1. ; getmodem proc near push bx push dx mov dx,mnst1a ; read status of port 1A in al,dx and al,80h ; set only DR bit mov bl,al ; save it mov dx,mnrdsa ; 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 shomd3 jnz getmd3 ; @@ [04-Feb-89] 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: push cx ; save regs cmp flowoff,0 ; Are we doing flow control. je outch2 mov cx,1500h ; about 15 sec in 4 millisec interval cmp ah,flowoff ; sending xoff? jne outch1 ; ne = no mov xofsnt,false ; supress xon from chkxon buffer routine outch1: cmp xofrcv,true ; Are we being held? jne outch2 ; No - it's OK to go on. push ax mov ax,4 ; 4 millisec wait loop call pcwait pop ax loop outch1 ; held, try for a while mov xofrcv,false ; timed out, force it off and fall thru. outch2: push dx ; Save register. xor cx,cx mov al,ah ; Parity routine works on AL. call dopar ; Set parity appropriately. ; Begin revised output routine mov ah,al mov temp,ax ; put data there cmp vt_ourarg.prt,'N' ; Network port ? jne outch6 ; ne = No. pop dx pop cx jmp outchn outch6: cmp vt_ourarg.prt,'D' ; DOS device ? jne outch7 ; ne = no jmp outchd outch7: mov dx,modem.mdstat outch3: in al,dx test al,txrdy jnz outch4 loop outch3 stc ; fail to send jmp outch5 outch4: mov al,ah mov dx,modem.mddat out dx,al clc ; we have sent it. outch5: pop dx pop cx clc 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 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 bx ; end of revised routine jmp outch5 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,NETCI_WRITE ; set function mov al,NETCI_PORT ; set port ; send0: mov cx,xmtcnt ; packet length jcxz send1 int NETCI_INT ; send packet 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 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. 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. do nothing here. 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 gbaud1: 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 prtch0 ; e=no. jmp prtchf prtch0: cmp vt_ourarg.prt,'D' jne prtch4 jmp prtchd prtch4: call chkxon cmp vt_ourarg.prt,'N' jne prtch3 jmp prtchn prtch3: 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: push ax push bx push cx push es mov ax,offset source mov rcvpnt,ax mov srcpnt,ax ; mov ah,NETCI_READ mov al,NETCI_PORT mov bx,offset source mov cx,bufsiz push ds pop es int NETCI_INT mov count,cx add srcpnt,cx pop es pop cx pop bx pop ax cmp count,0 jnz prtchn2 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 PRTCHR ENDP ; Local routine to see if we have to transmit an xon chkxon proc near push bx mov bx,portval cmp [bx].floflg,0 ; doing flow control? je chkxo1 ; no, skip all this cmp xofsnt,false ; have we sent an xoff? je chkxo1 ; no, forget it cmp count,mntrgh ; below trigger? jae chkxo1 ; no, forget it mov ax,[bx].flowc ; ah gets xon call outchr ; send it nop nop nop ; in case it skips mov xofsnt,false ; remember we've sent the xon. chkxo1: pop bx ; restore register ret ; and return chkxon endp ; IHOSTS - Initialize the host by sending XON, or equivalent, and enter the ; cycle of clear input buffer, wait 1 second, test if buffer empty then exit ; else repeat cycle. Requires that the port be initialized before hand. ; Ihosts is used by the local send-file routine just after initializing ; the serial port. ; 22 March 1986 [jrd] IHOSTS PROC NEAR push ax ; save the registers push bx push cx push dx mov bx,portval ; port indicator mov ax,[bx].flowc ; put Go-ahead flow control char in ah or ah,ah ; don't send null if flow = none jz ihosts1 ; z = null call outchr ; send it (release Host's output queue) nop ; outchr can do skip return nop nop ihosts1:call clrbuf ; clear out interrupt buffer mov ax,1 ; sleep for 1 second ; NOTE: for systems with a time-of-day clock uncomment the line below ; (call sleep) to provide an interval for the host to respond. call sleep ; procedure sleep is in msscom.asm cmp repflg,0 ; in replay mode ? jne ihosts2 ; ne=yes. call prtchr ; check for char at port jnc ihosts1 ; have a char in al, repeat wait/read cycle ihosts2: pop dx ; empty buffer. we are done here. pop cx pop bx pop ax ret IHOSTS ENDP ; IHOSTR - initialize the remote host for our reception of a file by ; sending the flow-on character (XON typically) to release any held ; data. Called by receive-file code just after initializing the serial ; port. 22 March 1986 [jrd] IHOSTR PROC NEAR ;@@ call pc98_bell push ax ; save regs push bx push cx mov bx,portval ; port indicator mov ax,[bx].flowc ; put Go-ahead flow control char in ah or ah,ah ; don't send null if flow = null jz ihostr1 ; z = null call outchr ; send it (release Host's output queue) ihostr1:pop cx pop bx pop ax clc 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 mov dx,modem.mdcom ; set command port mov al,chng ; hangup command out dx,al xor cx,cx ; counts for waiting loop serhng1: loop serhng1 mov pbaud_1,0FFFFh ; reset previous baud rate 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 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] --- SENDBR ENDP SENDBL PROC NEAR ; Long Break cmp flags.comflg,'N' je ub_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] --- 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 ; Called only when Kermit exits. Program pointer passed to mssker ; in word 'lclexit'. ; This is used as a local end routine. LCLCLOSE PROC NEAR push ax call clsprt ; close device if opened. cmp pcnet,0 ; network closed ? je lclclo1 ; e = yes mov ah,NETCI_CLOSE ; UB-NETCI close command mov al,NETCI_PORT int NETCI_INT mov pcnet,0 lclclo1: test vtgrph_flg,EXITG_BIT jz lclclo2 call gdisp_on ; graphic display on lclclo2: call reset_keydef ; reset key definition table call kbdlend ; local reset keyboard routine mov ah,prstr ;@@ mov dx,offset nrmscr ;@@ int dos ;@@ pop ax ret LCLCLOSE ENDP ; Open NETCI port chknet proc near cmp pcnet,0 ; netport is closed ? jne chknetx push ax push bx push cx push es ; push cs pop es mov temp,0 mov bx,offset temp mov cx,0 mov ah,NETCI_OPEN mov al,NETCI_PORT int NETCI_INT mov lclexit,offset lclclose call clrbuf mov xmtcnt,0 mov pcnet,2 ; pop es pop cx pop bx pop ax chknetx: 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 ; ; Set the current port. ; COMS PROC NEAR mov dx,offset comptab ; the table to examine mov bx,0 ; use keywords as help mov ah,cmkey ; parse keyword from comptab call comnd jnc coms0 ret ; no match coms0: cmp bl,'N' ; Network ? jne coms1 ; ne = no jmp comsn ; Yes, setup for networks coms1: cmp bl,'D' ; Device ? jne coms2 jmp comsd ; Yes, setup for device coms2: mov temp,bx mov ah,cmeol call comnd ; Get a confirm. jnc coms2_1 ret ; Didn't get a confirm. coms2_1: 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 call chknet ; start network usage cmp pcnet,0 ; is network alive (non-zero)? jne comsn4 ; ne = yes stc ret ; return failure comsn4: mov portval,offset portn ; set netowrk port data mov flags.comflg,'N' ; 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 ; COMS 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,ttvt100 je dmp_v1 cmp flags.vtflg,ttvt52 je 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 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.vtflg,ttvt100 ; 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 lclexit,offset lclclose ; set local close routine 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 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 di,srcpnt ; get buffer pointer mov dx,modem.mdstat ; is data available? in al,dx test al,rxrdy jz mnpro7 mov dx,modem.mddat ; read data in al,dx or al,al jz mnpro7 ; Ignore nulls. ; do NOT ignore rubouts, because TEK LOY code use this. ; cmp al,7FH ; Ignore rubouts, too. ; jz mnpro7 mov ah,al ; ; originally the following was ; ; and ah,7fH ; only consider low-order 7 bits for flow ctl. ; do NOT mask 8-th bit for flow control when parity is none. ; and ah,parmsk ; apply parity mask for flow ctl. mov bp,portval cmp ds:[bp].floflg,0 ; Doing flow control? je mnpro4 ; Nope. mov bx,ds:[bp].flowc ; Flow control char (BH = XON, BL = XOFF). cmp ah,bl ; Is it an XOFF? jne mnpro3 ; Nope, go on. mov xofrcv,true ; Set the flag. jmp short mnpro7 mnpro3: cmp ah,bh ; Get an XON? jne mnpro4 ; No, go on. mov xofrcv,false ; Clear our flag. jmp mnpro7 mnpro4: stosb cmp di,offset source + bufsiz jb mnpro5 ; not past end... mov di,offset source ; wrap buffer around mnpro5: mov srcpnt,di ; update ptr inc count cmp ds:[bp].floflg,0 ; Doing flow control? je mnpro7 ; No, just leave. cmp xofsnt,true ; Have we sent an XOFF? je mnpro7 ; Yes. cmp count,mntrgh ; Past the high trigger point? jbe mnpro7 ; No, we're within our limit. mov ah,bl ; Get the XOFF. call outchr ; Send it. nop ; ignore failure. nop nop mov xofsnt,true ; Remember we sent it. mnpro7: ret SERINT ENDP ; Initialization for using serial port. Returns normally. SERINI PROC NEAR cmp flags.comflg,'A' ;@@@@@ jae serin1 ;@@@@@ call inita serin0:;;;; call clrbuf ; Clear input buffer. ;; push bx ;; mov bx,portval ; get port ;; 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: mov bx,[bx].flowc ; get flow control chars ;; mov flowoff,bl ; xoff or null ;; mov flowon,bh ; xon or null ;; pop bx serin1: clc ; always success ! true ?! ret ; We're done. 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 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: 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 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 prthld,0 ; clear port hold flag at the beginning mov replay_hold,0 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: call vt100_restore call tek4014_restore mov fairness,0 mov kanji_smode,0 ; clear Kanji pending flag mov kanji_rmode,0 mov kanji_7smode,0 mov kanji_7rmode,0 mov argadr,ax ; save argument ptr mov si,ax ; 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 ;@@ 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,ttvt100 ; vt100 emulation ? je term_vt ; e = yes. cmp flags.vtflg,ttvt52 ; vt52 emulation ? je term_vt ; e = yes. cmp flags.vtflg,tttek ; Tek4014 emulation ? je term_tk ; e = yes. 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 jc short term2 ; c = no char, go on call outtty ; display and capture char inc fairness cmp fairness,100 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,ttvt100 ; vt100 emulation mode? jne vtchg_nvt100 call vt100_save jmp vtchg1 vtchg_nvt100: cmp flags.vtflg,tttek ; tek emulation mode? jne vtchg_ntek call tek4014_save jmp vtchg1 vtchg_ntek: vtchg1: inc flags.vtflg cmp flags.vtflg,TTTYPES jb vtchg2 mov flags.vtflg,ttgenrc jmp vtchg3 vtchg2: cmp flags.vtflg,ttgenrc jne vtchg21 jmp vtchg3 vtchg21: cmp flags.vtflg,ttvt100 jne vtchg22 call ent_vt jmp vtchg3 vtchg22: cmp flags.vtflg,tttek jne vtchg23 call ent_tk jmp vtchg3 vtchg23: call set_modlin call vt100_modlin jmp vtchg1 vtchg3: clc ; stay in connect mode ret ; ; reset terminal vtreset: cmp flags.vtflg,ttvt100 jne vtreset1 call vt100_reset jmp vtresetx vtreset1: cmp flags.vtflg,tttek jne vtreset2 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,ttvt100 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 vt_ourarg.flgs,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 ; 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 nametext 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