name msyv90 ; File MSYV90.ASM ; Copyright (C) 1982,1991, Trustees of Columbia University in the ; City of New York. Permission is granted to any individual or ; institution to use, copy, or redistribute this software as long as ; it is not sold for profit and this copyright notice is retained. ; Kermit system dependent module for VICTOR 9000/SIRIUS ; Use with msuv90.asm and msxv90.asm. ; SPECIAL VERSION WITH NEAR COMPLETE SUPPORT OF TEKTRONIX 4010 EMULATION ; as of MS-DOS KERMIT version 3.02. Victor 9000 Kermit without ; Tektronix emulation will no longer be supported. ; ; Edit history: ; 2 March 1991 version 3.10 ; Last modification: 2 March 1991 ; 6 Dec 1988 Replace dynamic screen space with static segment aagraph (see ; NOTE WELL msg below), add control of 7/8 bit displays, add TRANSLATE INPUT ; table workings. [jrd] ; 1 Mar 1988 add TERMTB terminal status display table and correct use ; of tektronix mode set to match that implemented in MSYIBM as of version ; 2.30. Also add use of CAN (control-X) to exit tektronix temporary ; mode. [bgp] ; 20 Sept 1987 clarify sequence of translation and 8 bit display. [jrd] ; 11 Sept 1987 Modify page_full routine for Tektronix emulation so that ; the indicator box put in the lower left corner of the screen on page ; full condition is put in with exclusive or instead of simple or. Then ; modified the homescr routine to remove that indicator box using an ; exclusive or operation if the page full condition exists and to be sure ; that the old text cursor is removed before moving the current cursor ; location to the upper left corner. [bgp] ; 7 Sept 1987 Remove keep_delete, filter null in portch, filter DEL in ; terminal read section for VT100 (pass through for Tek), add parmsk. [jrd] ; 29 August 1987 add temporary Tektronix mode so that the receipt of an ; ESCAPE FF (Tektronix clear screen sequence) will go to Tektronix mode with ; a clear screen. It will go back to the previous mode on the receipt of ; an ESCAPE US sequence or by entering the escape character. ; 29 August 1987 add support for keyboard translation. This uses a ; modified version of the translator for the GENERIC MS-DOS version. ; This modification required the addition of the following routines: ; CQUERY - help on connect ; CSTATUS - show status of connect ; CQUIT - exit from connect ; CHANG - hangup the phone (drop dtr) ; DMPSCN - dump the screen ; TRNPRS - toggle printer dump status ; SNULL - send a null ; KDOS - push to DOS ; KLOGOFF - suspend session logging ; KLOGON - resume session logging ; CPAGE - clear tektronix screen ; CHOME - move to home on tektronix screen ; 9 February 1987 Added set of keep_delete (byte) = 0 if delete to be ; ignored by serial port routines [bgp] ; 7 August 1986 fill out procedure DUMPSCR - it was borrowed from MSYIBM ; modified to fit the Victor format. It required a modification of ; LCLYINI to get the character set base [bgp] ; 7-DEC-85 ORIGINAL BGP ; 20-FEB-86 CORRECTED FOR ERROR IN PUTMOD IN MSXV9000 (BGP) ; 22-FEB-86 CLEANED UP CHARACTER SET FOR TEK EMULATION (BGP) ; 22-FEB-86 ADDED CODE TO SWALLOW ANSI ESCAPE SEQUENCES IN ; HEATH EMULATION MODE (BGP) ; ************************************************************ ; Remove segment Graph and replace it with memory dynamically allocated ; from DOS via procedure sbrk in mssker. Do allocation, verify that it ; is in the correct chunk of memory (and fix if necessary), initialize ; scrseg, and clear the area, all done in lclyini. 17 March 86 ; Joe R. Doupnik ; Add global procedure Dumpscr, called by Ter in file msster, to dump screen ; to a file. Just does a beep for now. 13 April 1986 [jrd] ; ; Added 'full' VT100 emulation using code by Andreas Stumpf ; (ZRZS@DS0RUS1I). The significant parts that are not emulated are ; esc c - reset terminal ; esc N - ?? ; esc O - ?? ; esc n - ?? ; esc l - ?? ; esc o - ?? ; esc < - go to ANSI mode (from VT52) ; esc [ q - fiddle with the LED's ; esc [ h - some modes not supported ; esc [ l - some modes not supported ; esc [ i - ?? ; esc [ p - ?? ; esc [ y - confidence tests ; and some codes that are not VT100 'standard' are supported ; esc [ E - ?? ; esc [ F - ?? ; esc [ G - ?? ; esc [ L - ?? ; esc [ M - ?? ; esc [ @ - ?? ; esc [ P - ?? ; esc [ X - ?? ; esc [ d - ?? ; esc [ e - ?? ; 22 April 86 Bryan G. Peterson public term, lclyini, vts, vtstat ; entry points public dumpscr, extmacro, vtmacname, vtmaclen, setchtab public cquery, cstatus, cquit, snull, kdos ; [bgp] public klogof, klogon, cpage, chome ; [bgp] public chang, trnprs, dmpscn, chrout ; [bgp] public termtb, trnmod public sescur, sesdisp, setnbios, fcsrtype ; NOTE WELL - The Victor 9000 machine requires high resolution (graphics) ; memory to be located in the first 128KB of system memory, even though ; programs are loaded into the same area(!). Here we define a special graphics ; segment, aagraph, and request the assembler to located segments ; as shown below, with _STACK last! ; Further we MUST place MSYV90.OBJ first in the Link list of .objs. ; [jrd 8 Dec 1988]. ; ; Start Stop Length Name Class ; 00000H 09C5FH 09C60H AAGRAPH KCODE ; 09C60H 14FB0H 0B351H CODE KCODE ; 14FC0H 1768FH 026D0H CODE1 KCODE ; 17690H 17690H 00000H CODE2 KCODE ; 17690H 24E9BH 0D80CH DATA KDATA ; 24EA0H 2627FH 013E0H DATA1 KDATA ; 26280H 26280H 00000H _TEXT CODE ; 26280H 26280H 00000H _DATA DATA ; 26280H 26280H 00000H CONST CONST ; 26280H 26280H 00000H _BSS BSS ; 26280H 26FC7H 00D48H _STACK STACK ; AAGRAPH SEGMENT PUBLIC 'kcode' DB 40032 DUP (?) ; graphics memory AAGRAPH ENDS ; Do the "include mssdef.h" file after the aagraph declaration. include mssdef.h ; Some extra ASCII definitions ENQ EQU 5 VTAB EQU 0BH ETB EQU 17H CAN EQU 18H GS EQU 1DH US EQU 1FH CURSOR_CHR EQU '_' ; The cursor character CURSOR_TIME EQU 100 ; cursor on countdown period ; this is the number of unsuccessful tries on getting a charcter ; from the input port before turning on the cursor. X_MAX EQU 799 Y_MAX EQU 399 TEK_X_MAX EQU 1023 TEK_Y_MAX EQU 780 TEXT_X_MAX EQU 789 TEXT_Y_MAX EQU 389 RPLINE EQU 11 ; rows per text line CPCHAR EQU 11 ; columns per text character R_MARG EQU 781 ; right margin position CUR_LEN EQU 10 ; length of arms on graphics cursor FALSE EQU 0 TRUE EQU 1 SEG_CRTC EQU 0E800H ; segment for crt controller OFF_CRTC EQU 0 ; offset for crt controller modfrm struc ; format of mode line db ' Esc-chr:' m_echr db 2 dup (?) db ' Help:' m_hlp db 2 dup (?) db '? Port:' m_prt db 1 dup (?) db ' Speed:' m_baud db 5 dup (?) db ' Parity:' m_par db 4 dup (?) db ' Echo:' m_echo db 3 dup (?) m_term db 13 dup (' ') ; 13 bytes for terminal type m_prn db 3 dup (' ') ; show PRN when printer is on db ' $' ; must be dollar terminated modfrm ends data segment extrn rdbuf:byte, flags:byte ; to get access to emulation extrn dmpname:byte, filtst:byte, trans:byte, prnhand:word extrn kbdflg:byte,rxtable:byte,taklev:byte,takadr:word,mcctab:byte termhlp db CR,LF,'Terminal type of Heath-19, VT102, VT52, none,' db ' or Tek4010$' termtb db 5 mkeyw 'Heath-19',ttheath mkeyw 'none',ttgenrc mkeyw 'Tek4010',tttek mkeyw 'VT102',ttvt100 mkeyw 'VT52',ttvt52 setchtab db 1 ; Set File Character-Set table mkeyw 'CP437',437 ; hardware default Code Page tty_generic db ' None ' tty_tek4010 db ' Tektronix ' tty_heath db ' Heath-19 ' tty_vt102 db ' VT-102 ' tty_vt52 db ' VT-52 ' tty_unkn db ' Unknown ' ; stuff for screen routines wflags label word ; so we can push yflags yflags db ? ; status flags... db 0 ; extra byte for flags flags1 db 0 ; internal flags. prtscr equ 80h ; print screen pressed inited equ 08h ; been here before... wrapped equ 04h ; on if wrapped on last char... argadr dw ? ; address of arg blk crt_cols db 80 ; number of screen columns (typ 80) crt_lins db 24 ; number of screen rows - 1 (typ 24) oldsp dw 0 ; offset to longjmp to for i/o failure vtmacname dw 0 ; pointer to selected macro name vtmaclen db 0 sescur dw 0 modbuf modfrm <> ; mode line buffer ; routine to call for captured output captrtn dw ? ; some static data for mode line unkbaud db 'Unkwn' ; must be 5 chars... baudn db ' 45.5' db ' 50' db ' 75' db ' 110' db ' 135' db ' 150' db ' 300' db ' 600' db ' 1200' db ' 1800' db ' 2000' db ' 2400' db ' 4800' db ' 9600' db '19200' db '38400' baudnsiz equ 16 ; # of baud rates known (tbl size / 4) parnams db 'Even' db 'Mark' db 'None' db 'Odd ' ; must be 4 chars db 'Spc ' offmsg db 'Off' onmsg db 'On ' lclmsg db 'Lcl' remmsg db 'Rem' portno db ? tscreen dw 1920 dup (?) ; place to save text screen tcurloc db 2 dup (?) ; column,row tscrseg dw 0F000H rptcur db 27,'n$' ; request cursor location escseq db 0 ; ANSI escape sequence indicator ; 0=none, 1=escape, 2=[, <0 eat chars ; until =0 ; stuff for the Tektronix emulation ; Order is essential:scrloc then scrseg scrloc dw 0 ; offset of screen memory [jrd] scrseg dw 0 ; segment of screen memory [jrd] parmsk db ? ; 8/7 bit parity mask, for reception temp_tek db FALSE ; for temporary tektronix mode [bgp] temp_mode dw 0 ; previous mode for temp tek mode [bgp] tek_allowed db TRUE ; flag for screen memory ok no_tek_msg db CR,LF,'SCREEN MEMORY ALLOCATION FAILED' db ' - TEKTRONIX EMULATION NOT ALLOWED',BELL,CR,LF,'$' first_in db TRUE ; this is the first time emulating intens db 14 ; CRT intensity setting status_line dw 80 dup (?) ; for CRT status line bit_mask db 1,2,4,8,16,32,64,128 combine dw pixel_or t_combine dw word_or start dw 0,0 ; vector start point endpt dw 0,0 ; end point (victor coords) cur_x dw 0 ; tek coordinates of current point cur_y dw 780 text_x dw 0 ; text cursor location (victor coords) text_y dw 0 ; upper left corner cursor_cnt dw 0 ; cursor countdown cursor db FALSE ; cursor state flag full_flag db FALSE ; flags page full condition x_inc dw 1 y_inc dw 1 delta_x dw 0 delta_y dw 0 part_accum dw 0 ; accumulator for line temp dw 0 ; temporary storage c_mask dw 0 ; mask for character work cur_stp dw 1 ; graphics cursor step crs_hor dw 0,0,0 ; cursor horizontal line (x1,x2,y) crs_ver dw 0,0,0 ; cursor vertical line (y1,y2,x) prtesc db FALSE ; escape from port in GIN mode trmesc db FALSE ; escape from terminal in GIN mode graph_mode db FALSE ; graphics mode flag echo_supp db FALSE ; echoplex suppression flag visible db 0 ; 0 to move, 1 to draw hiy dw 0 loy db 0 hix dw 0 lox db 0 lsb db 0 escflag db 0 tekjump dw TEKTXT,TEKESC,TEKHIY,TEKHIX ; The next variable defines the bit masks for the text font font dw 0,20H,70H,20H,20H,0,20H,20H,0,0,0 ; ! dw 0,88H,88H,88H,0,0,0,0,0,0,0 ; " dw 0,88H,88H,3FEH,88H,3FEH,88H,88H,0,0,0 ; # dw 0,1FCH,222H,22H,1FCH,220H,222H,1FCH,0,0,0 ; $ dw 0,10CH,8CH,40H,20H,10H,188H,184H,0,0,0 ; % dw 0,10H,28H,10H,28H,144H,84H,178H,0,0,0 ; & dw 0,30H,30H,20H,10H,0,0,0,0,0,0 ; ' dw 0,40H,20H,10H,10H,10H,20H,40H,0,0,0 ; ( dw 0,10H,20H,40H,40H,40H,20H,10H,0,0,0 ; ) dw 0,104H,88H,50H,3FEH,50H,88H,104H,0,0,0 ; * dw 0,20H,20H,20H,3FEH,20H,20H,20H,0,0,0 ; + dw 0,0,0,0,0,0,30H,30H,20H,10H,0 ; , dw 0,0,0,0,3FEH,0,0,0,0,0,0 ; - dw 0,0,0,0,0,0,30H,30H,0,0,0 ; . dw 0,100H,80H,40H,20H,10H,8,4,0,0,0 ; / dw 0,0F8H,184H,242H,222H,212H,10CH,0F8H,0,0,0 ; 0 dw 0,20H,30H,20H,20H,20H,20H,70H,0,0,0 ; 1 dw 0,1FCH,202H,200H,1FCH,2,2,3FEH,0,0,0 ; 2 dw 0,3FEH,100H,80H,1C0H,200H,202H,1FCH,0,0,0 ; 3 dw 0,102H,102H,102H,3FEH,100H,100H,100H,0,0,0 ; 4 dw 0,3FEH,2,2,1FEH,200H,200H,1FEH,0,0,0 ; 5 dw 0,1FCH,2,2,1FEH,202H,202H,1FCH,0,0,0 ; 6 dw 0,3FEH,100H,80H,40H,20H,20H,20H,0,0,0 ; 7 dw 0,0F8H,104H,88H,1FCH,202H,202H,1FCH,0,0,0 ; 8 dw 0,1FCH,202H,202H,3FCH,200H,200H,1FCH,0,0,0 ; 9 dw 0,0,30H,30H,0,0,30H,30H,0,0,0 ; : dw 0,0,30H,30H,0,0,30H,30H,20H,10H,0 ; ; dw 0,80H,40H,20H,10H,20H,40H,80H,0,0,0 ; < dw 0,0,0,3FEH,0,3FEH,0,0,0,0,0 ; = dw 0,8,10H,20H,40H,20H,10H,8,0,0,0 ; > dw 0,1FCH,202H,200H,1E0H,20H,0,20H,0,0,0 ; ? dw 0,1FCH,202H,3E2H,212H,1E2H,2,1FCH,0,0,0 ; @ dw 0,70H,88H,104H,3FEH,202H,202H,202H,0,0,0 ; A dw 0,0FEH,102H,102H,1FEH,202H,202H,1FEH,0,0,0 ; B dw 0,1FCH,202H,2,2,2,202H,1FCH,0,0,0 ; C dw 0,1FEH,202H,202H,202H,202H,202H,1FEH,0,0,0 ; D dw 0,3FEH,2,2,7EH,2,2,3FEH,0,0,0 ; E dw 0,3FEH,2,2,7EH,2,2,2,0,0,0 ; F dw 0,1FCH,202H,2,382H,202H,202H,3FCH,0,0,0 ; G dw 0,202H,202H,202H,3FEH,202H,202H,202H,0,0,0 ; H dw 0,0F8H,20H,20H,20H,20H,20H,0F8H,0,0,0 ; I dw 0,3E0H,80H,80H,80H,80H,84H,78H,0,0,0 ; J dw 0,202H,102H,82H,7EH,82H,102H,202H,0,0,0 ; K dw 0,2,2,2,2,2,2,3FEH,0,0,0 ; L dw 0,306H,28AH,252H,222H,202H,202H,202H,0,0,0 ; M dw 0,206H,20AH,212H,222H,242H,282H,302H,0,0,0 ; N dw 0,1FCH,202H,202H,202H,202H,202H,1FCH,0,0,0 ; O dw 0,1FEH,202H,202H,1FEH,2,2,2,0,0,0 ; P dw 0,1FCH,202H,202H,202H,282H,102H,2FCH,0,0,0 ; Q dw 0,1FEH,202H,202H,1FEH,82H,102H,202H,0,0,0 ; R dw 0,1FCH,202H,2,1FCH,200H,202H,1FCH,0,0,0 ; S dw 0,3FEH,20H,20H,20H,20H,20H,20H,0,0,0 ; T dw 0,202H,202H,202H,202H,202H,302H,2FCH,0,0,0 ; U dw 0,202H,202H,202H,104H,88H,50H,20H,0,0,0 ; V dw 0,202H,202H,202H,222H,222H,154H,88H,0,0,0 ; W dw 0,104H,88H,50H,20H,50H,88H,104H,0,0,0 ; X dw 0,202H,104H,88H,50H,20H,20H,20H,0,0,0 ; Y dw 0,3FEH,80H,40H,20H,10H,8,3FEH,0,0,0 ; Z dw 0,70H,10H,10H,10H,10H,10H,70H,0,0,0 ; [ dw 0,4,8,10H,20H,40H,80H,100H,0,0,0 ; \ dw 0,70H,40H,40H,40H,40H,40H,70H,0,0,0 ; ] dw 0,20H,70H,0A8H,124H,20H,20H,20H,0,0,0 ; ^ dw 0,0,0,0,0,0,0,0,0,0,7FFH ; _ dw 0,10H,20H,40H,0,0,0,0,0,0,0 ; ` dw 0,0,0,0F8H,100H,1F8H,104H,2F8H,0,0,0 ; a dw 0,4,4,0FCH,104H,104H,104H,0FCH,0,0,0 ; b dw 0,0,0,0F8H,104H,4,4,1F8H,0,0,0 ; c dw 0,100H,100H,1F8H,104H,104H,104H,1F8H,0,0,0 ; d dw 0,0,0,0F8H,104H,1FCH,4,1F8H,0,0,0 ; e dw 0,20H,50H,10H,38H,10H,10H,10H,0,0,0 ; f dw 0,0,0,1F8H,104H,104H,104H,1F8H,100H,100H,0F8H ; g dw 0,4,4,0FCH,104H,104H,104H,104H,0,0,0 ; h dw 0,0,20H,0,20H,20H,20H,20H,0,0,0 ; i dw 0,0,40H,0,40H,40H,40H,40H,40H,50H,20H ; j dw 0,4,4,44H,24H,3CH,44H,84H,0,0,0 ; k dw 0,30H,20H,20H,20H,20H,20H,0F8H,0,0,0 ; l dw 0,0,0,1DEH,222H,222H,222H,222H,0,0,0 ; m dw 0,0,0,0FCH,104H,104H,104H,104H,0,0,0 ; n dw 0,0,0,0F8H,104H,104H,104H,0F8H,0,0,0 ; o dw 0,0,0,0FCH,104H,104H,104H,0FCH,4,4,4 ; p dw 0,0,0,1F8H,104H,104H,104H,1F8H,100H,300H,100H ; q dw 0,0,0,0FCH,104H,4,4,4,0,0,0 ; r dw 0,0,0,0F8H,4,0F8H,100H,0FCH,0,0,0 ; s dw 0,10H,10H,78H,10H,10H,50H,20H,0,0,0 ; t dw 0,0,0,84H,84H,84H,84H,178H,0,0,0 ; u dw 0,0,0,104H,104H,88H,50H,20H,0,0,0 ; v dw 0,0,0,222H,222H,222H,222H,1DCH,0,0,0 ; w dw 0,0,0,88H,50H,20H,50H,88H,0,0,0 ; x dw 0,0,0,104H,104H,104H,104H,1F8H,100H,100H,0F8H ; y dw 0,0,0,0F8H,40H,20H,10H,0F8H,0,0,0 ; z dw 0,0C0H,20H,20H,10H,20H,20H,0C0H,0,0,0 ; { dw 0,20H,20H,20H,20H,20H,20H,20H,0,0,0 ; | dw 0,18H,20H,20H,40H,20H,20H,18H,0,0,0 ; } dw 0,0,1CH,222H,1C0H,0,0,0,0,0,0 ; ~ ; stuff for ANSI emulation [as] SUPERBIOS equ 0dfh ; SuperBios-Interrupt tt struc ; structure of keyboardtable head dw 2 dup (?) kd0 db 104*3 dup (?) kd12 dw 104*3 dup (?) extrtabl db 256 dup (?) tt ends afirst db 0 ; Parameterblock for setting/getting of keyboard-table parmblock db 3 laenge dw 1196 ; length of table offs dw offset oldtable segm dw seg oldtable ; block for call to get Console-driver-address condev dw 1 drivadr dd 0 ; address of consoledriver ; oldtable tt <,,,> ; saved old keytable numtbl tt <,,,> ; Table with Num-Keypad apptbl tt <,,,> ; Table with Appl-Keypad ; In order to avoid smashing stuff that may already be in the multi-char ; sequence table for the keyboard (or as little as possible) put it near the ; end of the table - the following parameters tells how deep into the table ; to start putting stuff START_EXTRTBL EQU 160 ; Cursorsequences ANSI appcur db 0 ; flag for cursor key modes curseq db 3,ESCAPE,'[A',3,ESCAPE,'[B',3,ESCAPE,'[D',3,ESCAPE,'[C' curapp db 3,ESCAPE,'OA',3,ESCAPE,'OB',3,ESCAPE,'OD',3,ESCAPE,'OC' ; Applikationkeypad appkeys db 0 ; flag for keypad modes applik db 3,ESCAPE,'[A',3,ESCAPE,'[B',3,ESCAPE,'[D',3,ESCAPE,'[C' db 3,ESCAPE,'OP',3,ESCAPE,'OQ',3,ESCAPE,'OR',3,ESCAPE,'OS' db 3,ESCAPE,'Ow',3,ESCAPE,'Ox',3,ESCAPE,'Oy',3,ESCAPE,'Om' db 3,ESCAPE,'Ot',3,ESCAPE,'Ou',3,ESCAPE,'Ov',3,ESCAPE,'Ol' db 3,ESCAPE,'Oq',3,ESCAPE,'Or',3,ESCAPE,'Os',3,ESCAPE,'OM' db 3,ESCAPE,'Op',3,ESCAPE,'On' sesctbl db 'DEHMNOZn|o[>=78c<)(#' ; table for char following single ESCAPE db FF ; ESCAPE FF goes temporary tektronix [bgp] sesclen equ $-sesctbl ; now the table for routines to process those characters sescsub dw processD dw processE dw processH dw processM dw ignore dw ignore dw procc0 ; same as ESCAPE [0c dw ignore dw ignore dw ignore dw processbra dw processgt dw processeq dw process7 dw process8 dw ignore dw ignore dw processrp dw processlp dw processlb dw process_ff ; temporary tektronix mode [bgp] ; table for the last characters in a ESCAPE'[' sequence mesctbl db '`EFGABCDHLM@PXKJfghilmrcnpyqde' mesclen equ $-mesctbl ; processing routine table for ESCAPE'[' sequences mescsub dw proce dw proce dw procuf dw procug dw curmov dw curmov dw curmov dw curmov dw procH dw procL dw procM dw procAt dw procP dw procX dw procK dw procJ dw procH dw procg dw prochl dw ignore dw prochl dw proclm dw procr dw procc dw procn dw ignore dw ignore dw ignore dw procld dw procle ; top db 1 ; scrolling region margins bottom db 24 escpnt dw offset escstring escstring db 80 dup (?) ; save area for Escape sequence tabstops db 0,0,0,0,0,0,0,0 ; tabulator stops db 1,0,0,0,0,0,0,0 db 1,0,0,0,0,0,0,0 db 1,0,0,0,0,0,0,0 db 1,0,0,0,0,0,0,0 db 1,0,0,0,0,0,0,0 db 1,0,0,0,0,0,0,0 db 1,0,0,0,0,0,0,0 db 1,0,0,0,0,0,0,0 db 1,0,0,0,0,0,0,0 chrset_mask db 0 ; mask for selecting character set char_base dw 0 ; screen character base crlf db cr,lf dmphand dw 0 ; handle for screen dump [bgp] dumpbuf db 80 dup (?),CR,LF ; line buffer for screen dump dumpsep db FF,CR,LF ; put in file between screen dumps dmperr db ' WARNING: cannot open the screen dump file$' data ends code1 segment ; Control text cursor. AL = 0 for off, 1 for on (nominally underline) fcsrtype proc far call csrtype ret fcsrtype endp code1 ends code segment extrn prtchr:near,outchr:near,cmblnk:near,poscur:near extrn putmod:near,clrmod:near,beep:near,sbrk:near ; [jrd] extrn comnd:near,isfile:near ; [bgp] extrn msuinit:near, keybd:near ; [bgp] extrn pntchr:near, pntflsh:near assume cs:code,ds:data,es:nothing ; do initialization local to this module... ; mainly get console driver address to speed up screen access [as] ; Memory for screen must lie either entirely within the first 64K of memory, ; or within the second 64K of memory due to architecture of the CRT controller ; connections. It must also be aligned on an exact multiple of 32 bytes ; (rather than just on paragraph alignment). ; 7 August 1986 added code to get character set base for dump [bgp] LCLYINI proc near mov flags.vtflg,ttvt102 ; start as a VT102 call msuinit ; init keyboard module msuv90 [bgp] mov ah,DCONIO mov dl,ESCAPE ; to set nowrap int DOS mov dl,'w' int DOS mov ax,ds mov es,ax mov ax,14 ; function 'get driveraddress' mov bx,offset condev int SUPERBIOS ; address is now in drivadr ; setup screen mov ax,aagraph ; segment of graphics memory (See Note above) cmp ax,1000H ; start in lower half? [bgp sub-mod] jae lclyini1 ; ae = no cmp ax,63BH ; maximum segment in lower half jb lclyini3 ; b = low enough to work, go on lclyini1: cmp ax,163BH ; maximum segment in top half jb lclyini3 ; b = ok - go on lclyini2: ; Tektronix emulation screen won't work... mov dx,offset no_tek_msg ; tell the user we can't do it mov ah,PRSTR int DOS mov tek_allowed,FALSE ; and flag it jmp lclyini4 lclyini3: ; Tektronix will work fine inc ax ; force round-up shr ax,1 ; divide by two shl ax,1 ; multiply by two - now multiple of 32 mov scrseg,ax ; save it [end bgp sub-mod] push es call clrscr ; make sure it is clear pop es ; end of mod [jrd] mov tek_allowed,TRUE ; flag that tektronix is ok lclyini4: push es mov ax,0F000H ; point at base of screen memory mov es,ax mov ax,word ptr es:3838 ; note: this should be the last character ; of the last line on the screen - if it was ; cleared as Kermit usually does when it starts ; up, this will be a space - it must be a space! and ax,7FFH ; strip off mode bits sub ax,' ' ; minus which char it is mov char_base,ax ; and save it pop es ret LCLYINI endp ; We need to save the arguments to TERM where they are a little more ; accessible than in the way they were passed ARGINI proc near ; read passed arguments mov bx,argadr ; base of argument block mov al,[bx].flgs ; get flags and al,CAPT+EMHEATH+TRNCTL+LCLECHO+MODOFF mov yflags,al ; mask for allowable and save and flags1,not (PRTSCR) ; these are allowable ; (others remain). mov al,[bx].prt cmp al,portno ; using same port? je argin1 ; yes, go on and flags1,not inited ; else re-init stuff mov first_in,TRUE ; graphics too... argin1: mov portno,al ; update port number mov ax,[bx].captr mov captrtn,ax ; buffer capture routine mov parmsk,0ffh ; parity mask, assume parity = None cmp [bx].parity,parnon ; is parity None? je argini1 ; e = yes, keep all 8 bits mov parmsk,07fh ; else keep lower 7 bits argini1:ret ; that's it ARGINI endp ; Toggle Mode Line trnmod proc near cmp flags.modflg,1 ; mode line enabled and owned by us? jne trnm1 ; ne = no, don't touch it test yflags,modoff ; mode line already off? jnz trnm2 ; nz = yes, go turn on or yflags,modoff ; say modeline is toggled off call clrmod ; clear mode line trnm1: clc ; clear c bit so don't exit Connect ret trnm2: cmp flags.vtflg,0 ; emulating a terminal? jne trnm3 ; ne = yes push dx ; scroll screen to save bottom line mov ah,prstr ; for terminal type none mov dx,offset crlf int dos pop dx trnm3: call modlin ; turn on modeline and yflags,not modoff ; say modeline is not toggled off clc ret trnmod endp ; We need to generate the mode line and output it MODLIN proc near ; turn on mode line push es push ds pop es ; make sure es is correct mov al,trans.escchr ; Connect mode escape character mov modbuf.m_echr,' ' ; first char is initial space mov modbuf.m_hlp,' ' ; goes here too. cmp al,32 ; printable? jnb modl1 ; yes, keep going add al,40h ; made printable mov modbuf.m_echr,'^' ; note control char mov modbuf.m_hlp,'^' modl1: mov modbuf.m_echr+1,al ; fill in character mov modbuf.m_hlp+1,al mov bx,argadr ; get argument block mov al,[bx].baudb ; get baud bits mov si,offset unkbaud ; assume unknown baud cmp al,baudnsiz ; too big? jnb modl2 ; yes, use default mov cl,5 ; each is 5 bytes long mul cl mov ah,0 add ax,offset baudn mov si,ax modl2: mov cx,size m_baud ; length of baud space mov di,offset modbuf.m_baud cld rep movsb ; copy in baud rate mov al,[bx].parity ; get parity code mov cl,2 ; each is 4 bytes long... shl al,cl mov ah,0 add ax,offset parnams ; names of parity settings mov si,ax mov cx,4 ; each is 4 long mov di,offset modbuf.m_par rep movsb mov si,offset remmsg ; Assume remote echoing. test yflags,lclecho ; Is remote side echoing? jz modl4 ; Yes, keep going mov si,offset lclmsg ; Else it's local echoing. modl4: mov cx,3 ; size of on/off mov di,offset modbuf.m_echo rep movsb mov al,'1' cmp portno,1 ; 1=1 je modl5 mov al,'2' ; 0=2 modl5: mov modbuf.m_prt,al ; fill in port number mov cl,13 mov di,offset modbuf.m_term ; fill in terminal type mov si,offset tty_generic ; assume generic first cmp flags.vtflg,TTGENRC je modl6 mov si,offset tty_heath ; try heath cmp flags.vtflg,TTHEATH je modl6 mov si,offset tty_vt102 ; try vt100 cmp flags.vtflg,TTVT100 je modl6 mov si,offset tty_vt52 ; try vt52 cmp flags.vtflg,TTVT52 je modl6 mov si,offset tty_tek4010 ; try tektronix cmp flags.vtflg,TTTEK je modl6 mov si,offset tty_unkn modl6: rep movsb mov modbuf.m_prn,' ' ; assume not printing mov modbuf.m_prn+1,' ' mov modbuf.m_prn+2,' ' test yflags,PRTSCR jz modl7 ; not mov modbuf.m_prn,'P' mov modbuf.m_prn+1,'R' mov modbuf.m_prn+2,'N' modl7: mov dx,offset modbuf ; where it is call putmod pop es ret MODLIN endp ; This is the entry point for terminal emulation ; Added option of VT100 emulation TERM proc near ; terminal emulator entry point mov oldsp,sp ; remember stack for i/o failure, mov argadr,ax ; save argument ptr push es ; save caller's extra segment address mov ax,seg data mov es,ax call argini ; init options from arg address call save_mode ; [bgp] cmp flags.vtflg,TTTEK ; emulating TEKTRONIX? jne term0 ; no call tek4010 ; go look like a TEKTRONIX jmp quit1 term0: test flags1,inited ; have we run yet? jz term1 ; no, forget this part call restscr ; restore screen jmp term2 term1: call cmblnk ; clear it off term2: or flags1,inited ; remember we've run already. call clrmod ; empty mode line test yflags,modoff ; is mode line disabled? jnz term3 ; yes, skip it call modlin ; turn on mode line term3: cmp flags.vtflg,TTVT100 ; emulating VT100? jne lp call ansie jmp quit lp: call portchr ; char at port? jnc lp1 ; nc = yes jmp chkinp ; no, keep going ; we want to swallow any ANSI escapes that come for now ; they are all of the form ESCAPE [ nn ; nn ; nn ; nn a ; where n is a numeric character, and a is a non-numeric character lp1: test flags.remflg,d8bit ; keep 8 bits for displays? jnz lp2 ; nz = yes and al,7fh ; strip 8th bit lp2: cmp escseq,0 ; escape sequence in progress? jne eat_esc_seq ; yes cmp al,ESCAPE ; got an escape? jne no_esc ; no mov escseq,1 ; yes, flag it jmp chkinp eat_esc_seq: cmp escseq,1 ; got [? jne eat_esc_seq2 ; yes cmp al,FF ; ESCAPE FF is go temp tek mode [bgp] jne eat_esc_seq0 ; no [bgp] cmp tek_allowed,FALSE ; is tek mode allowed? [bgp] jne eat_esc_seq00 ; yes, do it [bgp] mov dx,offset no_tek_msg ; tell them about it [bgp] mov ah,PRSTR ; [bgp] int DOS ; [bgp] jmp end_esc ; all through [bgp] eat_esc_seq00: mov escseq,0 ; not doing escape now [bgp] call savescr ; save current screen [bgp] call tektemp ; do it for a while [bgp] jnc eat_esc_seq000 ; carry=exit like esc char [bgp] call clrmod ; clear mode line [bgp] jmp quit1 ; screen already saved [bgp] eat_esc_seq000: call restscr ; restore the screen [bgp] jmp end_esc ; all through [bgp] eat_esc_seq0: cmp al,'[' je eat_esc_seq1 push ax ; not [, print esc and char mov al,ESCAPE call outtty ; send the escape pop ax ; and the following character mov escseq,0 ; no escape sequence jmp no_esc eat_esc_seq1: mov escseq,2 ; flag [ jmp chkinp eat_esc_seq2: cmp al,';' ; check for terminator je chkinp cmp al,'0' jl end_esc cmp al,'9' jg end_esc jmp chkinp ; no terminator, keep eating end_esc:mov escseq,0 ; end of sequence jmp chkinp no_esc: cmp rxtable+256,0 ; translation turned off? je no_esc1 ; e = yes, no translation push bx mov bx,offset rxtable ; address of translate table xlatb ; new char is in al pop bx no_esc1:call outtty ; print on terminal chkinp: call keybd ; get and translate a key [bgp] jc quit ; carry=esc character entered - quit [bgp] jmp lp ; keep looping [bgp] quit: call clrmod ; erase mode line call savescr ; save screen quit1: call rest_mode ; [bgp] mov al,yflags mov bx,argadr mov [bx].flgs,al ; update flags in arg block pop es ; restore segment register ret ; and return to caller TERM endp ; ANSI, VT100 emulation by Andreas Stumpf ANSIE proc near cmp afirst,1 ; have we run yet? jnz ansi2 ; no, forget this part mov bx,ds ; now restore keyboard too mov es,bx mov bx,offset parmblock mov ax,18 int SUPERBIOS jmp ansi3 ansi2: call initansi ansi3: mov afirst,1 ; remember we've run already. portc: call portchr ; char at port? jc achkinp ; c = no, get char from keyboard call doansi ; handle it somehow achkinp: call keybd ; get and translate a key stroke [bgp] jnc portc ; carry=esc char entered - quit [bgp] aquit: call finiansi ; fix keyboard up ret ANSIE endp ; DOANSI actually takes care of emulating the ANSI screen control stuff ; code by Andreas Stumpf - it expects the character to be in al DOANSI proc near test flags.remflg,d8bit ; keep 8 bits for displays? jnz w00a ; nz = yes and al,7fh ; strip 8th bit w00a: cmp al,ESCAPE ; got an escape? jne w00 ; ne = no jmp procesc0 ; escape terminates Escape-sequence, w00: ; so it has to be tested first cmp escseq,0 ; escape sequence in progress? jne w0a ; ne = yes, no translation cmp rxtable+256,0 ; translation turned off? je w0a ; e = yes, no translation push bx mov bx,offset rxtable ; address of translate table xlatb ; new char is in al pop bx w0a: cmp al,'X'-40h ; Control-X ? jne w0 jmp ignore w0: cmp al,'Z'-40h ; Control-Z jne w01 jmp ignore w01: cmp escseq,0 ; escape sequence in progress? je w02 jmp procesc ; yes w02: cmp al,' ' jb controls or al,chrset_mask ; [bgp] jmp noesc controls: cmp al,LF ; Linefeed,Formfeed and Vertical tab are ; processed as 'Scroll down, if at ; bottom margin, same function as ESCAPE'D' jne w1 jmp processD ; perform scrolling if necessary w1: cmp al,FF jne w2 jmp processD w2: cmp al,11 ; vertical tab jne w3 jmp processD w3: cmp al,TAB ; horizontal tab jne w4 call get_cur_pos ; get cursor position mov al,dh ; work on it here mov cx,80 sub cl,al ; # of cols to search for tab cmp cl,0 ; already off the end? jg t0 ; no mov cl,0 jmp t1 ; go to right margin t0: xor ah,ah mov di,offset tabstops add di,ax ; address of first tabstop to look for cld mov ax,1 ; compare table with 1 repnz scasb ; cl=0 is right margin t1: sub cl,80 neg cl mov dh,cl ; set new col pos call set_cur_pos ; done... jmp ignore w4: cmp al,14 ; shift to extra set? jne w5 mov chrset_mask,80H ; set top bit on these jmp ignore w5: cmp al,15 ; shift to normal set? jne w6 mov chrset_mask,0 ; clear top bit jmp ignore w6: cmp al,DEL ; DEL char? [jrd] jne w7 ; ne = no jmp ignore ; ignore DEL w7: jmp noesc ; else echo char to screen. procesc0: ; start of escape sequence processing mov escpnt,offset escstring mov escseq,1 ; flag it jmp doansi_d ; done with it procesc: ; have just got an escape cmp escseq,1 ; single char ESCape ? je procesc1 ; yes process it inc escseq inc escpnt ; store escape sequence for mov bx,escpnt ; further processing mov [bx],al cmp escseq,3 jg proccont1 cmp escseq,0 ; [bgp] jle proccont1a ; [bgp] cmp al,'?' ; 1st char after ESCAPE'[' may be a '?' jne proccont1 proccont1a: jmp doansi_d ; done with it proccont1: cmp al,';' jne proccont2 jmp doansi_d proccont2: cmp al,'-' ; may be first char of a number jne proccont3 ; continue checking mov bx,escpnt cmp byte ptr [bx-1],'0' ; preceding char in [0..9] ? jl procmin1 ; if yes, then syntax error => jmp ignore ; ignore Escapesequence procmin1: cmp byte ptr [bx-1],'9' jg procmin2 jmp ignore procmin2: jmp doansi_d proccont3: cmp al,'0' jl proccont cmp al,'9' jg proccont jmp doansi_d ; ESCAPE-seq hasn't finished yet proccont: jmp procmulti ; other char than 0..9 ';' => process them procesc1: ; function dispatcher for single char Escapesequences mov di,offset sesctbl mov cx,sesclen cld repnz scasb ; search for legal char following ESCAPE cmp al,[di-1] jnz notrecognized mov bx,sesclen sub bx,cx ; get offset in table dec bx shl bx,1 add bx,offset sescsub mov escseq,0 ; Escape sequence has finished jmp [bx] notrecognized: jmp noesc processbra: ; introduction of multi-char Escapesequence mov escseq,2 inc escpnt mov bx,escpnt mov [bx],al ; save that char jmp doansi_d ; and get next one processH: call get_cur_pos ; get cursor position mov al,dh ; get column here dec al ; range 0 to 79 mov bx,offset tabstops xor ah,ah add bx,ax mov byte ptr [bx],1 jmp ignore processD: call get_cur_pos ; get cursor position cmp dl,bottom ; is it last line? je delline ; yes, need to insert inc dl ; move down one line call set_cur_pos jmp ignore ; done delline: ; perform a scroll-up push dx ; save where we were mov dl,top mov dh,1 ; goto (top,1) call set_cur_pos mov al,ESCAPE call outtty mov al,'M' ; delete line call outtty pop dx ; get back where we were push dx mov dh,1 ; column 1 call set_cur_pos mov al,ESCAPE call outtty mov al,'L' ; insert line call outtty pop dx ; get it back again cmp dh,1 je processD1 ; done call set_cur_pos ; move to final position processD1: jmp ignore processE: mov al,CR ; same as ESCAPE'D', but in col 1 call outtty ; so write out Carriage return jmp processD processM: call get_cur_pos ; get cursor position cmp dl,top je insline ; yes, jump to insert dec dl ; move up one call set_cur_pos jmp ignore insline: ; perform a scroll-down push dx ; save current position mov dl,bottom mov dh,1 ; 1. position to bottom margin call set_cur_pos mov al,ESCAPE ; 2. delete line call outtty mov al,'M' call outtty mov dl,top mov dh,1 ; 3. position to top margin call set_cur_pos mov al,ESCAPE call outtty mov al,'L' ; 4. insert line with ESCAPE 'L' call outtty pop dx ; get back my position cmp dh,1 ; first col? je processM1 ; yes call set_cur_pos processM1: jmp ignore ; all done processeq: ; set applikation keypad mov ax,ds mov es,ax mov cx,8 mov di, offset apptbl.extrtabl add di,START_EXTRTBL ; don't want to start at the top cmp appcur,0 ; cursor keys application ? je peq1 mov si,offset curapp jmp peq2 peq1: mov si,offset curseq peq2: rep movsw ; move cursor keys to key-table mov appkeys,1 mov bx,offset parmblock mov byte ptr [bx],2 mov offs,offset apptbl mov ax,18 int SUPERBIOS ; set new keytable jmp ignore processgt: ; set numeric keypad mov ax,ds mov es,ax mov cx,8 mov di, offset numtbl.extrtabl add di,START_EXTRTBL ; don't want to start at the top cmp appcur,0 je pgt1 mov si,offset curapp jmp pgt2 pgt1: mov si,offset curseq pgt2: rep movsw mov appkeys,0 mov bx,offset parmblock mov byte ptr [bx],2 mov offs,offset numtbl mov ax,18 int SUPERBIOS jmp ignore process7: ; save cursor position mov al,ESCAPE call outtty mov al,'j' jmp noesc process8: ; restore cursor position mov al,ESCAPE call outtty mov al,'k' jmp noesc process_ff: ; temporary tektronix mode if allowed [bgp] cmp tek_allowed,FALSE ; ok? [bgp] jne process_ff1 ; yes [bgp] mov dx,offset no_tek_msg ; tell them [bgp] mov ah,PRSTR ; [bgp] int DOS ; [bgp] jmp ignore ; end of sequence [bgp] process_ff1: call savescr ; save the screen [bgp] mov escseq,0 ; [bgp] call tektemp ; [bgp] jc process_ff2 ; carry=esc char entered [bgp] call restscr ; restore the screen [bgp] jmp ignore ; end of sequence [bgp] process_ff2: pop ax ; return address from call to DOANSI [bgp] ; this is kludgey but it is necessary to ; make this look like we are actually at ; the point right after calling keybd and ; receiving an esc char. call finiansi ; restore old keyboard [bgp] pop ax ; imagine that we have returned from ANSI [bgp] call clrmod ; clear off the mode line [bgp] jmp quit1 ; normal exit but no save screen! [bgp] procmulti: ; function dispatcher for multi-character escape-sequences ; AL has terminating character mov cx,ds mov es,cx mov di,offset mesctbl mov cx,mesclen cld repnz scasb cmp al,[di-1] jnz notrec ; didn't find it in table mov bx,mesclen sub bx,cx ; get offset in table dec bx shl bx,1 add bx,offset mescsub jmp [bx] notrec: jmp noesc curmov: ; process Cursor movements cmp escseq,3 ; has no mumeric argument jne pars curmov0: mov al,ESCAPE call outtty mov bx,escpnt mov al,[bx] jmp noesc ; print it without '[' pars: ; parse numeric argument mov bx,offset escstring+2 ; skip ESCAPE'[' call getnum ; getnum returns the number in DL xor dh,dh cmp dl,80 jg curmovend cmp dl,0 jl curmovend je curmov0 mov cx,dx ; becomes loop counter mov bx,escpnt mov bl,[bx] ; put last char of sequence in bl parsl2: mov al,ESCAPE call outtty mov al,bl call outtty loop parsl2 curmovend: jmp ignore ; ignore invalid positioning procg: mov bx,offset escstring+2 call getnum cmp dl,0 jne procg1 call get_cur_pos mov al,dh ; current col here dec al ; range 0 to 79 mov bx,offset tabstops xor ah,ah add bx,ax mov byte ptr [bx],0 jmp ignore procg1: cmp dl,3 jne procg3 mov cx,80 push es push ds pop es ; make sure in right segment mov di,offset tabstops xor ax,ax rep stosb pop es ; get old es back procg3: jmp ignore procE: mov al,CR ; go to col 1 call outtty procle: mov bx,escpnt mov byte ptr [bx],'B' ; process cursor down jmp curmov procuF: mov al,CR ; go to col 1 call outtty mov bx, escpnt mov byte ptr [bx],'A' ; cursor up jmp curmov procuG: mov bx,offset escstring+2 call getnum cmp dl,0 jg procug1 mov dl,1 procug1: cmp dl,80 jle procug2 mov dl,80 procug2: mov cl,dl call get_cur_pos mov dh,cl ; set new column call set_cur_pos jmp ignore procld: mov bx,offset escstring+2 call getnum cmp dl,0 jg procld1 mov dl,1 procld1: cmp dl,24 jle procld2 mov dl,24 procld2: mov cl,dl call get_cur_pos mov dl,cl call set_cur_pos jmp ignore procH: ; position cursor mov bx,offset escstring+2 call getnum cmp dl,1 jge procH0 mov dl,1 ; provide default for invalid address procH0: cmp dl,24 jg badH cmp byte ptr [bx],';' jne procH01 inc bx procH01: push dx ; save row value call getnum pop ax ; get it back here cmp dl,1 jge procH1 mov dl,1 procH1: cmp dl,80 jg badH mov dh,dl ; get in right places mov dl,al call set_cur_pos badH: jmp ignore procL: mov bx,offset escstring+2 call getnum mov cx,dx cmp cx,0 jg procL0 mov cx,1 jmp procL1 procL0: cmp cx,24 jle procL1 mov cx,1 procL1: call get_cur_pos mov bh,dl mov bl,dh ; save these procL2: ; perform a insert line mov dl,bottom mov dh,1 call set_cur_pos mov al,ESCAPE call outtty mov al,'M' call outtty mov dl,bh ; get in right place mov dh,bl call set_cur_pos mov al,ESCAPE call outtty mov al,'L' call outtty loop procL2 jmp ignore procM: mov bx,offset escstring+2 call getnum mov cx,dx cmp cx,0 jg procM0 mov cx,1 jmp procM1 procM0: cmp cx,24 jle procM1 mov cx,1 procM1: call get_cur_pos mov bh,dl mov bl,dh procM2: ; perform a delete line mov al,ESCAPE call outtty mov al,'M' call outtty mov dl,bottom mov dh,1 call set_cur_pos mov al,ESCAPE call outtty mov al,'L' call outtty mov dl,bh ; get in right places mov dh,bl call set_cur_pos loop procM2 jmp ignore procAt: ; insert blank characters mov bx,offset escstring+2 call getnum mov cx,dx sub cx,1 mov al,ESCAPE call outtty mov al,'@' call outtty mov al,' ' call outtty mov al,BS call outtty cmp cx,0 jle procat1 procat2: mov al,' ' call outtty mov al,BS call outtty loop procat2 procat1: mov al,ESCAPE call outtty mov al,'O' call outtty jmp ignore procP: procX: mov bx,offset escstring+2 call getnum mov cx,dx cmp cx,0 jg procX1 mov cx,1 procX1: mov al,ESCAPE call outtty mov al,'N' call outtty loop procX1 jmp ignore procr: ; set margins mov top,1 mov bottom,24 mov bx,offset escstring+2 call getnum cmp dl,1 jl procr1 cmp dl,23 jg procr1 mov top,dl procr1: inc bx call getnum cmp dl,top jl procr2 cmp dl,24 jg procr2 mov bottom,dl procr2: mov dh,1 ; After inspecting what the VAX EDT editor does, mov dl,1 ; it appears that ESCAPE [ Pn r should leave call set_cur_pos ; the cursor in the upper left corner [bgp] jmp ignore procc: ; Terminal status request mov bx,offset escstring+2 cmp byte ptr [bx],'>' je procc2 cmp byte ptr [bx],'0' je procc0 cmp byte ptr [bx],'c' je procc0 jmp ignore procc0: push wflags ; need to save these and yflags,not lclecho ; force no echo for these mov al,ESCAPE call outprt mov al,'[' call outprt mov al,'?' call outprt mov al,'1' call outprt mov al,';' ; signal AVO option - we sort of have it call outprt mov al,'2' call outprt mov al,'c' call outprt pop wflags ; get back old flags procc2: jmp ignore procn: ; device status report mov bx,offset escstring+2 cmp byte ptr [bx],'5' je procn5 cmp byte ptr [bx],'6' je procn6 jmp ignore procn5: ; return operating status 'no malfunction' push wflags ; force no echo and yflags,not lclecho mov al,ESCAPE call outprt mov al,'[' call outprt mov al,'0' call outprt mov al,'n' call outprt pop wflags jmp ignore procn6: ; report cursor position push wflags ; force no echo and yflags,not lclecho call get_cur_pos mov al,dh ; get column here sub al,1fh ; get binary column aam add ax,3030h ; change to ASCII push ax mov al,dl ; get line here now sub al,1fh ; convert to binary aam ; and to ... add ax,3030h ; ASCII mov bx,ax mov al,ESCAPE ; put string out in form : ESCAPE'['line';'col'R' call outprt mov al,'[' call outprt cmp bh,30h ; don't need leading zero je procc61 mov al,bh call outprt procc61: mov al,bl call outprt mov al,';' call outprt pop bx cmp bh,30h je procc62 mov al,bh call outprt procc62: mov al,bl call outprt mov al,'R' call outprt pop wflags ; get these back jmp ignore proclm: ; do screen attributes mov bx,offset escstring+2 proclm1: call getnum cmp dl,0 jne proclm2 mov al,ESCAPE call outtty mov al,')' call outtty mov al,ESCAPE call outtty mov al,'q' call outtty mov al,ESCAPE call outtty mov al,'1' call outtty jmp proclm5 proclm2: cmp dl,1 jne proclm3 mov al,ESCAPE call outtty mov al,'(' call outtty jmp proclm5 proclm3: cmp dl,4 jne proclm4 mov al,ESCAPE call outtty mov al,'0' call outtty jmp proclm5 proclm4: cmp dl,7 jne proclm5 mov al,ESCAPE call outtty mov al,'p' call outtty proclm5: cmp byte ptr [bx],'m' je proclm6 inc bx jmp proclm1 proclm6: jmp ignore procJ: cmp escseq,3 je procJ0 mov bx,offset escstring+2 ; skip ESCAPE'[' call getnum cmp dl,0 je procJ0 cmp dl,1 je procJ1 cmp dl,2 je procJ2 jmp ignore ; ignore others procJ0: mov al,ESCAPE call outtty mov al,'J' jmp noesc procJ1: mov al,ESCAPE call outtty mov al,'b' jmp noesc procJ2: mov al,ESCAPE call outtty mov al,'E' jmp noesc prochl: mov bx,offset escstring+2 ; skip ESCAPE'[' call getnum cmp [escstring+2],'?' je quest mov bx,escpnt mov bl,[bx] ; contains 'h' or 'l' cmp dl,4 jne not4 mov al,ESCAPE call outtty mov al,'@' cmp bl,'l' jne enterins mov al,'O' enterins: jmp noesc not4: ; ignore the others jmp ignore quest: ; sequence like ESCAPE'[?'nn'h' mov bx,escpnt mov bl,[bx] cmp dl,1 jne not1 mov cx,8 cmp appkeys,0 je q1 mov offs,offset apptbl mov di, offset apptbl.extrtabl jmp q2 q1: mov offs,offset numtbl mov di, offset numtbl.extrtabl q2: add di,START_EXTRTBL ; don't want to start at the top cmp bl,'l' je q3 mov si,offset curapp mov appcur,1 jmp q4 q3: mov si,offset curseq mov appcur,0 q4: rep movsw mov bx,offset parmblock mov byte ptr [bx],2 mov ax,18 int SUPERBIOS jmp ignore not1: cmp dl,5 jne not5 mov al,ESCAPE call outtty mov al,'p' cmp bl,'h' je isreverse mov al,'q' isreverse: jmp noesc not5: cmp dl,7 jne not7 mov al,ESCAPE call outtty mov al,'v' cmp bl,'h' je autowrap mov al,'w' autowrap: jmp noesc not7: ; ignore the others jmp ignore procK: cmp escseq,3 je procK0 mov bx,offset escstring+2 ; skip ESCAPE'[' call getnum cmp dl,0 je procK0 cmp dl,1 je procK1 cmp dl,2 je procK2 jmp ignore ; ignore others procK0: mov al,ESCAPE call outtty mov al,'K' jmp noesc procK1: mov al,ESCAPE call outtty mov al,'o' jmp noesc procK2: mov al,ESCAPE call outtty mov al,'l' jmp noesc processrp: processlp: processlb: mov escseq,-1 ; have to eat one char jmp doansi_d ; noesc: ; That wasn't valid! (or print last char) call outtty ; print it out... ignore: ; Here to flag end of escape or ignore mov escseq,0 ; one that we don't like doansi_d: ret ; Here when we have no more to do DOANSI endp ; GETNUM gets a number from escapestring, returns it in DL. ; Input: pointer in BX. Destroys BX, CX, DH. Finishes on first ; encounteder non-numeric char except '-'. Assumes correct syntax ; ('-' only as first char - checked in procmulti) GETNUM proc near xor dx,dx cmp bx,escpnt ; is it to end of string already? jge getn4 ; yes - just exit with zero xor ch,ch ; assume positive number cmp byte ptr [bx],'?' ; first char may be a questionmark jne getn1 inc bx getn1: mov cl,[bx] cmp cl,';' je getn3 cmp cl,'-' jne getn2 mov ch,-1 getn2: cmp cl,'0' jl getn3 cmp cl,'9' jg getn3 sub cl,'0' shl dl,1 ; multiply by 10 (=1010b) mov dh,dl shl dl,1 shl dl,1 add dl,dh add dl,cl inc bx cmp bx,escpnt jl getn1 getn3: cmp ch,-1 jne getn4 neg dx getn4: ret GETNUM endp ; initialize keyboard and tables to build it [as] INITANSI proc near cld mov bx,ds mov es,bx mov bx,offset parmblock mov ax,18 int SUPERBIOS ; get old keyboard or ax,ax jz ansi01 jmp aend ansi01: mov cx,598 ; copy it mov si,offset oldtable mov di,offset numtbl cld rep movsw mov si,offset numtbl ; Index in Table mov byte ptr [si].kd0+25,7fh ; DEL to Backspace-key ; set cursorkeys mov word ptr [si].kd12+2*88,0A000h ; mov word ptr [si].kd12+2*89,0A000h ; with auto-repeat mov word ptr [si].kd12+2*98,0A000h mov word ptr [si].kd12+2*99,0A000h mov byte ptr [si].kd0+88,START_EXTRTBL ; offset in EXTRtabl mov byte ptr [si].kd0+89,START_EXTRTBL+4 mov byte ptr [si].kd0+98,START_EXTRTBL+8 mov byte ptr [si].kd0+99,START_EXTRTBL+12 mov di,offset numtbl.extrtabl add di,START_EXTRTBL ; Don't want to overwrite stuff mov si,offset curseq mov cx,8 rep movsw ; move the new sequences to keytable ; copy complete table to build Applikation-keypad-table mov cx,598 mov si,offset numtbl mov di,offset apptbl rep movsw ; now build keypad mov si,offset apptbl mov word ptr [si].kd12+2*28,8000h mov word ptr [si].kd12+2*29,8000h mov word ptr [si].kd12+2*30,8000h mov word ptr [si].kd12+2*31,8000h mov word ptr [si].kd12+2*49,8000h mov word ptr [si].kd12+2*50,8000h mov word ptr [si].kd12+2*51,8000h mov word ptr [si].kd12+2*52,8000h mov word ptr [si].kd12+2*69,8000h mov word ptr [si].kd12+2*70,8000h mov word ptr [si].kd12+2*71,8000h mov word ptr [si].kd12+2*72,8000h mov word ptr [si].kd12+2*90,8000h mov word ptr [si].kd12+2*91,8000h mov word ptr [si].kd12+2*92,8000h mov word ptr [si].kd12+2*93,8000h mov word ptr [si].kd12+2*100,8000h mov word ptr [si].kd12+2*101,8000h ; [bgp] mov word ptr [si].kd12+2*102,8000h mov byte ptr [si].kd0+28,START_EXTRTBL+16 ; offset in EXTRtabl mov byte ptr [si].kd0+29,START_EXTRTBL+20 mov byte ptr [si].kd0+30,START_EXTRTBL+24 mov byte ptr [si].kd0+31,START_EXTRTBL+28 mov byte ptr [si].kd0+49,START_EXTRTBL+32 mov byte ptr [si].kd0+50,START_EXTRTBL+36 mov byte ptr [si].kd0+51,START_EXTRTBL+40 mov byte ptr [si].kd0+52,START_EXTRTBL+44 mov byte ptr [si].kd0+69,START_EXTRTBL+48 mov byte ptr [si].kd0+70,START_EXTRTBL+52 mov byte ptr [si].kd0+71,START_EXTRTBL+56 mov byte ptr [si].kd0+72,START_EXTRTBL+60 mov byte ptr [si].kd0+90,START_EXTRTBL+64 mov byte ptr [si].kd0+91,START_EXTRTBL+68 mov byte ptr [si].kd0+92,START_EXTRTBL+72 mov byte ptr [si].kd0+93,START_EXTRTBL+76 mov byte ptr [si].kd0+100,START_EXTRTBL+80 mov byte ptr [si].kd0+101,START_EXTRTBL+80 mov byte ptr [si].kd0+102,START_EXTRTBL+84 mov di,offset apptbl.extrtabl add di,START_EXTRTBL ; avoid overwriting stuff... mov si,offset applik mov cx,44 cld rep movsw ; move new keycodes to table mov bx,offset parmblock mov byte ptr [bx],2 mov offs,offset numtbl ; set numeric keypad mov ax,18 int SUPERBIOS aend: ret INITANSI endp ; Save old keyboard stuff when exiting [as] FINIANSI proc near mov bx,offset parmblock mov byte ptr [bx],2 mov dx,offset oldtable xchg dx,offs ; save old keyboard-type in dx mov ax,18 int SUPERBIOS xchg dx,offs ; restore old keyboard-type ret FINIANSI endp ; Get the current cursor location - row in dl, col in dh ; (1,1) is upper left corner GET_CUR_POS proc near mov al,ESCAPE ; request cursor location call outtty mov al,'n' call outtty mov ah,CONINQ ; input no check int DOS ; gets the ESCAPE int DOS ; gets the Y int DOS sub al,31 mov dl,al int DOS sub al,31 mov dh,al ret GET_CUR_POS endp ; Set the cursor location - row in dl, col in dh ; (1,1) is upper left corner SET_CUR_POS proc near push dx ; save it to be sure mov al,ESCAPE call outtty mov al,'Y' call outtty pop dx push dx mov al,dl ; row add al,31 call outtty pop dx push dx mov al,dh ; column add al,31 call outtty pop dx ret SET_CUR_POS endp ; Save the screen so we can restore it SAVESCR proc near push es ; [bgp] call get_cur_pos ; get cursor location mov tcurloc,dl ; this is line number mov tcurloc+1,dh ; this is column number mov bx,SEG_CRTC ; where crt controller is mov es,bx mov bx,OFF_CRTC mov byte ptr es:[bx],12 mov ah,es:1[bx] and ah,7 ; only want bottom 3 bits mov byte ptr es:[bx],13 mov al,es:1[bx] shl ax,1 ; multiply by 2 (was word address) mov si,ax push ds pop es mov ds,tscrseg mov di,offset tscreen mov cx,1920 cld rep movsw push es pop ds call cmblnk ; let them start with a blank one pop es ; [bgp] ret ; and return SAVESCR endp ; Restore screen from scrsav buffer RESTSCR proc near push es ; [bgp] call cmblnk ; start with a clear screen mov si,offset tscreen mov es,tscrseg xor di,di ; start at start mov cx,1920 ; 1920 words to go rep movsw mov dx,word ptr tcurloc ; get cursor location call set_cur_pos pop es ; [bgp] ret RESTSCR endp ; Save the mode line so it can be restored when we are through [bgp] SAVE_MODE proc near push es ; to be sure mov bx,SEG_CRTC ; where crt controller is mov es,bx mov bx,OFF_CRTC mov byte ptr es:[bx],12 ; high screen origin register mov ah,es:1[bx] and ah,7 ; need bottom 3 bits mov byte ptr es:[bx],13 ; low screen origin register mov al,es:1[bx] shl ax,1 ; multiply by 2 (was word address) add ax,3840 ; where status line is mov si,ax mov di,offset status_line ; where to put it mov cx,80 ; 80 words long push ds pop es mov ds,tscrseg ; setment of screen cld rep movsw push es pop ds ; restore ds pop es ; and this too ret SAVE_MODE endp ; Restore mode line in case someone has something on it [bgp] REST_MODE proc near push es ; to be sure... mov bx,SEG_CRTC ; where crt controller is mov es,bx mov bx,OFF_CRTC mov byte ptr es:[bx],12 ; high screen origin register mov ah,es:1[bx] and ah,7 ; need bottom 3 bits mov byte ptr es:[bx],13 ; low screen origin register mov al,es:1[bx] shl ax,1 ; multiply by 2 (was word address) add ax,3840 ; where status line is mov di,ax mov si,offset status_line ; where to get it mov cx,80 ; 80 words long mov es,tscrseg ; segment of screen cld rep movsw pop es ; restore this ret REST_MODE 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. ; This reads the screen that was last saved by savescr - it is expected ; that savescr will be called just before this one. ; 7 August 1986 Add this routine - it is pirated from the file MSYIBM and ; modified to match the Victor's needs. Note that a screen dump is not ; possible in Tektronix mode (unfortunately) since I'm not sure how to dump ; it in a way that would make sense. [bgp] DUMPSCR PROC NEAR cmp flags.vtflg,TTTEK ; emulating Tektronix? jne dumpxx ; no, save screen jmp dumptek ; this won't do anything but beep dumpxx: 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 ; set up file pointer mov dx,-1 ; and offset mov al,2 ; move to eof minus one byte mov ah,LSEEK ; and seek the end int DOS jmp dmp1 dmp5: 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 clrmod ; clear place for mode line mov dx,offset dmperr ; get string to put there call putmod ; on mode line... pop dx pop cx pop bx pop ax ret dmp1: push di ; read screen buffer, write lines push si push es push ds pop es ; make sure this is right mov cx,24 ; 24 lines in buffer mov si,offset tscreen ; where screen is saved dmp2: push cx ; save outer loop counter mov di,offset dumpbuf ; data segment memory mov cx,80 ; 80 columns dmp3: mov ax,word ptr es:[si] ; read char + attribute and ax,7FFH ; take off attributes sub ax,char_base ; minus base mov byte ptr [di],al ; store the char inc si inc si inc di loop dmp3 ; do for each column std ; set scan backward mov cx,80 ; 80 columns mov di,offset dumpbuf+79 ; end of line mov al,' ' ; thing to scan over repe scasb ; scan until non-space cld ; set direction forward jz dmp3a ; z=all spaces inc cx inc di dmp3a: mov word ptr [di+1],0A0DH ; append cr/lf add cx,2 ; line count + cr/lf mov dx,offset dumpbuf ; array to be written mov bx,dmphand ; need file handle mov ah,WRITE2 ; write the line int DOS pop cx ; get line counter again loop dmp2 ; do next line mov dx,offset dumpsep ; put in ff/cr/lf mov cx,3 ; three bytes overall mov ah,WRITE2 ; write them mov bx,dmphand ; file handle int DOS mov ah,CLOSE2 ; close the file now int DOS dmp6: pop es pop si pop di pop dx pop cx pop bx pop ax ret dumptek:call beep ; what else should we do? ret DUMPSCR ENDP ; Come to here to act somewhat like a Tektronix 4010 terminal... TEK4010 proc near push es ; this will be used repeatedly mov es,scrseg mov cursor_cnt,CURSOR_TIME ; init cursor countdown timer cmp first_in,FALSE ; been here before? je tek0 ; yes call clrscr ; be sure screen is clear mov first_in,FALSE ; flag it tek0: call set_hires ; set to hires screen teklp: cmp full_flag,FALSE ; page full condition jne tekcki1 ; yes, I can't accept anything call portchr ; char at port? jc tekcki ; c = no, keep going call tekhandle ; go handle the character tekcki: dec cursor_cnt ; decrement cursor countdown jnz tekcki1 ; not ready call cursor_on ; turn on cursor tekcki1: call keybd ; get and translate a key [bgp] jnc teklp ; carry=esc char entered - quit [bgp] tekquit: call reset_hires ; reset to normal screen pop es ret TEK4010 endp ; Come to here to temporarily act somewhat like a Tektronix 4010 terminal... ; Added 29 August 1987 to allow ANSI or VT52 to go directly to Tektronix ; mode. This is entered at a point where conditions should be like a ; clear screen was just received (ESCAPE FF). We should exit on the receipt ; of an ESCAPE US sequence or if the esc char is entered from the keyboard. ; If the esc char is entered then return with carry set. [bgp] ; For compatibility we will also exit if a CAN (ctrl-X) is received (to be ; like the IBM-PC version). TEKTEMP proc near push es ; this will be used repeatedly mov es,scrseg mov ax,flags.vtflg mov temp_mode,ax ; save current emulation mov flags.vtflg,TTTEK ; set to tek emulation mov temp_tek,TRUE ; this is temporary mode... mov echo_supp,FALSE ; clear echo suppression mov cursor_cnt,CURSOR_TIME ; init cursor countdown timer mov escflag,0 ; not in escape sequence mov graph_mode,FALSE ; in full text mode call clrscr ; be sure screen is clear mov first_in,FALSE ; flag it call set_hires ; set to hires screen tektlp: cmp full_flag,FALSE ; page full condition jne tektcki1 ; yes, I can't accept anything call portchr ; char at port? jc tektcki ; c = no, keep going and al,7fh ; Tek gets only 7 bit characters call tekhandle ; go handle the character tektcki: dec cursor_cnt ; decrement cursor countdown jnz tektcki1 ; not ready call cursor_on ; turn on cursor tektcki1: call keybd ; get and translate a key jnc tektlp ; carry=esc char entered - quit call reset_hires ; reset to normal screen mov ax,temp_mode mov flags.vtflg,ax ; reset to previous emulation mov temp_tek,FALSE ; clear temp tektronix emulation pop es stc ; set carry - this is full quit ret TEKTEMP endp ; Take care of an incoming character TEKHANDLE proc near cmp escseq,0 ; escape sequence in progress? jne tekhand1 ; ne = yes, no translation cmp rxtable+256,0 ; translation turned off? je tekhand1 ; e = yes, no translation push bx mov bx,offset rxtable ; address of translate table xlatb ; new char is in al pop bx tekhand1:call capture ; in case we should cmp al,GS ; Group Separator? je tek2graf ; ->graphics with pen up cmp al,ESCAPE ; Escape? je tek2esc ; ->handle special commands mov bl,escflag xor bh,bh call tekjump[bx] ; Go to right routine mov cursor_cnt,CURSOR_TIME ; init cursor countdown ret tek2graf: mov visible,0 ; Pen up mov escflag,4 ; Get HIY next mov graph_mode,TRUE ret tek2esc: mov escflag,2 ; ESCAPE handler next ret TEKHANDLE endp ; TEXT mode - just put text on screen TEKTXT proc near call cursor_off ; be sure this is off cmp text_x,TEXT_X_MAX ; off screen? jle tektxta mov text_x,0 ; to left margin add text_y,RPLINE tektxta: cmp text_y,TEXT_Y_MAX jle tektxtb call page_full ; page is full! ret ; lost that character, oh well... tektxtb: cmp al,DEL ; Is it delete? jne tektxt1 ret tektxt1: cmp al,' ' ; Is it control? jl tektxt3 cmp echo_supp,FALSE ; In echoplex suppression? jne tektxt2 ; Yes, don't print it call character ; Output it call inc_char tektxt2: ret tektxt3: cmp al,BELL jne tektxt4 call beep mov echo_supp,FALSE ; Clear suppression ret tektxt4: cmp al,BS jne tektxt6 sub text_x,CPCHAR ; back up one cmp text_x,0 jge tektxt5 ; ok mov text_x,R_MARG ; right margin sub text_y,RPLINE ; back one line cmp text_y,0 ; top? jge tektxt5 mov text_y,0 ; top of screen tektxt5: mov echo_supp,FALSE ; Clear suppression ret tektxt6: cmp al,TAB jne tektxt7 call inc_char mov echo_supp,FALSE ; Clear suppression ret tektxt7: cmp al,LF ; Line feed? jne tektxt9 add text_y,RPLINE ; Down one line cmp text_y,TEXT_Y_MAX ; Past end? jle tektxt8 call page_full ; can't go any further! ret tektxt8: mov echo_supp,FALSE ; Clear suppression ret tektxt9: cmp al,VTAB jne tektxt11 sub text_y,RPLINE ; Up one line cmp text_y,0 ; Past top? jge tektxt10 mov text_y,0 tektxt10: mov echo_supp,FALSE ; Clear suppression ret tektxt11: cmp al,CR ; It is return? jne tektxt12 mov text_x,0 ; to left margin mov echo_supp,FALSE ; Clear suppression ret tektxt12: cmp al,CAN ; Is it CAN (control-X)? jne tektxt13 cmp temp_tek,FALSE ; in temporary mode? je tektxt13 ; no, just continue! mov echo_supp,FALSE ; clear suppression mov escflag,0 ; place in full text mode mov graph_mode,FALSE mov ax,temp_mode mov flags.vtflg,ax ; reset emulation mode mov temp_tek,FALSE ; clear temporary mode pop ax ; this is return to tekhandle pop ax ; this is return to tektemp call reset_hires ; have to make it look like a tektquit pop es ; with a carry clear state clc ret tektxt13: ret TEKTXT endp ; Move the text position by one char, perform auto wrap, and ; check for page full INC_CHAR proc near add text_x,CPCHAR ; Move to next column cmp text_x,TEXT_X_MAX ; Past end? jle inc_char0 mov text_x,0 ; Left margin add text_y,RPLINE cmp text_y,TEXT_Y_MAX ; Past end? jle inc_char0 call page_full ; Take no more! inc_char0: ret INC_CHAR endp ; ESCAPE mode - check what to do TEKESC proc near cmp al,FF ; Form feed? jne tekesc1 call clrscr mov echo_supp,FALSE ; Clear suppression jmp tekescq tekesc1: cmp al,CTLZ ; Control-Z? jne tekesc2 mov escflag,0 ; Just in case mov echo_supp,TRUE ; echoplex suppression call tekcrs ; Go to cross hairs ret ; Last char does its thing tekesc2: cmp al,ETB ; Make copy? jne tekesc2a mov echo_supp,FALSE ; Clear suppression jmp tekescq tekesc2a: cmp al,ENQ ; enquire? jne tekesc3 mov echo_supp,TRUE ; echoplex suppression call send_stat jmp tekescq ; do nothing for now *** tekesc3: cmp al,US ; return from temp tek mode [bgp] jne tekesc4 cmp temp_tek,FALSE ; in temporary mode? je tekescq ; no, just continue! mov echo_supp,FALSE ; clear suppression mov escflag,0 ; place in full text mode mov graph_mode,FALSE mov ax,temp_mode mov flags.vtflg,ax ; reset emulation mode mov temp_tek,FALSE ; clear temporary mode pop ax ; this is return to tekhandle pop ax ; this is return to tektemp call reset_hires ; have to make it look like a tektquit pop es ; with a carry clear state clc ret tekesc4: call tektxt ; It's just text... tekescq: mov escflag,0 ; Now in full text mode mov graph_mode,FALSE ret TEKESC endp ; Get coordinates escflag=4->expect hiy, escflag=6->expect hix TEKHIY proc near tekhix: call cursor_off ; make sure it is off cmp al,CR ; should we exit? jne tekhi1 mov cur_x,0 ; go to left margin mov echo_supp,FALSE ; Clear suppression jmp go2text tekhi1: cmp al,US ; another exit? jne tekhi2 mov echo_supp,FALSE ; Clear suppression jmp go2text tekhi2: cmp al,FF jne tekhi3 call clrscr mov echo_supp,FALSE ; Clear suppression jmp go2text tekhi3: cmp echo_supp,FALSE ; In suppression jne tekhi4 ; Yes, ignore this... cmp al,20H ; control character? jl tekhi4 cmp al,40H jl tekhi5 ; 20-3F are HIX or HIY cmp al,60H jl tekhi7 ; 40-5F are LOX ; Get to here must be 60-7F -> LOY mov ah,loy ; copy old loy mov lsb,ah ; to lsb (in case 4014) and al,1FH ; low 5 bits mov loy,al cmp escflag,6 ; 2nd in a row? je tekhi4 ; then previous was lsb anyway mov lsb,0 ; clear lsb mov escflag,6 ; expect HIX next tekhi4: ret ; Get either HIX or HIY depending on escflag tekhi5: and ax,1FH mov cl,5 shl ax,cl ; multiply by 32 cmp escflag,4 ; looking for HIY? jne tekhi6 ; no, HIX mov hiy,ax ret ; leave escflag=4 tekhi6: mov hix,ax mov escflag,4 ; look for HIY next ret ; Get LOX and do the movement tekhi7: and al,1FH mov lox,al mov ax,hix or al,lox mov cur_x,ax mov dx,hiy or dl,loy mov cur_y,dx call tek2victor ; convert the coords mov endpt,ax mov endpt+2,dx ; save them cmp visible,0 je tekhi8 call line ; draw the line tekhi8: mov visible,1 mov ax,endpt mov start,ax mov ax,endpt+2 mov start+2,ax ; end is now start mov escflag,4 ; want HIY next ret ; go2text: mov escflag,0 mov graph_mode,FALSE mov ax,cur_x mov dx,cur_y call tek2victor mov text_x,ax sub dx,10 ; mov to upper left corner cmp dx,0 jge go2text1 xor dx,dx go2text1: mov text_y,dx ret TEKHIY endp ; Go to CURSOR mode TEKCRS proc near call cursor_off mov combine,offset pixel_xor mov trmesc,FALSE mov prtesc,FALSE tekcrs_dr: mov ax,cur_x ; get x sub ax,CUR_LEN ; minus a little cmp ax,0 jge tekcrs_dr1 mov ax,0 tekcrs_dr1: mov dx,cur_y call tek2victor mov crs_hor,ax mov crs_hor+4,dx mov ax,cur_x add ax,CUR_LEN ; add a little cmp ax,TEK_X_MAX jle tekcrs_dr2 mov ax,TEK_X_MAX tekcrs_dr2: mov dx,cur_y call tek2victor mov crs_hor+2,ax mov dx,cur_y ; now y's sub dx,CUR_LEN ; minus a little cmp dx,0 jge tekcrs_dr3 mov dx,0 tekcrs_dr3: mov ax,cur_x call tek2victor mov crs_ver,dx mov crs_ver+4,ax mov dx,cur_y add dx,CUR_LEN ; plus a little cmp dx,TEK_Y_MAX jle tekcrs_dr4 mov dx,TEK_Y_MAX tekcrs_dr4: mov ax,cur_x call tek2victor mov crs_ver+2,dx call draw_cursor ; put it on tekcrs_lp: mov dl,0FFH mov ah,DCONIO ; get character int DOS cmp al,0 ; anything? jne tekcrs_hnd ; take care of it call portchr ; check port character jc tekcrs_lp ; c = nothing there cmp prtesc,FALSE ; received escape? je tekcrs_lp1 ; no mov prtesc,FALSE cmp al,FF je tekcrs_abt cmp al,ETB je tekcrs_abt cmp al,ENQ jne tekcrs_lp call send_stat ; send status jmp tekcrs_lp tekcrs_lp1: cmp al,BELL ; check for control and clear... je tekcrs_abt cmp al,BS je tekcrs_abt cmp al,CR je tekcrs_abt cmp al,TAB je tekcrs_abt cmp al,LF je tekcrs_abt cmp al,US je tekcrs_abt cmp al,ESCAPE jne tekcrs_lp ; try for more mov prtesc,TRUE jmp tekcrs_lp tekcrs_abt: mov echo_supp,FALSE ; clear echo suppression mov escflag,0 ; and text mode jmp tekcrs_xt ; and leave ; tekcrs_hnd: cmp trmesc,FALSE ; received escapes yet? jne tekcrs_hnd2 cmp al,ESCAPE ; escape character? je tekcrs_hnd1 jmp tekcrs_done ; finished tekcrs_hnd1: mov trmesc,TRUE ; flag it jmp tekcrs_lp tekcrs_hnd2: cmp al,'1' ; change step? jge tekcrs_hnd2z jmp tekcrs_done tekcrs_hnd2z: cmp al,'9' jle tekcrs_hnd3 cmp al,'A' jne tekcrs_hnd2a mov ax,cur_stp add cur_y,ax jmp tekcrs_und ; remove old and redraw tekcrs_hnd2a: cmp al,'B' jne tekcrs_hnd2b mov ax,cur_stp sub cur_y,ax jmp tekcrs_und ; remove old and redraw tekcrs_hnd2b: cmp al,'C' jne tekcrs_hnd2c mov ax,cur_stp add cur_x,ax jmp tekcrs_und tekcrs_hnd2c: cmp al,'D' jne tekcrs_hnd2d mov ax,cur_stp sub cur_x,ax jmp tekcrs_und tekcrs_hnd2d: jmp tekcrs_done ; its the one to send tekcrs_hnd3: sub al,'0' ; convert to number xor ah,ah mov cur_stp,ax ; new step value mov trmesc,FALSE jmp tekcrs_lp tekcrs_und: cmp cur_x,0 ; check for validity jge tekcrs_und1 mov cur_x,0 jmp tekcrs_und2 tekcrs_und1: cmp cur_x,TEK_X_MAX jle tekcrs_und2 mov cur_x,TEK_X_MAX tekcrs_und2: cmp cur_y,0 jge tekcrs_und3 mov cur_y,0 jmp tekcrs_und4 tekcrs_und3: cmp cur_y,TEK_Y_MAX jle tekcrs_und4 mov cur_y,TEK_Y_MAX tekcrs_und4: call draw_cursor ; remove the cursor mov trmesc,FALSE jmp tekcrs_dr ; and draw new one tekcrs_done: push cur_y ; want current coords push cur_x ; for sending call send_coord ; send character and coords tekcrs_xt: call draw_cursor ; remove the cursor mov ax,cur_x mov dx,cur_y ; need to set start point call tek2victor mov start,ax mov start+2,dx mov text_x,ax ; set text point also sub dx,10 ; move to upper left corner cmp dx,0 jge tekcrs_xt1 xor dx,dx tekcrs_xt1: mov text_y,dx mov combine,offset pixel_or ret TEKCRS endp ; DRAW CURSOR expects to have the appropriate endpoints in CRS_HOR for ; the horizontal line (x1,x2,y) and CRS_VER for the vertical line (y1,y2,x) DRAW_CURSOR proc near mov ax,crs_hor mov start,ax mov ax,crs_hor+4 mov start+2,ax mov endpt+2,ax mov ax,crs_hor+2 mov endpt,ax call line ; draw horizontal line mov ax,crs_ver mov start+2,ax mov ax,crs_ver+4 mov start,ax mov endpt,ax mov ax,crs_ver+2 mov endpt+2,ax call line ; draw vertical line ret DRAW_CURSOR endp ; Convert TEK coords to VICTOR coords ; entry: ax=x, dx=y (tek) ; exit: ax=x, dx=y (victor) TEK2VICTOR proc near push dx ; save y for now mov bx,X_MAX mul bx mov bx,TEK_X_MAX div bx cmp dx,TEK_X_MAX/2 ; need to round up? jl tek2vic1 inc ax tek2vic1: pop dx push ax ; save x now mov ax,dx mov bx,Y_MAX mul bx mov bx,TEK_Y_MAX div bx cmp dx,TEK_Y_MAX/2 ; need to round up? jl tek2vic2 inc ax tek2vic2: sub ax,Y_MAX ; need to swap it neg ax mov dx,ax pop ax ret TEK2VICTOR endp ; Set the CRT to hires mode SET_HIRES proc near push es call crt_lo_inten ; so you don't see so much jump mov ah,DCONIO mov dl,27 int DOS mov dl,'E' int DOS ; let's start with a clear screen mov bx,0E800H ; CRT controller segment mov es,bx ; fix the write to work on the VICKI - it has an 8086 [bgp and as] mov byte ptr es:0,0 ; reg 0 mov byte ptr es:1,3AH mov byte ptr es:0,1 mov byte ptr es:1,32H mov byte ptr es:0,2 mov byte ptr es:1,34H mov byte ptr es:0,3 mov byte ptr es:1,0C9H mov byte ptr es:0,0AH ; no cursor mov byte ptr es:1,20H ; end VICKI fix xor ah,ah ; assume using lower bank of memory test scrseg,1000H ; really? jz set_hires1 mov ah,10H set_hires1: or ah,20H ; VICKI fix again... mov byte ptr es:0,0CH ; reg 12 mov byte ptr es:1,ah mov byte ptr es:0,0DH mov byte ptr es:1,0 mov byte ptr es:0,0EH mov byte ptr es:1,0 mov byte ptr es:0,0FH mov byte ptr es:1,0 ; end VICKI fix mov cx,4e2H ; 1250 locations to set mov ax,scrseg ; where screen is shr ax,1 ; /2 mov di,0F000H ; in screen ram mov es,di xor di,di set_hires2: stosw ; set one inc ax ; next one loop set_hires2 call crt_hi_inten pop es ret SET_HIRES endp ; Reset the CRT to lo res mode RESET_HIRES proc near push es call crt_lo_inten ; to minimize jump mov bx,0E800H ; segment for CRT controller mov es,bx ; VICKI fix mov byte ptr es:0,0 ; reg 0 mov byte ptr es:1,5CH mov byte ptr es:0,1 mov byte ptr es:1,50H mov byte ptr es:0,2 mov byte ptr es:1,51H mov byte ptr es:0,3 mov byte ptr es:1,0CFH mov byte ptr es:0,0AH mov byte ptr es:1,0 ; steady block cursor mov byte ptr es:0,0CH mov byte ptr es:1,0 mov byte ptr es:0,0DH mov byte ptr es:1,0 mov byte ptr es:0,0EH mov byte ptr es:1,0 mov byte ptr es:0,0FH mov byte ptr es:1,0 ; end VICKI fix mov ah,DCONIO mov dl,27 int DOS mov dl,'E' int DOS ; insure screen is clear call crt_hi_inten pop es ret RESET_HIRES endp ; Set to lo intensity CRT_LO_INTEN proc near mov bx,0E804H ; CRT controller segment mov es,bx mov al,es:0 ; get current setting mov ah,al ; save it and al,1CH mov intens,al ; store it mov al,ah and al,0E3H ; zero intensity mov es:0,al ret CRT_LO_INTEN endp ; Set to hi intensity CRT_HI_INTEN proc near mov bx,0E804H ; Crt controller segment mov es,bx mov al,es:0 ; Get current setting and al,0E3H ; Clear intensity or al,intens ; Set to correct value mov es:0,al ret CRT_HI_INTEN endp ; Clear the hires screen area CLRSCR proc near les di,dword ptr scrloc ; get right location cld ; increment mov cx,20000 ; 40000 bytes mov ax,0 rep stosw ; doing it jmp clrscr1 homescr: ; keyboard translator verb entry [bgp] call cursor_off ; make sure it is off cmp full_flag,TRUE ; in page full condition? jne clrscr1 ; no, just go home the cursor les di,dword ptr scrloc ; get screen location add di,38424 ; get to lower left corner mov ax,0FFFFH ; want to clear them all xor es:[di],ax ; need to clear page full indicator inc di ; box in the lower left corner which inc di ; was put there when the page filled xor es:[di],ax ; up earlier inc di inc di xor es:[di],ax inc di inc di xor es:[di],ax clrscr1: mov cur_x,0 ; set to home position mov cur_y,780 mov hix,0 mov hiy,0 mov lox,0 mov loy,0 mov lsb,0 mov start,0 mov start+2,0 mov text_x,0 mov text_y,0 mov full_flag,FALSE ; page isn't full mov cursor,FALSE ; cursor isn't on mov cursor_cnt,CURSOR_TIME ; set up cursor countdown ret CLRSCR endp ; Put the character in al on the screen at location pointed at by ; text_x,text_y. Use combination routine pointed at by t_combine CHARACTER proc near cmp al,' ' ; is it a space? jne character1 ; no ret ; just return... character1: and al,07FH ; Be sure it is in range... cmp al,07FH ; Is it delete? jl character1a ret ; Don't do it... character1a: push ax ; save the character mov ax,text_y mov dx,text_x call convert_loc ; get to where we are going les di,dword ptr scrloc ; get screen location add si,di ; now we are in the right place mov cx,text_y and cx,0FH ; need mod(y,16) sub cx,16 neg cx ; how many to do in this section cmp cx,RPLINE ; more than one line? jle character1b mov cx,RPLINE ; make it just one line character1b: mov temp,cx ; need to remember this pop ax ; get back the character sub ax,'!' ; start with exclamation mark xor ah,ah mov dl,RPLINE ; number of entries per character shl dl,1 ; they are word entries mul dl mov di,ax ; where to get bit patterns mov dx,cx ; how many to do mov cx,bx ; this is the number to shift or cx,cx ; look at it jnz character1c jmp character8 ; no shifts necessary character1c: cmp cx,5 ; this goes within one word jg character4 ; spans word boundaries character2: mov bx,font[di] or bx,bx ; is it zero? jz character3 cmp si,0 ; too low? (start at 0 offset) [jrd] jb character3 cmp si,39999 ; too high? [jrd] jae character3 shl bx,cl ; shift to right place call t_combine character3: inc di inc di inc si inc si dec dx ; done one row jnz character2 add si,1568 ; go to top of next major row mov dx,RPLINE ; how many we needed to do sub dx,temp ; minus how many done mov temp,RPLINE ; claim we have done them all jg character2 ; do the rest jmp character10 character4: sub cx,16 ; convert to right shift neg cx mov ax,0FFFFH ; need to build mask shl ax,cl not ax mov c_mask,ax character5: mov bx,font[di] or bx,bx ; zero? jz character5a cmp si,0 ; too low? (starts at 0 offset) [jrd] jb character5a cmp si,39999 ; too high? [jrd] jae character5a jmp character6 character5a: inc si inc si jmp character7 character6: and bx,c_mask ; mask upper bits ror bx,cl ; get first batch call t_combine add si,32 ; next word column mov bx,font[di] shr bx,cl call t_combine sub si,30 ; back to right column, plus 2 character7: inc di inc di dec dx ; done one row jnz character5 add si,1568 ; go to top of next major row mov dx,RPLINE ; how many we needed to do sub dx,temp ; minus how many done mov temp,RPLINE ; claim we have done them all jg character5 ; do the rest jmp character10 character8: mov bx,font[di] or bx,bx ; is it zero? jz character9 cmp si,0 ; too low? (starts at 0 offset) [jrd] jb character9 cmp si,39999 ; too high? [jrd] jae character9 call t_combine character9: inc di inc di inc si inc si dec dx ; done one row jnz character8 add si,1568 ; go to top of next major row mov dx,RPLINE ; how many we needed to do sub dx,temp ; minus how many done mov temp,RPLINE ; claim we have done them all jg character8 ; do the rest jmp character10 character10: ret CHARACTER endp ; Cursor on - turn on the cursor if it isn't already on CURSOR_ON proc near cmp cursor,FALSE jne c_on_end ; already on push ax ; save this just in case mov t_combine,offset word_xor ; set combine rule mov ax,CURSOR_CHR call character ; print without advancing mov t_combine,offset word_or ; set combine rule mov cursor,TRUE ; flag it pop ax c_on_end: ret CURSOR_ON endp ; Cursor off - erase the cursor if it is there CURSOR_OFF proc near cmp cursor,FALSE je c_off_end ; already off push ax mov t_combine,offset word_xor ; set combine rule mov ax,CURSOR_CHR call character ; print without advancing mov t_combine,offset word_or ; set combine rule mov cursor,FALSE ; flag it pop ax c_off_end: ret CURSOR_OFF endp ; Notify the user that the page is full, and set flag to wait for ; him to clear it. PAGE_FULL proc near mov full_flag,TRUE ; page is full! call beep ; make some noise about it les di,dword ptr scrloc ; get screen location add di,38424 ; lower left corner mov ax,0FFFFH ; set them all! xor es:[di],ax inc di inc di xor es:[di],ax inc di inc di xor es:[di],ax inc di inc di xor es:[di],ax ret PAGE_FULL endp ; Connect points: start=startx, start+2=starty, endpt=endx, endpt+2=endy ; Uses combination routine pointed at by combine LINE proc near mov dx,start ; start x mov ax,endpt ; end x mov x_inc,1 ; assume incrementing sub ax,dx jnb line1 ; correct neg x_inc neg ax line1: mov delta_x,ax ; save delta mov dx,start+2 ; start y mov ax,endpt+2 ; end y mov y_inc,1 ; assume incrementing sub ax,dx jnb line2 ; correct neg y_inc neg ax line2: mov delta_y,ax ; save delta les di,dword ptr scrloc ; point at bit map region mov dx,start mov ax,start+2 call set_pixel ; set start point mov ax,delta_y cmp ax,delta_x ; which should we step on ja line_y ; line_x: mov cx,delta_x ; number of steps jcxz line_x_done ; nothing to do mov ax,cx shr ax,1 ; delta_x/2 mov part_accum,ax line_x_loop: mov ax,x_inc add start,ax mov ax,delta_y sub part_accum,ax jge line_x_ok mov ax,y_inc add start+2,ax mov ax,delta_x add part_accum,ax line_x_ok: mov dx,start mov ax,start+2 call set_pixel loop line_x_loop line_x_done: ret ; line_y: mov cx,delta_y ; number of steps jcxz line_y_done ; nothing to do mov ax,cx shr ax,1 ; delta_y/2 mov part_accum,ax line_y_loop: mov ax,y_inc add start+2,ax mov ax,delta_x sub part_accum,ax jge line_y_ok mov ax,x_inc add start,ax mov ax,delta_y add part_accum,ax line_y_ok: mov dx,start mov ax,start+2 call set_pixel loop line_y_loop line_y_done: ret LINE endp ; Set pixel at location dx,ax SET_PIXEL proc near cmp dx,X_MAX ja set_range cmp ax,Y_MAX ja set_range call convert_loc cmp bx,8 ; top byte? jb set_noinc ; no inc si sub bx,8 set_noinc: add si,di ; correct offset to segment mov bl,bit_mask[bx] call combine ret set_range: pop bx ; pop one return address ret ; do nothing if off the screen SET_PIXEL endp ; Convert x and y to word location and word bit number ; entry: dx=x, ax=y, exit: si=byte number, bx=bit number CONVERT_LOC proc near mov si,ax and si,0FH ; mod(y,16) mov bx,ax and bx,0FFF0H ; 16*int(y/16) shl bx,1 ; *2 (need 50 times) add si,bx ; that's 2 shl bx,1 ; *4 shl bx,1 ; *8 shl bx,1 ; *16 add si,bx ; that's 18 shl bx,1 ; *32 add si,bx ; that's 50 mov bx,dx and bx,0FFF0H ; 16*int(x/16) add si,bx shl si,1 ; byte address mov bx,dx and bx,0FH ; mod(x,16) ret CONVERT_LOC endp ; Or the mask in bl into byte at es:[si] PIXEL_OR proc near or es:[si],bl ret PIXEL_OR endp ; Exclusive-or mask in bl into byte at es:[si] PIXEL_XOR proc near xor es:[si],bl ret PIXEL_XOR endp ; Or the word in bx into word at es:[si] WORD_OR proc near or es:[si],bx ret WORD_OR endp ; Exclusive-or the word in bx into word at es:[si] WORD_XOR proc near xor es:[si],bx ret WORD_XOR endp ; Send the status out the back SEND_STAT proc near cmp graph_mode,FALSE ; in graph mode? je send_stat1 ; No push cur_y ; push current point, y first push cur_x ; then x mov al,39H ; bit 7=0, bit 6=1, bit 5=1 (no hcopy) ; bit 4=1 (ready for vector) ; bit 3=0 (graph mode) ; bit 2=0 (margin 0), bit 1=1 call send_coord ; send it out ret ; send_stat1: mov ax,text_y ; get current point add ax,10 ; move to lower left corner sub ax,Y_MAX ; need to swap it neg ax mov bx,TEK_Y_MAX ; convert to tek coords mul bx mov bx,Y_MAX div bx cmp dx,Y_MAX/2 ; need to round up? jl send_stat2 inc ax send_stat2: cmp ax,TEK_Y_MAX ; up too far? jbe send_stat3 ; okay mov ax,TEK_Y_MAX send_stat3: push ax ; save y mov ax,text_x mov bx,TEK_X_MAX ; convert to tek coords mul bx mov bx,X_MAX div bx cmp dx,X_MAX/2 ; need to round up? jl send_stat4 inc ax send_stat4: cmp ax,TEK_X_MAX ; up too far? jbe send_stat5 ; okay mov ax,TEK_X_MAX send_stat5: push ax ; save x mov al,3DH ; bit 7=0, bit 6=1, bit 5=1 (no hcopy) ; bit 4=1 (ready for vector) ; bit 3=1 (not graph mode) ; bit 2=0 (margin 0), bit 1=1 call send_coord ; send it out ret SEND_STAT endp ; Send the byte currently in the al register out the port, then follow ; it by the coordinates - x is the first on the stack, y is the second ; on the stack (i.e., x was pushed last, and popped first) SEND_COORD proc near call outprt ; send byte in al pop cx ; this is the return address pop ax ; this is x coord pop bx ; this is y coord push cx ; return back on push bx ; y back on push ax ; x back on mov cl,5 ; shift to hix shr ax,cl and al,31 ; keep 5 bits or al,32 ; this is hix now call outprt pop ax ; x again and al,31 or al,64 ; this is lox now call outprt pop ax ; get y coordinate push ax ; save it again for a flash mov cl,5 ; shift to hiy shr ax,cl and al,31 ; keep 5 bits or al,32 ; this is hiy now call outprt pop ax ; y again and al,31 or al,96 ; this is loy now call outprt ; Now for the termination string - use CR,EOT - this is the default for ; the 4051 microcomputer which is supposed to look like a 4012 - I hope ; they know what they are doing... mov al,13 call outprt mov al,4 call outprt ret SEND_COORD endp OUTPRT proc near test yflags,lclecho ; echoing? jz outpr1 ; z = no, forget it cmp flags.vtflg,TTTEK ; doing TEKTRONIX? je outpr00 ; e = yes, echo it nicely cmp flags.vtflg,TTVT100 ; doing VT100? je outpr0 ; e = yes, echo it nicely push ax ; save char call outtty ; print it pop ax ; restore jmp outpr1 outpr00:cmp full_flag,FALSE ; page full? jne outpr1 ; forget this push ax call tekhandle ; do the job in a smart way pop ax jmp outpr1 outpr0: push ax ; save char call doansi pop ax ; restore outpr1: mov ah,al ; this is where outchr expects it call outchr ; output to the port jc outpr4 ; c = failure ret outpr4: jmp endcon ; failure, end connection OUTPRT endp ; Get a character from the serial port in al ; returns with carry clear if a character is available PORTCHR proc near call prtchr ; character at port? jnc portc1 ; nc = yes portc0: ret portc1: and al,parmsk ; apply 8/7 bit parity mask or al,al ; is it a null char? jz portc0 ; z = yes, ignore it portc2: clc ; have a character ret ; and return PORTCHR endp ; Put the character in al to the screen ; Directly call the console-driver to get better speed (4 times, ~19200 ; baud) [as] OUTTTY proc near call capture push ax ; these are modified by the driver push bx push cx push dx push si push es mov cl,al mov ax,1 call dword ptr drivadr pop es pop si pop dx pop cx pop bx pop ax ret ; through OUTTTY endp ; Capture char in al to a file if we are supposed to ; Translation taken from msyibm with minimal modification CAPTURE proc near test yflags,CAPT ; capturing output? jz nocap ; no forget this part push ax ; save it call captrtn pop ax ; get char back nocap: test flags1,PRTSCR ; should we be printing? jz noprt ; no, go on call pntchr ; printer routine jnc noprt ; nc = successful print push ax call beep ; else make a noise and call trnprs ; turn off printing pop ax noprt: ret CAPTURE endp ; Set heath emulation on/off. ; Added VT100 emulation switch and TEKTRONIX switch - notifies of ; idiosyncracies if TEKTRONIX selected (also checks for allowability) ; [bgp]. With the addition of the official TEKTRONIX terminal type ; we no longer have to warn about weird results. VTS proc near mov dx,offset termtb mov bx,offset termhlp mov ah,CMKEY call comnd jc vtx ; c = failure push bx mov ah,cmeol call comnd ; Get a confirm pop bx jc vtx cmp bx,TTTEK ; doing TEKTRONIX? jne vt1 ; no cmp tek_allowed,FALSE ; can we do TEKTRONIX? jne vt1 ; yes mov dx,offset no_tek_msg ; tell him we can't mov ah,PRSTR int DOS ret ; don't do anything vt1: mov flags.vtflg,bx ; Set the emulation flag. vtx: ret VTS endp VTSTAT PROC NEAR ; For Status display [jrd] ret ; no emulator status to display VTSTAT ENDP ; Control text cursor. AL = 0 for off, 1 for on (nominally underline) csrtype proc far push dx mov escstring,ESCAPE mov escstring+1,'y' mov escstring+2,'5' mov escstring+3,'$' or al,al ; set mode? jnz csrty1 ; nz = yes dec escstring+1 ; 'x' is reset mode ESC x 5 csrty1: mov dx,offset escstring ; pass string to screen console mov ah,PRSTR int DOS pop dx ret csrtype endp ; The following are keyboard translator access routines added 29 August 1987. ; They are invoked by a jump instruction. They must return carry clear to ; continue processing or carry set to exit from Connect mode, in which case ; kbdflg will have the transfer character in it. [bgp] chrout: call outprt ; send a character out the port clc ret cpage: cmp flags.vtflg,TTTEK ; only works on tektronix emulation jne cpage1 call clrscr ; clear the tektronix screen clc ret cpage1: call beep clc ret chome: cmp flags.vtflg,TTTEK ; only works on tektronix emulation jne chome1 call homescr ; home the tektronix screen clc ret chome1: call beep clc ret cquery: mov al,'?' jmp cmdcom cstatus:mov al,'S' jmp cmdcom cquit: mov al,'C' jmp cmdcom chang: mov al,'H' jmp cmdcom kdos: mov al,'P' jmp cmdcom cmdcom: mov kbdflg,al ; pass to msster.asm via kbdflg stc ; need to exit connect mode ret dmpscn: cmp flags.vtflg,TTTEK ; emulating tektronix? jne dmpscn1 ; no, do it jmp dmpscn2 ; can't on tektronix... dmpscn1:call savescr ; have to save screen to dump it call dumpscr call restscr ; need to put it back again too clc ret dmpscn2:call beep ; nothing else to do I guess clc ret snull: xor ah,ah ; send a null call outchr ; send without echo or logging clc ret klogof: mov bx,argadr ; need to fix args and [bx].flags,not CAPT ; clear capture flag and yflags,not CAPT ; also local copy clc ret klogon: test flags.capflg,LOGSES ; logging enabled? jz klogon1 mov bx,argadr ; need to fix args or [bx].flags,CAPT ; set capture flag or yflags,CAPT ; also local copy klogon1:clc ret trnprs: push ax ; toggle ^ PrtSc screen to printer test yflags,prtscr ; are we currently printing? jnz trnpr2 ; nz = yes, its on and going off 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? je trnpr2 ; e = Ready trnpr1: call beep ; Not Ready, complain jmp trnpr3 ; and ignore request trnpr2: xor yflags,prtscr ; flip the flag test yflags,modoff ; mode line off? jnz trnpr3 ; nz = yes call modlin ; else rewrite mode line trnpr3: pop ax clc ; return carry clear (don't quit) ret ; 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 call pntflsh ; flush printer buffer 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 ; 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 ; finish in common code 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 near ; 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 ; Service SET NETBIOS-NAME name command at Kermit prompt level setnbios proc near ret setnbios endp sesdisp proc near ret sesdisp endp CODE ends end