NAME msyibm ; File MSYIBM.ASM include mssdef.h ; Copyright (C) 1982, 1997, Trustees of Columbia University in the ; City of New York. The MS-DOS Kermit software may not be, in whole ; or in part, licensed or sold for profit as a software product itself, ; nor may it be included in or distributed with commercial products ; or otherwise distributed by commercial concerns to their clients ; or customers without written permission of the Office of Kermit ; Development and Distribution, Columbia University. This copyright ; notice must not be removed, altered, or obscured. ; Edit history ; 12 Jan 1995 version 3.14 ; Last edit ; 12 Jan 1995 public lclyini, csrtype, fcsrtype, scrseg public atsclr, trnmod, vtbell, vtroll, crt_lins, crt_cols public vtemu, crt_mode, scbattr, refresh, low_rgt ; data public setchtab, extattr, vtcpage, tv_mode, dos_bottom public setpos, setatch, yflags, vtinited, useexp public vts, vtstat, termtb, modbuf, qsetatch ; terminal emulation public tv_segs, tv_sego ifndef no_terminal public term, enqbuf public chgdsp, vtclear, ftogmod, getatch, nextses, setprot, clrprot public prtbout, prtnout, vtscru, vtscrd, vclick, reset_color public getbold, setbold, clrbold, getblink, setblink, clrblink public getunder, setunder, clrunder, revideo, revscn, setcolor public setrev, clrrev, frepaint, touchup, reversed_screen ; action verb procedures for keyboard translator public uparrw, dnarrw, rtarr, lfarr, pf1, pf2, pf3, pf4 public kp0, kp1, kp2, kp3, kp4, kp5, kp6, kp7, kp8, kp9 public kpminus, kpcoma, kpenter, kpdot, chrout, cstatus, cquit public cquery, dmpscn, vtans52, vtinit, dnwpg, upwpg, endwnd, homwnd public upone, dnone, trnprs, dumpscr, modlin, snull, ignore_key public klogon, klogof, cdos, chang, khold, product, termesc_flag public vtksmac, vtkrmac, apcmacro, apcenable, vtenqenable public decf6,decf7,decf8,decf9,decf10,decf11,decf12,decf13,decf14 public dechelp,decdo,decf17,decf18,decf19,decf20, udkclear public decfind, decinsert, decremove, decselect, decprev public decnext, setudk, extmacro, vtmacname, vtmaclen public rtone, lfone, rtpage, lfpage, kbdcompose, kdebug public dgkc1,dgkc2,dgkc3,dgkc4,dgkf1,dgkf2,dgkf3,dgkf4,dgkf5 public dgkf6,dgkf7,dgkf8,dgkf9,dgkf10,dgkf11,dgkf12,dgkf13 public dgkf14,dgkf15, dgpoint, dgnckey public dgkSf1,dgkSf2,dgkSf3,dgkSf4,dgkSf5,dgkSf6,dgkSf7,dgkSf8 public dgkSf9,dgkSf10,dgkSf11,dgkSf12,dgkSf13,dgkSf14,dgkSf15 public udkf6, udkf7, udkf8, udkf9, udkf10, udkf11, udkf12, udkf13 public udkf14, udkf15, udkf16, udkf17, udkf18, udkf19, udkf20 public wykf1,wykf2,wykf3,wykf4,wykf5,wykf6,wykf7,wykf8 public wykf9,wykf10,wykf11,wykf12,wykf13,wykf14,wykf15,wykf16 public wykSf1,wykSf2,wykSf3,wykSf4,wykSf5,wykSf6,wykSf7,wykSf8 public wykSf9,wykSf10,wykSf11,wykSf12,wykSf13,wykSf14,wykSf15,wykSf16 public dgsettek, vtclrflg, tn_AYT, tn_IP, jpnxltkey, rcvmacro public srvmacro, crdisp_mode ifndef no_tcp public termswapout, termswapin, termswapdel, commbyte public ses1, ses2, ses3, ses4, ses5, ses6 endif ; no_tcp endif ; no_terminal ; some definitions SIchar equ 0fh SOchar equ 0eh DGescape equ 1eh CSI equ 9bh SS2 equ 8eh SS3 equ 8fh bapito_3270 equ 0b3h ; KERMIT BAPI extension, byte to 3270 ; hardware crt_status equ 3dah ; CGA crt status port disp_enb equ 8 ; CGA display enable bit crtmset equ 3D8H ; CGA CRT mode set port screen equ 10h ; Bios screen interrupt att_protect equ 01h ; protected in vsatt att_uline equ 02h ; underscored in vsatt att_rev equ 04h ; reversed video in vsatt att_bold equ 08h ; bold in main video word att_blink equ 80h ; blinking in main video word att_low_mask equ 06H ; Various attribute-related equates ;;;att_normal equ 07h att_underline equ 01H ; for mono monitors, in video word ifndef nls_portuguese modfrm struc ; format of mode (status) line db 'Esc:Alt-x help:Alt-h port:' m_prt db 20 dup (' ') m_baud db 6 dup (' ') m_par db 3 dup (' ') db ' echo:' m_echo db 3 dup (' ') m_term db 12 dup (' ') ; 12 bytes for term type m_prn db 3 dup (' ') ; show PRN when printer is on m_comp db ' ' ; Compose indicator db '$' ; terminator modfrm ends else modfrm struc ; format of mode (status) line db 'Esc:Alt-X help:Alt-H porta:' ; db 'Carac-Esc: ajuda: ? porta:' ; db 'Carac-Esc:' ; do not write in last column m_prt db 19 dup (' ') m_baud db 6 dup (' ') m_par db 3 dup (' ') db ' eco:' m_echo db 3 dup (' ') m_term db 12 dup (' ') ; 12 bytes for term type m_prn db 3 dup (' ') ; show PRN when printer is on m_comp db ' ' ; Compose indicator db '$' ; terminator modfrm ends endif ; nls_portuguese ; structure for status information table sttab. stent struc sttyp dw ? ; type (actually routine to call) msg dw ? ; message to print val2 dw ? ; needed value: another message, or tbl addr tstcel dw ? ; address of cell to test, in data segment basval dw 0 ; base value, if non-zero stent ends data segment extrn flags:byte, decbuf:byte, rdbuf:byte, xms:dword extrn filtst:byte, dmpname:byte, kbdflg:byte, rxtable:byte extrn trans:byte, comand:byte, kstatus:word, prnhand:word extrn comptab:byte, dosnum:word, fossil_port:word, termserver:byte ifndef no_terminal extrn anspflg:byte, scroll:byte, ttyact:byte extrn mar_top:byte, mar_bot:byte, npages:word extrn holdscr:byte, portval:word extrn taklev:byte, takadr:word, mcctab:byte, dupflg:byte extrn apctrap:byte, denyflg:word extrn kbcodes:byte, repflg:byte extrn param:word, nparam:word extrn upss:byte, GRptr:word, G1set:byte, G2set:byte extrn G3set:byte, cursor:word, linescroll:byte extrn savezlen:word, savezoff:word extrn savexoff:word, savexlen:word, savepoff:word extrn saveplen:word, rollwidth:word, dgkbl:byte, apcstring:word extrn blinkdis:byte, protectena:byte, dghscrdis:byte extrn dgwindcomp:byte, att_normal:byte extrn emsrbhandle:word, curattr:byte, saveuoff:word, saveulen:word extrn dgd470mode:byte, tekflg:byte, xmsrhandle:word extrn xmsghandle:word, xmsep:dword extrn parmsk:byte, flowon:byte, flowoff:byte, flowcnt:byte extrn isps55:byte ; [HF]940130 in MSXIBM.ASM extrn ps55mod:byte ; [HF]940206 in MSXIBM.ASM extrn domath_ptr:word, domath_cnt:word, domath_msg:word ifndef no_graphics extrn chcontrol:byte, softlist:word extrn tekgraf:byte, tekcursor:byte, dgcross:byte, cursorst:byte extrn savegoff:word, saveglen:word endif ; no_graphics ifndef no_network ifndef no_tcp extrn tcpnewline:byte extrn seslist:byte, sescur:word, tcphost:byte, tcpmode:byte extrn sestime:byte endif ; no_tcp endif ; no_network endif ; no_terminal inited equ 08h ; been here before prtscr equ 1 ; print screen pressed ; stuff for screen routines ;;;;;;;;;;;;;; start session save area even saveyoff label word yflags db 0 ; status flags vtemu emulst <> ; emulator flags vtsave db 7 dup (0) ; inuse/color/charset save around ANSI belltype db 0 ; 0 = aural bell, 1 = visual scbattr db ? ; screen background attribute savattr db ? ; current emulator attributes extattr db 0 ; extended scbattr colunder db 0ffh ; underline color (0ffh = uninited) vtclrflg db 0 ; erase with scbattr(0) or curattr(1) vtclkflg db 1 ; status line clock (0=off) reversed_screen db 0 ; if whole screen has been reversed crt_mode db 3 ; video mode (typ 3, must be text) ; keep crt_cols & crt_lins in order crt_cols db 80 ; number of screen columns (typ 80) crt_lins db 24 ; number of screen rows - 1 (typ 24) dos_bottom db 24 ; num of rows-1 at DOS level (typ 24) low_rgt dw 174fh ; lower right corner of text window ; high = row address (typ 23) ; low = column address (typ 79) handhsc db 0 ; hand horizontal scroll dosetcursor dw -1 ; place to set tekcursor, -1 = don't vtinited db 0 ; flag for emulator having been inited vtclear db 0 ; nonzero to redo emulator screen reset_color db 0 ; reset color on CSI m writemode db 0 ; screen writing mode vchgmode db 2 ; video-change mode (0=enabled) vtcpage dw 437 ; terminal code page apcenable db 0 ; enable APC macro (default is off) vtenqenable db 0 ; enable Answerback saveflag flginfo <> ; copy of flags array ytermtype dw 0 ymodetype db 0 keypend dw 0 ;[HF]940207 buffer for double byte code keyj7st dw 0 ;[HF]940211 keyoutput status for JIS7 enqbuf db 40 dup (0),0 ; local enquiry string, asciiz crdisp_mode db 0 ; CR display mode saveylen dw ($ - saveyoff) ;;;;;;;;;;;;;;;;; end of session save area modbuf modfrm <> ; mode line buffer argadr dw 0 ; address of arg blk skip dw 0 inemulator db 0 ; non-zero if term emlator active inwindows db 0 ; non-zero if Windows is active crlf db cr,lf,'$' even ifndef no_terminal vid7id db 'VEGA BIOS Code, ' ; Video 7 Vega version string subset vid7len equ $-vid7id ; length of string vid7id2 db 'Video Seven BIOS Code, ' ; Video 7 VGA board vid7len2 equ $-vid7id2 atiwid db 'ATI EGA Wonder Bios,' ; ATI EGA wonder version string subset atilen equ $-atiwid ; length of string, inc terminator atiwid2 db '761295520' ; ATI signature #2 atilen2 equ $-atiwid2 tsngid db 'Tseng' ; Tseng Labs EVA (& Orchid Designer) tsnglen equ $-tsngid stbvid db 'TVGA' ; STB VGA/EM (also Tseng TVGA) stbvlen equ $-stbvid stavid db '4000' ; STB VGA/EM Plus (Tesng 4000) stavlen equ $-stavid evrxid db 'Everex' ; Everex Micro Enhancer Deluxe EGA evrxlen equ $-evrxid evgid db 'VGA EV673' ; Everex EVGA EV-673 evglen equ $-evgid evvid db 'EV-678' ; Everex Viewpoint EV-678 evvlen equ $-evvid attvdc6 db '003116' ; AT&T video board, at c000:35h attvdlen equ $-attvdc6 attvdc7 db 'C02000' ; AT&T video board, at e000:10h pmega1 db '28190-A1001' ; Paradise AutoSwitch EGA Mono String1 pmegal1 equ $-pmega1 p30id db 'VGA' ; VGA Plus, Plus 16, Professional p30ln equ $-p30id ; and VGA1024 by Paradise emsrollname db 'KERMIT ',0 ; 8 byte EMS region name, + safety pageready dw -1 ; ems page currently active cols80 db 'COLS80.BAT',0 ; to 80 column mode batch file cols132 db 'COLS132.BAT',0 ; to 132 column mode batch file xga_reg_base dw -1 ; PS/2 MCA I/O register base emsname db 'EMMXXXX0',0 ; expanded memory manager dev name jis7des db 'B','B' ; [HF] 941016 JIS7 designators (Kanji/ASCII) cpwarn db cr,lf db '?Warning: Code Page CP866 is required but it is not active.$' endif ; no_terminal ega_mode db 0 ; non-zero if IBM EGA is in use tvhere equ 0feh ; Topview active query tvsynch equ 0ffh ; Topview resynch request tv_segs dw 0 ; Topview virtual screen, segment tv_sego dw 0 ; and offset tv_mode db 0 ; flag, 0 = no Topview or DESQview vtcpumode db 0 ; timeslice-release (0 = enabled) vs_ptr dd 0 ; offset, segment of vscreen (dynamic) vsat_ptr dd 0 ; offset, segment of vs's attributes ; Note: (vswidth+1)/2 bytes of attributes/line, at two attributes/byte vswidth equ 207 ; columns across DG virtual screen ; The following are used to turn the display back on (after scrolling etc.) msets db 2CH,28H,2DH,29H,2AH,2EH,1EH,29H wysecurtab db 0bh,0ah,0ch,08h ; VT to Wyse-50 cursor converter dgcurtab db 23,26,24,25 ; ANSI to DG cursor converter dgcrostab db 72,80,77,75 ; DG cursor to PC scan for croshair mtty db ' TTY ' ; no terminal type (mode line) fairness dw 0 fairprn dw 0 lincur dw ? ; cursor type save area dosattr db ? ; screen attributes at init time userbold db 0 ; screen bold attribute at start up dos_cols db 0 ; screen width (crt_cols) at DOS ifndef no_terminal oldsp dw 0 ; offset to longjmp to for i/o failure ten db 10 ; byte constant for key defines temp dw 0 ; scratch storage temp2 dw 0 ; scratch storage endif ; no_terminal ifndef no_terminal dmphand dw -1 ; screen dump file handle dumpsep db 0ch,cr,lf ; screen image separators dmperr db ' Cannot open file to save screen to disk $' memerr db cr,lf,'Not enough memory for terminal emulator$' pntmsg db 'Printer not ready, printing request skipped$' ; some static data for mode line modmaster modfrm <> ; master template unkbaud db 'unkwn ' ; must be 6 chars baudn db ' 45.5 ',' 50 ',' 75 ',' 110 ','134.5 ',' 150 ',' 300 ' db ' 600 ',' 1200 ',' 1800 ',' 2000 ',' 2400 ',' 4800 ',' 9600 ' db '14400 ', '19200 ','28800 ', '38400 ','57.6K ','115 K ' db '75/12 ' baudnsiz equ 21 ; # of baud rates known (tbl size / 6) repmsg db 'REPLAY' ; REPLAY message for speed field repmsgl equ $-repmsg parnams db '7e1','7m1','8n1','7o1','7s1' lclmsg db 'loc' remmsg db 'rem' portno db 0 termesc_flag db 0 ; SET TERM ESCAPE flag endif ; no_terminal ; storage for multi-window stuff slen equ 24 ; and length of text crt_norm db 3 ; video mode for normal screen inipara dw 0 ; initial paragraphs of scroll memory ; also is number ems pages for same refresh db 0 ; screen refresh (0=wait for retrace) vtroll db 0 ; auto roll back allowed (0 = no) useexp db 0 ; non-zero to use exp mem for rollback vsbuff_inited db 0 ; non-zero if inited screen buffers setnoshow db 0 ; quiet setatch flag lastsec db -1 ; seconds of last gettim call ifndef no_terminal vtkrname db 'KEYBOARDR' ; a macro name, must be Upper Case vtkrlen equ $-vtkrname vtksname db 'KEYBOARDS' ; a macro name, must be Upper Case vtkslen equ $-vtksname prodname db 'PRODUCT' vtplen equ $-prodname vtsesname db 'SESSION' vtsesnum db '1' vtseslen equ $-vtsesname vtmacname dw vtkrname ; pointer to selected macro name vtmaclen dw vtkrlen udkseg dw 18 dup (0) ; segment of user definable key defs even ; screen rollback material iniseg dw ? ; (BDT) initial seg of scroll memory ppl dw 0 ; (BDT) paragraphs per line lcnt dw 0 ; (BDT) number of "filled" buffer lines linef dw 0 ; (BDT) "first" filled line is here linec dw 0 ; (BDT) "current" screen line number linee dw 0 ; (BDT) total # of lines in the buffer lmax dw 0 ; (BDT) max lines in buff (less 1 scrn) lineems dw 0 ; lines per EMS 16KB page frame xgatmp1 dw 0 ; XGA display adapter work word pair xgatmp2 dw 0 tsave dw 6 dup (0) ; list of term swap paragraphs ; DG SPCL three stroke Compose key grab dw 0 ; zero if not grabbing output grabbox db 0,0 ; store incoming pair of bytes endif ; no_terminal setchtab db 10 ; Set File Character-Set table mkeyw 'CP437',437 ; hardware default Code Page mkeyw 'CP850',850 ; Multilingual CP mkeyw 'CP852',852 ; Latin2 CP mkeyw 'CP860',860 ; Portuguese CP mkeyw 'CP861',861 ; Icelandic CP mkeyw 'CP862',862 ; Hebrew CP mkeyw 'CP863',863 ; French Canadian CP mkeyw 'CP865',865 ; Norwegian CP mkeyw 'CP866',866 ; Latin5/Cryillic CP mkeyw 'Shift-JIS',932 ; Japanese Shift-JIS ifdef no_terminal ; begin Terminal emulator data set termtb db 1 ; entries for Status, not Set mkeyw 'none',ttgenrc vttbl db 0 ; number of entries endif ; no_terminal ifndef no_terminal ; begin Terminal emulator data set ifndef no_graphics termtb db tttypes ; entries for Status, not Set else termtb db tttypes - 1 endif mkeyw 'VT320',ttvt320 mkeyw 'VT220',ttvt220 mkeyw 'VT102',ttvt102 mkeyw 'VT100',ttvt100 mkeyw 'VT52',ttvt52 mkeyw 'Honeywell VIP7809',tthoney mkeyw 'Heath-19',ttheath ifndef no_graphics mkeyw 'Tek4010',tttek endif mkeyw 'PT200',ttpt200 mkeyw 'D217',ttd217 mkeyw 'D463',ttd463 mkeyw 'D470',ttd470 mkeyw 'Wyse50',ttwyse mkeyw 'Ansi-BBS',ttansi mkeyw 'none',ttgenrc ifndef no_graphics vttbl db 55 ; number of entries else vttbl db 55 - 2 endif ; no_graphics mkeyw 'Answerback',vtenqctl mkeyw 'APC-macro',apcctl mkeyw 'Arrow-keys',flg11 mkeyw 'Autodownload',vtdownld mkeyw 'Character-set',vtchar mkeyw 'Clock',vtclock mkeyw 'Code-Page',vtcodepage mkeyw 'Compressed-text',flg14 mkeyw 'Controls',flg9 mkeyw 'CR-display',vtcrdisp mkeyw 'Cursor-style',flg7 mkeyw 'Direction',flg4 mkeyw 'Escape-character',termesc mkeyw 'Expanded-memory',expmemory mkeyw 'Horizontal-scroll',flg13 mkeyw 'Keyclick',flg5 mkeyw 'Keypad',flg10 mkeyw 'Margin-bell',flg6 mkeyw 'Newline',flg1 mkeyw 'Reset',termreset mkeyw 'Screen-background',flg8 mkeyw 'Video-writing',scrwrite mkeyw 'Video-change',scrchange mkeyw 'Tabstops',tabmod mkeyw 'Timeslice-release',vtcpu mkeyw 'Width',flg12 mkeyw 'Wrap-lines',flg2 mkeyw 'Bell',vtbeep mkeyw 'Bytesize',vtbyte mkeyw 'Clear-screen',vtcls mkeyw 'Color',vtcolor mkeyw 'Display',vtbyte ; syn for set display 7/8 mkeyw 'Erase',vterase ifndef no_graphics mkeyw 'Graphics',vtgraph mkeyw 'Tek4010',vttyp40 endif ; no_graphics mkeyw 'Replay',replay mkeyw 'Rollback',vtrollbk mkeyw 'output-shift',vtshift mkeyw 'Underscore',vtucolor mkeyw 'UPSS',vtupss mkeyw 'Type',vttype ; SET TERM TYPE mkeyw 'None',vttyp0 mkeyw 'Heath-19',vttyp1 mkeyw 'VT52',vttyp2 mkeyw 'VT100',vttyp4 mkeyw 'VT102',vttyp8 mkeyw 'VT220',vttyp10 mkeyw 'VT320',vttyp20 mkeyw 'Honeywell',vttyp80 mkeyw 'PT200',vttyp100 mkeyw 'D217',vttyp1000 mkeyw 'D463',vttyp200 mkeyw 'D470',vttyp400 mkeyw 'Wyse50',vttyp800 mkeyw 'ANSI',vttyp2000 ontab db 2 ; two entries mkeyw 'off',0 mkeyw 'on',1 beltab db 3 ; bell type mkeyw 'audible',0 mkeyw 'visual',1 mkeyw 'none',2 clktab db 3 mkeyw 'Off',0 mkeyw 'On',1 mkeyw 'Elapsed-time',2 distab db 2 ; display mkeyw '7-bit',0 mkeyw '8-bit',d8bit erasetb db 2 ; erase mkeyw 'normal-background',0 mkeyw 'current-color',1 scrtab db 2 ; screen attributes mkeyw 'normal',0 mkeyw 'reverse',1 dirtab db 2 ; writing direction mkeyw 'left-to-right',0 mkeyw 'right-to-left',1 writetab db 2 ; writing mkeyw 'direct',0 mkeyw 'Bios',1 curtab db 2 ; cursor attributes mkeyw 'block',0 mkeyw 'underline',1 apctab db 3 ; three entries mkeyw 'off',0 mkeyw 'on',1 mkeyw 'unchecked',2 chatab db 32 ; National Replacement Character sets mkeyw 'ASCII',C_ASCII ; ASCII is default (0, no NRC) mkeyw 'British',C_UKNRC ; start NRC set (1-12) mkeyw 'Dutch',C_DUNRC mkeyw 'Finnish',C_FINRC mkeyw 'French',C_FRNRC mkeyw 'Fr-Canadian',C_FCNRC mkeyw 'German',C_DENRC mkeyw 'Hebrew-7',C_DHEBNRC mkeyw 'Italian',C_ITNRC mkeyw 'Norwegian/Danish',C_NONRC mkeyw 'Portuguese',C_PONRC mkeyw 'Spanish',C_SPNRC mkeyw 'Swedish',C_SENRC mkeyw 'Swiss',C_CHNRC ; end of NRC proper mkeyw 'Alternate-ROM',C_ALTROM ; Alternate-ROM character set mkeyw 'Transparent',C_XPARENT ; use native display adapter hardware mkeyw 'Latin1',C_LATIN1 ; Latin-1 in GR mkeyw 'Latin2',C_LATIN2 ; Latin-2 (will presume CP852) mkeyw 'Hebrew-ISO',C_HEBREWISO ; Hebrew-ISO (presumes CP862) mkeyw 'HP-Roman8',C_HPROMAN8 ; HP-Roman8 mkeyw 'DEC-MCS',C_DMULTINAT ; DEC Supplemental Graphics in GR mkeyw 'DEC-Technical',C_DECTECH mkeyw 'DEC-Special',C_DECSPEC mkeyw 'DG-International',C_DGINT mkeyw 'DG-Line-Drawing',C_DGLINE mkeyw 'DG-Word-Processing',C_DGWP mkeyw 'JIS-Kanji',C_JISKANJI ; [HF] JIS X 208, ISO(ECMA)#87 mkeyw 'JIS-Katakana',C_JISKAT ; [HF] JIS X 201, ISO(ECMA)#13 mkeyw 'JIS-Roman',C_JISROM ; [HF] JIS X 201, ISO(ECMA)#14 mkeyw 'Cyrillic-ISO',C_CYRILLIC_ISO mkeyw 'KOI8',C_KOI8 mkeyw 'Short-KOI',C_SHORT_KOI upsstab db 4 mkeyw 'DEC-MCS','5%' ; DEC Supplemental Graphics mkeyw 'Latin1','A' ; Latin-1 mkeyw 'Hebrew-7','4"' ; DEC Hebrew-7 mkeyw 'Hebrew-ISO','H' ; Hebrew-ISO sidetab db 4 ; SET TERM CHAR Gn mkeyw 'G0','0' mkeyw 'G1','1' mkeyw 'G2','2' mkeyw 'G3','3' shifttab db 8 ; SET TERM OUTPUT-SHIFT mkeyw 'none',0 mkeyw 'automatic',8 mkeyw 'SI/SO',1 mkeyw 'SS2',2 mkeyw 'SS3',4 mkeyw 'JIS7-Kanji',(128+1) ; [HF]940211 mkeyw 'EUC-Kanji',(128+2) ; [HF]940211 mkeyw 'DEC-Kanji',(128+3) ; [HF]941012 jis7tab db 6 ;[HF]941014 mkeyw 'JIS83-US','BB' ;[HF]941014 mkeyw 'JIS83-Roman','JB' ;[HF]941014 mkeyw 'JIS83-75Roman','HB' ;[HF]941014 mkeyw 'JIS78-US','B@' ;[HF]941014 mkeyw 'JIS78-Roman','J@' ;[HF]941014 mkeyw 'JIS78-75Roman','H@' ;[HF]941014 enqtab db 5 ; set term enquire table mkeyw 'off',0 mkeyw 'on',1 mkeyw 'message',2 mkeyw 'UNSAFE-MESSAGE',3 mkeyw 'UNSAFE-MESSAGE ',4 ; invisible to force spelled out graftab db 13 mkeyw 'auto-sensing',0 ; autosensing mkeyw 'CGA',1 mkeyw 'EGA',2 mkeyw 'VGA',3 mkeyw 'VESA(800x600)',9 mkeyw 'Hercules',4 mkeyw 'ATT',5 mkeyw 'WyseA(1280x800)',6 ; Wyse-700 1280 x 800 mode mkeyw 'WyseH(1280x780)',7 ; Wyse-700 1280 x 780 mode mkeyw 'WyseT(1024x780)',8 ; Wyse-700 1024 x 780 mode mkeyw 'character-writing',101h mkeyw 'color',103h mkeyw 'cursor',102h gchrtab db 2 ; set term graphics char-writing mkeyw 'opaque',1 mkeyw 'transparent',0 disatab db 2 ; Tek disable/enable table mkeyw 'disabled',1 ; video-change table mkeyw 'enabled',0 tabtab db 2 ; label says it all! mkeyw 'at',0FFH ; For setting tab stops mkeyw 'Clear',0 ; For clearing tab stops alltab db 2 ; more tab command decoding mkeyw 'all',0 mkeyw 'at',1 cntltab db 2 ; 8-bit controls mkeyw '7-bit',0 mkeyw '8-bit',1 kpamtab db 2 ; keypad, application mkeyw 'numeric',0 mkeyw 'application',1 arrtab db 2 ; cursor keys, application mkeyw 'cursor',0 mkeyw 'application',1 widtab db 2 mkeyw '80-columns',0 mkeyw '132-columns',1 vchgtab db 3 ; video-change mkeyw 'enabled',0 mkeyw 'disabled',1 mkeyw 'DOS-only',2 hstab db 2 ; horizontal scrolling mkeyw 'auto',0 mkeyw 'manual',1 cmptab db 2 mkeyw 'graphics',0 mkeyw 'text-132',1 emmtab db 4 mkeyw 'off',0 mkeyw 'expanded',1 mkeyw 'extended',2 mkeyw 'on',3 termesctab db 2 ; SET TERM ESCAPE mkeyw 'Enabled',0 mkeyw 'Disabled',1 crdisptab db 2 mkeyw 'normal',0 mkeyw 'CRLF',1 colortb db 0,4,2,6,1,5,3,7 ; color reversed-bit setting bytes clrset db 0 ; Temp for SET Term Tabstops xxx erms41 db cr,lf,'?More parameters are needed$' tbserr db cr,lf,'?Column number is not in range 1 to screen width-1$' colerr db cr,lf,'?Value not in range of 0, 1, 10, 30-37, or 40-47$' vtwrap db 'Term wrap-lines: $' vtbellm db 'Term margin-bell: $' vtnewln db 'Term newline: $' vtcur db 'Term cursor-style: $' vtcset db 'Term character-set: $' vtclik db 'Term key-click: $' vtscrn db 'Term screen-background: $' txtcolst1 db 'Term color (normal) f:3$' colst2 db ' b:4$' colst3 db ' rst:$' undcolst1 db 'Term underscore color f:3$' grcolst1 db 'Term graphics color f:3$' vtgraf db 'Term graphics: $' vtrolst db 'Term rollback: $' vtdir db 'Term direction: $' vtcntst db 'Term controls: $' vtkpst db 'Term keypad: $' vtarst db 'Term arrow-keys: $' vtbset db 'Term bell: $' vtgchst db 'Term graph char: $' vtwdst db 'Term width: $' vtupsst db 'Term UPSS: $' vtshftst db 'Term output-shift: $' vthscst db 'Term horizontal-scroll: $' vtapcst db 'Term APC-macro: $' vtenqst db 'Term Answerback: $' vtenqst2 db 'ab msg: ' vtenqst2_len equ $-vtenqst2 vtwrtst db 'Term video-writing: $' vtexpmst db 'Term expanded-memory: $' vtcpagest db 'Term Code-Page: $' vtcmptst db 'Term compressed-text: $' vtchgst db 'Term video-change: $' vtcpust db 'Term timeslice-release: $' vtclrst db 'Term erase: $' vtdnldst db 'Term autodownload: $' vtcrdispst db 'Term CR-display: $' ; terminal emulator vtstbl stent ; Answerback stent stent ; char set stent ; APC-macro stent ; colors stent ; keyclick stent ; colors stent ; line wrap ifndef no_graphics stent ; colors endif ; no_graphics stent ; controls stent ; erase stent ;margin bell stent ; cursor type stent ; bell stent ; write direct stent ; newline ifndef no_graphics stent ; graphics endif ; no_graphics stent ; rollback ifndef no_graphics stent ; chr cntrl endif ; no_graphics stent ; arrow-keys stent ; screen stent ; keypad stent ; width stent ; UPSS stent ; output-shift stent ; Horz scroll stent ; V change stent ; exp mem stent ; Writing stent ; Code-Page stent ; compress stent ; timeslice stent ; CR-display stent ; autodownload stent ; VT320 tab status - needs one whole line dw 0 ; end of table vtmacroptr dd vtmacro ; FAR pointer ftogmod dd togmod ; FAR pointer termlatch db 0 ; reentry block for session macros rcvstring db 9,0,'RECEIVE',CR,'C' rcvstring_len equ $-rcvstring-2 srvstring db 5,0,'SER',CR,'C' srvstring_len equ $-srvstring-2 endif ; no_terminal data ends ifndef no_terminal data1 segment vthlp db ' one of the following:',cr,lf db ' TYPE of: None, ANSI, Heath-19, Honeywell VIP7809, Wyse50,' db ' VT52, VT100, VT102' db cr,lf db ' VT220, VT320 (default), Tek4010,' db ' PT200 (Prime), D217, D463, D470 (Data Gen)' db cr,lf db ' Newline-mode Cursor-style Character-set' db cr,lf db ' Keyclick Margin-bell Screen-background' db ' (normal, reverse)',cr,lf db ' Tabstops Wrap (long lines) Color (fore & background)' db cr,lf,' Answerback response (on or off, default is off)' db cr,lf,' APC-macro (APC cmd from host invokes local cmds)' db cr,lf,' Autodownload (on, off=default) kermit file xfers' db cr,lf,' Arrow-keys cursor (normal) or application mode' db cr,lf,' Bell audible or visual or none' db cr,lf,' Clear-screen (clears old startup screen)' db cr,lf,' Clock (status line HH:MM) on or off, default is off' db cr,lf,' Code-Page (overrides default)' db cr,lf,' Compressed-text Graphics or Text-132 (for D463/D470)' db cr,lf,' Controls 7-bit or 8-bit (permits VT320 to send' db ' 8-bit control sequences (C1))' db cr,lf,' CR-display normal or CR-LF' db cr,lf,' Direction Left-to-right or Right-to-left' db ' (screen writing direction)' db cr,lf,' Display or Bytesize 7-bit or 8-bit' db cr,lf,' Erase in normal bkground or in current char color' db cr,lf,' Expanded/extended-memory (rollback), default on' db cr,lf,' Graphics (type of display adapter when in Tek4010' db ' mode, and char writing)' db cr,lf,' Horizontal scrolling, auto (default) or manual' db cr,lf,' Keypad numeric (normal) or application mode' db cr,lf,' Output-shift (prefix 8-bit data for 7-bit channel)' db cr,lf,' Reset, resets terminal emulation to startup defaults' db cr,lf,' Rollback (undo screen roll back before writing new' db ' chars, default=off)' db cr,lf,' TEK ENABLE or DISABLE (activation by host command)' db cr,lf,' Timeslice-release (OS/2, DV, Windows, def: enabled)' db cr,lf,' Underscore Color (same syntax as SET TERM COLOR)' db cr,lf,' Width 80 or 132 columns, if the adapter can do it' db cr,lf,' Video-change, enable or disable 132 column switching' db ' or restrict to DOS-only' db cr,lf,' Video-writing, Direct or via Bios$' clrhlp db ' one of the following:' db cr,lf,' AT #s (to set tabs at column #s) or' db ' AT start-column:spacing' db cr,lf,' Clear AT #s (clears individual tabs) or' db ' AT start-column:spacing' db cr,lf,' Clear ALL (to clear all tabstops)' clrhlp2 db cr,lf,' Ex: Set term tab at 10, 20, 34 sets tabs' db cr,lf,' Ex: Set term tab at 1:8 sets tabs at 1, 9,' db cr,lf,' Ex: Set term tab clear at 9, 17, 65 clears tabs' db cr,lf,' Ex: Set term tab clear at 1:8 clears tabs at 1, 9,' db ' 17,...$' colhlp db cr,lf,' Set Term Color value, value, value, ...' db cr,lf,' 0 no-snow mode on an IBM CGA and white on black' db cr,lf,' 1 for high intensity foreground' db cr,lf,' 10 for fast CGA screen updating (may cause snow)' db cr,lf,' 20 to restore normal colors after ESC [ 0 m' db cr,lf,' Foreground color (30-37) = 30 + sum of colors' db cr,lf,' Background color (40-47) = 40 + sum of colors' db cr,lf,' where colors are 1 = red, 2 = green, 4 = blue' db cr,lf,' Ex: 0, 1, 37, 44 IBM CGA(0), bright(1) white(37)' db ' chars on a blue(44) field' db cr,lf,' Attributes are applied in order of appearance.$' upsshlp db ' User Preferred Supplemental Set:' db cr,lf, 'DEC-MCS, Latin-1, Hebrew-7, Hebrew-ISO$' apchlp db cr,lf,'ON to allow APC cmd from host to invoke commands' db cr,lf,'OFF to prevent all use of APC from the host' db ' (default)' db cr,lf,'UNCHECKED to allow any command to be executed$' dnldhlp db cr,lf,'ON to act upon incoming Kermit file transfer packets' db cr,lf,'OFF to prevent that action. Default is off$' enqhlp db cr,lf,' ON to permit Answerback to Control-E Enquire request' db ' (default is OFF),' db cr,lf,' MESSAGE text to append local message to safe' db ' response prefix' db cr,lf,' UNSAFE-MESSAGE text to send message as-is, without' db ' prefix$' enqhlp2 db ' string to send$' expmhlp db cr,lf,' Use expanded or extended memory for screen rollback' db ' buffer,' db cr,lf,' OFF, EXPANDED, EXTENDED, or ON (try expanded first)$' ; structures below: byte cnt of combos, dw input combo list, db output list ; using DG International or Latin1 codes for output. grl1dgi db 48 ; case and order insensitive dw '++','AA','((','//','/<','^ ','(-','/^',')-','<<' dw '0^','* ','+-','>>','SS','/U','2^','3^','C/','C|' dw 'L-','L=','Y-','Y=','SO','S!','S0','XO','X0','A-' dw 'CO','C0','PP','P!','.^','O-','12','!!','??','T-' dw 'TM','FF','<=','>=',',-','""',2727h,'RO' grc1dgi db '#', '@', '[', '\', '\', '^', '{', '|', '}', 0b1h db 0bch,0bch,0b6h,0b0h,0fch,0a3h,0a4h,0a5h,0a7h,0a7h db 0a8h,0a8h,0b5h,0b5h,0bbh,0bbh,0bbh,0a6h,0a6h,0a9h db 0adh,0adh,0b2h,0b2h,0b9h,0aah,0a2h,0abh,0ach,0afh db 0b3h,0b4h,0b7h,0b8h,0a1h,0bdh,0beh, 0aeh grl1lat db 44 ; case and order insensitive dw '<<','0^','* ','+-','>>','SS','/U','2^','3^','C/' dw 'C|','L-','L=','Y-','Y=','SO','S!','S0','XO','X0' dw 'A-','CO','C0','PP','P!','.^','O-','12','!!','??' dw 'TM',',-','""',2727h,'RO','||','--','-^',',,','34' dw 'XX','-:','1^','14' grc1lat db 0abh,0b0h,0b0h,0b1h,0bbh,0dfh,0b5h,0b2h,0b3h,0a2h db 0a2h,0a3h,0a3h,0a5h,0a5h,0a7h,0a7h,0a7h,0a4h,0a4h db 0aah,0a9h,0a9h,0b6h,0b6h,0b7h,0bah,0bdh,0a1h,0bfh db 0aeh,0ach,0a8h,0b4h, 0aeh,0a6h,0adh,0afh,0b8h,0beh db 0d7h,0f7h,0b9h,0bch grl2dgi db 25 ; case sensitive, order insensitive dw '''A','`A','^A','"A','~A','*A','''E','`E','^E','"E' dw '''I','`I','^I','"I','~N','''O','`O','^O','"O','~O' dw '''U','`U','^U','"U','"Y' grc2dgi db 0c0h, 0c1h,0c2h,0c3h,0c4h,0c5h,0c8h, 0c9h,0cah,0cbh db 0cch, 0cdh,0ceh,0cfh,0d0h, 0d1h,0d2h,0d4h,0d6h,0d5h db 0dah, 0d9h,0dbh,0dch,0ddh grl2lat db 25 ; case sensitive, order insensitive dw '''A','`A','^A','"A','~A','*A','''E','`E','^E','"E' dw '''I','`I','^I','"I','~N','''O','`O','^O','"O','~O' dw '''U','`U','^U','"U','''Y' grc2lat db 0c1h, 0c0h,0c2h,0c4h,0c3h,0c5h,0c9h, 0c8h,0cah,0cbh db 0cdh, 0cch,0ceh,0cfh,0d1h, 0d3h,0d2h,0d4h,0d6h,0d5h db 0dah, 0d9h,0dbh,0dch,0ddh grl3dgi db 7 ; case and order sensitive dw 'EO','AE',',C','/O','ae',',c','/o' grc3dgi db 0d7h,0c6h,0c7h,0d6h,0e6h,0e7h,0f6h grl3lat db 10+2 ; case and order sensitive ; The last two, OE/oe dipthong, are for DEC MCS but added here for user help dw 'AE',',C','/O','HT','-D','ae',',c','/o','ht','-d' dw 'OE','oe' grc3lat db 0c6h,0c7h,0d8h,0deh,0d0h,0e6h,0e7h,0f8h,0feh,0f0h db 0d7h,0f7h ; CP852 Latin 2 codes in gr<1/2/3>lat2 grl1lat2 db 24 ; case and order insensitive db '%%','::','--','==',"''",'&&',',,','##','xx','..' db '++','AA','aa','((','//','/<','))','(-','/^',')-' db '^^','``','~~','""' grc1lat2 db 0a2h,0a8h,0adh,0b2h,0b4h,0b7h,0b8h,0bdh,0d7h,0ffh db '#','@','@','[','\','\',']','{','|','}' db '^','`','~','"' grl2lat2 db 83 ; case sensitive, order insensitive db 'A=','L/','L&',"S'",'S&','S,','T&',"Z'",'Z&','Z.' db 'a=','l/','l&',"s'",'s&','s,','t&',"z'",'z&','z.' db "R'","A'",'A^','A%','A"',"L'","C'",'C,','C&',"E'" db 'E=','E"','E&',"I'",'I^','D&','D-',"N'",'N&',"O'" db 'O^','O#','O"','R&','U*',"U'",'U#','U"',"Y'",'T,' db 'ss',"r'","a'",'a^','a%','a"',"I'","c'",'c,','c&' db "e'",'e=','e"','e&',"i'",'i^','d&','d-',"n'",'n&' db "o'",'o^','o#','o"','r&','u*',"u'",'u#','u"',"y'" db 't,',".'",',.' grc2lat2 db 0a1h,0a3h,0a5h,0a6h,0a9h,0aah,0abh,0ach,0aeh,0afh db 0b1h,0b3h,0b5h,0b6h,0b9h,0bah,0bbh,0bbh,0beh,0bfh db 0c0h,0c1h,0c2h,0c3h,0c4h,0c5h,0c6h,0c7h,0c8h,0c9h db 0cah,0cah,0cch,0d8h,0d9h,0dah,0dbh,0dch,0ddh,0deh db 0d4h,0d5h,0d6h,0fch,0deh,0e9h,0ebh,09ah,0edh,0ddh db 0dfh,0e0h,0e1h,0e2h,0e3h,0e4h,0e5h,0e6h,0e7h,0e8h db 0e9h,09ah,0ebh,0ech,0edh,0eeh,0efh,0f0h,0f1h,0f2h db 0f3h,0f4h,0f5h,0f6h,0f8h,0f9h,0fah,0fbh,0fch,0fdh db 0feh,"'", ',' grl3lat2 db 12 ; case and order sensitive db 'XO','X0','xo','x0','SO','S!','S0','so','s!','s0' db '0^','-:' grc3lat2 db 0a4h,0a4h,0a4h,0a4h,0a7h,0a7h,0a7h,0a7h,0a7h,0a7h db 0b0h,0f7h ;[HF] 941012 Double-byte katakana code table kanatbl dw 2121h, 2123h, 2156h, 2157h, 2122h, 2126h, 2572h, 2521h ;[HF] dw 2523h, 2525h, 2527h, 2529h, 2563h, 2565h, 2567h, 2543h ;[HF] dw 213ch, 2522h, 2524h, 2526h, 2528h, 252ah, 252bh, 252dh ;[HF] dw 252fh, 2531h, 2533h, 2535h, 2537h, 2539h, 253bh, 253dh ;[HF] dw 253fh, 2541h, 2544h, 2546h, 2548h, 254ah, 254bh, 254ch ;[HF] dw 254dh, 254eh, 254fh, 2552h, 2555h, 2558h, 255bh, 255eh ;[HF] dw 255fh, 2560h, 2561h, 2562h, 2564h, 2566h, 2568h, 2569h ;[HF] dw 256ah, 256bh, 256ch, 256dh, 256fh, 2573h, 212bh, 212ch ;[HF] data1 ends ; end of Terminal data set code1 segment extrn ans52t:far, vsinit:near ; in mszibm extrn anstty:near, ansini:near, ansrei:near ; in mszibm extrn anskbi:near, ansdsl:near, chrdef:near ; in mszibm extrn tabset:near, tabclr:near, dgnctoggle:far extrn toupr:far, domath:far, cboff:far, cbrestore:far assume cs:code1 fanskbi proc far call anskbi ; in mszibm ret fanskbi endp ftabset proc far call tabset ; in mszibm ret ftabset endp ftabclr proc far call tabclr ; in mszibm ret ftabclr endp fchrdef proc far call chrdef ret fchrdef endp code1 ends endif ; no_terminal ifndef no_graphics code2 segment extrn tekini:far, tekemu:far, tekend:far, tekrint:far ;in msgibm extrn ttxtchr:far, teksetcursor:far, tekremcursor:far extrn croshair:far, dgcrossrpt:far code2 ends endif ; no_graphics ifndef no_tcp _TEXT segment extrn ktcpcom:far _TEXT ends _DATA segment commbyte db 0 ; byte from msyibm to 3270 emulator _DATA ends endif ; no_tcp code1 segment extrn strlen:far, strcpy:far, strcat:far, isfile:far extrn dec2di:far assume cs:code1 code1 ends code segment extrn prtchr:near, outchr:near, pcwait:far extrn clrmod:near, putmod:near, cmblnk:near, cptchr:near extrn telnet:near, srchkww:near, jpnftox:near extrn srchkb:near, srchkw:near, pasz:near extrn prompt:near, comnd:near, statc:near, replay:near extrn crun:near, serini:near, spath:near extrn prttab:near, ctlu:near extrn pntchr:near, pntflsh:near, serrst:near ifndef no_graphics extrn tekgcptr:near, tekdmp:near endif ; no_graphics ifndef no_network extrn ubclose:near endif ; no_network ifndef no_tcp extrn tcpstart:near, winupdate:far endif ; no_tcp ifndef no_terminal extrn takopen_macro:far extrn msuinit:near, keybd:near, kbhold:near ; in msuibm endif ; no_terminal assume cs:code, ds:data, es:nothing ifdef no_terminal ; do initialization local to this module ; Dynamically allocates 4000 bytes for screen save/restore buffer plus ; 320 to 38400 bytes for screen scroll back buffers. Tries to leave space ; for Command.com before enlarging buffers. lclyini proc near call far ptr flclyini ; far call specifics ret lclyini endp ; begin Terminal set & status code ; SET Term parameters, especially for use with VT100 emulator. ; VTS is called only by mssset to set terminal type and characteristics. ; Exit carry set for failure. VTS proc near ; SET TERM whatever mov ah,cmeol ; Clear-screen call comnd ret VTS endp ; end of Set Term things ; Terminal Status display, called within STAT0: in MSSSET VTSTAT proc near ; enter with di within sttbuf, save bx jmp statc ; status common code, in mssset vtstat endp trnmod proc near ret trnmod endp ; Screen dump entry from keyboad xlat dmpscn proc near ; dump screen to file stc ret dmpscn endp endif ; no_terminal ifndef no_terminal ; do initialization local to this module ; Dynamically allocates 4000 bytes for screen save/restore buffer plus ; 320 to 38400 bytes for screen scroll back buffers. Tries to leave space ; for Command.com before enlarging buffers. lclyini proc near call msuinit ; initialize keyboard module msuxxx call far ptr flclyini ; far call specifics ret lclyini endp ; begin Terminal set & status code ; SET Term parameters, especially for use with VT100 emulator. ; VTS is called only by mssset to set terminal type and characteristics. ; Exit carry set for failure. VTS proc near ; SET TERM whatever mov kstatus,kssuc ; success mov ah,cmkey ; Parse another keyword mov bx,offset vthlp ; Use this help mov dx,offset vttbl ; Use this table call comnd jnc vset1 ; nc = success ret ; failure vset1: call bx ; dispatch to processing routine ret vtcls: mov ah,cmeol ; Clear-screen call comnd jc vtclsx ; c = failure mov vtclear,2 ; set trigger for emulator clear scn clc ; success vtclsx: ret vtclock:mov ah,cmkey ; SET TERM CLOCK {ON | OFF | ELAPSED} xor bx,bx mov dx,offset clktab call comnd jnc vtclo1 ret vtclo1: mov vtclkflg,bl ; status line clock flag ret vterase:mov ah,cmkey ; SET TERM ERASE xor bx,bx ; table is help mov dx,offset erasetb ; use this table call comnd jc vterasex ; c = failure mov vtclrflg,bl vterasex:ret ; SET TERM kind vttyp0: mov bx,ttgenrc ; NONE jmp vsett1 vttyp1: mov bx,ttheath ; Heath-19 jmp vsett1 vttyp2: mov bx,ttvt52 ; VT52 jmp vsett1 vttyp4: mov bx,ttvt100 ; VT100 jmp vsett1 vttyp8: mov bx,ttvt102 ; VT102 jmp vsett1 vttyp10:mov bx,ttvt220 ; VT220 jmp vsett1 vttyp20:mov bx,ttvt320 ; VT320 jmp vsett1 vttyp40:mov bx,tttek ; Tek jmp vsett1 vttyp80:mov bx,tthoney ; Honeywell VIP7809 jmp vsett1 vttyp100:mov bx,ttpt200 ; Prime PT200 jmp short vsett1 vttyp200:mov bx,ttd463 ; Data General D463 jmp short vsett1 vttyp400:mov bx,ttd470 ; Data General D470 jmp short vsett1 vttyp800:mov bx,ttwyse ; Wyse-50 jmp short vsett1 vttyp1000:mov bx,ttd217 ; Data General D217 jmp short vsett1 vttyp2000:mov bx,ttansi ; Ansi-BBS call ansi_save ; save settings jmp short vsett1 vttype: mov ah,cmkey ; SET TERM TYPE xor bx,bx ; table is help mov dx,offset termtb ; use this table call comnd jnc vsett1 ; nc = success ret ; failure vsett1: mov temp,bx ; save terminal type mov vtemu.vtchop,-1 ; say reinit char tables mov temp2,-1 ; assume no enable/disable Tek cmp bx,ttansi ; going to be ANSI? je vsett1a ; e = yes cmp vtsave,0 ; VT save area in use? je vsett1a ; e = no mov ax,word ptr vtsave+1 ; get saved video and char set mov vtemu.vtchset,al ; restore current char set mov si,vtemu.att_ptr ; pointer to attributes mov [si],ah ; restore current screen coloring mov ax,word ptr vtsave+3 mov reset_color,al ; this too mov savattr,ah mov ax,word ptr vtsave+5 mov vtcpage,ax ; restore terminal Code Page mov vtclear,1 ; signal color change mov vtsave,0 ; save area is free vsett1a:cmp bx,tttek ; set term tek? jne vsett2 ; ne = no mov dx,offset disatab ; disable/enable keyword table xor bx,bx ; help is the table mov comand.cmcr,1 ; allow bare CR's mov ah,cmkey ; get enable/disable keyword call comnd mov comand.cmcr,0 ; no more bare CR's jc vsett2 ; c = no such keyword ifndef no_graphics mov temp2,bx ; save enable/disable keyword value mov bx,flags.vtflg ; get current terminal type mov temp,bx ; and force it here endif ; no_graphics vsett2: mov ah,cmeol call comnd ; get a confirm jc vsettx ; c = failure vsett3: mov bx,temp mov flags.vtflg,bx ; Set the terminal emulation type call ansi_save ; save if going to ANSI mov tekflg,0 ; clear graphics mode or vtemu.vtflgst,vscompress+vshscroll ; set compress to text-132 or vtemu.vtflgop,vscompress+vshscroll ; and horz scroll to manual cmp bx,tttek ; adjusting Tek? je vsett4 ; e = yes test bx,ttd463+ttd470+ttd217 ; DG D463/470/217? jz vsett6 ; z = no and vtemu.vtflgst,not (vshscroll) ; comp = graphics, and vtemu.vtflgop,not (vshscroll) ; horz scroll = auto vsett6: cmp temp2,-1 ; just enable/disable tek? je vsett5 ; e = no vsett4: ifndef no_graphics and denyflg,not tekxflg ; enable Tek cmp temp2,1 ; ought we disable? jne vsett5 ; ne = no endif ; no_graphics or denyflg,tekxflg ; disable Tek vsett5: call fchrdef ; make tables in mszibm.asm clc ; success vsettx: ret ; save coloring and character set around ANSI terminal type, worker ansi_save proc near cmp flags.vtflg,ttansi ; are we ANSI now? jne ansi_savex ; ne = no cmp vtsave,0 ; save area in use? jne ansi_savex ; ne = yes mov vtsave,1 ; state that save area is in use mov al,vtemu.vtchset ; get current char set mov si,vtemu.att_ptr ; pointer to attributes mov ah,[si] ; get current screen coloring mov word ptr vtsave+1,ax ; save them mov al,reset_color ; this too mov ah,savattr mov word ptr vtsave+3,ax mov ax,437 ; forced codepage is 437 xchg ax,vtcpage ; get old CP mov word ptr vtsave+5,ax ; save old CP mov reset_color,1 ; reset colors with CSI m mov byte ptr [si],07h ; dim white on black mov savattr,07h mov vtclear,1 ; signal color change mov vtemu.vtchset,15 ; Transparent char set or flags.remflg,d8bit ; set 8-bit display ansi_savex: ret ansi_save endp vtchar: mov ah,cmkey ; Set Term character set xor bx,bx ; character set table for help mov temp,bx ; counter of trailing items mov dx,offset chatab ; character set table call comnd jc vtcharx ; c = failure call chkcp866 ; check on CP866 requirements mov decbuf,bl ; save here mov ax,word ptr vtemu.vttable ; table of 4 overrides now mov word ptr decbuf+1,ax ; copy them to temporary table mov ax,word ptr vtemu.vttable+2 mov word ptr decbuf+3,ax vtchar1:mov comand.cmcr,1 ; allow bare CR's mov ah,cmkey xor bx,bx mov dx,offset sidetab ; read Gnumber item, if any call comnd mov comand.cmcr,0 ; no bare CR's jc vtchar2 ; c = no match, get confirm inc temp ; say have a trailing table number and bx,3 ; remove ASCII value encoding add bx,offset decbuf+1 ; address of slot to store info mov al,decbuf ; set ident mov [bx],al ; store table ident in G0..G3 slot jmp short vtchar1 ; repeat ; vtemu.vtchset: changed to new set if no table trailers, else intact ; vtemu.vttable db 4 dup(0ffh) char set numbers for G0..G3 as overrides, ; use 0ffh to mean no override for table Gn vtchar2:mov ah,cmeol ; get EOL confirmation call comnd jc vtcharx ; c = failure, quit mov vtemu.vtchop,-1 ; say reinit char tables cmp temp,0 ; trailers (skip regular setup)? jne vtchar3 ; ne = yes mov al,decbuf ; get character set mov vtemu.vtchset,al ; set default character set clc ret ; just overrides vtchar3:mov ax,word ptr decbuf+1 ; first pair of char set idents mov word ptr vtemu.vttable,ax mov ax,word ptr decbuf+3 ; second pair mov word ptr vtemu.vttable+2,ax clc vtcharx:ret vtshift:mov ah,cmkey ; Set Term Output-shift auto, none xor bx,bx mov dx,offset shifttab call comnd jc vtshifx ;[HF] c = failed cmp bl,(128+1) ;[HF] JIS7-Kanji ? jne vtshif3 ;[HF] ne = no mov temp2,bx ; save shift from above mov temp,'BB' ;[HF] set default mov comand.cmcr,1 ;[HF] allow bare CR mov ah,cmkey ;[HF] get Roman/ASCII set xor bx,bx ;[HF] mov dx,offset jis7tab ;[HF] call comnd ;[HF] jc vtshif2 ;[HF] get confirm mov temp,bx ;[HF] set value vtshif2:mov ah,cmeol ;[HF] get confirm call comnd ;[HF] jc vtshifx ;[HF] mov bx,temp ;[HF] restore value mov word ptr jis7des,bx ;[HF] set it mov bx,temp2 ; initial shift mov flags.oshift,bl ; shift clc ;[HF] ret vtshif3:push bx mov ah,cmeol call comnd pop bx jc vtshifx mov flags.oshift,bl ; shift clc vtshifx:ret vtrollbk:mov ah,cmkey ; Set Term Roll On/Off, auto roll back xor bx,bx ; Use on/off table as help mov dx,offset ontab ; Use on/off table call comnd jc vtrollx ; c = failure push bx mov ah,cmeol ; get a confirm call comnd pop bx jc vtrollx ; c = failure mov vtroll,bl ; set roll state (0=no auto rollback) clc vtrollx:ret ; Set Term Color foreground, background vtcolor:mov bx,vtemu.att_ptr ; get address of attributes byte mov bl,[bx] ; get attributes mov decbuf,bl ; save in work temp mov al,vtclear ; screen clear state mov ah,refresh ; refresh state mov word ptr decbuf+1,ax ; save here mov al,reset_color ; reset color state mov decbuf+3,al call vsetcol ; get and analyze colors jc vtcolo1 ; c = failure mov al,decbuf ; get current attributes mov bx,vtemu.att_ptr ; get address of attributes byte mov [bx],al ; store attributes mov savattr,al ; saved emulator attributes and al,att_bold ; pick up userbold preference mov userbold,al mov ax,word ptr decbuf+1 mov vtclear,al ; update these items mov refresh,ah mov al,decbuf+3 mov reset_color,al ; reset color state clc vtcolo1:ret ; setup color information vsetcol:mov ah,cmword ; get number(s) after set term color mov dx,offset colhlp ; use this help mov bx,offset rdbuf ; temp buffer mov comand.cmcr,1 ; allow bare c/r's mov comand.cmcomma,1 ; commas are equivalent to spaces call comnd jc vsetco2 ; c = failure or ax,ax ; text given? jz vsetco1 ; z = no mov si,offset rdbuf ; si = string call vsetco3 ; analyze jmp short vsetcol ; get more data vsetco1:mov ah,cmeol ; get end of line confirm call comnd vsetco2:ret ; c set if failure vsetco3:mov dx,si call strlen ; get string count mov domath_ptr,si mov domath_cnt,cx call domath mov si,domath_ptr ; where to read next string byte cmp domath_cnt,0 jne vsetco1 ; ne = did not convert whole string or ax,ax ; reset all? regular IBM CGA refresh jnz vsetco4 ; nz = no mov word ptr decbuf+2,0 ; slow screen refresh, no reset color mov decbuf,07h ; clear all, set white on black mov decbuf+1,2 ; set trigger for emulator clear scrn jmp short vsetcol vsetco4:cmp ax,1 ; high intensity? jne vsetco5 ; e = no or decbuf,08h ; set high intensity mov decbuf+1,1 ; set trigger for emulator keep screen jmp short vsetcol vsetco5:cmp ax,10 ; fast refresh? jne vsetco5a ; ne = no mov decbuf+2,1 ; Fast screen refresh jmp short vsetcol vsetco5a:cmp ax,20 ; reset color upon CSI m? jne vsetco6 ; ne = no mov decbuf+3,1 ; reset color state is yes jmp vsetcol vsetco6:cmp ax,30 ; check range jb vsetco8 ; b = too small, complain cmp ax,37 ja vsetco7 ; 30-37 is foreground color sub al,30 ; remove foreground bias and decbuf,not 07H ; clear foreground bits mov bx,ax mov al,colortb[bx] ; get reversed bit pattern or decbuf,al ; load new bits mov decbuf+1,2 ; set trigger for emulator clear scn jmp vsetcol vsetco7:cmp ax,40 jb vsetco8 ; b = bad value cmp ax,47 ; compare as unsigned ja vsetco8 ; 40-47 is background sub al,40 ; remove background bias and decbuf,not 70H ; clear background bits mov bx,ax mov al,colortb[bx] ; get reversed bit pattern mov cl,4 ; rotate 4 positions rol al,cl or decbuf,al ; load new bits mov decbuf+1,2 ; set trigger for emulator clear scn jmp vsetcol vsetco8:mov ah,prstr ; not in range - complain and exit mov dx,offset colerr int dos mov kstatus,ksgen ; general failure stc ; error ret vtucolor:mov al,vtclear ; screen clear state mov ah,refresh ; refresh state mov word ptr decbuf+1,ax ; save here mov al,scbattr mov decbuf,al call vsetcol ; get and analyze colors jc vtucol1 ; c = failure mov al,decbuf ; get current attributes mov colunder,al ; saved underlined color mov ax,word ptr decbuf+1 mov vtclear,al ; update these items mov refresh,ah clc vtucol1:ret ifndef no_graphics vtgraph:mov ah,cmkey ; Set Term graphics xor bx,bx ; Use graphics table as help mov dx,offset graftab ; Use graphics table call comnd jc vtgrapx ; c = failure cmp bx,100h ; in the special options area? ja vtgrap1 ; a = yes push bx mov ah,cmeol ; get a confirm call comnd pop bx jc vtgrapx ; c = failure mov tekgraf,bl ; set Tek graphics board type clc vtgrapx:ret vtgrap1:cmp bx,101h ; character writing? jne vtgrap2 ; ne = no mov ah,cmkey ; Set Term graphics char-writing xor bx,bx ; no help mov dx,offset gchrtab ; opaque/transparent table call comnd jc vtgrapx ; c = failure push bx mov ah,cmeol ; get a confirm call comnd pop bx jc vtgrapx mov chcontrol,bl ; set/reset opaque char control clc ret vtgrap2:cmp bx,102h ; cursor on/off? jne vtgrap4 ; ne = no mov ah,cmkey ; Set Term graphics cursor on/off xor bx,bx ; no help mov dx,offset ontab ; on/off table call comnd jc vtgrapx ; c = failure push bx mov ah,cmeol ; get a confirm call comnd pop bx jc vtgrapx mov tekcursor,bl ; set Tek text cursor on/off clc ret vtgrap4:cmp bx,103h ; Color? jne vtgrap6 ; ne = no call tekgcptr ; get pointer to active Tek color pal mov al,[bx] ; get background attributes and al,7 ; discard intensity bit mov cl,4 shl al,cl mov ah,[bx+7] ; get foreground attributes or al,ah mov decbuf,al ; setup work temp for vsetcol push bx ; save index call vsetcol ; get and analyze colors pop bx jnc vtgrap5 ; nc = ok ret vtgrap5:mov al,decbuf ; get current attributes mov ah,al ; get background bits mov cl,4 shr ah,cl ; just background here and al,0fh ; just foreground here mov [bx],ah ; store colpal[0] as background mov [bx+7],al ; store colpal[7] as foreground clc ; success vtgrap6:ret endif ; no_graphics vtbeep: mov ah,cmkey ; SET TERM BELL xor bx,bx ; use table as help mov dx,offset beltab ; use Bell table call comnd jc vtbeepx ; c = failure push bx mov ah,cmeol ; get a confirm call comnd pop bx jc vtbeepx ; c = failure mov belltype,bl ; set bell type vtbeepx:ret ; return carry clear or set ; SET TERM BYTESIZE {7-bit | 8-bit} vtbyte: mov ah,cmkey ; SET TERM DISPLAY {7-bit | 8-bit} mov dx,offset distab ; table xor bx,bx ; help is table call comnd jc vtbytex ; c = failure push bx mov ah,cmeol ; get a confirm call comnd pop bx jc vtbytex ; c = failure and flags.remflg,not d8bit ; clear display 8-bit bit or flags.remflg,bl ; set or clear the bit vtbytex:ret vtupss: mov ah,cmkey ; SET TERM UPSS mov bx,offset upsshlp ; help mov dx,offset upsstab ; UPSS table call comnd ; get UPSS char set jc vtupssx ; failure push bx mov ah,cmeol call comnd pop bx jc vtupssx ; c = fail mov al,96 ; assume 96 byte set or bh,bh ; one byte set identifier? jz vtupss1 ; z = yes mov al,94 ; a 94 byte set vtupss1:mov upss,al ; set length mov word ptr upss+1,bx ; store set ident mov vtemu.vtchop,-1 ; clear operational char set to reinit clc vtupssx:ret ; SET TERM RESET termreset:mov vtinited,0 ; say uninitialized clc ret apcctl: cmp apctrap,0 ; doing within an APC-macro? jne apcctl1 ; ne = yes, don't do it mov ah,cmkey ; SET TERM APC-macro enable, disable mov bx,offset apchlp ; help mov dx,offset apctab ; APC table call comnd jc apcctl1 ; failure push bx mov ah,cmeol call comnd pop bx jc apcctl1 ; c = fail mov apcenable,bl ; enable flag clc apcctl1:ret vtdownld:mov ah,cmkey ; AUTODOWNLOAD {ON, OFF} mov bx,offset dnldhlp mov dx,offset ontab call comnd jc vtdownldx mov vtemu.vtdnld,bl ; status clc vtdownldx:ret vtenqctl:mov ah,cmkey ; SET TERM Answerback {ON, OFF} mov bx,offset enqhlp ; help mov dx,offset enqtab ; on/off/message table call comnd jc vtenqctl1 ; failure cmp bl,2 ; message? je vtenqctl1 ; e = yes cmp bl,3 ; unsafe-message? je vtenqctl1 ; e = yes push bx ; else 0=off, 1=on mov ah,cmeol call comnd pop bx jc vtenqctlx ; c = fail mov vtenqenable,bl ; enable (1) flag clc ret vtenqctl1: mov enqbuf,0 ; presume save message cmp bl,3 ; unsafe? jne vtenqctl2 ; ne = no mov enqbuf,1 ; say unsafe vtenqctl2: mov dx,offset enqhlp2 ; help mov comand.cmdonum,1 ; \number conversion allowed mov comand.cmblen,length enqbuf-1 ; length of analysis buffer mov bx,offset rdbuf ; temp response buffer mov ah,cmline call comnd jc vtenqctlx ; c = failure mov si,offset rdbuf ; temp response buffer mov di,offset enqbuf+1 ; enquire response buffer call strcpy ; copy string, asciiz clc vtenqctlx:ret scrwrite:mov ah,cmkey ; SET TERM SCREEN-WRITING xor bx,bx ; help mov dx,offset writetab ; screen table call comnd jc scrwritx ; failure push bx mov ah,cmeol call comnd pop bx jc vtupssx ; c = fail mov writemode,bl ; store writing mode clc scrwritx:ret scrchange:mov ah,cmkey ; SET TERM VIDEO-CHANGE xor bx,bx ; help mov dx,offset vchgtab ; enable/disable/dos-only call comnd jc scrchangex ; failure push bx mov ah,cmeol call comnd pop bx jc scrchangex ; c = fail mov vchgmode,bl ; store video-change mode clc scrchangex:ret expmemory:mov ah,cmkey ; EXPANDED-MEMORY {OFF, EXTENDED, EXP} mov bx,offset expmhlp ; help mov dx,offset emmtab ; emm choice table call comnd jc expmem2 ; failure push bx mov ah,cmeol call comnd pop bx jc expmem2 ; c = fail cmp useexp,bl ; changing kinds? je expmem1 ; e = no mov vsbuff_inited,0 ; say reinitialize buffer memory mov useexp,bl ; enable (1) flag expmem1:clc expmem2:ret vtcodepage:mov ah,cmkey ; SET TERM CODE-PAGE xor bx,bx ; help mov dx,offset setchtab ; Code Page table call comnd jc vtcode1 ; failure push bx mov ah,cmeol call comnd pop bx jc vtcode1 ; c = fail mov vtcpage,bx ; new terminal Code Page mov vtemu.vtchop,-1 ; force change of working set clc vtcode1:ret vtcpu: mov ah,cmkey ; SET TERM Timeslice-release xor bx,bx ; help mov dx,offset disatab ; enable/disable call comnd jc vtcpux ; failure push bx mov ah,cmeol call comnd pop bx jc vtcpux ; c = fail mov vtcpumode,bl ; store timeslice release mode clc vtcpux: ret vtcrdisp:mov ah,cmkey xor bx,bx mov dx,offset crdisptab ; table call comnd jc vtcrdispx push bx mov ah,cmeol call comnd pop bx jc vtcrdispx mov crdisp_mode,bl clc vtcrdispx:ret termesc:mov ah,cmkey ; SET TERM ESCAPE xor bx,bx mov dx,offset termesctab ; table call comnd jc termescx push bx mov ah,cmeol pop bx jc termescx mov termesc_flag,bl clc termescx:ret ; SET Term flags. These are the (near) equivalent of VT100 Setup mode values. flg1: mov ax,vsnewline ; NEWLINE mov dx,offset ontab jmp short flgset flg2: mov ax,vswrap ; WRAP mov dx,offset ontab jmp short flgset flg4: mov ax,vswdir ; DIRECTION mov dx,offset dirtab jmp short flgset flg5: mov ax,vskeyclick ; KEYCLICK mov dx,offset ontab jmp short flgset flg6: mov ax,vsmarginbell ; MARGIN BELL mov dx,offset ontab jmp short flgset flg7: mov ax,vscursor ; CURSOR mov dx,offset curtab jmp short flgset flg8: mov ax,vsscreen ; SCREEN mov dx,offset scrtab jmp short flgset flg9: mov ax,vscntl ; CONTROLS mov dx,offset cntltab jmp short flgset flg10: mov ax,deckpam ; KEYPAD mov dx,offset kpamtab jmp short flgset flg11: mov ax,decckm ; ARROW mov dx,offset arrtab jmp short flgset flg12: mov ax,deccol ; WIDTH mov dx,offset widtab jmp short flgset flg13: mov ax,vshscroll ; Horizontal scrolling mov dx,offset hstab jmp short flgset flg14: mov ax,vscompress ; compressed text display mov dx,offset cmptab ;; jmp short flgset flgset: push ax ; save flag mov ah,cmkey ; another keyword xor bx,bx ; use default help, dx has table ptr call comnd pop ax ; recover index jc flgse0 ; c = failure push ax push bx ; save result of keyword mov ah,cmeol ; get confirm call comnd pop bx pop ax ; recover flag jc flgse0 ; c = failure or bx,bx ; set or clear? jz flgse1 ; z = clear it or vtemu.vtflgst,ax ; set the flag or vtemu.vtflgop,ax ; in runtime flags too flgse3: test ax,deccol ; modifying screen width? jz flgse2 ; z = no mov al,crt_cols ; current width mov dos_cols,al ; width to remember, for changes flgse2: clc ; success flgse0: ret flgse1: not ax ; Complement and vtemu.vtflgst,ax ; clear the indicated setup flag and vtemu.vtflgop,ax ; clear the indicated runtime flag not ax jmp short flgse3 ; test for screen change ; SET Term Tabstops Clear ALL ; SET Term Tabstops Clear AT n1, n2, ..., nx ; SET Term Tabstops At n1, n2, ..., nx tabmod: mov ah,cmkey ; parse keyword mov bx,offset clrhlp ; help text mov dx,offset tabtab ; table call comnd jc tabmo2 ; c = failure mov clrset,2 ; 2 = code for set a tab or bl,bl ; clear? jnz tabmo4 ; nz = no, SET. parse column number(s) mov clrset,1 ; code for clear at/all tab(s) mov ah,cmkey ; CLEAR, parse ALL or AT mov bx,offset clrhlp ; help text mov dx,offset alltab ; parse ALL or AT call comnd jc tabmo2 ; c = failure or bx,bx ; ALL? jnz tabmo4 ; nz = AT, clear at specific places mov ah,cmeol ; confirm the ALL call comnd jc tabmo2 ; c = failure mov cx,vswidth ; ALL, means clear all tab stops tabmo1: mov dx,cx dec dl ; column number, starting with 0 mov si,vtemu.vttbs ; the cold-start buffer call ftabclr ; clear the tab loop tabmo1 ; do all columns mov si,vtemu.vttbs mov di,vtemu.vttbst ; and active buffer call tabcpy ; update active tabs clc ; success tabmo2: ret ; a success/fail return point tabmo4: mov si,vtemu.vttbs ; from the cold-start buffer mov di,offset decbuf ; temp work buffer call tabcpy ; make a working copy of the tabs mov skip,0 ; clear spacing-active flag mov temp,0 ; place where last tab was written tabmo6: mov dx,offset clrhlp2 ; tell them we want a column number mov ah,cmword ; get line of text mov bx,offset rdbuf ; temp buffer mov comand.cmcomma,1 ; commas are equivalent to spaces call comnd jc tabmo2 ; c = failure or ax,ax ; anything given? jnz tabmo7 ; nz = yes mov ah,cmeol ; confirm end of line call comnd jc tabmo2 ; failure mov si,offset decbuf ; copy tabs from temp work buffer mov di,vtemu.vttbs ; to the cold-start buffer call tabcpy ; copy work to cold start mov di,vtemu.vttbst ; and terminal emulator's active buf call tabcpy clc ret tbsbad: mov ah,prstr ; not in range - complain mov dx,offset tbserr int dos stc ret tabmo7: mov si,offset rdbuf ; si = string tabmo8: mov dx,si call strlen ; get length of this word jcxz tabmo6 ; empty, get more user input mov domath_ptr,si ; try for expression mov domath_cnt,cx mov domath_msg,1 ; do not complain call domath mov si,domath_ptr ; where to read next string byte jnc tabmo9 ; got a value cmp byte ptr [si],',' ; comma syntax? jne tabmo8a ; ne = no inc si ; skip the comma and try next field jmp short tabmo8 tabmo8a:cmp byte ptr [si],':' ; spacing separator? jne tbsbad ; ne = no, no number available inc si ; skip colon, do start:space analysis inc skip ; set spacing-active flag jmp short tabmo8 ; get another token tabmo9: cmp skip,0 ; want spacing value now? jne tabmo11 ; ne = yes, go do it mov dx,ax ; column (1-vswidth style) dec dx ; put column in range 0-131 or dx,dx ; check range (1-vswidth-->0-...) js tbsbad ; s = too small. complain cmp dl,vswidth-1 ; more than the right most column? ja tbsbad ; a = yes, quit mov temp,dx ; remember last written position jmp tabmo15 ; and write this member tabmo11:mov dx,temp ; continue spacing analysis mov skip,0 ; clear spacing-active flag mov cx,ax ; "space" value or cx,cx ; zero spacing? jnz tabmo12 ; nz = no inc cx ; don't get caught with zero spacing tabmo12:cmp dx,vswidth-1 ; largest tab stop ja tabmo8 ; a = done largest tab stop mov temp,dx ; remember last written tabstop push si mov si,offset decbuf ; the work buffer cmp clrset,2 ; set? jne tabmo13 ; ne = no, clear call ftabset ; set tabstop in column DL jmp short tabmo14 tabmo13:call ftabclr ; clear tabstop in column DL tabmo14:add dx,cx ; new column value pop si jmp short tabmo12 ; finish spacing loop tabmo15:push si ; individual tabstop mov si,offset decbuf ; the work buffer cmp clrset,2 ; set? jne tabmo16 ; ne = no, clear call ftabset ; set tabstop in column DL jmp short tabmo17 ; get next command value tabmo16:call ftabclr ; clear tabstop in column DL tabmo17:pop si jmp tabmo8 ; get next command value VTS endp ; end of Set Term things ; Terminal Status display, called within STAT0: in MSSSET VTSTAT proc near ; enter with di within sttbuf, save bx mov bx,offset vtstbl ; table of things to show jmp statc ; status common code, in mssset vtstat endp txtcolstat proc near ; text color status report push si mov si,offset txtcolst1 mov bx,vtemu.att_ptr ; pointer to attributes byte call colstd ; report worker mov si,offset colst3 txtcols1:lodsb cmp al,'$' je txtcols2 stosb jmp short txtcols1 txtcols2:mov al,reset_color or al,al ; resetting color after CSI [ m? jz txtcols3 ; z = no mov al,'2' ; show as "20" stosb txtcols3:mov al,'0' stosb pop si ret txtcolstat endp undcolstat proc near ; underline color status report push si mov si,offset undcolst1 mov bx,offset colunder ; pointer to attributes byte call colstd ; report worker pop si ret undcolstat endp ifndef no_graphics grcolstat proc near ; graphics color status report push si mov si,offset grcolst1 call tekgcptr ; get pointer to active Tek color pal call colstd ; report worker pop si ret grcolstat endp endif ; no_graphics ; enter with offset of initial msg in si and ptr to color codes in bx colstd proc near ; worker for color status reports cld colstd1:lodsb cmp al,'$' ; end of string? je colstd2 ; e = yes stosb jmp short colstd1 colstd2:mov bl,byte ptr[bx] ; attributes xor bh,bh push bx and bx,7 ; get foreground set mov al,colortb[bx] ; get reversed bit pattern add al,'0' ; add ascii bias stosb pop bx mov si,offset colst2 colstd3:lodsb cmp al,'$' je colstd4 stosb jmp short colstd3 colstd4:mov cl,4 ; rotate 4 positions shr bl,cl and bx,7 ; get background set mov al,colortb[bx] ; get reversed bit pattern add al,'0' ; add ascii bias stosb ret colstd endp tabstat proc near ; worker,display tabs ruler for Status push dx cld mov al,cr stosb cmp cl,10 ; are we on a new line? jb tabsta0 ; b = no, do a lf now mov al,lf stosb tabsta0:xor cl,cl ; column index xor ax,ax ; ah = tens, al = units counter tabsta1:mov dl,'.' ; default position symbol inc al cmp al,10 ; time to roll over? jb tabsta2 ; b = not yet xor al,al ; modulo 10 inc ah mov dl,ah ; display a tens-digit add dl,'0' cmp dl,'9' ; larger than 90? jbe tabsta2 ; be = no sub dl,10 ; roll over to 0, 1, etc tabsta2:push dx push si mov dl,cl ; column number, counted from 0 mov si,vtemu.vttbst ; the active buffer call istabs ; is tab set here? pop si pop dx jnc tabsta3 ; nc = no mov dl,'T' ; yes, display a 'T' tabsta3:push ax mov al,dl stosb pop ax inc cl cmp cl,byte ptr low_rgt ; done yet? jb tabsta1 ; b = not yet pop dx ret tabstat endp ; Returns carry set if column in DL is a tab stop, else carry clear. ; Enter with column number in DL (starts at column 0, max of vswidth-1) ; and tabstop buffer offset in SI. istabs proc near push bx push cx mov cl,dl ; column number (0 to swidth-1) and cl,00000111b ; keep bit in byte (0-7) inc cl ; map to 1-8 mov bl,dl ; column shr bl,1 ; bl / 8 to get byte shr bl,1 shr bl,1 xor bh,bh ; clear high byte mov bl,[si+bx] ; get a byte of tab bits ror bl,cl ; rotate to put tab-set bit into carry pop cx pop bx ret istabs endp ansbkstat proc near mov ax,di ; starting place push ax mov si,offset vtenqst2 mov cx,vtenqst2_len cld rep movsb mov si,offset enqbuf+1 ; skip safe/unsafe byte mov dx,si call strlen ; append local string rep movsb pop ax mov cx,di sub cx,ax ; return space used ret ansbkstat endp filler proc near ; use space mov cx,20 mov al,' ' cld rep stosb ret filler endp ; Jump here to exit Connect mode and execute macros 'KEYBOARDR' (vtkrmac) or ; 'KEYBOARDS' (vtksmac). Does nothing if macro does not exist. ; Preserves registers except ax. Returns to TELNET caller with 'C' in kbdflg. vtkrmac proc near ; RESET macro mov vtmacname,offset vtkrname ; select macro name mov vtmaclen,vtkrlen ; and its length call dword ptr vtmacroptr ; FAR pointer, finish in common code jc vtkrmac1 ; c = failure jmp far ptr endcon ; end connect mode, do macro vtkrmac1:ret vtkrmac endp vtksmac proc near ; SET macro mov vtmacname,offset vtksname mov vtmaclen,vtkslen call dword ptr vtmacroptr ; FAR pointer jc vtksmac1 ; c = failure jmp far ptr endcon ; end connect mode, do macro vtksmac1:ret vtksmac 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 call dword ptr vtmacroptr ; FAR pointer jc extmac1 ; c = failure jmp far ptr endcon ; end connect mode, do macro extmac1:mov kbdflg,' ' ; report ' ' to TERM's caller ret ; to resume Connect mode extmacro endp ; Invokes macro PRODUCT with variables \%1..\%9 ; defined as the ascii renditions of the control sequence numeric paramters ; param[0]..param[8], and sets script ARGC item to one greater than this. product proc near call far ptr prodwork ; FAR pointer jc prodmac1 ; c = failure jmp far ptr endcon ; end connect mode, do macro prodmac1:ret product endp term proc near call far ptr fterm ret term endp fclrmod proc far call clrmod ret fclrmod endp fputmod proc far call putmod ret fputmod endp fcmblnk proc far call cmblnk ret fcmblnk endp fkbhold proc far call kbhold ret fkbhold endp fprtchr proc far call prtchr ret fprtchr endp fkeybd proc far call keybd ret fkeybd endp fpntflsh proc far call pntflsh ret fpntflsh endp fpntchr proc far call pntchr ret fpntchr endp foutchr proc far call outchr ret foutchr endp fspath proc far call spath ret fspath endp fcrun proc far call crun ret fcrun endp fserini proc far call serini ret fserini endp fctlu proc far ; [HF]940211 call ctlu ; [HF]940211 ret ; [HF]940211 fctlu endp ; [HF]940211 vtinit proc near call fvtinit ret vtinit endp rtone proc near call frtone ret rtone endp rtpage proc near call frtpage ret rtpage endp lfone proc near call flfone ret lfone endp lfpage proc near call flfpage ret lfpage endp homwnd proc near call fhomwnd ret homwnd endp endwnd proc near call fendwnd ret endwnd endp dnwpg proc near call fdnwpg ret dnwpg endp dnone proc near call fdnone ret dnone endp upwpg proc near call fupwpg ret upwpg endp upone proc near call fupone ret upone endp fcptchr proc far call cptchr ret fcptchr endp fserrst proc far call serrst ret fserrst endp ifndef no_network fubclose proc far call ubclose ret fubclose endp endif ; no_network endif ; no_terminal code ends code1 segment assume cs:code1 ; Kermit startup time initialization flclyini proc far mov ah,conout ; write a space to determine mov dl,' ' ; DOS's default cursor coloring int dos call getpcur ; get current cursor position into dx mov lincur,cx ; save cursor type (scan line #'s) dec dl ; backup to last char or dl,dl jns lclyin5 ; ns = no problem xor dl,dl ; else set cursor back to left margin lclyin5:call setpcur ; set the cursor call getpcha ; read current attributes into AH mov scbattr,ah ; save video attributes mov savattr,ah ; and saved attributes mov dosattr,ah ; and here too and ah,att_bold ; select intensity bit mov userbold,ah ; save bit for user Bold control mov ega_mode,0 ; assume no EGA mov ax,1200H ; EGA: Bios alternate select mov bl,10H ; Ask for EGA info mov bh,0ffH ; Bad info, for testing mov cl,0fH ; Reserved switch settings int screen ; EGA, are you there? cmp cl,0cH ; Test reserved switch settings jge lclyin1 ; ge = no EGA in use push es mov ax,40h ; check Bios 40:87h for ega being mov es,ax ; the active display adapter test byte ptr es:[87h],8 ; is ega active? pop es jnz lclyin1 ; nz = no mov ega_mode,1 ; yes, set flag to say ega is active mov crt_norm,3 ; assume color monitor is attached or bh,bh ; is color mode in effect? jz lclyin1 ; z = yes mov crt_norm,7 ; else use mode 7 for mono lclyin1:call scrseg ; test running in an Environment call dvtest ; test for running under DESQview call scrmod ; read video state, get crt_mode mov dosetcursor,-1 ; cursor position reminder, none mov ax,low_rgt ; lower right corner of screen mov al,crt_mode mov crt_norm,al ; save as normal mode mov ah,crt_cols mov dos_cols,ah ; remember for exiting Connect mode ifndef no_terminal mov keypend,0 ; [HF]940207 clear double byte flag mov keyj7st,0 ; [HF]940211 clear keyoutput status mov cursor,0 ; initial cursor call vsalloc ; allocate memory for virtual screen jnc lclyin4 ; nc = success mov ah,prstr mov dx,offset memerr ; say not enough memory to operate int dos mov flags.extflg,1 ; set Kermit exit flag ret lclyin4:call vsinit ; init terminal emulator module MSZ mov bx,vtemu.att_ptr ; attributes pointer mov ah,dosattr ; startup video attributes and ah,not att_bold ; emulation intensity to normal or ah,userbold mov [bx],ah ; set initial emulation attributes and vtemu.vtflgst,not deccol ; assume 80 column screen and vtemu.vtflgop,not deccol cmp crt_cols,80 ; screen cols now, wide screen? jbe lclyin6 ; be = no or vtemu.vtflgst,deccol ; say using 132 columns screen or vtemu.vtflgop,deccol endif ; no_terminal lclyin6:ret flclyini endp ifndef no_terminal ; Allocate memory for virtual screen buffers vscreen and vsat. ; Return carry clear if success, else carry set. Removes older allocations. vsalloc proc near call vsalloc4 ; free alloc'd memory, if any mov al,crt_lins ; one minus number of screen rows inc al mov cl,vswidth ; virtual screen vscreen mul cl ; lines time width, words for vscreen add ax,ax ; need words add ax,15 ; round up mov cl,4 ; convert to paragraphs shr ax,cl ; need words rather than bytes mov cx,ax ; save total wanted paragraphs in cx mov bx,ax ; ask for the memory mov ah,alloc ; allocate memory int dos ; bx has # free paragraphs mov word ptr vs_ptr+2,ax ; seg of vsscreen (offset is zero) cmp cx,bx ; got what we wanted jb vsalloc5 ; b = no push es mov es,ax xor di,di shl cx,1 shl cx,1 shl cx,1 ; paragraphs to words mov ah,scbattr mov al,' ' cld rep stosw ; clear the memory with def colors pop es mov al,crt_lins inc al ; attributes (nibbles) mov cl,vswidth ; lines time width, bytes for vsattr mul cl add ax,15 ; round up mov cl,4 ; convert to paragraphs shr ax,cl mov cx,ax ; save total wanted paragraphs in cx mov bx,ax ; ask for the memory mov ah,alloc ; allocate the memory int dos ; bx has # free paragraphs mov word ptr vsat_ptr+2,ax ; seg of vsattr (offset is zero) cmp cx,bx ; got what we wanted jb vsalloc4 ; b = no push es mov es,ax xor di,di shl cx,1 shl cx,1 shl cx,1 shl cx,1 ; paragraphs to bytes xor al,al rep stosb ; clear the memory with def extattr pop es clc ; report success ret vsalloc4:mov ax,word ptr vsat_ptr+2 ; seg of vsattr (offset is zero) or ax,ax ; unused? jz vsalloc5 ; z = yes push es mov es,ax ; allocated segment mov ah,freemem ; free it int dos mov word ptr vsat_ptr+2,0 ; clear pointer too pop es vsalloc5:mov ax,word ptr vs_ptr+2 ; seg of vsscreen or ax,ax ; unused? jz vsalloc6 ; z = yes push es mov es,ax ; allocated segment mov ah,freemem ; free it int dos mov word ptr vs_ptr+2,0 ; clear pointer too pop es vsalloc6:stc ; return failure ret vsalloc endp ; Allocate memory for screen rollback buffers. ; Return carry clear if success, else carry set to exit. vsbuff proc near ; screen roll back buffers cmp vsbuff_inited,0 ; inited yet? je vsbuff0 ; e = no clc ; say success ret vsbuff0:mov vsbuff_inited,1 ; say we are initializing cmp emsrbhandle,-1 ; valid EMS rollback handle? je vsbuff20 ; e = no mov ah,emsrelease ; release pages mov dx,emsrbhandle ; handle int emsint mov emsrbhandle,-1 ; invalidate EMS rollback handle mov iniseg,0 ; and no segment for page frame jmp short vsbuff21 vsbuff20:cmp xmsrhandle,0 ; using XMS? je vsbuff20a ; e = no mov dx,xmsrhandle ; handle for memory block mov ah,xmsrelease ; release the memory block call dword ptr xmsep ; xms handler entry point mov xmsrhandle,0 mov dx,xmsghandle ; and the graphics area too mov ah,xmsrelease ; release the memory block call dword ptr xmsep ; xms handler entry point mov xmsghandle,0 vsbuff20a: mov ax,iniseg ; memory segment, window area or ax,ax ; anything allocated? jz vsbuff21 ; z = no mov es,ax mov ah,freemem ; free regular memory segment int dos mov iniseg,0 vsbuff21: mov bx,rollwidth ; columns to roll back or bx,bx ; user override given? jnz vsbuff1 ; nz = yes, else physical screen mov bl,crt_cols ; physical screen xor bh,bh mov rollwidth,bx ; set final roll width vsbuff1:add bx,7 ; round up (cancel common times twos) mov cl,3 shr bx,cl ; bytes/line to paragraphs/line mov ppl,bx ; paragraphs/line vsbuff11: ; expanded memory test useexp,1 ; use expanded memory? jz vsbuff10 ; z = no, try XMS mov ah,open2 ; file open xor al,al ; 0 = open readonly mov dx,offset emsname ; device name EMMXXXX0 int dos jc vsbuff10 ; can't open, no expanded memory push ax ; save handle mov bx,ax ; handle ax xor al,al ; get device info mov ah,ioctl int dos pop ax push dx ; save status report in dx mov dx,ax ; handle mov ah,close2 ; close device int dos pop dx ; recover status report rcl dl,1 ; put ISDEV bit into the carry bit jnc vsbuff10 ; nc = not a device mov ax,sp ; do push sp test for XT vs AT/386 push sp ; XT pushes sp-2, AT's push old sp pop cx ; recover pushed value, clean stack xor ax,cx ; same? jne vsbuff5 ; ne = no, XT. Don't do Int 2fh mov ax,xmspresent ; XMS presence test int 2fh cmp al,80h ; present? jne vsbuff10 ; ne = no mov ah,getintv ; get interrupt vector mov al,emsint ; EMS interrupt 67h int dos ; to es:bx mov ax,es or ax,bx ; check for null jz vsbuff10 ; z = interrupt not activated mov ah,emsmgrstat ; LIM 3.2 manager status int emsint or ah,ah ; ok? jnz vsbuff10 ; nz = not ok mov ax,1024 ; 1024 paragraphs per ems 16KB page xor dx,dx div ppl ; divide by paragraphs per line mov lineems,ax ; lines per ems page, remember mov al,crt_lins ; lines-1 per physical screen xor ah,ah mov cx,npages ; number of roll back screens wanted inc cx ; include current screen mul cx ; times number screens div lineems ; lines total / (lines/emspage) or dx,dx ; remainder? jz vsbuff2 ; z = no inc ax ; add page for fraction vsbuff2:push ax ; ax is number of emspages mov ah,emsgetnpgs ; get number pages free int emsint ; to bx pop ax or bx,bx ; any pages free? jz vsbuff10 ; z = no, try XMS cmp bx,ax ; enough? jb vsbuff3 ; b = less, use what we can get mov bx,ax ; number of pages wanted vsbuff3:mov ah,emsalloc ; allocate bx pages int emsint or ah,ah ; successful? jnz vsbuff10 ; nz = no, failure mov emsrbhandle,dx ; returned handle mov ax,bx ; pages allocated mov inipara,ax ; save for later resizing of buffers mov ah,emsgetseg ; get segment of page frame int emsint ; to bx or ah,ah ; status, success? jnz vsbuff10 ; nz = no, no expanded memory today mov iniseg,bx ; save here mov ah,emsgetver ; get EMS version number int emsint ; to al (high=major, low=minor) cmp al,40h ; at least LIM 4.0? jb vsbuff4 ; b = no, so no name for our area mov si,offset emsrollname ; point to name for rollback area mov di,offset emsrollname+6 ; add digits mov dx,emsrbhandle mov ax,dx call dec2di ; write to handle name mov ax,emssetname ; set name for handle from ds:si int emsint mov useexp,1 ; say using expanded vsbuff4:jmp vsbuff9 vsbuff10: ; XMS, try this first test useexp,2 ; use extended memory? jz vsbuff5 ; z = no, try conventional cmp xmsrhandle,0 ; have already allocated xms? je vsbuff10a ; e = no mov ah,xmsrelease ; release memory block mov dx,xmsrhandle call dword ptr xmsep ; release the memory jmp short vsbuff10b vsbuff10a:xor bx,bx ; clear entry point response mov es,bx mov ax,xmsmanager ; get XMS manager entry point int 2fh ; to es:bx mov word ptr xmsep,bx ; save entry point in xmsep mov ax,es or bx,ax ; is there an entry point returned? jz vsbuff5 ; z = no, use regular memory mov word ptr xmsep+2,ax vsbuff10b:mov ax,ppl ; paragraphs / line mul crt_lins ; times lines-1 on physical screen mov cx,npages ; number of roll back screens wanted inc cx ; include current screen mul cx ; total number of paragraphs wanted mov cx,6 vsbuff10c:shr dl,1 rcr ah,1 rcr al,1 ; get kilobytes to ax loop vsbuff10c ; divide by 2^6 mov dx,ax ; KB wanted to dx push dx mov ah,xmsquery call dword ptr xmsep ; get largest block KB into ax pop dx cmp dx,ax ; wanted KB vs available KB jbe vsbuff10d ; be = have space mov dx,ax ; else use space available vsbuff10d:push dx ; save KB request amount mov ah,xmsalloc ; allocate block of dx KB call dword ptr xmsep mov xmsrhandle,dx ; returned XMS handle of block pop dx ; recover KB request amount mov cx,6 ; convert dx KB to paragraphs in AX mov ax,dx ; KB allocated to AX xor dx,dx vsbuff10e:shl al,1 ; convert KB to paragraphs rcl ah,1 loop vsbuff10e ; times 2^6, yield paragarphs in ax mov inipara,ax ; initial number of paragraphs mov useexp,2 ; say using extended jmp vsbuff9 ; end XMS ; no ems, so use regular memory vsbuff5:mov useexp,0 ; say no ems mov bx,0ffffh ; ask for all of memory, to get size mov ah,alloc ; allocate all of memory (must fail) int dos ; bx has # free paragraphs mov ax,bx ; ax has copy of number free paragraphs sub bx,26000D/16 ; space for Command.com copy #2 jc vsbuff7 ; c = not enough for it mov ax,ppl ; paragraphs / line mul crt_lins ; times lines-1 on physical screen cmp bx,ax ; minimum roll back space left over? jbe vsbuff7 ; be = not even that much mov cx,npages ; number of roll back screens wanted inc cx ; include current screen mul cx ; total number of paragraphs wanted mov cx,ax ; save in cx or dx,dx ; want more than 1 MB of real memory? jz vsbuff6 ; e = no mov cx,0ffffh ; set all of real memory vsbuff6:cmp bx,cx ; got vs wanted paras for roll back jbe vsbuff8 ; be = enough but not more than needed mov bx,cx ; limit to our actual needs jmp short vsbuff8 ; ask for all we really want vsbuff7:xor bx,bx ; use no space at all mov cx,bx ; remember this new request vsbuff8:mov ah,alloc int dos mov iniseg,ax ; (BDT) memory segment, window area mov inipara,bx ; save for later resizing of buffers cmp cx,bx ; paragraphs wanted vs delivered jae vsbuff9 ; ae = enough mov ah,prstr mov dx,offset memerr ; say not enough memory to operate int dos stc ; carry set = fail ret vsbuff9:call bufadj ; set roll back buffer parameters clc ; carry clear for success ret vsbuff endp scrini proc far ; init screen stuff call chkwindows ; check for Windows being active mov al,crt_lins ; screen lines - 1 mov ah,crt_mode ; preserve this too push ax ; save call scrmod ; get screen mode now mov ax,100h ; assume 80 column mode, no-renter test vtemu.vtflgop,deccol ; supposed to be in 80 col? jz scrin5 ; z = yes inc al ; say want 132 cols scrin5: call chgdsp ; set to 80/132 columns call scrmod ; get crt_lins again pop ax mov crt_mode,ah ; restore in case in graphics now cmp al,crt_lins ; changed? je scrin2 ; e = no mov vtinited,0 ; say must reinit emulator mov cursor,0 call vsalloc ; reallocate virtual screen jnc scrin2 ; nc = success mov ah,prstr mov dx,offset memerr ; say not enough memory to operate int dos mov sp,oldsp ret ; must be Far return scrin2: scrin1: mov ah,savattr ; saved emulator attributes mov scbattr,ah ; restore active value call scrseg ; update screen segment tv_seg(s/o) call getpcur ; get cursor position DX and type CX cmp flags.vtflg,0 ; emulating anything? jne scrin4 ; ne = yes mov cursor,dx ; use physical cursor scrin4: mov dx,cursor ; use old cursor, if any call setpos ; set cursor position cmp vtinited,inited ; inited emulator yet? je scrin11 ; e = yes, do reinit call fvtinit ; init it now call repaint ; repaint screen ret scrin11: ifndef no_graphics cmp flags.vtflg,tttek ; Tek mode? je scrin12 ; e = yes test tekflg,tek_tek+tek_dec ; Tek submode? jz scrin14 ; z = no scrin12:call tekini ; init graphics mode ret endif ; no_graphics scrin14:call ansrei ; reinit the emulator call repaint ; restore screen from vscreen scrin15:ret scrini endp chkwindows proc near mov inwindows,0 ; presume not in Windows mov ax,sp ; do push sp test for XT vs AT/386 push sp ; XT pushes sp-2, AT's push old sp pop cx ; recover pushed value, clean stack xor ax,cx ; same? jne chkwin2 ; ne = no, XT. Don't do Int 2fh mov ax,1683h ; Windows 3, get current virt machine int 2fh cmp ax,1683h ; virtual machine, if any je chkwin2 ; e = none mov inwindows,1 ; say in Windows chkwin2:ret chkwindows endp ; Initialize terminal emulators fvtinit proc far mov ax,apcstring ; seg of apcmacro memory area or ax,ax ; empty? jz vtini4 ; z = yes mov es,ax mov ah,freemem int dos ; free that memory mov apcstring,0 vtini4: mov holdscr,0 ; clear holdscreen mov vtclear,0 ; clear clear-screen indicator mov keypend,0 ; [HF]940207 clear double byte flag mov keyj7st,0 ; [HF]940211 clear keyoutput status call fkbhold ; tell DEC LK250 the state, in msuibm or vtinited,inited mov dosetcursor,0 ; cursor position reminder, none mov bx,portval mov dl,[bx].ecoflg ; local echo flag and yflags,not lclecho or yflags,dl mov bx,argadr ; address of argument block mov dl,[bx].baudb ; baud rate code in dl mov dh,[bx].parity ; parity code in bits mov cl,4 ; 0-3 of dh shl dh,cl or dh,07H ; just say 7 data bits test flags.remflg,d8bit ; eight bit display? jz vtini1 ; z = no inc dh ; set low four bits to value 8 vtini1: cmp flags.vtflg,0 ; doing emulation? je vtini3 ; e = no cmp tekflg,tek_active+tek_tek ; Tek graphics mode? je vtini2 ; e = yes, do it's reinit cmp tekflg,tek_active+tek_dec ; Tek graphics submode? je vtini2 ; e = yes, do it's reinit xor ax,ax ; assume 80 col mode (al=0) test vtemu.vtflgst,deccol ; want wide display? jz vtini1a ; z = no inc al ; set AL to 1 for set 132 col mode vtini1a:call chgdsp ; set screen width call ansini ; call startup routine in mszibm cmp flags.vtflg,tttek ; full Tek mode? jne vtinix ; ne = no or tekflg,tek_tek ; say tek mode jmp short vtini2 ; e = yes vtinix: clc ret vtini2: ifndef no_graphics call tekrint ; reinitialize Tek emulator endif ; no_graphics clc ret vtini3: call fcmblnk ; clear the screen clc ret fvtinit endp 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 mov al,[bx].prt mov portno,al ; update port number ret argini endp fterm proc FAR ; terminal mode entry point mov argadr,ax ; save argument ptr mov oldsp,sp ; remember stack for i/o failure, mov apctrap,0 ; un-trap certain commands ifndef no_tcp cmp flags.comflg,'t' ; doing internal Telnet? jne fterm2 ; ne = not Telnet cmp termlatch,0 ; have we been here for macro? jne fterm2 ; ne = yes, reset it and skip macro mov termlatch,1 ; arm reentry bypass mov bx,sescur ; get session to bl call vtsesmac ; this returns us to the Kermit prompt jc fterm2 ; c = no such macro else jmp short fterm2 endif ; no_tcp fterm1: call fserrst ; shut down serial port now mov kbdflg,'C' ; say exit Connect mode ret ; return, to process macro fterm2: mov termlatch,0 ; disable bypass, enable macro again mov handhsc,0 ; cancel hand scrolling call vsbuff ; allocate screen buffer memory jc fterm1 ; c = failure, quit now mov grab,0 ; clear Compose/Spcl output grabber call argini ; init options from arg address mov inemulator,1 ; say in terminal emulator (local) call scrini ; call screen setup or kbcodes,80h ; set need-to-init flg for kbd xtlator mov fairprn,0 ; set printer buffer flush counter lp: call fprtchr ; char at port? jnc short lpinp ; nc = yes, go handle ifndef no_graphics cmp tekflg,tek_active+tek_sg ; special graphics active? jne lpcross ; ne = no, stay in idle loop mov dx,dosetcursor ; preserved cursor position cmp dx,-1 ; should we set the cursor? je lpcursor ; e = no call teksetcursor ; set the cursor at dx mov dosetcursor,-1 ; turn off reminder lpcursor:test flags.vtflg,ttd463+ttd470+ttd217 ; doing DG emulation? jz lpcross ; z = not DG cmp dgcross,0 ; is DG crosshair active? je lpcross ; e = no xor al,al ; feed it a null command, to do mouse call croshair ; call Tek crosshair to read mouse endif ; no_graphics lpcross:cmp repflg,0 ; REPLAY? jne lpkbd ; ne = yes push bx mov bx,portval ; port structure address cmp [bx].portrdy,0 ; is port ready for business? pop bx jne lpkbd ; ne = ready jmp quit ; end the communications now lpkbd: mov fairness,0 ; say kbd was examined call dvpause ; tell DESQview we are not busy inc fairprn ; inc printer dump counter cmp fairprn,100 ; been here enough times now? jb lpkbd1 ; b = no call fpntflsh ; flush printer buffer jnc lpkbd0 ; nc = success call pntdead ; call bad printer notifier lpkbd0: mov fairprn,0 ; reset for next time lpkbd1: call fkeybd ; call keyboard translator in msu jc quit ; carry set = quit connect mode call clkdsp ; display clock jmp short lp ; and repeat idle loop lpinp: and al,parmsk ; apply 8/7 bit parity mask call outtty ; print on terminal inc fairness ; say read port but not kbd, again cmp fairness,100 ; this many port reads before kbd? jb lp ; b = no, read port again jmp short lpkbd ; yes, let user have a chance too quit: mov sp,oldsp ; recover startup stack pointer ; TERM caller's return address is now ; on the top of stack. A longjmp. mov ah,scbattr ; current emulator attributes mov savattr,ah ; save them here call fpntflsh ; flush printer buffer ifndef no_graphics call tekend ; cleanup Tektronix mode endif ; no_graphics mov inemulator,0 ; say not in terminal emulator (local) mov al,1 call csrtype ; turn on underline cursor mov ah,dosattr ; attributes at init time mov scbattr,ah ; background = original state call fclrmod ; clear mode line with DOS attributes mov ax,100h ; assume using 80 col screen cmp dos_cols,80 ; startup screen width jbe quit1 ; be = assume 80 columns inc al ; say do 132 columns quit1: push vtemu.vtflgop or vtemu.vtflgop,vscompress ; turn off compressed mode call chgdsp ; reset display width to startup pop vtemu.vtflgop call scrmod ; update size info ; for ega in non-standard # lines test tv_mode,10h ; DV active? jnz quit2 ; nz = yes, it messes with the cursor cmp ega_mode,0 ; ega board active? je quit2 ; e = no cmp byte ptr low_rgt+1,23 ; is screen standard length? je quit2 ; e = yes, so regular cursor set is ok cmp byte ptr low_rgt+1,24 ; ANSI, is screen standard length? je quit2 ; e = yes, so regular cursor set is ok push es ; turn off ega cursor emulation mov ax,40h ; byte 40:87H is ega Info byte mov es,ax push es:[87h] ; save info byte around call or byte ptr es:[87h],1 ; set emulation off (low bit = 1) mov cx,lincur ; cursor shape to set mov ah,1 ; set the shape int screen ; back to starting value pop es:[87h] ; recover original Info byte pop es ; and our work reg jmp short quit3 ; skip regular mode cursor setting quit2: ; for regular sized screen mov cx,lincur ; cursor type at startup mov ah,1 int screen ; restore cursor type quit3: mov dh,byte ptr low_rgt+1 ; bottom line -1 xor dl,dl ; left most column call setpcur ; set cursor physical position mov al,yflags mov bx,argadr mov [bx].flgs,al ; update flags in arg block call dvpause ; tell DESQview we are not busy cmp isps55,0 ; [HF]940214 Japanese PS/55? je quit4 ; [HF]940214 e = no cmp ps55mod,0 ; [HF]940214 system modeline ? jne quit4 ; [HF]940214 ne = no push ax ; [HF]940211 push dx ; [HF]940211 mov ah,prstr ; [HF]940211 we need newline for DOS mov dx,offset crlf ; [HF]940211 int dos ; [HF]940211 call fctlu ; [HF]940211 clear new line pop dx ; [HF]940211 pop ax ; [HF]940211 quit4: ret fterm endp ; put the character in al to the screen outtty proc near test flags.remflg,d8bit ; keep 8 bits for displays? jnz outtt1 ; nz = yes, 8 bits if possible and al,7fh ; remove high bit outtt1: cmp flags.vtflg,0 ; emulating a terminal? je outnp10 ; e = no cmp vtroll,0 ; auto roll back allowed? je outem1 ; e = no, leave screen as is test tekflg,tek_active ; Tek mode active? jnz outem1 ; nz = yes, skip screen rolling push ax ; (BDT) save this for a tad mov ax,linec ; (BDT) are we at the buffer end? cmp ax,lcnt pop ax ; (BDT) restore the register je outem1 ; (BDT) e = yes push ax ; (BDT) save AX again call fendwnd ; do END to roll screen to end of buf pop ax ; (BDT) restore the register outem1: test tekflg,tek_active ; graphics mode active? jz outem2 ; z = no test tekflg,tek_tek+tek_dec ; Tek submode active for input? jnz outem3 ; nz = yes, use Tek emulator outem2: call anstty ; call terminal emulator, char in AL ret outem3: ifndef no_graphics call tekemu ; use Tek emulator and return endif ; no_graphics ret ; use DOS for screen output outnp10:test flags.remflg,d8bit ; keep 8 bits for displays? jnz outnp9 ; nz = yes, 8 bits if possible and al,7fh ; remove high bit outnp9: cmp rxtable+256,0 ; translation turned off? je outnp7 ; e = yes, no translation push bx mov bx,offset rxtable ; address of translate table xlatb ; new char is in al pop bx outnp7: test anspflg,prtscr ; should we be printing? jz outnp8 ; no, keep going call fpntchr ; queue char for printer jnc outnp8 ; nc = successful print push ax call vtbell ; else make a noise and call ftrnprs ; turn off printing pop ax outnp8: test yflags,capt ; capturing output? jz outnp6 ; no, forget this part call fcptchr ; give it captured character outnp6: test yflags,trnctl ; debug? if so use Bios tty mode jz outnp4 ; z = no mov ah,conout ; DOS screen write cmp al,7fh ; Ascii Del char or greater? jb outnp1 ; b = no je outnp0 ; e = Del char push ax ; save the char mov dl,7eh ; output a tilde for 8th bit int dos pop ax ; restore char and al,7fh ; strip high bit outnp0: cmp al,7fh ; is char now a DEL? jne outnp1 ; ne = no and al,3fH ; strip next highest bit (Del --> '?') jmp outnp2 ; send, preceded by caret outnp1: cmp al,' ' ; control char? jae outnp3 ; ae = no add al,'A'-1 ; make visible outnp2: push ax ; save char mov dl,5eh ; caret int dos ; display it pop ax ; recover the non-printable char outnp3: push ax mov dl,al int dos pop ax ret outnp4: cmp al,bell ; bell (Control G)? jne outnp5 ; ne = no jmp vtbell ; use short beep, avoid char loss outnp5: mov dl,al ; write without intervention mov ah,conout int dos ; else let dos display char ret outtty endp ;[IU2] Here to output an unsigned 8-bit number (in al) to the port ; Used by terminal emulator escape sequence output. prtnout proc near jmp short prtno2 ; ensure at least a zero prtno1: or al,al jnz prtno2 ; nz = yes, do more digits ret ; no, return from recursive call prtno2: xor ah,ah ; clear previous remainder mov bl,10 ; output in base 10 div bl ; divide off a digit push ax ; push remainder (in ah) on stack call prtno1 ; recurse pop ax ; pop off a digit add ah,'0' ; make it ASCII mov al,ah ; send to port, in ah call outprt jc prtno3 ; failure, end connection ret prtno3: jmp far ptr endcon prtnout 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 mov ah,1 ; say local echo is permitted jmp short outprt0 prtbout:xor ah,ah ; no local echo outprt0:cmp grab,0 ; grabbing output? je outprt0a ; e = no call fgrabber ; yes, give it to the guy ret outprt0a:test al,80h ; high bit set? jz outpr2 ; z = no test flags.vtflg,ttd463+ttd470+ttd217 ; Data General? jz outprt4 ; z = no test flags.remflg,d8bit ; chop DG high bit? jnz outpr2 ; nz = no, send as-is and al,7fh ; chop high bit jmp short outpr1 ; send with possible DG SI/SO brackets outprt4:cmp al,0a0h ; C1 area? jae outpr1 ; ae = no cmp vtemu.vtchset,C_XPARENT ; TRANSPARENT? je outpr2 ; e = yes, pass as-is test vtemu.vtflgop,vscntl ; sending 8-bit controls? jz outprt5 ; z = no, force use of 7-bit controls cmp parmsk,7fh ; using parity? jne outpr2 ; ne = no, no need to force on that outprt5:push ax ; save char mov al,Escape ; C1 as ESCAPE call outpr2 ; send ESCAPE pop ax ; recover char sub al,40h ; relocate the code jmp short outpr2 ; send the char ; GRight printable characters outpr1: cmp flags.vtflg,ttgenrc ; doing term type of NONE? je outpr2 ; e = yes, no tables (maybe SO/SI?) cmp parmsk,7fh ; using parity? jne outpr2 ; ne = no, no shifts needed cmp flags.oshift,0 ; allowing shifts on output? je outpr2 ; e = no and al,not 80h ; strip high bit test flags.oshift,8 ; Auto? jnz outpr1a ; nz = yes test flags.oshift,1 ; force SI/SO? jnz outpr8 ; nz = yes jmp short outpr1b ; else SS2/SS3 outpr1a:cmp GRptr,offset G1set ; GR points to G1 char set? je outpr8 ; e = yes, use SO/char/SI outpr1b:push ax ; save char mov al,Escape ; send SS2 as ESC N call outpr2 ; ESC N is Single Shift 2 mov al,'N' cmp flags.oshift,4 ; force SS3? jb outpr7 ; b = force SS2 je outpr1c ; e = force SS3 cmp GRptr,offset G2set ; GR points to G2 char set? je outpr7 ; e = yes, else use SS3 (ESC P) outpr1c:inc al ; use ESC P for Single Shift 3 outpr7: call outpr2 pop ax ; recover char jmp short outpr2 outpr8: push ax ; save char mov al,SOchar ; SO locking shift 1 for G1 to GL cmp flags.vtflg,ttd463+ttd470+ttd217 ; D463/D470/D217? jz outpr8a ; z = no mov al,DGescape ; send SO as DG's RS N call outpr2 mov al,'N' outpr8a:call outpr2 ; send it pop ax push ax ; preserve ah around call call outpr2 ; send real character (7 bit'd) pop ax mov al,SIchar ; shift back to normal test flags.vtflg,ttd463+ttd470+ttd217 ; D463/D470/D217? jz outpr2 ; z = no mov al,DGescape ; send SI as DG's RS O call outpr2 mov al,'O' outpr2: or ah,ah ; local echo permitted? jz outpr3 ; z = no test yflags,lclecho ; echoing ourselves? jz outpr3 ; z = no, forget it push ax ; save char call outtty ; display it pop ax ; restore ifndef no_network cmp al,CR ; sending CR? jne outpr3 ; ne = no cmp flags.comflg,'t' ; doing Telnet? jne outpr3 ; ne = no ifndef no_tcp cmp tcpnewline,1 ; newline mode is on? ja outpr3 ; a = RAW, no extra LF je outpr2a ; e = yes, send CR/LF (else NVT/Bin) cmp tcpmode,0 ; NVT-ASCII? jne outpr3 ; ne = no, Binary so no extra LF endif ; no_tcp outpr2a:push ax mov al,LF ; locally show LF which we will send call outtty pop ax endif ; no_network outpr3: mov ah,al ; this is where outchr expects it call foutchr ; output to the port jc outpr4 ; c = failure ret outpr4: jmp far ptr endcon ; failure, end connection outprt endp fansdsl proc far call ansdsl ret fansdsl endp foutprt proc far call outprt ret foutprt endp ; keyboard handler verbs come here to sidestep transparent mode ALT-nnn outprt_key proc far test al,80h ; high bit set? jz outprt_key1 ; z = no, send as-is cmp al,0a0h ; C1 area? jae outprt_key1 ; ae = no, send as-is cmp vtemu.vtchset,C_XPARENT ; TRANSPARENT? jne outprt_key1 ; ne = no push ax ; mov al,Escape ; C1 as ESCAPE call outprt ; send escape pop ax sub al,40h ; relocate the code outprt_key1: call outprt ret outprt_key endp fprtbout proc far call prtbout ret fprtbout endp fprtnout proc far call prtnout ret fprtnout endp ; Product macro worker prodwork proc far push si push di push es mov ax,ds mov es,ax mov di,offset decbuf+2 ; macro def buffer starts here mov si,offset prodname ; pointer to macro name mov cx,vtplen ; length of macro name cld rep movsb ; copy to rdbuf+2 mov byte ptr [di],0 ; null terminator mov cx,nparam ; number of parameters cmp cx,9 ; more than 9? jle produc1 ; le = no mov cx,9 ; limit to 9 produc1:jcxz produc3 ; z = none xor bx,bx ; parameter subscript produc2:push bx push cx mov al,' ' ; and a space separator stosb shl bx,1 ; address words mov ax,param[bx] ; get parameter to use as definition call dec2di ; convert numerics to ascii string pop cx pop bx inc bx loop produc2 produc3:xor al,al ; safety terminator mov [di],al ; don't count in length mov ax,di sub ax,offset decbuf + 2 ; compute length mov vtmaclen,ax ; pass along to vtmacro mov vtmacname,offset decbuf+2 ; say this is our macro text ptr pop si pop di pop es jmp short vtmacro prodwork endp ; ; Reference Macro structure for db number of entries (mac names) ; is file table mcctab |-> dw length of macroname ; 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 decbuf+2 ; macro def buffer starts here mov si,vtmacname ; pointer to macro name mov cx,vtmaclen ; length of macro nametext mov [di-2],cx ; counted string field cld rep movsb ; copy to rdbuf mov byte ptr [di],0 ; null terminator mov si,offset decbuf+2 ; look for name-text separator mov cx,vtmaclen 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 length correctly vtmac1a:sub si,offset decbuf+2+1 ; compute length of macro name mov cx,si mov vtmaclen,cx ; 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 ax,[bx] ; length of this name cmp ax,vtmaclen ; length same as desired keyword? jne vtmac3 ; ne = no, search again mov si,bx add si,2 ; point at first char of name push cx ; save name counter push di ; save reg mov cx,vtmaclen ; length of name 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 di ; recover saved regs pop cx je vtmac4 ; e = matched vtmac3: add bx,ax ; step to next name, add name length add bx,4 ; + count and 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 stc ; say failure ret vtmac4: call takopen_macro ; open a 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 cx,word ptr decbuf ; length of count + string mov [bx].takcnt,cx ; number of chars in definition mov [bx].takargc,0 ; our argument count mov [bx].takptr,offset decbuf+2 ; where to read next command char pop es pop di pop si pop cx pop bx clc ; say success, can exit connect mode ret vtmacro endp ; APC macro. Macro string (word count, string text) preset by mszibm.asm ; into seg apcstring offset 0. apcmacro proc near cmp taklev,maxtak ; room in take level? jb apcmac1 ; b = yes stc ; fail ret apcmac1:call takopen_macro ; open macro mov bx,takadr ; point to current macro structure mov ax,apcstring ; segment of buffer mov [bx].takbuf,ax ; segment of definition string struc mov [bx].takcnt,cx ; number of chars in definition or [bx].takattr,take_malloc; say have buffer to be removed cmp apcenable,2 ; enable all commands? je apcmac2 ; e = yes mov apctrap,1 ; trap certain commands apcmac2:mov apcstring,0 ; takclos will delete the buffer jmp far ptr endcon ; exit Connect mode cleanly apcmacro endp rcvmacro proc near call takopen_macro ; open macro mov bx,takadr ; point to current macro structure mov ax,seg rcvstring ; segment of buffer mov [bx].takbuf,ax ; segment of definition string struc mov [bx].takptr,offset rcvstring+2 mov [bx].takcnt,rcvstring_len ; number of chars in definition mov termserver,1 ; say Connect mode started receive jmp far ptr endcon ; exit Connect mode cleanly rcvmacro endp srvmacro proc near call takopen_macro ; open macro mov bx,takadr ; point to current macro structure mov ax,seg srvstring ; segment of buffer mov [bx].takbuf,ax ; segment of definition string struc mov [bx].takptr,offset srvstring+2 mov [bx].takcnt,srvstring_len ; number of chars in definition mov termserver,1 ; say Connect mode started server jmp far ptr endcon ; exit Connect mode cleanly srvmacro 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 FAR 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 tabcpy proc far push es ; worker copy routine push si push di mov cx,ds mov es,cx mov cx,(vswidth+7)/8 ; update all active tab stops cld rep movsb pop di pop si pop es clc ; success ret tabcpy endp ifndef no_terminal ; Issue warning that CP866 is needed but not loaded for Cyrillic char sets chkcp866 proc far cmp bl,C_CYRILLIC_ISO ; these Cyrillic character sets? je chkcp1 ; e = yes cmp bl,C_KOI8 je chkcp1 cmp bl,C_SHORT_KOI je chkcp1 ret chkcp1: cmp vtcpage,866 ; Code Page is CP866? je chkcp2 ; e = yes, no warning push ax push dx mov ah,prstr mov dx,offset cpwarn ; issue warning int dos pop dx pop ax chkcp2: ret chkcp866 endp endif ; no_terminal ; Display HHMM on status line over the led dots clkdsp proc far cmp inemulator,0 ; in terminal emulator? je clkdsp1 ; e = no, no mode line cmp vtclkflg,0 ; do not use clock je clkdsp1 ; e = correct, no clock cmp inwindows,0 ; in Windows? ;;; jne clkdsp1 ; ne = yes, no clock cmp flags.modflg,1 ; mode line enabled and owned by us? jne clkdsp1 ; ne = no, don't touch it test flags.vtflg,tttek ; Tek mode? jnz clkdsp1 ; nz = yes test tekflg,tek_dec ; in Tek submode? jnz clkdsp1 ; nz = yes, no mode line changes test yflags,modoff ; mode line off? jnz clkdsp1 ; nz = yes cmp flags.vtflg,0 ; emulating none? jne clkdsp2 ; ne = no clkdsp1:ret clkdsp2:push ax push bx push cx push dx push es call cboff ; turn off Control-Break sensing mov ah,gettim ; read DOS tod clock int dos ; ch=hours, cl=minutes, dh=seconds cmp dh,lastsec ; compare with previous call mov lastsec,dh ; remember last sec je clkdsp9 ; e = same, do nothing cmp vtclkflg,1 ; do regular time of day? je clkdsp6 ; e = yes mov al,60 mul ch ; hours to minutes in ax add al,cl ; plus minutes adc ah,0 mov bl,dh ; save seconds in bx xor bh,bh mov cx,60 mul cx ; hh+mm to seconds in dx:ax add ax,bx ; plus seconds adc dx,0 ; total seconds in dx:ax mov bx,portval ifndef no_tcp cmp flags.comflg,'t' ; doing TCP/IP Telnet? je clkdsp4 ; e = yes endif ; no_tcp sub ax,word ptr starttime[bx] sbb dx,word ptr starttime[bx+2] jns clkdsp5 ; ns = not wrapped add ax,20864 ; add one day adc dx,1 ; of 86400 seconds jmp short clkdsp5 clkdsp4: ifndef no_tcp mov bx,sescur ; current session ident shl bx,1 shl bx,1 ; quad bytes sub ax,word ptr sestime[bx] sbb dx,word ptr sestime[bx+2] jns clkdsp5 ; ns = not wrapped add ax,20864 ; add one day adc dx,1 ; of 86400 seconds endif ; no_tcp clkdsp5:mov cx,60*60 ; convert seconds back to ch,cl,dh div cx ; ax = quo = hours, dx = rem = secs mov ch,al ; ch has hours mov ax,dx ; remaining seconds to ax mov cl,60 div cl ; al = quo = minutes, ah = secs mov cl,al ; minutes xchg dh,ah ; seconds to dh clkdsp6:mov ax,tv_segs ; screen segment mov es,ax mov al,crt_cols ; typically 80 mul crt_lins ; typically 24 mov bx,65+6 ; led_col from mszibm.asm, dots sub bl,handhsc ; minus hand scrolling left sbb bh,0 jc clkdsp4 ; c = off screen add ax,bx shl ax,1 ; char cells mov bx,ax mov al,ch ; hours xor ah,ah div ten ; al = quo, ah=rem add ax,'00' mov es:[bx],al mov es:[bx+2],ah mov es:[bx+4],al mov al,' ' test dh,1 ; odd seconds? jnz clkdsp8 ; nz = yes, show blank mov al,':' ; show colon clkdsp8:mov es:[bx+4],al mov al,cl xor ah,ah div ten ; quo = al, rem = ah add ax,'00' mov es:[bx+6],al mov es:[bx+8],ah push di mov di,bx ; es:di is start address add di,9 ; is now ending address mov cx,5 ; bytes changed call scrsync ; sync virtual screen pop di clkdsp9:call cbrestore ; restore Control-Break sensing pop es pop dx pop cx pop bx pop ax ret clkdsp endp code1 ends code segment assume cs:code ;;; Action routines (verbs) for keyboard translator KEYBD in msuibm. ; These are invoked by a jump instruction. Return carry clear for normal ; processing, return carry set for invoking Quit (kbdflg has transfer char). uparrw: mov al,'A' ; cursor keys jmp short comarr dnarrw: mov al,'B' jmp short comarr rtarr: mov al,'C' test vtemu.vtflgop,vswdir ; writing left to right? jz comarr ; z = yes mov al,'D' ; reverse sense of keys jmp short comarr lfarr: mov al,'D' test vtemu.vtflgop,vswdir ; writing left to right? jz comarr ; z = yes mov al,'C' ; reverse sense of keys comarr: test flags.vtflg,ttwyse ; Wyse-50? jnz comar7 ; nz = yes test flags.vtflg,ttd463+ttd470+ttd217 ; D463/D470/D217? jz comar4 ; z = no cmp dgd470mode,0 ; in D470 ANSI mode? je comar6 ; e = no push ax ; these send ESC [ mov al,escape call foutprt mov al,'[' call foutprt ; pop ax is done by comar3 jmp short comar3 ; send the letter comar6: sub al,'A' ; translate to DG 463/470/217 form ifndef no_graphics cmp tekflg,tek_active+tek_sg ; in special graphics mode? jne comar5 ; ne = no test dgcross,1 ; DG crosshair active? jz comar5 ; z = no test dgcross,2 ; DG crosshair active for keypad? jz comar5 ; z = no mov bx,offset dgcrostab ; use scan code table instead xlatb call croshair ; send AL to graphics to move cursor ret endif ; no_graphics comar5: mov bx,offset dgcurtab ; VT to DG cursor code table xlatb push ax ; setup for comar3 jmp short comar3 comar7: mov bx,offset wysecurtab ; VT to Wyse-50 code table sub al,'A' ; remove bias xlatb push ax jmp short comar3 comar4: push ax ; save final char mov ttyact,0 ; network, group chars for packet mov al,Escape ; send the ESC test vtemu.vtflgop,decanm ; ANSI mode? jz comar1 ; z = no mov al,CSI ; CSI character test vtemu.vtflgop,decckm ; cursor keys in application mode? jz comar1 ; z = no, in cursor mode mov al,SS3 ; SS3 character comar1: call outprt_key ; send in 7 or 8 bit form, with echo comar3: pop ax ; recover final char mov ttyact,1 ; network, restore tty active flag call foutprt ret pf1: mov al,'P' ; keypad function keys PF1-4 jmp short compf pf2: mov al,'Q' jmp short compf pf3: mov al,'R' jmp short compf pf4: mov al,'S' compf: push ax ; save final char mov ttyact,0 ; network, group chars for packet mov al,Escape ; send the ESC test vtemu.vtflgop,decanm ; ansi mode? jz short compf2 ; z = no mov al,SS3 ; SS3, ESC O compf2: call outprt_key ; send 7 or 8 bit version compf1: pop ax ; get the saved char mov ttyact,1 ; network, restore tty active flag call foutprt ret ignore_key: ; key is to be ignored ret kp0: mov al,'p' ; keypad numeric keys 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 kpminus:mov al,'m' jmp short comkp kpcoma: mov al,'l' jmp short comkp kpenter:mov al,'M' jmp short comkp kpdot: mov al,'n' comkp: test vtemu.vtflgop,deckpam ; keypad application mode active? jnz comkp1 ; nz = yes, use escape sequences sub al,40h ; deduct offset to numeric symbols push ax ; save final char jmp short comkp3 ; and send that single char comkp1: push ax mov ttyact,0 ; network, group chars for packet test vtemu.vtflgop,decanm ; ANSI mode? jz comkp2 ; z = no mov al,SS3 ; SS3 character call outprt_key ; send 7 or 8 bit version jmp short comkp3 comkp2: mov al,escape ; output "ESC ?" call foutprt mov al,'?' call foutprt comkp3: pop ax ; recover final char mov ttyact,1 ; network, restore tty active flag call foutprt ; send it ret klogon proc near ; resume logging (if any) test flags.capflg,logses ; session logging enabled? jz klogn ; z = no, forget it push bx mov bx,argadr or [bx].flgs,capt ; turn on capture flag pop bx or yflags,capt ; set local msy flag as well klogn: clc ret klogon endp klogof proc near ; suspend logging (if any) push bx mov bx,argadr and [bx].flgs,not capt ; stop capturing pop bx and yflags,not capt ; reset local msy flag as well clc ret klogof endp kdebug proc near INT 3 NOP NOP xor flags.debug,logses ; toggle debugging xor yflags,trnctl ; Debug mode local edition ret kdebug endp snull proc near ; send a null byte xor al,al ; the null call fprtbout ; send without logging and local echo ret snull endp khold: xor holdscr,1 ; toggle Hold screen byte for msx call kbhold ; tell DEC LK250 the hold kbd state clc ; kbhold is in file msuibm.asm ret tn_AYT: mov ah,255 ; 'I' Telnet Are You There call outchr ; send IAC (255) AYT (246) mov ah,246 call outchr clc ret tn_IP: mov ah,255 ; 'I' Telnet Interrrupt Process call outchr ; send IAC (255) IP (244) mov ah,244 call outchr clc ret ; Data General "Fn" function keys dgkf1: mov al,113 ; F1 sends RS q jmp dgkeyccom dgkf2: mov al,114 ; F2 sends RS r jmp dgkeyccom dgkf3: mov al,115 ; F3 sends RS s jmp dgkeyccom dgkf4: mov al,116 ; F4 sends RS t jmp short dgkeyccom dgkf5: mov al,117 ; F5 sends RS u jmp short dgkeyccom dgkf6: mov al,118 ; F6 sends RS v jmp short dgkeyccom dgkf7: mov al,119 ; F7 sends RS w jmp short dgkeyccom dgkf8: mov al,120 ; F8 sends RS x jmp short dgkeyccom dgkf9: mov al,121 ; F9 sends RS y jmp short dgkeyccom dgkf10: mov al,122 ; F10 sends RS z jmp short dgkeyccom dgkf11: mov al,123 ; F11 sends RS { jmp short dgkeyccom dgkf12: mov al,124 ; F12 sends RS | jmp short dgkeyccom dgkf13: mov al,125 ; F13 sends RS } jmp short dgkeyccom dgkf14: mov al,126 ; F14 sends RS ~ jmp short dgkeyccom dgkf15: mov al,112 ; F15 sends RS p jmp short dgkeyccom dgkSf1: mov al,'a' ; SF1 sends RS a jmp short dgkeyccom dgkSf2: mov al,'b' ; SF2 sends RS b jmp short dgkeyccom dgkSf3: mov al,'c' ; SF3 sends RS c jmp short dgkeyccom dgkSf4: mov al,'d' ; SF4 sends RS d jmp short dgkeyccom dgkSf5: mov al,'e' ; SF5 sends RS e jmp short dgkeyccom dgkSf6: mov al,'f' ; SF6 sends RS f jmp short dgkeyccom dgkSf7: mov al,'g' ; SF7 sends RS g jmp short dgkeyccom dgkSf8: mov al,'h' ; SF8 sends RS h jmp short dgkeyccom dgkSf9: mov al,'i' ; SF9 sends RS i jmp short dgkeyccom dgkSf10:mov al,'j' ; SF10 sends RS j jmp short dgkeyccom dgkSf11:mov al,'k' ; SF11 sends RS k jmp short dgkeyccom dgkSf12:mov al,'l' ; SF12 sends RS l jmp short dgkeyccom dgkSf13:mov al,'m' ; SF13 sends RS m jmp short dgkeyccom dgkSf14:mov al,'n' ; SF14 sends RS n jmp short dgkeyccom dgkSf15:mov al,'`' ; SF15 sends RS ` jmp short dgkeyccom ; Data General "C" keys C1..C4 dgkc1: mov al,92 ; C1 sends RS \ jmp short dgkc5 dgkc2: mov al,93 ; C2 sends RS ] jmp short dgkc5 dgkc3: mov al,95 ; C3 sends RS ^ jmp short dgkc5 dgkc4: mov al,96 ; C4 sends RS _ dgkc5: cmp dgd470mode,0 ; D470 ANSI mode active? je dgkeyccom ; e = no add al,40 ; yes, bias, C1=132 et seq dgkeyccom: ; common code mov ttyact,0 ; network, group chars for packet push ax cmp dgd470mode,0 ; D470 ANSI mode active? je dgkeyccom1 ; e = no mov al,ESCAPE ; send ESC [ 0 z call fprtbout mov al,'[' call fprtbout mov al,'0' ; first byte, always "0" call fprtbout pop ax sub al,112 ; remove bias (to 0..23) mov cl,10 ; split into two bytes xor ah,ah div cl ; al = quotient, ah = remainder push ax ; save remainder add al,'0' ; send high part (0..2) call fprtbout pop ax xchg ah,al add al,'0' ; send low part (0..9) call fprtbout mov al,'z' ; terminator mov ttyact,1 ; network, restore tty active flag ret dgkeyccom1:mov al,DGescape ; send DG escape (RS) call fprtbout ; with no echo pop ax mov ttyact,1 ; network, restore tty active flag call fprtbout ; send the second byte ret ; Keyboard "Compose" key to compose characters by the three stroke method kbdcompose proc near mov grab,1 ; say grabbing normal output call togmod call togmod ; update mode line ret kbdcompose endp ; DG POINT (aka CMD CURSOR-TYPE) dgpoint proc near ifndef no_graphics cmp tekflg,tek_active+tek_sg ; special graphics mode? jne dgpoint1 ; ne = no, ignore cmd call dgcrossrpt ; send crosshair report endif ; no_graphics dgpoint1:ret dgpoint endp ; DG N/C (normal, compressed font) key dgnckey proc near test flags.vtflg,ttd463+ttd470+ttd217 ; D463/D470/D217? jz dgnckey1 ; z = no, ignore call dgnctoggle ; toggle normal/compressed mode dgnckey1:clc ret dgnckey endp ; Compose char lookup and reemitter. fgrabber proc far push bx mov bx,grab ; count chars grabbed (want two) dec bx ; first char becomes bx=0 mov grabbox[bx],al ; stuff char in short buffer cmp bx,1 ; got both chars? pop bx jae fgrab2 ; ae = yes, go produce output inc grab ; keep grabbing ret ; return for the second ; process the byte pair fgrab2: mov grab,0 ; say done grabbing output push dx ; compose new single char result push di push es mov di,seg data1 mov es,di mov di,offset grl1lat ; use Latin1 ptr cmp vtcpage,852 ; CP852? jne fgrab2a ; ne = no mov di,offset grl1lat2 ; use Latin 2 fgrab2a:test flags.vtflg,ttd463+ttd470+ttd217 ; D463/D470/D217? jz fgrab3 ; z = no cmp dgkbl,16 ; Latin1? je fgrab3 ; e = yes mov di,offset grl1dgi ; get DG Internat ptr to structure cmp dgkbl,20 ; DG keyboard language, DG Internat? jne fgrab15 ; ne = no fgrab3: mov ax,word ptr grabbox ; get pair of chars call toupr ; convert AX to upper case call match jnc fgrab11 ; nc = found xchg ah,al call match jnc fgrab11 ; nc = match fgrab5: mov di,offset grl2lat ; use Latin1 ptr cmp vtcpage,852 ; CP852? jne fgrab5a ; ne = no mov di,offset grl2lat2 ; use Latin 2 fgrab5a:test flags.vtflg,ttd463+ttd470+ttd217 ; D463/D470/D217? jz fgrab6 ; z = no cmp dgkbl,16 ; Latin1? je fgrab6 ; e = yes mov di,offset grl2dgi ; get DG Internat ptr to structure cmp dgkbl,20 ; DG keyboard language, DG Internat? jne fgrab15 ; ne = no fgrab6: mov ax,word ptr grabbox mov dx,ax cmp vtcpage,852 ; CP852? je fgrab6a ; e = yes, use as-is call toupr ; convert AX to upper case fgrab6a:call match jnc fgrab7 ; nc = found xchg ah,al ; try reversed order xchg dh,dl call match jc fgrab8 ; c = not found fgrab7: cmp vtcpage,852 ; CP852? je fgrab11 ; e = yes, output as-is cmp dl,'a' ; lower case char? jb fgrab11 ; b = no, upper case or al,20h ; move to lower case output codes jmp short fgrab11 fgrab8: mov di,offset grl3lat ; use Latin1 ptr cmp vtcpage,852 ; CP852? jne fgrab8a ; ne = no mov di,offset grl3lat2 ; use Latin 2 fgrab8a:test flags.vtflg,ttd463+ttd470+ttd217 ; D463/D470/D217? jz fgrab9 ; z = no cmp dgkbl,16 ; Latin1? je fgrab9 ; e = yes mov di,offset grl3dgi ; get DG Internat ptr to structure cmp dgkbl,20 ; DG keyboard language, DG Internat? jne fgrab15 ; ne = no fgrab9: mov ax,word ptr grabbox xchg ah,al call match ; look for matching combination jc fgrab16 ; c = failed fgrab11:call foutprt ; send it to the host fgrab15:call togmod call togmod ; update mode line pop es pop di pop dx ret fgrab16:call fvtbell ; mismatch, beep, cancel jmp short fgrab15 ; finish up fgrabber endp ; worker for above match proc near push bx push si push di mov cl,es:[di] ; get count of pairs xor ch,ch inc di mov si,di ; start of char lists jcxz match2 ; nothing to look at mov si,di ; remember where pairs start mov bx,di add bx,cx add bx,cx ; output singles start here cld push cx ; save counter repne scasw ; look for a match pop cx jne match2 ; ne = no match sub di,2 ; backup to match sub di,si ; get item count shr di,1 ; count bytes mov al,es:[bx+di] ; get new output char pop di pop si pop bx clc ; say success ret match2: pop di pop si pop bx stc ; say no match ret match endp ; DEC LK201 keyboard keys and "User Definable Keys" in VT3xx mode decfind:mov al,1 ; Find jmp dfkout decinsert:mov al,2 ; Insert jmp dfkout decremove:mov al,3 ; Remove jmp dfkout decselect:mov al,4 ; Select jmp dfkout decprev:mov al,5 ; Previous screen jmp dfkout decnext:mov al,6 ; Next screen jmp dfkout decf6: mov al,17 ; key ident for DEC F6 jmp dfkout ; process it decf7: mov al,18 ; key ident for DEC F7 jmp dfkout ; process it decf8: mov al,19 ; key ident for DEC F8 jmp dfkout ; process it decf9: mov al,20 ; key ident for DEC F9 jmp dfkout ; process it decf10: mov al,21 ; key ident for DEC F10 jmp dfkout ; process it decf11: mov al,23 ; key ident for DEC F11 jmp dfkout ; process it decf12: mov al,24 ; key ident for DEC F12 jmp dfkout ; process it decf13: mov al,25 ; key ident for DEC F13 jmp dfkout ; process it decf14: mov al,26 ; key ident for DEC F14 jmp dfkout ; process it dechelp:mov al,28 ; key ident for DEC HELP jmp dfkout ; process it decdo: mov al,29 ; key ident for DEC DO jmp dfkout ; process it decf17: mov al,31 ; key ident for DEC F17 jmp dfkout ; process it decf18: mov al,32 ; key ident for DEC F18 jmp dfkout ; process it decf19: mov al,33 ; key ident for DEC F19 jmp dfkout ; process it decf20: mov al,34 ; key ident for DEC F20 jmp dfkout ; process it ; common worker to output contents of User Definable Key definition strings ; Enter with al = key ident (17 - 34) dfkout proc near push ax push bx push cx push es mov ttyact,0 ; network, group chars for packet test flags.vtflg,ttvt320+ttvt220 ; VT320/VT220? jnz dfkout4 ; nz = yes, else use VT100/VT52 default test flags.vtflg,tttek ; Tek? jnz dfkout4 ; nz = yes, try this mov ttyact,1 ; network, restore tty active flag cmp al,23 ; F11 sends ESC jne dfkou1 ; ne = not F11 mov al,escape call foutprt jmp dfkoutx dfkou1: cmp al,24 ; F12 sends BS jne dfkou2 ; ne = not F12 mov al,BS call foutprt jmp dfkoutx dfkou2: cmp al,25 ; F13 sends LF jne dfkoutx ; ne = not F13, ignore mov al,LF call foutprt dfkou3: jmp dfkoutx dfkout4:push ax ; VT320, use default definitions mov al,Escape ; char to send, CSI call foutprt mov al,'[' call foutprt ; send lead-in char in 7/8-bit form pop ax call fprtnout ; key ident (17-34) as ascii digits mov al,7eh ; tilde terminator mov ttyact,1 ; network, restore tty active flag call foutprt dfkoutx:pop es pop cx pop bx pop ax clc ret dfkout endp ; User Definable Keys udkf6: mov al,17 ; key ident for DEC F6 jmp udkout ; process it udkf7: mov al,18 ; key ident for DEC F7 jmp udkout ; process it udkf8: mov al,19 ; key ident for DEC F8 jmp udkout ; process it udkf9: mov al,20 ; key ident for DEC F9 jmp udkout ; process it udkf10: mov al,21 ; key ident for DEC F10 jmp udkout ; process it udkf11: mov al,23 ; key ident for DEC F11 jmp udkout ; process it udkf12: mov al,24 ; key ident for DEC F12 jmp udkout ; process it udkf13: mov al,25 ; key ident for DEC F13 jmp udkout ; process it udkf14: mov al,26 ; key ident for DEC F14 jmp udkout ; process it udkf15: mov al,28 ; key ident for DEC HELP jmp udkout ; process it udkf16: mov al,29 ; key ident for DEC DO jmp udkout ; process it udkf17: mov al,31 ; key ident for DEC F17 jmp udkout ; process it udkf18: mov al,32 ; key ident for DEC F18 jmp udkout ; process it udkf19: mov al,33 ; key ident for DEC F19 jmp udkout ; process it udkf20: mov al,34 ; key ident for DEC F20 ; jmp udkout ; process it udkout proc near push es mov ttyact,0 ; network, group chars for packet mov bl,al ; VT3XX key ident, UDK style (17-34) sub bl,17 ; minus starting offset of 17 xor bh,bh cmp bl,17 ; out of range? ja udkoutx ; a = yes, ignore shl bx,1 ; index words mov bx,udkseg[bx] ; segment of definition or bx,bx ; anything there? jz udkoutx ; z = no mov es,bx ; definition segment xor bx,bx ; and offset mov cl,es:[bx] ; get string length byte xor ch,ch ; use cx as a counter jcxz udkoutx ; z = empty udkou1: inc bx ; es:bx is now the string text mov al,es:[bx] ; get a char push bx push cx push es cmp cx,1 ; last byte jne udkou2 ; ne = not last byte mov ttyact,1 ; network, restore tty active flag udkou2: call foutprt ; output pop es pop cx pop bx loop udkou1 udkoutx:pop es clc ret udkout endp ; Wyse-50 function keys F1..F16 wykf1: mov al,'@' ; Wyse F1 jmp short wykfcom wykf2: mov al,'A' ; Wyse F2 jmp short wykfcom wykf3: mov al,'B' jmp short wykfcom wykf4: mov al,'C' jmp short wykfcom wykf5: mov al,'D' jmp short wykfcom wykf6: mov al,'E' jmp short wykfcom wykf7: mov al,'F' jmp short wykfcom wykf8: mov al,'G' jmp short wykfcom wykf9: mov al,'H' jmp short wykfcom wykf10: mov al,'I' jmp short wykfcom wykf11: mov al,'J' jmp short wykfcom wykf12: mov al,'K' jmp short wykfcom wykf13: mov al,'L' jmp short wykfcom wykf14: mov al,'M' jmp short wykfcom wykf15: mov al,'N' jmp short wykfcom wykf16: mov al,'O' ; Wyse F16 jmp short wykfcom ; Wyse-50 Shift function keys F1..F16 wykSf1: mov al,'`' ; Wyse Shift F1 jmp short wykfcom wykSf2: mov al,'a' ; Wyse Shift F2 jmp short wykfcom wykSf3: mov al,'b' jmp short wykfcom wykSf4: mov al,'c' jmp short wykfcom wykSf5: mov al,'d' jmp short wykfcom wykSf6: mov al,'e' jmp short wykfcom wykSf7: mov al,'f' jmp short wykfcom wykSf8: mov al,'g' jmp short wykfcom wykSf9: mov al,'h' jmp short wykfcom wykSf10:mov al,'i' jmp short wykfcom wykSf11:mov al,'j' jmp short wykfcom wykSf12:mov al,'k' jmp short wykfcom wykSf13:mov al,'l' jmp short wykfcom wykSf14:mov al,'m' jmp short wykfcom wykSf15:mov al,'n' jmp short wykfcom wykSf16:mov al,'o' ; Wyse Shift F16 wykfcom:mov ttyact,0 ; network, group chars for packet push ax ; save key code mov al,1 ; send SOH keycode CR call foutprt pop ax call foutprt mov al,CR mov ttyact,1 ; network, restore tty active flag call foutprt ret ; Change Telnet sessions ifndef no_tcp ses1 proc near mov bx,0 mov cx,1 jmp short nextses4 ses1 endp ses2 proc near mov bx,1 mov cx,1 jmp short nextses4 ses2 endp ses3 proc near mov bx,2 mov cx,1 jmp short nextses4 ses3 endp ses4 proc near mov bx,3 mov cx,1 jmp short nextses4 ses4 endp ses5 proc near mov bx,4 mov cx,1 jmp short nextses4 ses5 endp ses6 proc near mov bx,5 mov cx,1 jmp short nextses4 ses6 endp endif ; no tcp nextses proc near ifndef no_tcp cmp flags.comflg,'t' ; doing Telnet? je nextses1 ; e = yes clc ; do not exit Connect mode ret nextses1:mov bx,sescur ; current session ident mov cx,6 ; sessions to consider nextses3:inc bx cmp bx,6 ; over the top yet jb nextses4 ; b = no xor bx,bx ; wrap nextses4:cmp seslist[bx],0 ; is this session active? jge nextses5 ; ge = yes loop nextses3 clc ret ; do nothing nextses5:push bx mov bx,sescur ; old session call termswapout ; save current terminal items pop bx mov sescur,bx ; next session, from above call tcpstart ; start session, ident in bl mov bx,sescur ; new session call termswapin ; get data structures mov kbdflg,' ' ; return Connect mode stc ; but exit Connect mode now else clc endif ; no_tcp ret nextses endp vtsesmac proc far ; SESSION macro mov vtmacname,offset vtsesname mov al,bl ; session number add al,'1' ; to ascii, from 1 mov vtsesnum,al ; to name mov vtmaclen,vtseslen call dword ptr vtmacroptr ; FAR pointer ret vtsesmac endp ; Call from mszibm DG components to put system into DG special graphics mode, ; and thus to cause incoming material to be still sent to the text emulator. ; This also unshifts the screen (as seen on the status line) before starting ; graphics so the column 81 stuff comes out right. dgsettek proc far ifndef no_graphics cmp tekflg,tek_active+tek_sg ; inited already? je dgsettek3 ; e = yes push bx push cx mov cl,byte ptr low_rgt+1 ; examine whole screen inc cl ; lines in emulation part xor ch,ch mov bx,cx ; for status line xor al,al xchg al,linescroll[bx] ; status line scroll value or al,al jz dgsettek2 ; z = no shift in effect xor bx,bx ; start of screen dgsettek1:sub linescroll[bx],al ; unscroll by status line amount inc bx ; next line loop dgsettek1 ; do all emulation lines dgsettek2:pop cx pop bx or tekflg,tek_sg ; set special graphics mode call TEKINI ; go to Tektronix Emulator endif ; no_graphics dgsettek3:ret dgsettek endp ;[HF]940206 jpnxltkey ;[HF]940207 ;[HF]940206 Check if leading byte of Japanese double byte code ;[HF]940207 Range of Japanese second byte ;[HF]940207 ((AL >= 0x40) && (AL <= 0x7e))||((AL >= 0x80) && (AL <= 0xfc)) ;[HF]940207 ;[HF]940206 If not Japanese, clear carry and return. ;[HF]940207 jpnxltkey proc near ;[HF]940206 cmp keypend,0 ;[HF]940207 Kanji second byte? jne jpnxltk3 ;[HF]940207 ne = yes, second byte call iskanji1 ;[HF]941010 Kanji leading byte ? jc jpnxltk2 ;[HF]941010 c = yes call iskana ;[HF]941010 Katakana ? jnc jpnxltk1 ;[HF]941010 nc = no cmp flags.oshift,(128+3) ;[HF]941012 DEC-Kanji ? je jpnxltk1c ;[HF]941012 e = yes, use X208 Katakana cmp flags.oshift,(128+2) ;[HF]941012 EUC-Kanji ? jne jpnxltk1b ;[HF]941012 ne = no call outkana ;[HF]941011 katakana output mov keypend,0 ;[HF]941011 no pending char stc ;[HF]941011 say, we have done ret ;[HF]941011 jpnxltk1b: ;[HF]941011 cmp flags.oshift,(128+1) ;[HF]941012 JIS7-Kanji ? jne jpnxltk1a ;[HF]941012 ne = no jpnxltk1c: ;[HF]941012 call dblkana ;[HF]941012 get double byte code or ax,8080h ;[HF]941012 make it GR mov keypend,ax ;[HF]941012 jmp jpnxltk5c ;[HF]941012 jpnxltk1: ;[HF]940207 cmp flags.oshift,(128+1) ;[HF]940211 JIS7? jne jpnxltk1a ;[HF]940211 ne = no cmp keyj7st,0 ;[HF]940211 ASCII state? je jpnxltk1a ;[HF]940211 e = yes push ax ;[HF]940211 mov al,ESCAPE ;[HF]940211 call chrout ;[HF]940211 mov al,'(' ;[HF]940211 call chrout ;[HF]940211 mov al,byte ptr jis7des+1 ;[HF]940211 call chrout ;[HF]940211 mov keyj7st,0 ;[HF]940211 pop ax ;[HF]940211 jpnxltk1a: ;[HF]940211 mov keypend,0 ;[HF]940207 Clear second byte flag clc ;[HF]940206 tell that not Japanese ret ;[HF]940206 jpnxltk2: ;[HF]940206 push ax ;[HF]940207 mov ah,al ;[HF]940207 xor al,al ;[HF]940207 mov keypend,ax ;[HF]940207 save it for later use pop ax ;[HF]940207 stc ;[HF]940206 tell that Japanese ret ;[HF]940206 jpnxltk3: ;[HF]940207 cmp al,40h ;[HF]940207 jb jpnxltk4 ;[HF]940207 not the second byte cmp al,7eh ;[HF]940207 jbe jpnxltk5 ;[HF]940207 Yes second byte cmp al,80h ;[HF]940207 jb jpnxltk4 ;[HF]940207 not the second byte cmp al,0fch ;[HF]940207 jbe jpnxltk5 ;[HF]940207 Yes second byte jpnxltk4: ;[HF]940207 jmp jpnxltk1 ;[HF]940211 treat as single byte char. jpnxltk5: ;[HF]940207 mov byte ptr keypend,al ;[HF]940207 make double byte code mov ax,keypend ;[HF]940207 Shift-JIS code call jpnftox ;[HF]940207 translate to EUC(JIS-GR) jpnxltk5c: ;[HF]941012 cmp flags.oshift,(128+1) ;[HF]940211 JIS7? je jpnxltk5a ;[HF]940211 e = yes cmp flags.oshift,(128+2) ;[HF]940214 EUC? je jpnxltk5b ;[HF]940214 e = yes cmp flags.oshift,(128+3) ;[HF]941012 DEC? je jpnxltk5b ;[HF]941012 e = yes mov ax,keypend ;[HF]940214 No. use Shift-JIS code jmp short jpnxltk5b ;[HF]940211 jpnxltk5a: ;[HF]940211 and ax,7f7fh ;[HF]940211 cmp keyj7st,2 ;[HF]940211 Kanji state? je jpnxltk5b ;[HF]940211 e=yes, no shift push ax ;[HF]940211 mov al,ESCAPE ;[HF]940211 call chrout ;[HF]940211 mov al,'$' ;[HF]940211 call chrout ;[HF]940211 mov al,byte ptr jis7des ;[HF]940211 call chrout ;[HF]940211 mov keyj7st,2 ;[HF]940211 pop ax ;[HF]940211 jpnxltk5b: ;[HF]940211 push ax ;[HF]940214 save dble byte code mov al,ah ;[HF]940207 call chrout ;[HF]940207 send leading byte pop ax ;[HF]940214 remember dble byte code mov ah,al ;[HF]940207 call chrout ;[HF]940207 send second byte mov keypend,0 ;[HF]940207 clear double byte flag stc ;[HF]940207 say no more char ret ;[HF]940207 jpnxltkey endp ;[HF]940206 ;[HF]941011 outkana ;[HF]941011 ;[HF]941011 Output Shift-JIS katakana code in AL to com port. outkana proc near ;[HF]941011 push ax ;[HF]941011 save AX push bx ;[HF]941011 save BX cmp flags.oshift,(128+1) ;[HF]941012 JIS7 ? je outkan1 ;[HF]941012 e = yes mov bl,flags.oshift ;[HF]941011 save output-shift mov flags.oshift,0 ;[HF]941011 Do our own shift mov bh,al ;[HF]941011 save AL mov al,SS2 ;[HF]941011 SS2 call chrout ;[HF]941011 mov al,bh ;[HF]941011 restore AL or al,80h ;[HF]941011 8th bit On call chrout ;[HF]941011 jmp outkanx ;[HF]941012 outkan1:cmp keyj7st,1 ;[HF]941012 already in katakana mode? je outkan3 ;[HF]941012 e = yes cmp keyj7st,2 ;[HF]941012 in kanji mode? jne outkan2 ;[HF]941012 ne = no mov bh,al ;[HF]941012 save AL mov al,ESCAPE ;[HF]941012 call chrout ;[HF]941012 mov al,'(' ;[HF]941012 call chrout ;[HF]941012 mov al,byte ptr jis7des+1 ;[HF]941012 call chrout ;[HF]941012 outkan2:mov al,SOchar ;[HF]941012 SO call chrout ;[HF]941012 mov keyj7st,1 ;[HF]941012 mov al,bh ;[HF]941012 outkan3:and al,7fh ;[HF]941012 mask 8th bit call chrout ;[HF]941012 outkanx:mov flags.oshift,bl ;[HF]941011 restore output-shift pop bx ;[HF]941011 restore BX pop ax ;[HF]941011 restore AX ret ;[HF]941011 outkana endp ;[HF]941011 ;[HF]941012 dblkana ;[HF]941012 ;[HF]941012 convert single byte katakana code to double byte code ;[HF]941012 Input: AL Katakana code in JIS ;[HF]941012 Outpt: AX Double byte JIS katakana code (AH first) dblkana proc near ;[HF]941012 push es push bx ;[HF]941012 sub ax,32 ;[HF]941012 and ax,3fh ;[HF]941012 mov bx,seg kanatbl mov es,bx mov bx,offset kanatbl ;[HF]941012 add bx,ax ;[HF]941012 add bx,ax ;[HF]941012 word address mov ax,es:[bx] ;[HF]941012 pop bx ;[HF]941012 pop es ret ;[HF]941012 dblkana endp ;[HF]941012 ;[HF]941010 iskana ;[HF]941010 ;[HF]941010 Check if AL is Shift-JIS Katakana code or not. ;[HF]941010 If Katakana, program returns with carry set, ;[HF]941010 if not, carry clear. ;[HF]941010 ;[HF]941010 Note: Shift-JIS Katakana is in the range ;[HF]941010 ((AL >= 0xa0) && (AL <= 0xdf)) ;[HF]941010 where AL = 0xa0 is space ;[HF]941010 iskana proc near ;[HF]941010 cmp al,0a0h ;[HF]941010 jb iskanan ;[HF]941010 b = no cmp al,0dfh ;[HF]941010 ja iskanan ;[HF]941010 a = no stc ;[HF]941010 yes, katakana jmp short iskanax ;[HF]941010 iskanan:clc ;[HF]941010 no, not katakana iskanax:ret ;[HF]941010 iskana endp ;[HF]941010 ;[HF]940207 Range of Shift-JIS Kanji leading byte ;[HF]940207 ((AL >= 0x81) && (AL <= 0x9f))||((AL >= 0xe0) && (AL <= 0xfc)) iskanji1 proc near ;[HF]941010 cmp al,81h ;[HF]940207 jb iskan1n ;[HF]940207 b = No, not Kanji leading cmp al,9fh ;[HF]940207 jbe iskan1y ;[HF]940207 Yes, Japanese leading byte cmp al,0e0h ;[HF]940207 jb iskan1n ;[HF]940207 No, not Japanese cmp al,0fch ;[HF]940207 jbe iskan1y ;[HF]940207 Yes, Japanese leading byte iskan1n:clc ;[HF]941010 jmp short iskan1x ;[HF]941010 iskan1y:stc ;[HF]941010 iskan1x:ret ;[HF]941010 iskanji1 endp ;[HF]941010 code ends code1 segment assume cs:code1 ; Set (define) the DEC "User Definable Keys". Inserts text definitions for ; keyboard verbs \KdecF6 ...\KdecF14, \KdecHELP, \KdecDO, \KdecF17...\KdecF20. ; Enter with the DCS definition string as key-number/hex-chars. UDK key number ; is 17 for \KdecF6, et seq, the definition are pairs of hex digits converted ; here to a single byte per pair. The DCS definition string is pointed at by ; DS:SI, and the byte count is in CX. ; Example: 17/54657374204636 means key \KdecF6 sends string "Test F6" setudk proc near push ax push bx push cx push si push di push es cld lodsb ; get key ident first byte sub al,'0' ; ascii to binary mul ten ; times 10 xchg ah,al ; to ah lodsb ; get key ident second byte sub al,'0' ; ascii to binary add al,ah ; plus high order part xor ah,ah mov bx,ax ; key ident, 17 - 34 lodsb ; skip slash separator sub cx,3 ; three less bytes in the string jge setudk0 ; ge = had three or more bytes jmp setudkx ; else error setudk0:sub bx,17 ; remove key ident bias of 17 cmp bx,17 ; out of range? ja setudkx ; a = yes, ignore shl bx,1 ; index words cmp udkseg[bx],0 ; has a segment been allocated for it? je setudk1 ; e = no mov ax,udkseg[bx] ; get segment to es mov es,ax mov ah,freemem ; deallocate old memory block, es:0 int dos mov udkseg[bx],0 ; clear table entry too setudk1:and cl,not 1 ; force an even number of inputs jcxz setudkx ; z = no definition, clear entry push bx ; save index BX mov bx,cx ; get string length shr bx,1 ; two hex digits per final byte add bx,15+1 ; round up plus length byte shr bx,1 ; convert to paragraphs shr bx,1 shr bx,1 shr bx,1 mov di,bx ; remember request mov ah,alloc ; allocate BX paragraphs int dos jc setudkx ; c = failure cmp di,bx ; requested vs allocated pop bx ; recover bx je setudk2 ; e = enough mov ah,freemem ; return the memory, es is ptr int dos jmp short setudkx ; exit failure setudk2:mov es,ax ; segment of allocated memory mov udkseg[bx],ax ; segment:0 of definition string xor di,di cld mov al,cl ; length of string shr al,1 ; two hex bytes per stored byte xor ch,ch stosb ; store length byte jcxz setudkx ; z = empty string setukd3:lodsb ; get first hex digit dec cx ; adjust count remaining or al,20h ; to lower case cmp al,'9' ; digit? jbe setudk4 ; be = yes sub al,'a'-'9'-1 ; hex letter to column three setudk4:sub al,'0' ; ascii to binary shl al,1 ; times 16 shl al,1 shl al,1 shl al,1 mov ah,al ; save in ah lodsb ; get second hex digit or al,20h ; to lower case cmp al,'9' ; digit? jbe setudk5 ; be = yes sub al,'a'-'9'-1 ; hex letter to column three setudk5:sub al,'0' ; ascii to binary add al,ah ; join both parts stosb ; store final byte loop setukd3 setudkx:pop es pop di pop si pop cx pop bx pop ax clc ret setudk endp ; Clear all User Definable Keys, deallocate memory for their definitions udkclear proc near push ax push bx push cx push es mov cx,17 ; 17 entries xor bx,bx udkcle1:mov ax,udkseg[bx] ; segment of definition or ax,ax ; segment defined? jz udkcle2 ; z = no, try next key mov es,ax mov udkseg[bx],0 ; clear the entry mov ah,freemem ; release the memory int dos udkcle2:add bx,2 ; word index loop udkcle1 ; do all pop es pop cx pop bx pop ax clc ret udkclear endp fsetpos proc far call setpos ret fsetpos endp frepaint proc far call repaint ret frepaint endp code1 ends code segment assume cs:code ; these commands invoke Quit cdos: mov al,'P' ; Push to DOS jmp short cmdcom cstatus:mov al,'S' ; Status jmp short cmdcom cquit: mov al,'C' ; Exit Connect mode jmp short cmdcom cquery: mov al,'?' ; Help jmp short cmdcom chang: mov al,'H' ; Hangup, drop DTR & RTS jmp short cmdcom cmdcom: mov kbdflg,al ; pass char to msster.asm via kbdflg stc ; signal that Quit is needed ret ; general character out for emulator chrout proc near cmp flags.vtflg,0 ; emulating? je chrou5 ; e = no call fanskbi ; say we had keyboard input cmp al,cr ; CR? jne chrou5 ; ne = no, just output it and return test vtemu.vtflgop,anslnm ; ANSI new-line mode set? jz chrou5 ; z = no, just send the cr cmp dupflg,0 ; full duplex? je chrou4 ; e = yes cmp al,trans.seol ; End of Line char? jne chrou5 ; ne = no chrou4: mov ah,trans.seol ; save eol char push ax ; save on stack mov trans.seol,lf ; make LF the eol char call foutprt ; output a carriage-return mov al,lf ; followed by a line feed call foutprt ; send the LF pop ax mov trans.seol,ah ; restore eol char ret chrou5: call foutprt ret chrout endp ; Screen dump entry from keyboad xlat dmpscn proc near ; dump screen to file ifndef no_graphics cmp flags.vtflg,tttek ; doing Tektronix emulation? je dmpscn2 ; e = yes, use Tek emulator cmp tekflg,tek_active+tek_dec ; emulation a Tektronix? jne dmpscn1 ; ne = no dmpscn2:call tekdmp ; near-call Tek screen dump utility clc ret endif ; no_graphics dmpscn1:call dumpscr ; do buffer to file clc ; do not exit Connect mode ret dmpscn 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 reads the screen image saved in vscreen. dumpscr proc near 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: mov ah,3 ; get cursor position xor bh,bh ; page 0 int screen push dx ; save it mov dh,byte ptr low_rgt+1 ; go to status line inc dh xor dl,dl ; left most column mov ah,2 ; set cursor xor bh,bh ; page 0 int screen mov dx,offset dmperr ; say no can do mov ah,prstr int dos pop dx ; get original cursor position mov ah,2 ; set cursor xor bh,bh ; page 0 int screen 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 push di ; read screen buffer, write lines push si push es mov cl,byte ptr low_rgt+1 ; number of lines - 2 add cl,2 ; number of line on screen xor ch,ch les si,vs_ptr ; seg and offset of vscreen sub si,vswidth*2 ; prep for inc below dmp2: add si,vswidth*2 ; virtual screen width in bytes push si push cx ; save outer loop counter push di mov di,offset decbuf ; data segment memory mov cl,byte ptr low_rgt ; number of columns on screen -1 inc cl xor ch,ch dmp3: mov ax,word ptr es:[si] ; read char + attribute or al,al ; is it a null? jnz dmp3c ; nz = no mov al,' ' ; replace null with space dmp3c: mov byte ptr [di],al ; store just char, don't use es: inc si ; update pointers inc si inc di loop dmp3 ; do for each column mov cl,byte ptr low_rgt ; number of columns on screen - 1 inc cl xor ch,ch push es mov ax,ds mov es,ax ; set es to data segment for es:di mov di,offset decbuf ; start of line add di,cx ; plus length of line dec di ; minus 1 equals end of line mov al,' ' ; thing to scan over std ; set scan backward repe scasb ; scan until non-space cld ; set direction forward pop es je dmp3a ; e = 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 decbuf ; array to be written mov bx,dmphand ; need file handle mov ah,write2 ; write the line int dos pop di pop cx ; get line counter again pop si ; screen offset jc dmp3b ; c = error loop dmp2 ; do next line dmp3b: mov dx,offset dumpsep ; put in formfeed/cr/lf mov bx,dmphand ; need file handle mov cx,3 ; three bytes overall mov ah,write2 ; write them mov bx,dmphand ; file handle int dos mov bx,dmphand ; need file handle mov ah,close2 ; close the file now int dos pop es pop si pop di pop dx pop cx pop bx pop ax clc ret dumpscr endp togmod proc FAR call trnmod ; FAR callable trnmod ret togmod endp ; Toggle Mode Line trnmod proc near cmp inemulator,0 ; in terminal emulator? je trnm1 ; e = no, no mode line cmp flags.modflg,1 ; mode line enabled and owned by us? jne trnm1 ; ne = no, don't touch it cmp flags.vtflg,tttek ; Tek mode? je trnm1 ; e = yes test tekflg,tek_dec ; in Tek submode? jnz trnm1 ; nz = yes, no mode line changes test yflags,modoff ; mode line already off? jnz trnm2 ; nz = yes, go turn on or yflags,modoff ; say modeline is toggled off cmp flags.vtflg,0 ; emulating none? jne trnm0 ; ne = no mov lastsec,-1 ; tickle tod clock push dx call fgetpcur ; get physical cursor mov cursor,dx pop dx trnm0: 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 call fgetpcur ; get physical cursor mov cursor,dx 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 modlin proc near cmp isps55,0 ; [HF]940206 Japanese PS/55 ? je modl21 ; [HF]940206 e = no cmp ps55mod,0 ; [HF]940206 can we use modeline? jne modl21 ; [HF]940206 ne = yes mov ax,1401h ; [HF]940206 user uses the modeline mov ps55mod,al ; [HF]940206 save current status int 16h ; [HF]940206 OK, now in our hands modl21: push si push di push es mov ax,ds mov es,ax mov si,offset modmaster ; master template mov di,offset modbuf ; working copy mov lastsec,-1 ; tickle tod clock cld modl20: lodsb stosb cmp al,'$' ; at end? jne modl20 ; ne = no mov bx,argadr ; get argument block mov al,[bx].baudb ; get baud bits mov si,offset unkbaud ; assume unknown baud mov cx,size m_baud ; length of baud space cmp al,baudnsiz ; beyond end of table? jnb modl2 ; nb = yes, use default mul cl xor ah,ah add ax,offset baudn mov si,ax modl2: mov di,offset modbuf.m_baud cld rep movsb ; copy in baud rate mov bx,portval mov al,[bx].parflg ; get parity code and al,3 ; regular parity uses two bits mov ah,al shl al,1 ; each is 3 bytes long add al,ah xor ah,ah add ax,offset parnams ; names of parity settings mov si,ax mov cx,3 ; each is 3 long mov di,offset modbuf.m_par push di rep movsb pop di test [bx].parflg,PARHARDWARE ; using hardware parity? jz modl2b ; z = no mov al,'8' ; say 8 data bits stosb jmp short modl2a modl2b: cmp byte ptr [di],'8' ; any parity? jne modl2a ; ne = yes, use existing '7' test flags.remflg,d8bit ; 8 bit display? jnz modl2a ; nz = yes mov al,'7' stosb ; overwrite '8' with '7' modl2a: mov si,offset remmsg ; assume remote echoing test yflags,lclecho ; local echo on? jz modl3 ; z = no mov si,offset lclmsg ; say echo is local modl3: mov cx,3 ; size of value mov di,offset modbuf.m_echo rep movsb mov al,portno ; communications port cmp al,' ' ; binary (non-printable)? jae modl4 ; ae = no, ascii add al,'0' ; convert to ascii modl4: mov modbuf.m_prt,al ; fill in port number mov al,portno cmp repflg,0 ; REPLAY? je modl5 ; e = no mov si,offset repmsg ; say "REPLAY" mov cx,repmsgl ; its length mov di,offset modbuf.m_prt mov al,' ' ; start with a space stosb mov dx,24 ; space to be filled sub dx,cx ; amount we will use here rep movsb ; copy string mov cx,dx rep stosb ; flesh out with spaces jmp modl10 modl5: cmp al,'4' ; in networks material? jbe modl10 ; be = no ifndef no_tcp cmp flags.comflg,'t' ; doing TCP/IP Telnet? jne modl5d ; ne = no mov si,offset tcphost ; name of host mov di,offset modbuf.m_prt - 5 ; overwrite "port:" ifdef nls_portuguese dec di ; "porta:" endif ; nls_portuguese modl5c: mov ax,sescur ; ident of session add al,'1' ; ascii, show as 1:nodename mov ah,':' stosw ; store that much mov cx,28 ; bytes max modl5a: lodsb or al,al ; at null terminator? jz modl5b ; z = yes stosb loop modl5a modl5b: mov al,' ' ; fill out with spaces rep stosb ; noop if cx == 0 jmp short modl5d ; done with tcp/ip endif ; no_tcp modl5d: mov bx,offset comptab ; table of comms ports mov cl,[bx] ; number of entries xor ch,ch inc bx modl6: mov dx,[bx] ; length of this entry mov si,bx add si,2 ; points to entry text string add si,dx ; point to qualifier cmp [si],al ; our port? je modl7 ; e = yes add bx,[bx] ; add text length add bx,4 ; plus count and qualifier loop modl6 ; next entry jmp short modl10 ; no match, curious modl7: mov si,bx ; point at entry add si,2 ; point at string mov cx,[bx] ; length of string mov di,offset modbuf.m_prt mov al,' ' ; start with a space stosb mov dx,17 ; space to be filled ifdef nls_portuguese dec dx endif ; nls_portuguese sub dx,cx ; amount we will use here rep movsb ; copy string cmp flags.comflg,'F' ; Fossil? jne modl9 ; ne = no mov al,'-' ; punctuation stosb mov ax,fossil_port ; port inc ax ; count from one to user push dx ; preserve reg for below call dec2di ; write port pop dx sub dx,2 ; dash and digit add di,2 cmp fossil_port,9 ; two digits? jbe modl9 ; be = no dec dx ; yes, one less slot inc di modl9: mov cx,dx mov al,' ' rep stosb ; flesh out with spaces modl10: mov cx,8 ; blank out terminal id field mov si,offset mtty ; assume no terminal emulation mov di,offset modbuf.m_term ; destination rep movsb ; copy it in mov word ptr modbuf.m_prn,' '; assume not printing the screen mov modbuf.m_prn+2,' ' test anspflg,prtscr+2 ; print the screen? (msz uses 1 & 2) jz modl10a ; z = no mov word ptr modbuf.m_prn,'RP' ; yes. display PRN at end of line mov modbuf.m_prn+2,'N' modl10a:mov modbuf.m_comp,' ' ; flag for not-compose cmp grab,0 ; doing Compose grabbing? je modl11 ; e = no mov modbuf.m_comp,'C' ; flag for compose modl11: cmp inemulator,0 ; in terminal emulator now? jne modl11a ; ne = yes pop es ; do nothing pop di pop si ret modl11a:push dx cmp flags.vtflg,0 ; emulating? je modl12 ; e = no and yflags,not modoff ; update local flags (mode line on) call fansdsl ; get extras from emulator modl12: mov dx,offset modbuf ; mode line image ptr for putmod call putmod ; display mode line mov dx,cursor ; restore active cursor position call fsetpos ; set cursor pop dx pop es pop di pop si ret modlin endp fmodlin proc far call modlin ret fmodlin endp ; toggle between text and graphics modes vtans52 proc near cmp flags.vtflg,0 ; emulating? je vtans52a ; e = no call ans52t ; call MSZ toggle-it routine cmp flags.vtflg,tttek ; Tek now? je vtans52a ; e = yes test tekflg,tek_tek+tek_dec+TEK_SG ; Tek submode? jnz vtans52a ; nz = yes call scrini ; check on screen size changes vtans52a:clc ; clear c bit so don't exit Connect ret vtans52 endp ftrnprs proc far call trnprs ret ftrnprs endp trnprs proc near push ax ; toggle ^ PrtSc screen to printer test anspflg,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 fvtbell ; Not Ready, complain ; pop ax ; stc ; say failure ; ret ; and ignore request trnpr2: xor anspflg,prtscr ; flip the flag test yflags,modoff ; mode line off? jnz trnpr3 ; nz = yes call fmodlin ; else rewrite mode line trnpr3: pop ax clc ; return carry clear (don't quit) ret trnprs endp code ends code1 segment assume cs:code1 pntdead proc near ; display printer is inoperative msg push ax test yflags,modoff ; is mode line off? jnz pntdea1 ; nz = off, skip msg push bx mov dx,offset pntmsg ; say printer not ready call fputmod ; write on mode line pop bx pntdea1:pop ax stc ; say printer not ready ret pntdead endp endif ; no_terminal ;;;;; General screen management routines for IBM PC ; computes screen location to ax, given row and col in [dh,dl], resp. scrloc proc near push cx mov cl,crt_cols cmp inemulator,0 ; emulating? je scrloc1 ; e = no cmp flags.vtflg,0 ; emulating anything? je scrloc1 ; e = no mov cl,vswidth scrloc1:mov al,dh ; get row mul cl ; multiply by number of columns add al,dl ; plus current column number adc ah,0 ; ripple carry shl ax,1 ; double for attributes pop cx ret scrloc endp ; Routine to set cursor type. Pass cursor type in al: 0,4 = No cursor, ; 1 = Underline cursor, 2 = Block cursor. All cursors blink due to hardware. ; For EGA boards running in non-25 line mode the cursor emulation is turned ; off during cursor shape changing and restored afterward. It's another ; ega Feature. [jrd] ; Sense crt_mode 18h as Tseng Labs UltraPAK mono board in 132 column mode. csrtype proc near push cx ; save the reg mov cx,0F00H ; assume no cursor test al,4 ; no cursor? jz csrtyp6 ; z = no xor al,al ; set type to invisible csrtyp6:or al,al ; no cursor? jz csrty2 ; z = yes, no cursor cmp crt_mode,7 ; B&W card? je csrty3 ; e = yes, different sizes cmp crt_mode,18h ; Tseng UltraPAK mono board? je csrty3 ; e = yes, use mono cursor mov cx,0607H ; use CGA underline cursor cmp al,2 ; Block? jne csrty2 ; ne = no, set it now csrty1: xor ch,ch ; make cursor a block csrty2: cmp ega_mode,0 ; ega board active? je csrty4 ; e = no test tv_mode,10h ; DV active? jnz csrty4 ; nz = yes, it messes with the cursor cmp byte ptr low_rgt+1,23 ; standard screen length? je csrty4 ; e = yes, use regular cursor setting cmp byte ptr low_rgt+1,24 ; ANSI, standard screen length? je csrty4 ; e = yes, use regular cursor setting push es ; EGA. turn off cursor emulation mov ax,40h ; 40:87h is ega Info byte mov es,ax push es:[87h] ; save Info byte around call or byte ptr es:[87h],1 ; set emulation off (low bit = 1) mov ah,1 ; video function for set cursor type int screen pop es:[87h] ; restore Info byte pop es ; and our work register pop cx ret csrty4: push ax mov ah,1 ; video function for set cursor type int screen ; regular cursor shape setting pop ax csrty5: pop cx ret csrty3: mov cx,0B0CH ; assume B&W underline cursor cmp al,2 ; Block? jne csrty2 ; ne = no, set it now jmp short csrty1 ; make it a block csrtype endp fcsrtype proc far call csrtype ret fcsrtype endp ; Get CRT mode - returns mode in variable crt_mode, ; updates crt_cols, and low_rgt. ; For EGA active it looks in Bios work memory 40:84H for number of rows scrmod proc near push ax push dx mov ah,0fh ; get current video state int screen and al,not 80h ; strip "preserve regen" bit 80h mov crt_mode,al ; store CRT mode value mov crt_cols,ah ; store # of cols mov dl,ah ; # of cols again mov dh,crt_lins ; and # of rows (constant from msster) cmp tv_mode,0 ; Topview active? je scrmod2 ; e = no test tv_mode,20h ; Japanese DOS active? jnz scrmod2 ; nz = yes, do not do Int 15h push cx push bx mov ah,12h ; TV, Get Object Length mov bx,0901h ; object, BL = 01 = chars/line int 15h pop ax ; chars/line from stack dword cmp al,10 ; keep things sane, chars per line ja scrmod7 ; a = might be sane pop ax ; clean stack jmp scrmod2 ; wacko, ignore DV stuff scrmod7:mov crt_cols,al ; TV windowed screen columns pop ax ; clear rest of dword from stack mov ah,12h ; send mov bx,1 ; handle (0*256) + window (me, 1) int 15h pop bx ; handle low word pop bx ; handle high word to BX for next call mov ax,1024h ; TV Get Virtual Screen Info int 15h ; can yield 8KB, yikes scrmod1:cmp cx,80*25*2 ; get sanity for DV big DOS window jbe scrmod1a ; be = reasonable size shr cx,1 ; reduce size jmp short scrmod1 ; and try again scrmod1a:mov ax,cx ; CX is virtual screen size, bytes mov bl,crt_cols ; divide by columns to get width shl bl,1 ; get words (char and attribute) div bl ; al = lines, ah = fractions of line dec al ; count this from zero like the Bios mov crt_lins,al ; visible screen lines -1 (24) mov dh,al mov dl,crt_cols ; visible screen columns (80) pop bx pop cx jmp short scrmod4 scrmod2:cmp ega_mode,0 ; ega active? je scrmod4 ; e = no push es ; yes, permit different lengths mov ax,40h ; refer to 40:84h for # ega rows mov es,ax mov ah,es:[84h] ; get number of rows - 1 (typ 24) cmp ah,20 ; less than 20 rows? jb scrmod3 ; b = yes, ignore this length cmp ah,80 ; more than 80 rows? ja scrmod3 ; a = yes, ignore this length mov dh,ah ; use this length mov dos_bottom,dh ; remember for DOS screen pager ifndef no_terminal cmp flags.vtflg,ttansi ; ANSI? jne scrmod2b ; ne = no inc dh ; make mode line a regular text line mov flags.modflg,2 ; mode line enabled and owned by host scrmod2b:cmp isps55,0 ; [HF]940206 is Japanese PS/55 ? je scrmo2a ; [HF]940206 e = no cmp ps55mod,0 ; [HF]940206 can we use modeline? jne scrmo2a ; [HF]940206 ne = yes inc dh ; [HF]940206 no, add modeline endif ; no_terminal scrmo2a:mov crt_lins,dh ; update our working constant scrmod3:pop es scrmod4:dec dl ; max text column, count from zero dec dh ; max text row, count from zero ifndef no_terminal cmp flags.vtflg,ttgenrc ; no terminal emulation je scrmod6 ; e = yes cmp tekflg,tek_active+tek_sg ; doing special graphics? jne scrmod4a ; ne = no mov crt_cols,128 ; VT style special graphics uses this scrmod4a: cmp crt_cols,80 ; doing wide now? ja scrmod5 ; a = yes mov dl,80-1 ; assume 80 column width test vtemu.vtflgop,deccol ; 132 column mode set? jz scrmod6 ; z = no scrmod5:mov dl,132-1 ; set to 132 column mode endif ; no_terminal scrmod6:mov low_rgt,dx ; save away window address pop dx pop ax ret scrmod endp ; Get screen segment. Returns screen segment in ax, and full address in es:di scrseg proc near xor di,di ; start at beginning of screen (0,0) mov ax,0B800H ; video memory is here on color cmp crt_mode,7 ; normal color modes? jb scrse1 ; b = yes mov ax,0B000H ; assume B&W card cmp crt_mode,12 ; jb scrse1 cmp crt_mode,18h ; Tseng UltraPAK mono in 132 col? je scrse1 ; e = yes, use seg B000H cmp crt_mode,56h ; Paradise EGA Mono in 132x43 mode? je scrse1 ; e = yes, use seg B000H cmp crt_mode,57h ; Paradise EGA Mono in 132x25 mode? je scrse1 ; e = yes, use seg B000H mov ax,0B800H ; video memory is here on color cmp crt_mode,18 ; end of ordinary 640x480 graphics ja scrse1 ; a = no, assume CGA segment mov ax,0A000H ; graphics scrse1: mov es,ax ; tell Topview our hardware address needs mov tv_segs,es ; save our hardware screen address mov tv_sego,di ; segment and offset form or tv_mode,1 ; assume we're running under Topview mov ah,tvhere ; query Topview for its presence int screen mov ax,es ; get its new segment for screen work cmp ax,tv_segs ; same as hardware? jne scrse2 ; ne = no, we are being mapped cmp di,tv_sego ; check this too jne scrse2 ; ne = no too. Use TV's work buf as screen and tv_mode,not 1 ; else no Topview or no mapping scrse2: mov tv_segs,es ; save segment mov tv_sego,di ; and offset ret scrseg endp ; Synchronize a Topview provided virtual screen buffer with the image ; seen by the user. Requires cx = number of words written to screen ; (char & attribute bytes) and es:di = ENDING address of screen write. ; Changes ax and di. Skip operations for DESQview scrsync proc near cmp tv_mode,0 ; Topview mode active? je scrsyn1 ; e = no, skip Bios call below push ax push cx push di sub di,cx ; backup to start byte (cx = words) sub di,cx ; after storing words to screen mov ah,tvsynch ; tell Topview we have changed screen int screen ; so user sees updated screen pop di pop cx pop ax scrsyn1:ret scrsync endp ; The following two routines are used to turn off the display while we ; are reading or writing the screen in one of the color card modes. ; Turn screen off for (known) color card modes only. All regs preserved. ; Includes code for old procedure scrwait. 16 June 1987 [jrd] scroff proc near cmp ega_mode,0 ; Extended Graphics Adapter in use? jne scrofx ; ne = yes, no waiting cmp tv_mode,0 ; Topview mode? jne scrofx ; ne = yes, no waiting cmp crt_mode,7 ; B&W card? jnb scrofx ; nb = yes - just return cmp refresh,0 ; slow refresh? jne scrofx ; ne = no wait push ax ; save ax and dx push dx mov dx,crt_status ; CGA: Wait for vertical retrace scrof1: in al,dx test al,disp_enb ; display enabled? jnz scrof1 ; yes, keep waiting scrof2: in al,dx test al,disp_enb ; now wait for it to go off jz scrof2 ; so can have whole cycle mov dx,crtmset ; output to CRT mode set port mov al,25H ; this shuts down the display out dx,al pop dx ; restore regs pop ax scrofx: ret scroff endp ; Turn screen on for (known) color card modes only ; All registers are preserved. scron proc near cmp ega_mode,0 ; Extended Graphics Adapter in use? jne scronx ; ne = yes, no waiting cmp tv_mode,0 ; Topview mode? jne scronx ; ne = yes, no waiting cmp crt_mode,7 ; B&W card? jnb scronx ; nb = yes - just return cmp refresh,0 ; slow refresh? jne scronx ; ne = no wait push ax ; save ax, dx, and si push dx push si mov al,crt_mode ; convert crt_mode to a word xor ah,ah mov si,ax ; get it in a usable register mov al,msets[si] ; fetch the modeset byte mov dx,crtmset ; this port out dx,al ; flash it back on pop si pop dx pop ax scronx: ret scron endp ifndef no_terminal ; Determine screen roll back buffer parameters depending on current screen ; dimensions and available memory. Each rollback screen line has its own ; segment (lines start on segment boundaries for rollback). One full screen ; must be allocated to hold the current display, deduct this from lmax. bufadj proc near push bx push cx push dx mov bx,rollwidth ; rollback line width add bx,7 ; (BDT) round up to paragraph boundary mov cl,3 ; (BDT) now convert to shr bx,cl ; (BDT) paragraphs / line mov ppl,bx ; (BDT) save this in buffer area xor dx,dx ; high order dividend, clear it cmp emsrbhandle,0 ; using EMS? jle bufadj2 ; le = no (-1 means not used) mov ax,1024 ; 1024 paragraphs per ems 16KB page div bx ; divide by paragraphs per line mov lineems,ax ; lines per ems page, remember mul inipara ; times number of ems pages jmp short bufadj3 ; ax has number of lines ; conventional memory bufadj2:mov ax,inipara ; (BDT) compute the number of lines div bx ; (BDT) in the buffer bufadj3:mov lmax,ax ; max line capacity of the buffer mov linee,ax ; (BDT) save as number of total lines or ax,ax ; have any lines? jz bufadj1 ; z = no, no space at all xor bh,bh ; (BDT) get lines / screen mov bl,byte ptr low_rgt+1 ; (BDT) rows on user/host screen inc bx ; (BDT) adjust for counting from 0 sub lmax,bx ; minus master "current" screen jg bufadj1 ; g = have some rollback space mov lmax,0 ; say none bufadj1:mov lcnt,0 ; (BDT) # of lines filled in buffer mov linef,0 ; (BDT) first filled in line mov linec,0 ; (BDT) last filled in line pop dx pop cx pop bx ret bufadj endp endif ; no_terminal ; Test for DESQview in operation, set tv_mode bit 10h to non-zero if so. dvtest proc near and tv_mode,not 30h ; assume no DV and no Japanese DOS ifndef no_terminal cmp isps55,0 ; [HF] 940130 Japanese PS/55 ? je dvtest4 ; [HF] 940130 no or tv_mode,30h ; [HF] 940205 say Japanese & DV ret ; [HF] do not use Int 15h for Japan endif ; no_terminal dvtest4:xor bx,bx ; for version number mov cx,'DE' ; DV signature mov dx,'SQ' mov ax,2B01h ; DOS set date (with illegal value) int dos cmp al,0ffh ; DOS should say invalid if no DV je dvtest2 ; e = yes, invalid so no DV cmp bx,2 ; DV version 2.00? jne dvtest1 ; ne = no xchg bh,bl ; get major version into bh dvtest1:or tv_mode,10h ; say using DV dvtest2:ret dvtest endp ; Execute DESQview function call provided in BX. dvcall proc near push ax mov ax,101ah ; switch to DV stack int 15h mov ax,bx ; function to do int 15h mov ax,1025h ; switch from DV stack int 15h pop ax ret dvcall endp ; Call this to release the cpu during idle times dvpause proc near cmp vtcpumode,0 ; timeslice-release enabled? jne dvpaus2 ; ne = no test tv_mode,10h ; in DV? jz dvpaus1 ; z = no push bx mov bx,1000h ; say release control call dvcall ; to DV pop bx dvpaus1:cmp byte ptr dosnum+1,5 ; DOS verson, major high, minor low jb dvpaus2 ; b = too old for this operation mov ax,1680h ; release current virtual machine int 2fh ; time slice (Windows, OS/2, DPMI) dvpaus2:ret dvpause endp ; Screen clearing routine ; Call: ax = coordinates of first screen location to be cleared. ; bx = coordinates of last location to be cleared. ; Coord: ah = row [0-24], al = column [0-206]. Preserves all registers. atsclr proc near cmp ax,bx ; correct order? jbe atsclr9 ; be = yes xchg ax,bx ; larger to bx atsclr9:push ax ; save regs push cx push dx mov dx,bx ; compute last screen offset from bx push ax call scrloc ; get screen start address in ax mov cx,ax ; save it in cx for a minute pop dx ; compute first screen offset in ax call scrloc sub cx,ax ; compute number of locs to clear add cx,2 ; +1 for span, +1 for round up sar cx,1 ; make byte count a word count jle atscl3 ; le = nothing to clear push di ; save regs push es ; save es ifndef no_terminal cmp inemulator,0 ; in terminal emulator now? je atscl1 ; e = no cmp flags.vtflg,0 ; emulating anything? je atscl1 ; e = no, using DOS les di,vs_ptr ; es:di is virtual screen jmp short atscl2 endif ; no_terminal atscl1: push ax ; save displacement call scroff ; turn screen off if color card call scrseg ; get address of screen into es:di pop ax atscl2: add di,ax ; location in buffer mov ah,scbattr ; use current screen background attr mov al,' ' ; use space for fill push cx ; save word count for Topview cld rep stosw ; copy to screen pop cx ; recover word count ifndef no_terminal cmp inemulator,0 ; in terminal emulator now? je atscl2a ; e = no cmp flags.vtflg,0 ; emulating anything? jne atscl2b ; ne = yes endif ; no_terminal atscl2a:call scron ; turn screen back on if color card call scrsync ; synch Topview atscl2b:pop es pop di atscl3: pop dx pop cx pop ax ; back to regs at call time ifndef no_terminal cmp inemulator,0 ; in terminal emulator now? je atscl6 ; e = no cmp flags.vtflg,0 ; emulating anything? je atscl6 ; e = no, using DOS push dx ; do extended attributes push ax push bx push cx mov dx,ax ; starting place mov al,dh ; row mov cl,vswidth ; row char cells mul cl add al,dl ; plus starting column adc ah,0 ; char cells to starting place mov dx,ax ; save here mov al,bh ; ending row mul cl add al,bl ; plus ending column adc ah,0 mov bx,ax sub bx,dx ; number of cells -1 to clear inc bx mov cx,bx ; cx = cells to clear xchg bx,dx ; bx = start offset, dx=cells push es push di les di,vsat_ptr ; where attributes are stored add di,bx ; offset plus start byte xor ax,ax cld shr cx,1 jnc atscl4 stosb atscl4: rep stosw ; clear those bytes ;;; mov extattr,0 ; and the extension byte too pop di pop es pop cx pop bx pop ax mov dl,ah ; first row mov dh,bh ; last row call touchup ; repaint this part of the screen pop dx ; finish cleaning stack endif ; no_terminal atscl6: ret atsclr endp ifndef no_terminal ; Screen-scrolling routines. fhomwnd proc far ; "home" to start of the buffer mov cl,byte ptr low_rgt+1 ; save this many lines inc cl ; full text screen xor ch,ch call putcirc ; save them mov linec,0 ; reset the current pointer call getcirc ; now get the new screen clc ret fhomwnd endp fendwnd proc far ; "end" to end of the buffer mov cl,byte ptr low_rgt+1 ; save this many lines inc cl ; full text screen xor ch,ch call putcirc ; save them mov ax,lcnt ; reset the current pointer mov linec,ax ; save the results call getcirc ; now get the new screen clc ret fendwnd endp fdnwpg proc far ; scroll down 1 page mov cl,byte ptr low_rgt+1 ; save this many lines inc cl ; full text screen xor ch,ch call putcirc ; save them mov ax,linec ; reset the current pointer add ax,cx cmp ax,lcnt ; did we go past the end? jbe dnwpg1 ; be = no, we're OK mov ax,lcnt ; yup, back up dnwpg1: mov linec,ax ; save the results call getcirc ; now get the new screen clc ret fdnwpg endp fdnone proc far ; scroll down 1 line mov cl,byte ptr low_rgt+1 ; save this many lines inc cl ; full text screen xor ch,ch call putcirc ; save them mov ax,linec ; reset the current pointer inc ax ; to the next line cmp ax,lcnt ; oops, did we go past the end? jbe dnone1 ; be = no, we're OK mov ax,lcnt ; yup, back up dnone1: mov linec,ax ; save the results call getcirc ; now get the new screen clc ret fdnone endp fupwpg proc far ; scroll up 1 page mov cl,byte ptr low_rgt+1 ; save this many lines inc cl ; full text screen xor ch,ch call putcirc ; save a full screen mov ax,linec ; reset the current pointer sub ax,cx ; to the previous page jge upwpg1 ; ge = not past end, we're OK xor ax,ax ; stop at the beginning of the buffer upwpg1: mov linec,ax ; line counter to use call getcirc ; get the new screen clc ret fupwpg endp fupone proc far ; scroll up 1 line mov cl,byte ptr low_rgt+1 ; save this many lines inc cl ; full text screen xor ch,ch call putcirc ; save them mov ax,linec ; reset the current pointer sub ax,1 ; to the previous line jge upone1 ; ge = not past end, we're OK xor ax,ax ; yup, back up upone1: mov linec,ax ; save the results call getcirc ; now get the new screen clc ret fupone endp ; Horizontal scrolling keyboard verbs frtpage proc far mov cx,20 ; step size call rtcommon ret frtpage endp frtone proc far mov cx,1 call rtcommon ret frtone endp ; Move screen to the right margin by CX columns rtcommon proc near push bx mov bl,byte ptr cursor+1 ; current cursor row xor bh,bh mov al,linescroll[bx] ; horz scroll in effect for this line pop bx add al,handhsc ; plus hand scrolling now present add al,crt_cols ; right most char on visible screen adc ah,0 cmp ax,vswidth ; too far already? ja rtcomm2 ; a = yes, do nothing sub ax,vswidth ; available distance neg ax cmp ax,cx ; space vs desired scroll jbe rtcomm1 ; be = less than desired, use space mov ax,cx ; enough room, use desired scroll rtcomm1:add handhsc,al ; indicate how much done by hand call repaint rtcomm2:clc ret rtcommon endp flfpage proc far mov cx,20 ; step size call lfcommon ret flfpage endp flfone proc far mov cx,1 ; step size call lfcommon ret flfone endp ; Move screen toward left margin by CX columns lfcommon proc near push bx mov bl,byte ptr cursor+1 ; current cursor row xor bh,bh mov al,linescroll[bx] ; horz scroll in effect for this line pop bx add al,handhsc ; available distance to move jz lfcomm2 ; z = no space to move sub al,cl ; minus our desired jump jge lfcomm1 ; ge = no overscroll the wrong way add cl,al ; reduce cx request by overage lfcomm1:sub handhsc,cl ; successful, new handhsc call repaint lfcomm2:clc ret lfcommon endp ; Scrolling routines. vtscru scrolls up, vtscrd scrolls down 'scroll' ; rows. Top lines are saved in the circular buffer before scrolling up. ; When running under an Environment control number of line positions moved ; to be less than scrolling region. ; All registers are preserved. ; ; Screen scroll up "scroll" lines (text moves up) for terminal emulator use. vtscru proc near push ax push bx push cx push dx push si push di mov al,mar_bot ; compute size of scroll sub al,mar_top inc al ; lines in scrolling region mov dl,scroll ; desired scroll xor dh,dh cmp dl,al ; scrolling more than needed? jbe vtscru1 ; be = no mov dl,al ; limit scrolling mov scroll,al vtscru1:or dl,dl jnz vtscru2 jmp vtscru9 ; z = nothing to do vtscru2:cmp mar_top,0 ; scrolling the top screen line? jne vtscru5 ; ne = no, do not save in roll back mov cx,dx ; cx is how many lines call putcirc ; put screen lines in circular buffer add linec,cx ; (BDT) increment the current line mov cx,linec ; new current line number sub cx,lcnt ; minus # in buf = qty new lines added jc vtscru3 ; c = not extending buffer add lcnt,cx ; (BDT) increment the line counter vtscru3:mov cx,lcnt ; (BDT) check: are we cmp cx,lmax ; (BDT) beyond the end? jb vtscru5 ; (BDT) b = no sub cx,lmax ; (BDT) compute overflow count add linef,cx ; (BDT) adjust the "first" line mov cx,linef ; (BDT) check: time to wrap? cmp cx,linee ; (BDT) ... jb vtscru4 ; (BDT) b = no sub cx,linee ; (BDT) yup mov linef,cx ; (BDT) adjust it vtscru4:mov cx,lmax ; (BDT) get the maximum line count mov lcnt,cx ; (BDT) reset the line counter mov linec,cx ; (BDT) reset the current line vtscru5:mov di,word ptr vs_ptr ; offset of virtual screen mov cl,vswidth mov al,mar_top ; top line number (from 0) mul cl ; times chars/line add ax,ax ; char + attribute add di,ax ; destination (mar_top) mov al,dl ; number of lines to scroll mov cl,vswidth mul cl ; vswidth * total lines to scroll mov bx,ax ; number of cells to clear add ax,ax ; bytes mov si,di add si,ax ; src is that many bytes down screen mov al,mar_bot ; lines in scrolling region sub al,mar_top inc al sub al,dl ; minus scrolled portion mul cl ; times words per line mov cx,ax ; number of cells to copy mov dh,scbattr ; need this for later (in seg data) push cx ; save number of words for attribute push es push ds mov ax,word ptr vs_ptr+2 ; segment of vscreen mov ds,ax mov es,ax cld rep movsw ; copy src to dest mov cx,bx ; count of words to clear mov ah,dh ; default attriubte mov al,' ' ; filler for clearing a line rep stosw ; store after new src pop ds pop es ; bx is number of words cleared mov di,word ptr vsat_ptr ; offset of attributes mov cl,vswidth ; char cells per attributes line mov al,mar_top ; top line number (from 0) mul cl ; times cells per line add di,ax ; destination (mar_top) mov si,di mov al,dl ; number of lines to scroll mul cl ; vswidth * total lines to scroll mov bx,ax ; number of cells to clear add si,bx ; src is that many bytes down screen pop cx ; number of vscreen cells copied push es push ds mov ax,word ptr vsat_ptr+2 ; segment of vsatt mov ds,ax mov es,ax cld rep movsb ; copy src to dest mov cx,bx ; count of bytes to clear xor al,al ; default attributes of none rep stosb ; store after new src pop ds pop es cmp writemode,0 ; use direct screen writing? je vscru5a ; e = yes ifndef no_graphics cmp tekflg,tek_active+tek_sg ; special graphics mode? jne vscru5b ; ne = no endif ; no_graphics vscru5a:cmp tekflg,tek_active+tek_sg ; special graphics mode? jne vtscru8 ; ne = no ifndef no_graphics call tekremcursor ; turn off text cursor vscru5b:mov dosetcursor,-1 ; don't turn on automatically mov al,' ' ; write space mov ah,scbattr ; in normal colors xor dl,dl ; at mar_top, left margin mov dh,mar_top ; to set normal text mode for the cmp tekflg,tek_active+tek_sg ; special graphics mode? jne vscru5d ; ne = no xor cl,cl ; no extended attribute call ttxtchr ; graphics adapter endif ; no_graphics vscru5d:mov ax,0600h ; scroll up whole region mov dh,mar_bot ; bottom row mov dl,crt_cols cmp isps55,0 ; [HF]940216 Japanese PS/55? jne vscru5e ; [HF]940216 ne=yes, allowed > 80cols. cmp dl,80 ; more than physical screen? jbe vscru5e ; be = no cmp dl,131 ; really wide screen jae vscru5e ; ae = yes mov dl,80 ; else 128 col fake text wide screen vscru5e:dec dl ; right most physical col for scroll mov ch,mar_top ; top row of scrolling region xor cl,cl ; left most column mov bh,scbattr ; attributes mov bl,dh sub bl,ch ; region size - 1 line jz vscru2b ; z = region is 1 line, do one scroll mov al,scroll ; number of lines to scroll, from msz vscru2a:cmp al,bl ; want to scroll more that than? jbe vscru2b ; be = no push ax mov al,bl ; limit to region - 1 for Windows int screen ; and do in parts pop ax sub al,bl ; al = amount yet to scroll jmp short vscru2a ; do next part vscru2b:int screen ; scroll up that region mov dx,cursor mov dosetcursor,dx ; reminder of where to set cursor jmp short vtscru9 vtscru8:mov dh,mar_bot ; real text mode mov dl,mar_top ; setup touchup, lines changed call touchup ; touch up real screen vtscru9:pop di pop si pop dx pop cx pop bx pop ax ret vtscru endp ; Screen-roll down. Move text down scroll lines, for terminal emulator only. vtscrd proc near push ax push bx push cx push dx push si push di push bp push es les si,vs_ptr ; source is top line of virtual screen mov al,mar_top ; top margin line (0..) mov cl,vswidth ; chars across vscreen mul cl add ax,ax ; words to bytes add si,ax ; offset of start of top line mov bp,si ; remember top line for later mov cl,mar_bot ; compute number of lines to move sub cl,mar_top inc cl ; qty of lines in region mov ch,scroll cmp ch,cl ; want to scroll more than region? jbe vtscrd1 ; be = no mov ch,cl ; set scroll to whole region mov scroll,ch ; remember for attributes vtscrd1:sub cl,ch ; less lines to be skipped mov bl,ch ; save effective scroll for below mov al,vswidth ; number of character cells mul cl mov cx,ax ; number of words in the movement dec ax ; compute to end word add ax,ax ; number of bytes add si,ax ; go to the end mov di,si mov al,vswidth ; words in a line buffer mul bl ; number of chars dest is below src mov bx,ax ; save number of chars here for clear add ax,ax ; number of bytes (char + attribute) add di,ax ; destination offset push ds mov ax,es mov ds,ax std rep movsw ; copy down the lines cld pop ds mov di,bp ; fill top line in scrolling region mov ah,scbattr mov al,' ' mov cx,bx ; number of char cells to clear rep stosw ; fill top line(s) with spaces ; do extended attributes the same way les si,vsat_ptr ; source of extended attributes mov al,mar_top ; top margin line (0..) mov cl,vswidth ; attribute cells/line mul cl add si,ax ; offset of start of top line mov bp,si ; remember top line for later mov cl,mar_bot ; compute number of lines to move sub cl,mar_top inc cl ; qty of lines in region mov ch,scroll sub cl,ch ; less lines to be skipped mov bl,ch ; save effective scroll for below mov al,vswidth ; number of attribute cells/line mul cl mov cx,ax ; number of bytes in the movement dec ax ; compute to end byte add si,ax ; go to the end mov di,si mov al,vswidth ; number of attribute cells/line mul bl ; number of cells dest is below src mov bx,ax ; save number of bytes here for clear add di,ax ; destination offset push ds mov ax,es mov ds,ax std rep movsb ; copy down the lines cld pop ds mov di,bp ; fill top line in scrolling region xor al,al ; null attributes for filler mov cx,bx ; number of attributes bytes to clear rep stosb ; fill top line(s) with spaces pop es pop bp cmp writemode,0 ; use direct screen writing? je vscrd1 ; e = yes cmp tekflg,tek_active+tek_sg ; special graphics mode? jne vscrd3a ; ne = no vscrd1: ifndef no_graphics cmp tekflg,tek_active+tek_sg ; special graphics mode? je vscrd3 ; e = yes endif ; no_graphics mov dl,mar_top ; setup touchup, lines changed mov dh,mar_bot call touchup ; touch up real screen jmp short vscrd8 ifndef no_graphics vscrd3: call tekremcursor ; turn off text cursor endif ; no_graphics vscrd3a:mov dosetcursor,-1 ; don't turn on automatically mov al,' ' ; write space mov ah,scbattr ; in normal colors ifndef no_graphics xor dl,dl ; at mar_bot, left margin mov dh,mar_bot ; to set normal text mode for the cmp tekflg,tek_active+tek_sg ; special graphics mode? jne vscrd3b ; ne = no xor cl,cl ; no extended attribute call ttxtchr ; graphics adapter endif ; no_graphics vscrd3b:mov ax,0700h ; scroll down whole region mov ch,mar_top ; top margin line xor cl,cl ; left most column mov dh,mar_bot ; bottom margin line mov dl,crt_cols cmp isps55,0 ; [HF]940216 Japanese PS/55 jne vscrd3c ; [HF]940216 ne=yes, allowed > 80 cols cmp dl,80 ; more than physical screen? jbe vscrd3c ; be = no cmp dl,131 ; really wide screen jae vscrd3c ; ae = yes mov dl,80 ; else 128 col fake text wide screen vscrd3c:dec dl ; right most physical col for scroll mov bh,scbattr ; attributes mov bl,dh sub bl,ch ; region size - 1 line jz vscrd7 ; z = region is 1 line, do one scroll mov al,scroll ; number of lines to scroll, from msz vscrd7: cmp al,bl ; want to scroll more that than? jbe vscrd2 ; be = no push ax mov al,bl ; limit to region-1 for Windows int screen ; and do in parts pop ax sub al,bl ; get remainder jmp short vscrd7 ; do next part vscrd2: int screen ; scroll it down mov dx,cursor mov dosetcursor,dx ; reminder of where to set cursor vscrd8: pop di pop si pop dx pop cx pop bx pop ax ret vtscrd endp ; Put the top cx lines from the virtual screen in to the circular buffer ; starting at line index linec (counted from zero, modulo linee). putcirc proc near jcxz putcir6 ; z = no lines to save cmp lmax,0 ; any buffer space? jne putcir7 ; ne = yes, have some putcir6:ret putcir7:push ax push bx push cx push dx push si push di push es cld mov pageready,-1 ; ems page number currently active mov si,word ptr vs_ptr ; offset of screen buffer mov bx,linef ; index of the first line add bx,linec ; add the current line counter dec bx putcir1:inc bx cmp bx,linee ; at the end of the buffer now? jb putcir2 ; b = no sub bx,linee ; backup to start of buffer putcir2:mov ax,bx ; line index cmp emsrbhandle,0 ; EMS in use? jg putcir3 ; g = yes cmp xmsrhandle,0 ; XMS rollback in use? je putcir3 ; e = no call putxms ; do the put via xms jmp short putcir4 putcir3:call emsfixup ; do expanded memory conversion work mul ppl ; times paragraphs per line add ax,iniseg ; plus initial seg of buffer mov es,ax ; now we have the segment pointer xor di,di ; buffer offset is always 0 push cx ; save the number of lines mov cx,rollwidth ; get the number of characters to move push si ; save starting vscreen offset push ds ; get the offset of the screen cld mov ds,word ptr vs_ptr+2 ; seg of vscreen rep movsw ; move them pop ds ; restore DS pop si ; vscreen offset add si,vswidth*2 ; inc to next vscreen line pop cx ; restore the line count putcir4:loop putcir1 ; go back for more pop es pop di pop si pop dx pop cx pop bx pop ax clc ret putcirc endp ; Put CX lines into XMS based rollback buffer putxms proc near mul ppl ; line number times paragraphs/line push cx mov cx,4 ; have paragraphs, want bytes xor dx,dx putxms1:shl al,1 rcl ah,1 rcl dl,1 ; get bytes to dx:ax loop putxms1 ; times 16 pop cx mov word ptr xms.offset_dst,ax ; low order address mov word ptr xms.offset_dst+2,dx ; high order mov ax,rollwidth shl ax,1 ; times two mov word ptr xms.xms_count,ax ; byte count mov ax,word ptr vs_ptr+2 ; src seg mov word ptr xms.offset_src+2,ax mov word ptr xms.offset_src+0,si ; low order mov xms.handle_src,0 ; source is local mov ax,xmsrhandle ; dest is rollback area mov xms.handle_dst,ax push si mov si,offset xms ; ds:si is request block mov ah,xmsmove call dword ptr xmsep pop si add si,vswidth*2 ; inc to next vscreen line ret putxms endp ; Get CX lines from the circular buffer, non destructively, starting at ; line index linec (counted from zero, modulo linee) and put them at ; the top of the virtual screen. Fewer lines are written if the buffer ; holds fewer than CX. getcirc proc near or cx,cx ; check on qty jnz getcir0 ; nz = some ret getcir0:cmp lmax,0 ; any buffer space? jne getcir5 ; ne = yes, have some ret getcir5:push ax push bx push cx push dx push si push di push es mov pageready,-1 ; ems page number currently active les di,vs_ptr ; seg and offset of vscreen mov bx,linef ; get the first line pointer add bx,linec ; add the current line counter dec bx cld getcir1:inc bx cmp bx,linee ; at the end of the buffer now? jb getcir2 ; b = no sub bx,linee ; backup to start of buffer getcir2:mov ax,bx ; line index cmp emsrbhandle,0 ; EMS in use? jg getcir3 ; g = yes cmp xmsrhandle,0 ; XMS rollback in use? je getcir3 ; e = no call getxms ; get from XMS jmp short getcir4 getcir3:call emsfixup ; do expanded memory conversion work mul ppl ; times paragraphs per line add ax,iniseg ; plus initial seg of buffer xor si,si ; initial offset is always 0 push cx ; save the number of lines mov cx,rollwidth ; get the number of characters to move push di ; save vscreen offset push ds ; save DS for a tad mov ds,ax ; now we have the segment pointer rep movsw ; move them pop ds ; restore DS pop di ; recover vscreen offset add di,vswidth*2 ; next vscreen line pop cx ; restore the line count getcir4: loop getcir1 ; go back for more call repaint ; repaint screen pop es pop di pop si pop dx pop cx pop bx pop ax clc ret getcirc endp getxms proc near mul ppl ; line number times paragraphs/line push cx mov cx,4 ; have paragraphs, want bytes xor dx,dx getxms1:shl al,1 rcl ah,1 rcl dl,1 ; get bytes to dx:ax loop getxms1 ; times 16 pop cx mov word ptr xms.offset_src,ax ; low order address mov word ptr xms.offset_src+2,dx ; high order mov ax,rollwidth shl ax,1 ; times two for words mov word ptr xms.xms_count,ax ; byte count mov ax,word ptr vs_ptr+2 ; dst seg mov word ptr xms.offset_dst+2,ax mov word ptr xms.offset_dst+0,di ; low order mov xms.handle_dst,0 ; destination is local mov ax,xmsrhandle ; source is rollback area mov xms.handle_src,ax ; source is rollback area push si mov si,offset xms ; ds:si is request block mov ah,xmsmove call dword ptr xmsep pop si add di,vswidth*2 ; next vscreen line ret getxms endp ; Convert rollback line number in AX to line number in ems page, and invoke ; that page. Destroys dx, returns ax as line number in page. emsfixup proc near cmp emsrbhandle,0 ; EMS in use? jg emsfix1 ; g = yes (-1 is not in use) ret emsfix1:xor dx,dx div lineems ; line number / lines per ems page push bx mov bx,ax ; quotient, page number mov ax,dx ; remainder, line in page cmp bx,pageready ; is this page now present? je emsfix2 ; e = yes mov pageready,bx ; remember push ax mov ah,emsmapmem ; map logical page in bx xor al,al ; to physical page zero mov dx,emsrbhandle ; our ems rollback handle int emsint pop ax ; return ax as line in page emsfix2:pop bx ret emsfixup endp ; Repaint screen from the vscreen buffer repaint proc near push dx xor dl,dl ; top row mov dh,crt_lins ; physical screen rows-1, incl status cmp isps55,0 ; [HF]940209 Japanese PS/55? je repain1 ; [HF]940209 e = no cmp ps55mod,0 ; [HF]940209 system uses modeline? jne repain1 ; [HF]940209 ne = no dec dh ; [HF]940209 yes, don't touch modeline repain1:call touchup pop dx ret repaint endp ; Repaint part of screen from the vscreen buffer, with linescroll offset ; dh is bottom line number, dl is top line number (dh >= dl) ftouchup proc far call touchup ret ftouchup endp touchup proc near ; get lines from virtual screen cmp flags.vtflg,ttgenrc ; terminal type of none? jne touch1 ; ne = no ret touch1: push ax push bx push cx push dx push si push di push es mov cl,dh ; last row to change sub cl,dl ; number of lines -1 cmp cl,crt_lins ; out of bounds value? jbe touch1b ; be = no xor cl,cl ; stay sane touch1b:inc cl ; number of lines to update xor ch,ch cmp tekflg,tek_active+tek_sg ; special graphics mode? je touch1c ; e = yes, skip text screen update test tekflg,tek_active ; other graphics mode? jnz touch9 ; nz = yes, no touchup call scroff ; turn off text screen mov es,tv_segs ; get the segment of the screen mov di,tv_sego ; initial screen offset touch1c:mov al,crt_cols ; physical screen width mul dl ; chars into physical screen add ax,ax ; chars to bytes add di,ax ; offset of start of phy update area mov si,word ptr vs_ptr mov al,vswidth ; chars per line mul dl ; ax = bytes to first vscreen line add ax,ax ; chars to bytes add si,ax ; si = starting vscreen line offset mov bl,dl ; top line number xor bh,bh ; index for linescroll cld push dx mov dh,dl ; set row into dh, temporarily touch2: push si ; save the current line pointer push cx ; save the number of lines mov cl,crt_cols ; get the number of characters to move xor ch,ch xor dl,dl mov al,linescroll[bx] ; get horiz scroll for this line add al,handhsc ; hand done shift, total to AL cbw ; sign extend or ax,ax ; sane? jge touch2c ; ge = yes xor ax,ax ; remove negative overshifts touch2c:add si,ax ; offset into vscreen add si,ax ; char cells to words mov ah,dgwindcomp[bx] test ah,2 ; soft font? jz touch2g ; z = no ifndef no_graphics cmp tekflg,tek_active+tek_sg ; special graphics mode? je touch2d ; e = yes push ax call dgsettek ; set special graphics mode now pop ax jmp short touch2d endif ; no_graphics touch2g:cmp writemode,0 ; use direct writing? je touch2a ; e = yes cmp tekflg,tek_active+tek_sg ; special graphics mode? je touch2d ; e = yes call tchbios ; Bios writing jmp short touch4 touch2a:cmp tekflg,tek_active+tek_sg ; special graphics mode? jne touch3 ; ne = no touch2d: ifndef no_graphics push bx mov bl,al ; horizontal scroll for this line xor bh,bh test ah,1 ; is this line compressed? jz touch2e ; z = no mov cl,128 ; compressed, 5 dot chars, 128/line touch2e:mov al,vswidth mul dh ; cells in previous rows add al,dl ; cells across to this column adc ah,0 add bx,ax ; cells from start of screen touch2b:push bx push cx push si push es shl bx,1 ; address words les si,vs_ptr ; main vscreen mov ax,es:[si+bx] ; obtain char and attribute les si,vsat_ptr ; extended attributes shr bx,1 ; count bytes, vs words above mov cl,es:[bx+si] ; obtain extended attribute byte pop es ; to get font indicator pop si call ttxtchr ; write character pop cx pop bx inc dl ; next column inc bx loop touch2b pop bx jmp short touch4 endif ; no_graphics touch3: push ds mov ds,word ptr vs_ptr+2 ; segment of vscreen rep movsw ; from vscreen+hsc to real screen+0 pop ds touch4: pop cx ; restore the line count pop si ; restore the buffer counter inc bx ; for next line add si,vswidth*2 ; point to next line inc dh dec cx jz touch4a ; z = have done all lines jmp touch2 ; do more lines touch4a:pop dx mov ah,byte ptr cursor+1 ; row of cursor cmp ah,dl ; cursor before this line? jb touch5 ; b = yes, skip cursor cmp ah,dh ; cursor after this line? ja touch5 ; a = yes, skip cursor ifndef no_graphics mov cursorst,0 ; say cursor has been zapped off endif ; no_graphics push dx mov dx,cursor mov bl,dh ; get row xor bh,bh sub dl,linescroll[bx] ; deduct horiz scroll for this line sub dl,handhsc ; hand done shift call setpcur ; reset the cursor pop dx touch5: cmp tekflg,tek_active+tek_sg ; special graphics mode? je touch9 ; e = yes cmp tv_mode,0h ; TV active? je touch8 ; e = no mov cl,dh ; tell Topview/Desqview sub cl,dl ; number of lines -1 cmp cl,crt_lins ; out of bounds value? jbe touch7 ; be = no xor cl,cl ; stay sane touch7: inc cl ; number of lines to update mov al,crt_cols ; chars/line mul cl mov cx,ax ; cx = words changed call scrsync ; synch Topview touch8: call scron ; turn on the screen touch9: pop es pop di pop si pop dx pop cx pop bx pop ax ret touchup endp ; Write screen via Bios. Enter with SI pointing at starting screen buffer ; offset, dh is current screen row, cx has chars to write across a line. tchbios proc near push bx xor bh,bh ; video page zero push dx mov ah,3 int screen mov temp,dx ; save current cursor pop dx mov cl,crt_cols xor ch,ch xor dl,dl ; column zero cld push ds mov ds,word ptr vs_ptr+2 ; source is virtual screen buffer add di,cx ; move DI to match si movemen add di,di ; word's worth tchbios1:push cx mov ah,2 ; set cursor position to dx int screen lodsw ; char+attribute mov bl,ah ; attribute mov cx,1 ; one char mov ah,9 ; write char at cursor position int screen ; do the Bios Int 10h call inc dl ; next column pop cx loop tchbios1 pop ds push dx mov dx,temp ; starting cursor position mov ah,2 ; set it back there int screen pop dx pop bx ret tchbios endp ; Character write/read and cursor manipulation routines for terminal emulator ; All registers other than returned values are preserved. ; Read char and attributes under virtual cursor (DH = row, DL = column). ; Returns AL = character, AH = video attributes, CL = logical attribute bit ; pair. getatch proc near push bx push si push es mov al,vswidth ; width of vscreen line mul dh ; count down rows (0..) add al,dl ; add column adc ah,0 add ax,ax ; times two for char and attrib mov bx,ax ; address subscript les si,vs_ptr ; main vscreen mov ax,es:[si+bx] ; obtain char and attribute les si,vsat_ptr ; extended attributes shr bx,1 ; count bytes, vs words above mov cl,es:[bx+si] ; obtain extended attribute byte pop es pop si pop bx ret getatch endp endif ; no_terminal ; Set virtual cursor postion ; DL = column, DH = row, both counted from 0,0 at upper left corner. ; If not displaced, handhsc = 0, then scroll left if virtual > crt_cols. ; If displaced, handhsc != 0, then scroll right if virtual < handhsc. ; For the D463/D470 only, set carry bit (for setatch) if the cursor is off ; the visible screen and horizontal scrolling is disabled. setpos proc near push ax push bx push cx push dx ; save outside virtual cursor mov cl,crt_cols ; physical screen width push cx ; save here ifndef no_terminal cmp inemulator,0 ; emulating? je setpos9 ; e = no, no virtual screen cmp tekflg,tek_active+tek_sg ; special graphics mode? jne setpos1 ; ne = no mov bl,dh ; get row xor bh,bh test dgwindcomp[bx],1 ; is this line compressed? jz setpos1 ; z = no mov crt_cols,128 ; compressed, 5 dot chars, 128/line setpos1:mov ch,vswidth ; leftmost legal margin (207) sub ch,crt_cols ; minus screen physical width xor cl,cl ; cl is flag for repainting needed (if != 0) xchg handhsc,cl ; hand-done horiz scroll, clear it or cl,cl ; need to undo it? jz setpos2 ; z = no call repaint ; repaint screen without hand scroll xor cl,cl ; remove repaint indicator setpos2:mov bl,dh ; current row xor bh,bh mov ah,linescroll[bx] ; current horz scroll setpos3:mov al,dl ; virtual column where we ought to be sub al,ah ; virtual - already scrolled jc setpos4 ; c = cursor off screen to the left cmp al,crt_cols ; beyond right physical screen? jb setpos5 ; b = no, use this mov cl,1 ; say need repaint inc ah ; scroll screen left one column jc setpos3a ; c = over did it cmp ah,ch ; going beyond largest scroll? jbe setpos3 ; be = no setpos3a:mov ah,ch ; yes, stay here jmp short setpos5 ; done, do real operation setpos4:mov cl,1 ; say repaint needed mov ah,dl ; reduce horz scroll setpos5:or cl,cl ; repaint needed? jnz setpos5c ; ne = yes mov bl,byte ptr low_rgt+1 ; screen bottom inc bl ; lines in emulation part xor bh,bh cmp linescroll[bx],ah ; status line, need to scroll? jbe setpos8 ; be = already scrolled properly mov linescroll[bx],ah ; modify status line push dx mov dl,bl mov dh,bl call touchup ; redraw status line pop dx jmp short setpos8 ; set cursor setpos5c:test flags.vtflg,ttd463+ttd470+ttd217 ; D463/D470/D217? jz setpos5a ; z = no cmp dghscrdis,0 ; D463/D470 horz scroll disabled? je setpos5a ; e = no, check auto vs manual stc ; c = do not show on real screen jmp short setposx ; skip screen update setpos5a:test vtemu.vtflgop,vshscroll ; horizontal scrolling, manual? jnz setpos9 ; nz = yes manual, else auto setpos5b:mov bl,mar_top ; auto scrolling, top row xor bh,bh mov cl,mar_bot sub cl,bl xor ch,ch inc cx ; lines in scrolling region setpos6:cmp linescroll[bx],ah ; any change? je setpos7 ; e = no mov linescroll[bx],ah ; set scroll for this line push dx mov dl,bl mov dh,bl call touchup ; repaint this line pop dx setpos7:inc bx loop setpos6 ; do all lines in window setpos7a:push ax ; now do status line push si mov cl,byte ptr low_rgt+1 ; examine whole screen inc cl ; lines in emulation part xor ch,ch mov bx,cx ; save for status line mov si,offset linescroll mov ah,[si] ; smallest horizontal shift found cld setpos10:lodsb ; current line scroll to al cmp al,ah ; smaller than smallest? ja setpos11 ; a = no mov ah,al ; remember smallest or ah,ah ; zero? jz setpos11a ; can't get any smaller than this setpos11:loop setpos10 ; just status line setpos11a:cmp linescroll[bx],ah ; status line, need to scroll? je setpos12 ; e = already scrolled properly mov linescroll[bx],ah ; modify status line push dx mov dl,bl mov dh,bl call touchup ; redraw status line pop dx setpos12:pop si pop ax setpos8:sub dl,ah ; virtual - horz scrolled column endif ; no_terminal setpos9:call setpcur ; set physical cursor clc ; set status for ok to show setposx:pop cx mov crt_cols,cl pop dx pop cx pop bx pop ax ret setpos endp ; Read physical cursor position ; DL = column, DH = row, both counted from 0,0 at upper left corner ; CX = cursor lines getpcur proc near push ax push bx mov ah,3 ; get cursor position xor bh,bh ; page 0 int screen pop bx pop ax ret getpcur endp fgetpcur proc far call getpcur ret fgetpcur endp ; Set physical cursor postion ; DL = column, DH = row, both counted from 0,0 at upper left corner setpcur proc near push dx cmp dl,crt_cols ; out of bounds? jb setpcur1 ; b = ok cmp dl,207 ; off screen to left? jbe setpcur0 ; be = no xor dl,dl ; put at column zero jmp short setpcur1 setpcur0:mov dl,crt_cols ; physical cols on screen dec dl ; count from zero setpcur1: ifndef no_terminal cmp inemulator,0 ; emulating? je setpcur4 ; e = no, no virtual screen cmp tekflg,tek_active+tek_sg ; special graphics mode? jne setpcur4 ; ne = no push ax push es mov ax,40h mov es,ax mov ax,es:[50h] ; current position mov es:[50h],dx ; text page 0 cursor, keep it tracking cmp ax,dx ; same? pop es pop ax ifndef no_graphics jne setpcur2 ; not same, draw cursor cmp cursorst,0 ; is cursor off now? jne setpcur3 ; ne = no, skip redrawing setpcur2: mov dosetcursor,dx ; reminder of where to set cursor call tekremcursor ; ensure it's off endif ; no_graphics setpcur3:pop dx ret endif ; no_terminal setpcur4:push ax push es mov ax,40h mov es,ax mov ax,es:[50h] ; current position cmp ax,dx ; same? pop es jne setpcur5 ; ne = no pop ax pop dx ret setpcur5:push bx mov ah,2 ; set cursor xor bh,bh ; page 0 int screen pop bx pop ax pop dx ret setpcur endp ; Read char and attributes under physical cursor. ; Returns AL = character, AH = video attributes getpcha proc near push bx mov ah,8 ; read char and attributes xor bh,bh ; page 0 int screen ; Bios video call pop bx ret getpcha endp ; Write char and attribute to screen at cursor position, do not move cursor. ; AL = char, AH = video attribute, DL = column, DH = row, CL = logical ; attribute bits. Does not update physical screen. qsetatch proc near mov setnoshow,1 ; turn off physical screen update jmp setatch ; call with same args qsetatch endp ; Write char and attribute to screen at cursor position, do not move cursor. ; AL = char, AH = video attribute, DL = column, DH = row, CL = logical ; attribute bits. Turns off setnoshow at the end. setatch proc near push bx push es push cx ; save logical attribute push ax ; save char and attribute cmp setnoshow,0 ; show on real screen? jne setatc1 ; ne = no, do just virtual screen push cx call setpos ; set cursor at dx location pop cx jc setatc1 ; c = do not show character cmp inemulator,0 ; emulating a terminal now? je setatc4 ; e = no ifndef no_graphics cmp flags.vtflg,tttek ; full Tek? je setatc5 ; e = yes cmp tekflg,tek_active+tek_sg ; special graphics mode? jne setatc4 ; ne = no, text mode setatc5:push dx push si push di mov bl,dh ; get row xor bh,bh sub dl,linescroll[bx] ; deduct horizontal scroll call ttxtchr ; display char in graphics mode pop di pop si pop dx jmp short setatc1 endif ; no_graphics setatc4: mov cx,1 ; one char mov bl,ah ; attribute xor bh,bh ; page 0 mov ah,9 ; write char, do not move cursor int screen setatc1:mov setnoshow,0 ; always reset this automatically ; write same material to vscreen mov al,vswidth ; width of vscreen line mul dh ; count across rows (0..) xor bh,bh mov bl,dl ; get position add bx,ax ; add column add bx,bx ; times two for char and attrib pop ax ; recover char and attribute pop cx ; recover logical attribute ifndef no_terminal cmp inemulator,0 ; in terminal emulator? je setatc2 ; e = no, so no virtual screen push di les di,vs_ptr ; virtual screen mov es:[di+bx],ax ; store char and attribute push ax ; save ah attributes les di,vsat_ptr ; attributes byte array shr bx,1 ; bytes, vs words above mov es:[bx+di],cl ; set extended attributes pop ax pop di endif ; no_terminal setatc2:pop es pop bx ret setatch endp ifndef no_terminal ; Get bold video attribute bit ; Returns AH = bold attribute bit (0 if not bold) getbold proc near and ah,att_bold test flags.vtflg,ttd463+ttd470+ttd217 ; D463/D470/D217? jnz getbold1 ; nz = yes xor ah,userbold ; invert with user bold getbold1:ret getbold endp ; Set bold video attribute bit, current video attribute supplied in AH setbold proc near or ah,att_bold cmp colunder,0ffh ; uninited? je setbold2 ; e = yes, don't change here or colunder,att_bold setbold2:test flags.vtflg,ttd463+ttd470+ttd217 ; D463/D470/D217? jnz setbold1 ; nz = yes xor ah,userbold ; invert with user bold cmp colunder,0ffh ; uninited? je setbold1 ; e = yes, don't change here push ax mov ah,userbold xor colunder,ah pop ax setbold1:ret setbold endp ; Clear bold video attribute bit, current video attribute supplied in AH clrbold proc near and ah,not att_bold cmp colunder,0ffh ; uninited? je clrbold2 ; e = yes, don't change here and colunder,not att_bold clrbold2:test flags.vtflg,ttd463+ttd470+ttd217 ; D463/D470/D217? jnz clrbold1 ; nz = yes xor ah,userbold ; invert with user bold cmp colunder,0ffh ; uninited? je clrbold1 ; e = yes, don't change here push ax mov ah,userbold or colunder,ah pop ax clrbold1:ret clrbold endp ; Get blink video attribute bit ; Returns AH = blink attribute bit getblink proc near and ah,att_blink ret getblink endp ; Set blink video attribute bit, current video attribute supplied in AH setblink proc near or ah,att_blink ret setblink endp ; Clear blink video attribute bit, current video attribute supplied in AH clrblink proc near and ah,not att_blink ret clrblink endp ; Set extended attribute for protection in extattr and in CL. setprot proc near ; set protected mode or extattr,att_protect or cl,att_protect ; and in cl ret setprot endp ; Clear extended attribute for protection in extattr and in CL. clrprot proc near ; clear protected mode and extattr,not att_protect and cl,not att_protect ret clrprot endp ; Get underline video attribute bit from extattr ; Returns CL = underline attribute bit getunder proc near mov cl,extattr ; get extended attribute and cl,att_uline ; return underline status bit ret getunder endp ; Set underline video attribute bit, current video attribute supplied in AH ; and extended attributes in extattr. Returns new AH and extattr in CL. setunder proc near test extattr,att_uline ; extended attributes, on already? jz setund1 ; z = no ret ; else do nothing setund1:or extattr,att_uline ; set underline attribute for MSZ or cl,att_uline cmp crt_mode,7 ; monochrome display adapter mode? je setund6 ; e = yes cmp colunder,0ffh ; uninited? je setund10 ; e = yes and ah,att_blink ; preserve blink or ah,colunder ; user specified underline coloring test extattr,att_rev ; are we reversed per char? jz setund8 ; z = no call revideo setund8:cmp reversed_screen,0 ; whole screen reversed too? je setund9 ; e = no call revideo setund9:ret setund10:push bx push dx mov bh,al ; preserve possible char in al mov dl,scbattr ; screen fill and dl,70h ; background colors mov bl,extattr ; extended attributes and bl,att_rev ; per char reversed video mov dh,ah ; current character attributes and dh,not 77h ; blink/bold attributes only and ah,77h ; colors only mov al,ah shr al,1 shr al,1 shr al,1 shr al,1 ; background to lower nibble and ah,7 ; foreground only or bl,bl ; reversed video attribute? jz setund3 ; z = no, normal xchg ah,al ; real background color to al setund3:xor al,ah ; modify background or dl,dl ; case of black background? jnz setund4 ; nz = no mov al,ah dec al and al,7 ; background goes to (foreground-1)/8 or al,al ; still black? jnz setund4 ; nz = no mov al,7 ; force non-black (white foreground) setund4:shl al,1 ; background to high nibble shl al,1 shl al,1 shl al,1 or ah,al ; or new background or bl,bl ; per char reversal? jz setund5 ; z = no rol ah,1 ; yes, flip fore/background again rol ah,1 rol ah,1 rol ah,1 setund5:or ah,dh ; restore blink and bold pop dx mov al,bh ; restore possible char pop bx ret setund6:push bx mov bl,al ; preserve char in AL call brkatt ; monochrome, break apart mov ah,att_underline ; set mono underline coloring or ah,al ; put back blink/bold test extattr,att_rev ; are we reversed per char? jz setund6a ; z = no call revideo setund6a:cmp reversed_screen,0 ; whole screen reversed too? je setund6b ; e = no call revideo setund6b:mov al,bl ; restore char in AL pop bx ret setunder endp ; Clear underline video attribute bit, current video attribute supplied in AH ; and extended attributes in extattr. Returns new AH and extattr in CL. clrunder proc near test extattr,att_uline ; extended attributes, off already? jnz clrund1 ; nz = no ret ; else do nothing clrund1:and extattr,not att_uline ; clear underline attribute for MSZ and cl,not att_uline cmp crt_mode,7 ; monochrome display adapter mode? je clrund6 ; e = yes, otherwise reverse video cmp colunder,0ffh ; user spec underline inited? je clrund10 ; e = no and ah,att_blink ; preserve blink or ah,att_normal ; current normal coloring test extattr,att_rev ; are we reversed per char? jz clrund1a ; z = no call revideo clrund1a:cmp reversed_screen,0 ; whole screen reversed too? je clrund1b ; e = no call revideo clrund1b:ret clrund6:push bx mov bl,al ; preserve char in al call brkatt ; mono, break apart attributes mov ah,07h ; set normal coloring or ah,al ; reassemble attributes test extattr,att_rev ; are we reversed per char? jz clrund6a ; z = no call revideo clrund6a:cmp reversed_screen,0 ; whole screen reversed too? je clrund6b ; e = no call revideo clrund6b:mov al,bl ; restore char in AL pop bx ret clrund10:push bx push dx mov bh,al ; save possible char in al xor bl,bl mov dl,scbattr ; screen fill and dl,70h ; background colors mov bl,extattr ; extended attributes and bl,att_rev ; per char reversed video mov dh,ah ; current char attributes and dh,not 77h ; blink/bold attributes only and ah,77h ; colors only mov al,ah shr al,1 shr al,1 shr al,1 shr al,1 ; background to lower nibble and ah,7 ; foreground only or bl,bl ; reversed video attribute? jz clrund3 ; z = no, normal xchg ah,al ; real background color to al clrund3:or dl,dl ; case of black background? jz clrund4 ; z = yes, leave it black (empty) xor al,ah shl al,1 ; background to high nibble shl al,1 shl al,1 shl al,1 or ah,al ; or in new background clrund4:or bl,bl ; per char reversal? jz clrund5 ; z = no rol ah,1 ; yes, reverse nibbles again rol ah,1 rol ah,1 rol ah,1 clrund5:or ah,dh ; restore blink and bold pop dx mov al,bh ; restore possible char pop bx ret clrunder endp endif ; no_terminal ; Compute reversed video attributes, given displayables in AH and extended ; in extattr. Returns new attribute in AH and CL holding new extattr setrev proc near test extattr,att_rev ; reversed now? jnz setrev2 ; nz = yes call revideo ; do reversal or extattr,att_rev ; update extended attribute or cl,att_rev setrev2:ret setrev endp ; Compute un-reversed video attributes, given displayables in AH and extended ; in extattr. Returns new attribute in AH and CL holding new extattr clrrev proc near test extattr,att_rev ; reversed now? jz clrrev1 ; z = no call revideo ; do reversal and extattr,not att_rev ; update extended attribute and cl,not att_rev ; update extended attribute clrrev1:ret clrrev endp ; Compute reversed video attribute byte. Normally preserves blink/bold. ; Enter with AH = video attribute byte, returns new attribute byte in AH. revideo proc near push bx mov bl,al ; preserve char in AL call brkatt ; separate colors from blink/bold rol ah,1 ; reverse foreground & background rol ah,1 ; RGB bits rol ah,1 rol ah,1 cmp crt_mode,7 ; monochrome? jne revideo1 ; ne = no test al,att_bold ; bold? jz revideo1 ; z = no test ah,7 ; black foreground now? jnz revideo1 ; nz = no, something to brighten and al,not att_bold ; remove bolding revideo1:or ah,al ; reinsert bold/blink bits mov al,bl ; restore char in AL pop bx ret revideo endp ; This routine picks an attribute apart into its component "parts" - the ; base attribute for the screen and the "extras" - i.e., blink, intensity ; and underline. ; enter with ah = a cursor attribute ; return ah = base attribute for screen (07H normal, 70H reverse). ; al = "extra" attributes ; Note that there is a complementary routine, addatt, for putting attributes ; back together. brkatt: mov al,ah ; copy displayables and al,(att_blink+att_bold) ; get modifiers and ah,not (att_bold+att_blink) ; strip blink/bold, leave color ret ; This routine builds a cursor attribute given the base attribute for the ; screen background and the "extra" attributes we want (blink, etc.). ; enter with ah = base attribute for background (07H or 70H) ; al = "extra" attributes (89H for all three) ; return ah = base combined with "extras". addatt: or ah,al ; OR the attributes ret ifndef no_terminal ; This routine is called when we want to reverse everything on the screen ; from normal to reverse video, or vice versa. It is called only when ; the decscnm attribute is changed. ; Call: no arguments. revscn proc near push ax push bx push cx push dx xor reversed_screen,1 ; remember we did this mov dh,byte ptr low_rgt+1 ; compute last screen offset in ax inc dh ; one more row to catch mode line mov dl,vswidth ; logical screen buffer dec dl ; and we count from 0 call scrloc ; get screen offset into ax mov cx,ax ; save it in cx for a minute add cx,2 sar cx,1 ; in 16-bit words please push di ; Save some more acs push es les di,vs_ptr ; seg and offset of vscreen cld revsc1: mov ax,es:[di] ; fetch a word mov bl,al ; save the character call revideo ; get reversed video attributes (AH) mov al,bl ; restore character stosw ; stuff into screen memory loop revsc1 ; loop for entire screen pop es ; restore segment register pop di ; and destination index pop dx pop cx pop bx call repaint pop ax ret revscn endp ; Set coloring attributes. ; Enter with AH holding current video attribute byte, ; BL holding ANSI color code (30-37 or 40-47) where 30's are foreground, ; 40's are background. ANSI colors are 1 = red, 2 = green, 4 = blue. ; Return new attribute byte in AH. setcolor proc near test extattr,att_rev ; normal video currently? jz setcol0 ; z = yes mov al,ah ; make a copy and ax,7788h ; strip bold,blink, keep both in al rol ah,1 ; get colors in right parts rol ah,1 ; of ah = back, al = foreground rol ah,1 rol ah,1 call setcol0 ; set fore or background color rol ah,1 ; reverse coloring again rol ah,1 rol ah,1 rol ah,1 or ah,al ; put back blink and bold ret setcol0:cmp bl,30 ; ANSI color series? jb setcol7 ; b = no cmp bl,37 ; foreground set (30-37)? ja setcol4 ; a = no, try background set sub bl,30 ; take away the bias and ah,not 07H ; clear foreground bits test bl,1 ; ANSI red? jz setcol1 ; z = no or ah,4 ; IBM red foreground bit setcol1:test bl,2 ; ANSI & IBM green? jz setcol2 ; z = no or ah,2 ; IBM green foreground bit setcol2:test bl,4 ; ANSI blue? jz setcol3 ; z = no or ah,1 ; IBM blue foreground bit setcol3:ret setcol4:cmp bl,40 ; background color set? jb setcol7 ; b = no cmp bl,47 ; background set is 40-47 ja setcol7 ; nb = no, not a color command sub bl,40 ; take away the bias and ah,not 70H ; clear background bits test bl,1 ; ANSI red? jz setcol5 ; z = no or ah,40h ; IBM red background bit setcol5:test bl,2 ; ANSI & IBM green? jz setcol6 ; z = no or ah,20h ; IBM green background bit setcol6:test bl,4 ; ANSI blue? jz setcol7 ; z = no or ah,10h ; IBM blue background bit setcol7:ret setcolor endp ifndef no_tcp ; Save terminal emulator, session is in BX. ; Delete older save buffer for this session, so that compressed vscreen ; can be saved properly. termswapout proc far cmp bx,6 ; legal session number? jb termso0 ; b = yes stc ret termso0:push ax push bx push cx push si push di shl bx,1 ; to words mov temp,bx ; save session ident cmp tsave[bx],0 ; have a storage buffer? je termso9 ; ne = no, create one now shr bx,1 ; get original BL session indicator call termswapdel ; delete old save area shl bx,1 ; restore word indexing termso9: ifndef no_graphics mov ax,31*2 ; softlist, 31 words else xor ax,ax endif ; no_graphics call getvssize ; get size of vscreen, compressed add ax,bx ; accumulate new from bx call getvasize ; size of attributes add bx,ax ; new total to bx add bx,savexlen ; plus length of MSX save area add bx,saveylen ; plus MSY save area add bx,savezlen ; plus MSZ area add bx,saveplen ; plus parser in MSSCMD add bx,saveulen ; plus MSU area ifndef no_graphics add bx,saveglen ; plus MSG area endif ; no_graphics add bx,15 ; round up mov cl,4 shr bx,cl ; convert to paragraphs mov cx,bx ; save request in cx mov ah,alloc ; please, more space int dos ; paragraph to ax, num paras to bx cmp bx,cx ; given vs wanted jae termso1 ; ae = got it pop di pop si pop cx pop bx pop ax stc ; fail ret termso1: ifndef no_graphics push temp push ax call tekend ; exit graphics mode pop ax pop temp endif ; no_graphics mov bx,temp ; get 2 * session number (sescur) mov tsave[bx],ax ; save starting paragraph push es mov es,ax ; save area is destination xor di,di ; offset of save area ifndef no_graphics mov si,seg softlist ; where softlist lives push ds mov ds,si mov si,offset softlist mov cx,31 ; number of entries cld rep movsw ; save segs of soft font in msgibm pop ds endif ; no_graphics push es ; save tsave seg push di ; save current dest ptr mov cx,ds mov es,cx mov cx,size flginfo ; length of saved flags array mov di,offset saveflag ; saved array mov si,offset flags ; working array rep movsb ; save pop di ; tsave dest offset pop es ; tsave seg ; virtual screen is saved as structure ; scr-len dw text screen length (typically 24 lines) ; with the items below repeated for each line (scr-len total lines) ; per-line dw saved chars on this line ; dw per-line dup (char & attribute) ; with the last saved char on each line being repeated to endofline on screen push bx ; virtual screen saving mov cl,crt_lins ; number of screen lines - 1 inc cl ; add status line to save block xor ch,ch mov ax,cx cld stosw ; store screen length as first word xor bx,bx ; line counter mov si,word ptr vs_ptr ; offset of vscreen termso3:push cx ; save line loop counter mov cx,word ptr rdbuf[bx] ; get number of saveable chars on line mov ax,cx ; store char count as first word stosw mov ax,word ptr vs_ptr+2 ; get vscreen segment push si push ds mov ds,ax rep movsw ; copy saveable chars pop ds pop si pop cx ; recover line counter add bx,2 ; next line, get length info add si,vswidth*2 ; next line, offset of vscreen line loop termso3 pop bx ; end of vscreen saving ; push bx ; virtual screen saving mov cl,crt_lins ; number of screen lines - 1 inc cl ; do all lines termso3b:xor ch,ch mov ax,cx cld stosw ; store screen length as first word xor bx,bx ; line counter mov si,word ptr vsat_ptr ; offset of vsattr termso7:push cx ; save line loop counter mov cx,word ptr rdbuf[bx+120]; get num of saveable bytes on line mov ax,cx ; store char count as first word stosw mov ax,word ptr vsat_ptr+2 ; get vsattr segment push si push ds mov ds,ax shr cx,1 ; get odd byte count info jnc termso7a ; nc = even count movsb termso7a:rep movsw ; copy saveable bytes pop ds pop si pop cx ; recover line counter add bx,2 ; next line, get length info add si,vswidth ; next line, offset of vsattr line loop termso7 pop bx ; end of vsattr saving ; mov si,offset saveyoff ; offset of MSY save area mov cx,saveylen ; length of MSY save area cld shr cx,1 ; even/odd? jnc termso4 ; nc = even movsb ; the odd byte termso4:rep movsw mov si,offset savezoff ; offset of MSZ save area mov cx,savezlen ; length of MSZ save area shr cx,1 jnc termso5 movsb termso5:rep movsw mov si,offset savexoff ; offset of MSX save area mov cx,savexlen ; length of MSX save area cld cli ; cautious about serial ints shr cx,1 ; even/odd? jnc termso6 ; nc = even movsb ; the odd byte termso6:rep movsw sti mov si,offset savepoff ; offset of MSSCMD parser save area mov cx,saveplen ; length of the area shr cx,1 jnc termso6a movsb termso6a:rep movsw mov si,offset saveuoff ; offset of MSUIBM kbd save area mov cx,saveulen ; length of the area shr cx,1 jnc termso6b movsb termso6b:rep movsw ifndef no_graphics mov si,offset savegoff ; offset of MSG save area mov cx,saveglen ; length of MSG save area shr cx,1 ; graphics mode exited above jnc termso6c movsb termso6c:rep movsw endif ; no_graphics pop es mov ax,100h ; assume using 80 col screen cmp dos_cols,80 ; startup screen width jbe termso8 ; be = assume 80 columns inc al ; say do 132 columns termso8:push vtemu.vtflgop or vtemu.vtflgop,vscompress ; turn off compressed mode call chgdsp ; reset display width to startup pop vtemu.vtflgop pop di pop si pop cx pop bx pop ax clc ret termswapout endp ; Restore terminal emulator, session is BX ; Delete save buffer after restoration. termswapin proc far cmp bx,6 ; valid session? jb termsi0 ; b = yes stc ret termsi0:push bx shl bx,1 ; to words cmp tsave[bx],0 ; have a storage buffer? pop bx jne termsi1 ; ne = yes, use it mov vtinited,0 ; say not inited stc ; fail ret termsi1:push ax push bx push cx push si push di push es ; virtual screen restore ifndef no_graphics test tekflg,tek_active ; current graphics mode status jz tswapin1a ; z = not in graphics mode push bx call tekend pop bx endif ; no_graphics tswapin1a: shl bx,1 ; address words mov ax,tsave[bx] ; starting paragraph for save area push ds mov ds,ax ; save area is source xor si,si ; offset of save area ifndef no_graphics mov di,seg softlist ; seg of destination mov es,di mov di,offset softlist mov cx,31 ; number of entries cld rep movsw ; restore segs of soft font in msgibm endif ; no_graphics pop ds les di,vs_ptr ; seg and offset of vscreen mov ax,tsave[bx] ; starting paragraph of save area push ds mov ds,ax ; source segment is save area lodsw ; get screen length mov cx,ax ; counter of vscreen lines to do tswapi2:push cx ; save line counter lodsw ; get count of saved chars of line dec ax ; omit repeated char til next step mov cx,ax ; count for saved char writes rep movsw ; copy saved chars except last one mov cx,vswidth ; total line width (chars) sub cx,ax ; minus those done lodsw ; get last char (this repeats to end) rep stosw ; repeat last char pop cx ; recover line counter loop tswapi2 ; do all text lines (omit status) pop ds ; restore DS, SI is ready for nxt grp ; end of virtual screen restoration ; attributes, vsatt, for vscreen les di,vsat_ptr ; seg and offset of vsatt mov ax,tsave[bx] ; starting paragraph of save area push ds mov ds,ax ; source segment is save area lodsw ; get screen length mov cx,ax ; counter of vsattr lines to do tswapi7:push cx ; save line counter lodsw ; get count of saved bytes of line dec ax ; omit repeated byte til next step mov cx,ax ; count for saved byte writes shr cx,1 ; do odd byte copy jnc tswapi7a ; nc = even count movsb tswapi7a:rep movsw ; copy saved bytes except last one mov cx,vswidth ; total line width (bytes) sub cx,ax ; minus those done lodsb ; get last byte (this repeats to end) rep stosb ; repeat last byte pop cx ; recover line counter loop tswapi7 ; do all text lines (omit status) pop ds ; restore DS, SI is ready for nxt grp ; end of virtual screen restoration mov ax,ds ; regular data seg "data" mov es,ax ; new data seg mov di,offset saveyoff ; offset of MSY save area mov cx,saveylen ; length of MSY save area mov ax,tsave[bx] ; starting paragraph of save area push ds mov ds,ax ; source segment is save area cld shr cx,1 ; even/odd? jnc termsi3 ; nc = even movsb ; the odd byte termsi3:rep movsw mov di,offset savezoff ; offset of MSZ save area mov cx,es:savezlen ; length of MSZ save area shr cx,1 jnc termsi4 movsb termsi4:rep movsw mov di,offset savexoff ; offset of MSX save area mov cx,es:savexlen ; length of MSX save area cli ; cautious about serial ints shr cx,1 jnc termsi5 movsb termsi5:rep movsw sti mov di,offset savepoff ; offset of MSSCMD parser area mov cx,es:saveplen ; length shr cx,1 jnc termsi6 movsb termsi6:rep movsw mov di,offset saveuoff ; offset of MSUIBM kbd area mov cx,es:saveulen ; length shr cx,1 jnc termsi6a movsb termsi6a:rep movsw ifndef no_graphics mov di,offset savegoff ; offset of MSGIBM area mov cx,es:saveglen ; length shr cx,1 jnc termsi8 movsb termsi8:rep movsw endif ; no_graphics pop ds mov cx,ds mov es,cx mov cx,size flginfo ; length of saved flags array mov si,offset saveflag ; saved array mov di,offset flags ; working array rep movsb ; restore mov ah,savattr ; get saved coloring mov scbattr,ah ; replace what DOS may have used and tekflg,not tek_active ; say graphics is not active pop es pop di pop si pop cx pop bx pop ax call termswapdel ; delete this saved area, BL=session clc ret termswapin endp ; Remove saved terminal emulator buffers, BX is sescur (-1 means all) termswapdel proc far cmp bx,-1 ; all? jne tswapdw ; ne = no, just one mov cx,6 ; number of possible sessions push bx xor bx,bx ; session index tswapd1:call tswapdw ; delete bufs for this session (BX) inc bx loop tswapd1 ; and all others pop bx ret tswapdw proc far ; worker within termswapdel push ax ; delete session BX push bx cmp bx,5 ; largest session ja tswapd2 ; a = illegal, ignore shl bx,1 ; to words xor ax,ax ; clearing indicator xchg ax,tsave[bx] ; paragraph of save area or ax,ax ; anything there? jnz tswapd3 ; nz = yes tswapd2:pop bx pop ax stc ret tswapd3: ifndef no_graphics push es push ax ; save seg of save buffer push cx mov es,ax ; seg of save buffer xor si,si ; offset in save area of softlist mov cx,31 ; number of entries cld tswapd4:lodsw ; saved segs of soft font in msgibm or ax,ax ; any seg defined? jz tswapd5 ; z = no push es mov es,ax ; set paragraph to es for DOS mov ah,freemem int dos pop es tswapd5:loop tswapd4 pop cx pop es ; recover seg of save buffer from AX mov ah,freemem ; free the memory int dos pop es endif ; no_graphics pop bx pop ax clc ret tswapdw endp termswapdel endp ; Examine vscreen line by line. Count number of characters by excluding the ; trailing repetitions (keep first example) on each line, sum them. Add to ; the sum a word per line to hold the count of such characters and one more ; word to hold the screen length. ; Return the number of bytes in register bx for malloc-ing. getvssize proc near push ax push cx push dx push di push es les di,vs_ptr ; pointer to vscreen xor bx,bx ; line counter mov cl,crt_lins ; lines on screen - 1 xor ch,ch inc cl ; add status line mov dx,cx ; accumulated count inc dx ; count screen size word itself add di,(vswidth - 1) * 2 ; offset of last char on the line getvssi1:push cx ; save line counter mov cx,vswidth-1 ; chars on line - 1 mov ax,es:[di] ; get last char+attrib on the line push di sub di,2 std ; scan backward repe scasw ; scan while equal (trim trailing rpt) cld pop di je getvssi2 ; e = ended on all same char inc cx ; ne case gobbles extra char getvssi2:inc cx ; count the trailing char mov word ptr rdbuf[bx],cx ; store number of words here add dx,cx ; accumulate count of chars add bx,2 ; next line add di,vswidth*2 ; end of next line pop cx ; line counter loop getvssi1 add dx,dx ; chars to bytes accumulated mov bx,dx ; return it in bx pop es pop di pop dx pop cx pop ax ret getvssize endp ; Examine vsattr line by line. Count number of attributes by excluding the ; trailing repetitions (keep first example) on each line, sum them. Add to ; the sum a word per line to hold the count of such characters and one more ; word to hold the screen length. Stores temp length indicator in ; words rdbuf+120 et seq (one word per line). ; Return the number of bytes in register bx for malloc-ing. getvasize proc near push ax push cx push dx push di push es les di,vsat_ptr ; pointer to vsattr xor bx,bx ; line counter mov cl,crt_lins ; lines on normal screen - 1 inc cl ; include status line xor ch,ch mov dx,cx ; accumulated count inc dx ; count screen size word itself add dx,dx ; convert to bytes used add di,vswidth - 1 ; offset of last attrib on the line getvasi1:push cx ; save line counter mov cx,vswidth -1 ; bytes on line - 1 mov ax,es:[di] ; get last attribute byte on the line push di dec di std ; scan backward repe scasb ; scan while equal (trim trailing rpt) cld pop di je getvasi2 ; e = ended on all same byte inc cx ; ne case gobbles extra byte getvasi2:inc cx ; count the trailing byte mov word ptr rdbuf[bx+120],cx; store number of bytes here add dx,cx ; accumulate count of bytes add bx,2 ; next line add di,vswidth ; end of next line pop cx ; line counter loop getvasi1 mov bx,dx ; return bytes needed in bx pop es pop di pop dx pop cx pop ax ret getvasize endp endif ; no_tcp ; ; CHKDSP - procedure to check for hardware support of 132 cols ; Supported hardware: ; ATI EGA and VGA Wonder ; AT&T ; Everex Viewpoint EV-659, FVGA-673, EV-678, Micro Enhancer Deluxe ; IBM XGA ; Paradise AutoSwitch EGA Mono, VGA Professional, VGA Plus, VGA Plus 16 ; STB VGA/EM (Tseng TVGA) ; STB VGA/EM Plus (Tseng 4000), VGA/EM-16, VGA/EM-16 Plus ; Tseng Labs EVA board w/132-col kit installed ; Tseng Labs UltraPAK mono/Herc board w/132 column modes. ; Tseng Labs ET4000 SVGA. ; VESA compatible Bios'. ; Video 7 Vega Deluxe w/ 132X25.COM driver installed and VGA board. ; The routine checks for the presence of a 132-column-capable adapter. If ; one is found its handler executes the desired mode setting and returns ; carry clear; it returns carry set otherwise. ; Adding new boards - place an identification string in the data segment, ; construct a mode setting routine and insert it in the call list below ; (setting 132 column mode is byte AL non-zero). Byte AH is non-zero to ; avoid saving old screen and running scrini; it is used to set the screen ; width when starting/exiting Connect mode ; chgdsp proc near ifndef no_graphics or al,al ; 80 column mode? jnz chgdsg1 ; nz = no, want 132 cols test tekflg,tek_active ; graphics mode active? jz chgdsp_start ; z = no push ax push dx call tekend ; exit special graphics call scrmod ; update video mode info pop dx pop ax jmp short chgdsp_start ; set 80 col mode chgdsg1:test vtemu.vtflgop,vscompress ; allowed to use graphics for it? jnz chgdsp_start ; nz = no, use 132 column text mode cmp tekflg,tek_active+tek_sg ; special graphics mode active? je chgdsg3 ; e = yes, no change needed mov cl,byte ptr low_rgt+1 ; examine whole screen add cl,2 ; lines in emulation part + status xor ch,ch xor bx,bx chgdsg2:or dgwindcomp[bx],1 ; set compressed mode flag non-zero inc bx loop chgdsg2 call dgsettek ; setup special graphics mode chgdsg3:mov byte ptr low_rgt,131 ; 132 columns in special graphics mov crt_cols,128 ; but 128 physical columns ret endif ; no_graphics chgdsp_start: push es ; save all we use push ax push bx push cx push dx push si push di mov temp,ax ; save set/reset flag from msz mov ax,sp ; do push sp test for XT vs AT/386 push sp ; XT pushes sp-2, AT's push old sp pop cx ; recover pushed value, clean stack xor ax,cx ; same? jne chgdspnw ; ne = no, XT. Don't do Int 2fh test tv_mode,10h ; DESQview active? jz chgdspndv ; z = no jmp chgdsx1 ; exit without screen change chgdspndv: cmp vchgmode,1 ; change permissions, disabled? je chgdspnw ; e = 1 = disabled mov ax,1683h ; Windows 3, get current virt machine int 2fh cmp ax,1683h ; virtual machine, if any je chgdspok ; e = none cmp vchgmode,2 ; DOS-only (2)? jne chgdspok ; ne = no chgdspnw:jmp chgdsx1 ; exit without screen change chgdspok:mov ax,temp cmp crt_cols,80 ; are we narrow? jbe chgds3 ; be = narrow width now or al,al ; resetting to narrow width? jz chgds4 ; z = yes, do it jmp chgdsx1 ; else we are there now chgds3: or al,al ; resetting to narrow width? jnz chgds4 ; nz = no, setting to wide jmp chgdsx1 ; narrow width, we are there now chgds4: or ah,ah ; are we connected now? jnz chgds0 ; nz = no, skip flow control etc mov ah,flowoff ; get xoff or ah,ah ; flow control? jz chgds4a ; z = none call foutchr ; send it chgds4a:cmp byte ptr temp+1,0 ; exiting Connect mode? jne chgds0 ; ne = yes mov ax,200 ; wait 200 millisec before video tests call pcwait ; so don't mix screen and port intrpts chgds0: call ckteva ; try Tseng Labs EVA jnc chgds1 ; nc = found call ckstbv ; try STB VEGA/EM jnc chgds1 ; nc = found call ckv7vd ; try Video 7 EGA Deluxe and VGA jnc chgds1 ; nc = found call ckatiw ; try ATI EGA Wonder jnc chgds1 ; nc = found call ckevrx ; try Everex Micro Enhancer Deluxe jnc chgds1 ; nc = found call ckevga ; try Everex EVGA-673 jnc chgds1 ; nc = found call ckatt ; ATT boards jnc chgds1 ; nc = found call chkpa ; Paradise EGA/VGA boards jnc chgds1 ; nc = found call chkvesa ; VESA compatibles jnc chgds1 ; nc = found call ckxga ; IBM XGA jnc chgds1 ; nc = found mov si,offset cols80 ; name of 80 column file cmp byte ptr temp,0 ; setting 80 cols? je chgdsx2 ; e = yes mov si,offset cols132 ; use 132 column file chgdsx2:mov di,offset decbuf ; a temp buffer for path= usage call strcpy mov ax,di ; spath wants ptr in ax call fspath jc chgdsx ; c = file not found mov si,ax ; crun wants ptr in si call fcrun ; run the batch file, si = filespec call fserini ; reengage serial port, mode changes mov ax,0c06h ; clear kbd buffer and do function mov dl,0ffh ; console input int dos ; discard character(s) ; Perform mode change chgds1: cmp byte ptr temp+1,0 ; do without serial port xon/xoff? jne chgdsx1 ; ne = yes cmp flags.modflg,1 ; is mode line enabled? jbe chgdsx ; be = yes, and off or locally owned mov flags.modflg,1 ; remove foreign ownership chgdsx: mov ah,flowon ; get flow-on byte or ah,ah ; using flow control? jz chgdsx1 ; z = no call foutchr ; send it chgdsx1:mov al,crt_lins ; previous conditions mov ah,crt_cols push ax call scrmod ; pick up current screen size pop ax ifndef no_tcp cmp al,crt_lins ; screen size change? jne chgdsx1a ; ne = yes cmp ah,crt_cols je chgdsx1b ; no chgdsx1a:call winupdate ; window update req for TCP/IP Telnet chgdsx1b: endif ; no_tcp pop di ; restore what we saved pop si pop dx pop cx pop bx pop ax pop es ret ; return to caller ; Individual tests for various 132-column boards ; Tseng LABS EVA, UltraPAK, ET4000 ckteva: mov ax,0c000h ; seg addr for EVA mov es,ax ; set into es register mov di,76h ; offset of board's string lea si,tsngid ; validation string mov cx,tsnglen ; length of validiation string cld repe cmpsb ; compare strings je ckteva2 ; e = strings match mov ax,4d00h ; check for UltraPAK mono driver int screen cmp ax,5aa5h ; driver signature? jne ckteva4 ; ne = no mov ax,7 ; default to mono (7) for this board cmp byte ptr temp,0 ; setting 132 columns? je ckteva1 ; e = resetting to normal mov ax,18h ; set to 132 cols (Set Mode 18H) ckteva1:int screen clc ; carry clear means success ret ; an EVA board - check for 132 col kit ckteva2:cmp byte ptr es:099h,0 ; check 132 col kit installed jne catfnd ; ne = installed, do the mode change ckteva3:stc ; indicate adapter not present ret ; and exit ckteva4:mov dx,03cdh ; ET4000 test in al,dx ; Segment Select Register, get value push ax xor al,15h ; create test condition jmp $+2 jmp $+2 out dx,al ; set condition jmp $+2 jmp $+2 mov ah,al ; save condition in al,dx ; get new condition jmp $+2 jmp $+2 cmp ah,al ; did it work (same)? pop ax out dx,al ; restore original condition jne ckteva3 ; ne = no, ET4000 not present mov ax,3 ; default to cga 3 cmp byte ptr temp,0 ; setting 132 columns? je ckteva5 ; e = resetting to normal mov ax,23h ; set to 132 cols (Set Mode 23H) ckteva5:int screen clc ret ; ckstbv: mov ax,0c000h ; STB's VGA/EM, VGA/EM-16, EM-16 Plus mov es,ax ; mov di,70h ; where to look for signature lea si,stbvid ; the signature mov cx,stbvlen ; cld ; repe cmpsb ; test je catfnd ; e = found mov di,70h ; where to look for signature lea si,stavid ; the signature mov cx,stavlen cld repe cmpsb ; test je catfnd ; e = found stc ; else say not there ret ; ; ATI EGA Wonder ckatiw: mov ax,0c000h ; seg addr for EGA Wonder mov es,ax ; set into es register mov di,012fh ; offset of message in ROM lea si,atiwid ; offset of message here mov cx,atilen ; length of validation string cld repe cmpsb ; compare strings je catfnd ; e = they match lea si,atiwid2 ; alternative signature mov di,30h ; start at this offset mov cx,atilen2 ; alternative signature length mov ax,es:[di] ; get first two bytes cmp al,atiwid2 ; string starts here? je ckatiw1 ; e = yes inc di ; try next location, just in case cmp ah,atiwid2 ; or here? je ckatiw1 ; e = yes stc ; strings differ ret ckatiw1:repe cmpsb ; check the whole string je catfnd ; e = matches the whole thing stc ; fail on mismatch ret catfnd: mov ax,0003h ; prepare to reset video mode cmp byte ptr temp,0 ; are we setting or resetting? je catfnd1 ; e is reset, exit mov ax,0023h ; set to 132 cols (Set Mode 23H) catfnd1:int screen clc ; carry clear means success ret chkpa: mov ax,0c000h ; load Paradise ROM BIOS address mov es,ax mov ax,0057h ; assume 132x25 mono display needed mov di,0009h ; load EGA board identifier index lea si,pmega1 ; Paradise Autoswitch Mono ident mov cx,pmegal1 cld repe cmpsb ; do identification strings match? je chgpa2 ; e = yes, check num of display lines mov di,007dh ; no, load VGA board identifier index lea si,p30id ; Paradise VGA, other flavors mov cx,p30ln repe cmpsb ; do identification strings match? je chgpa1 ; e = yes, check for color mode stc ; fail ret chgpa1: cmp crt_norm,3 ; is the "normal" screen in color? ja chgpa2 ; a = no, orig assumption is correct mov ax,0055h ; assume 132x25 color required chgpa2: cmp crt_lins,25 ; is the "normal" screen 25 lines? jna chgpa3 ; na = yes, check num of cols needed dec ax ; change assumption to 132x43 chgpa3: cmp byte ptr temp,0 ; switching to a 132 column mode? jne chgpa4 ; ne = yes mov al,crt_norm ; load "normal" display mode chgpa4: int screen ; issue BIOS call to change display clc ; success ret ; Video 7 Vega Deluxe ckv7vd: mov ax,0c000h ; seg addr for Vega rom bios mov es,ax ; set into es register mov di,002ah ; offset of message in ROM lea si,vid7id ; offset of message here mov cx,vid7len cld repe cmpsb ; compare strings je cnv7fn1 ; e = same mov di,002ah ; offset of ident string mov si,offset vid7id2 ; Video 7 VGA board mov cx,vid7len2 repe cmpsb je cnv7fn2 ; e = found cnv7fx: stc ; strings are different ret ; cnv7fn1:test byte ptr es:[03ffeh],1 ; is this a 'Deluxe' Vega? jz cnv7fx ; z = nope, can't do it mov ah,35h ; DOS Get Vector mov al,10h ; Bios video interrupt int dos ; get it into es:bx mov di,bx ; es:bx is returned int 10h entry pnt sub di,5ah ; back offset to msg in 132X25.COM lea si,vid7id ; offset of validation message mov cx,vid7len ; length of validation string cld repe cmpsb ; Look for repeat of msg by 132X25.COM jne cnv7fn2 ; if different mov al,crt_mode ; prepare to reset video mode xor ah,ah cmp byte ptr temp,0 ; are we setting or resetting? je cnv7fn2a ; e is reset mov ax,0000h ; set to 132 cols (old 40x25) cnv7fn1a:int screen clc ret cnv7fn2:mov ax,6f00h ; check for VegaBios driver int screen cmp bx,'V7' ; Video 7 Bios presence response jne cnv7fx ; ne = not there mov ax,6f01h ; al gets monitor type (mono,color,ega) int screen mov bx,51h ; presume mono 132x25, page 0 cmp crt_lins,42 ; 43 lines active? jb cnv7fn2a ; b = no inc bx ; use bx = 52h for 132x43 cnv7fn2a: cmp al,10h ; analogue fixed freq (IBM 85xx)? je cnv7fx ; e = yes, no 132 columns cmp al,2 ; 1 = mono, 2 = color, above = ega jb cnv7fn3 ; b = mono or unknown mov bx,4fh ; presume med res color 132x25 je cnv7fn3 ; e = med res color, al = 2 mov bx,41h ; ega high res 132x25, enhanced mons cmp crt_lins,42 ; 43 lines active? jb cnv7fn3 ; b = no inc bx ; use bx = 42h for 132x43 cnv7fn3:mov ax,6f05h ; set special mode found in bl cmp byte ptr temp,0 ; resetting to 80 column mode? jne cnv7fn4 ; ne = no, setting 132x25 mov al,crt_norm ; get normal mode xor ah,ah ; set mode cmp crt_lins,42 ; 43 lines active? jb cnv7fn4 ; b = no mov bl,40h ; use Video 7 mode 40h 80x43 for color mov ax,6f05h ; and do special mode set cnv7fn4:int screen ; special mode is in bl mov ax,0f00h ; a nop screen bios command int screen clc ret ckevrx: mov ax,0c000h ; seg addr for Everex EV-659 mov es,ax ; set into es register mov di,0047h ; offset of message in ROM lea si,evrxid ; offset of message here mov cx,evrxlen ; length of validation string cld repe cmpsb ; compare strings jne ckfnr2 ; ne = strings differ mov ah,crt_lins ; we recognize either 44 or 25 rows cmp ah,43 ; equal to 44-1 rows? jne ckfnr1 ; ne = no mov ax,0070h ; Everex extended mode ident mov bl,09h ; prepare to reset video mode to 80x44 cmp byte ptr temp,0 ; are we setting or resetting? je ckfnr4 ; e is reset, exit mov bl,0bh ; 132x44 int screen clc ret ckfnr1: cmp ah,24 ; equal to 25-1 rows? je ckfnr3 ; e = yes ckfnr2: stc ; return failure ret ckfnr3: mov ax,0003h ; prepare to reset video mode cmp byte ptr temp,0 ; are we setting or resetting? je ckfnr4 ; e is reset, exit mov ax,0070h ; Everex extended mode ident mov bl,0ah ; 132x25 ckfnr4: int screen clc ret ckevga: mov ax,0c000h ; Everex FVGA-673, EV-678 rom segment mov es,ax mov di,76h ; offset in rom for board's id string lea si,evgid ; id string mov cx,evglen ; length of id string cld repe cmpsb ; do they match? je ckevg0 ; e = yes mov di,9dh ; offset in ROM for board's ID string lea si,evvid ; ID string mov cx,evvlen ; length of ID string cld repe cmpsb ; do they match? jne ckevg2 ; ne = no ckevg0: mov ax,3 ; prepare to reset video mode cmp byte ptr temp,0 ; setting or resetting mode? je ckevg1 ; e = resetting, exit mov ax,0070h ; mode for 132x25 mov bl,0ah ; Everex mode 0ah ckevg1: int screen clc ret ckevg2: stc ; say board not found ret ; AT&T EGA/VGA boards ckatt: mov ax,0c000h ; seg of first signature mov es,ax mov si,offset attvdc6 ; first pattern mov di,35h ; test area cld mov cx,attvdlen ; length repe cmpsb je ckatt2 ; e = found mov cx,attvdlen ; try second signature, same length mov si,offset attvdc7 mov ax,0e000h ; seg of second signature mov es,ax mov di,10h ; test area repe cmpsb je ckatt2 ; e = found stc ; not found ret ckatt2: mov al,crt_norm ; old mode xor ah,ah cmp byte ptr temp,0 ; resetting to 80 col? je ckatt3 ; e = yes mov ax,0055h ; 132 cols, set mode 55h ckatt3: int screen clc ret ; VESA compatibles chkvesa:mov di,seg rdbuf ; es:di is buffer for results mov es,di mov di,offset rdbuf mov ax,4f00h ; get SVGA information int screen cmp ax,4fh ; success? jne chkvesax ; ne = no cmp word ptr rdbuf,'EV' ; 'VESA' jne chkvesax ; ne = no cmp word ptr rdbuf+2,'AS' jne chkvesax ; ne = no mov ax,4f01h ; get mode info to es:di buffer mov cx,109h ; 109h is 132x25 text int screen cmp ax,4fh ; success? jne chkvesax ; ne = no mov bx,3 ; assume 80 columns cmp byte ptr temp,0 ; setting or resetting mode? je chkvesa2 ; e = resetting mov bx,109h ; mode for 132x25 chkvesa2:mov ax,4f02h ; set mode from bx int screen cmp ax,4fh ; success? jne chkvesax ; ne = no clc ; say success ret chkvesax:stc ; say failure ret ; IBM XGA 132 columns ckxga: push bp ; (old BIOSes are still around) push ds ; set es to data segment pop es mov ax,1b00h ; get functionality table xor bx,bx mov di,offset decbuf ; es:di is 64 bytes of workspace int screen cmp al,1bh ; is this call supported? jne ckxgax ; ne = no, fail les bx,dword ptr decbuf ; get the address of the modes info test byte ptr es:[bx+2],10h ; is mode 14h supported? jz ckxman ; z = no, try manual method for now mov ax,3 ; assume resetting to mode 3, 80x25 cmp byte ptr temp,0 ; setting 132 columns? je ckxga1 ; e = no, resetting to 80 columns mov ax,14h ; invoke IBM XGA mode 14h, 132x25 ckxga1: int screen ckxga2: pop bp clc ; say success ret ckxgax: pop bp mov xga_reg_base,-2 ; flag saying no XGA Adapter found stc ; say failure ret ckxman: call xgaman ; do tests/sets manually pop bp jnc ckxman1 ; nc = success mov xga_reg_base,-2 ; flag saying no XGA Adapter found ckxman1:ret chgdsp endp ; XGA mode setting via going to the hardware manually ; Code furnished by Bert Tyler, National Institue of Health xgaman proc near cmp xga_reg_base,-2 ; has the XGA detector already failed? je xgafail ; e = yes, fail again cmp xga_reg_base,-1 ; have we already found the XGA? je xga_loc ; e = no jmp xga_do1 ; yes, process it xga_loc:push es mov ah,35h ; DOS get interrupt vector mov al,15h ; Int 15h int dos ; returns vector in es:bx mov ax,es ; segment part pop es or ax,ax ; undefined vector? jz xgafail ; z = yes mov dx,-1 ; start with an invalid POS address mov ax,0c400h ; look for POS base address int 15h ; (Microchannel machines only) jc xgafail ; c = error, not a MC machine mov xgatmp1,dx ; save pos_base_address xor cx,cx ; check all MCA slots & motherboard cmp dx,-1 ; do we have a good POS? jne xga_lp1 ; ne = yes, proceed with MCA checks xgafail:stc ; fail ret xga_lp1:cli ; no interrupts, please cmp cx,0 ; treat the motherboard differently? jne xga_sk4 ; ne = yes mov al,0dfh ; enable the motherboard for setup mov dx,94h out dx,al jmp short xga_sk5 xga_sk4:mov ax,0c401h ; enable an MCA slot for setup mov bx,cx ; this slot int 15h xga_sk5:mov dx,xgatmp1 ; get pos record for the slot in ax,dx ; ID mov xgatmp2,ax add dx,2 ; compute IO Res Base in al,dx ; get POS data byte1 and ax,0eh ; muck about with it to get reg base shl ax,1 shl ax,1 shl ax,1 add ax,2100h mov xga_reg_base,ax cmp cx,0 ; treat the motherboard differently? jne xga_sk6 ; ne = yes mov al,0ffh ; enable the motherboard for normal out 094h,al jmp short xga_sk7 xga_sk6:mov ax,0c402h ; enable the MCA slot for normal mov bx,cx ; this slot int 15h xga_sk7:sti ; interrupts on again mov ax,xgatmp2 ; is an XGA adapter on this slot? cmp ax,08fd8h jae xga_sk8 ; ae = yes jmp xga_lp2 ; try another slot xga_sk8:cmp ax,08fdbh ; still within range? jbe xga_sk9 ; be = yes jmp xga_lp2 ; no, try another slot xga_sk9:mov dx,xga_reg_base ; is there a monitor on this slot? add dx,0ah mov al,052h out dx,al mov dx,xga_reg_base add dx,0bh in al,dx and al,0fh cmp al,0fh jne xga_ska ; ne = yes jmp xga_lp2 ; no xga_ska:mov dx,xga_reg_base ; is this XGA in VGA mode? in al,dx test al,1 jnz xga_do1 ; nz = yes, found it! xga_lp2:inc cx ; try another adapter? cmp cx,9 ; done all slots? ja xga_no ; a = yes jmp xga_lp1 ; no, try another slot xga_no: jmp xgafail ; fail ; *finally* put the XGA into 132-column or 80-column mode xga_do1:cmp byte ptr temp,0 ; setting 80-column mode? jne xga_do2 ; ne = no, 132 columns jmp xga_do3 ; do 80 column mode ; 132-column mode routine xga_do2:mov dx,xga_reg_base ; (the manual doesn't explain...) add dx,0ah mov ax,1550h out dx,ax mov ax,1450h out dx,ax mov ax,0454h out dx,ax mov ax,1202h ; select 400 scan lines mov bl,30h int screen mov ax,0+3 ; set video mode 3 int screen mov dx,xga_reg_base ; (the manual doesn't explain...) add dx,0ah mov al,50h out dx,al inc dx in al,dx or al,1 out dx,al mov dx,xga_reg_base ; (the manual doesn't explain...) add dx,0ah mov al,50h out dx,al inc dx in al,dx and al,0fdh out dx,al mov dx,xga_reg_base ; (the manual doesn't explain...) add dx,0ah mov al,50h out dx,al inc dx in al,dx and al,0fch out dx,al mov dx,xga_reg_base ; (the manual doesn't explain...) mov al,3 out dx,al mov dx,xga_reg_base ; (the manual doesn't explain...) add dx,0ah mov ax,0154h out dx,ax mov ax,8070h out dx,ax mov dx,xga_reg_base ; (the manual doesn't explain...) add dx,0ah mov al,50h out dx,al inc dx in al,dx and al,0efh out dx,al mov dx,03d4h ; (the manual doesn't explain...) mov ax,11h out dx,al inc dx in al,dx and al,7fh out dx,al mov dx,03d4h ; (the manual doesn't explain...) mov ax,0 out dx,al inc dx mov ax,0a4h out dx,al mov dx,03d4h ; (the manual doesn't explain...) mov ax,1 out dx,al inc dx mov ax,83h out dx,al mov dx,03d4h ; (the manual doesn't explain...) mov ax,2 out dx,al inc dx mov ax,84h out dx,al mov dx,03d4h ; (the manual doesn't explain...) mov ax,3 out dx,al inc dx mov ax,83h out dx,al mov dx,03d4h ; (the manual doesn't explain...) mov ax,4 out dx,al inc dx mov ax,90h out dx,al mov dx,03d4h ; (the manual doesn't explain...) mov ax,5 out dx,al inc dx mov ax,80h out dx,al mov dx,xga_reg_base ; (the manual doesn't explain...) add dx,0ah mov ax,0a31ah out dx,ax mov ax,001bh out dx,ax mov dx,03d4h ; (the manual doesn't explain...) mov ax,13h out dx,al inc dx mov ax,42h out dx,al mov dx,03d4h ; (the manual doesn't explain...) mov al,11h out dx,al inc dx in al,dx or al,80h out dx,al mov dx,xga_reg_base ; (the manual doesn't explain...) add dx,0ah mov al,50h out dx,al inc dx in al,dx or al,3 out dx,al mov dx,03c4h ; (the manual doesn't explain...) mov ax,1 out dx,al inc dx in al,dx or al,1 out dx,al mov dx,03dah ; (the manual doesn't explain...) in al,dx mov dx,003c0h ; (the manual doesn't explain...) mov al,13h out dx,al xor al,al out dx,al mov al,20h out dx,al mov ax,40h ; tell the BIOS we have 132 columns mov es,ax mov byte ptr es:[4ah],132 ; set Bios screen width data area clc ; return success ret ; Set 80 column mode xga_do3:mov dx,xga_reg_base ; (the manual doesn't explain...) add dx,01h xor al,al out dx,al mov dx,xga_reg_base ; (the manual doesn't explain...) add dx,4 xor al,al out dx,al mov dx,xga_reg_base ; (the manual doesn't explain...) add dx,5 mov al,0ffh out dx,al mov dx,xga_reg_base ; (the manual doesn't explain...) add dx,0ah mov ax,0ff64h out dx,ax mov dx,xga_reg_base ; (the manual doesn't explain...) add dx,0ah mov ax,1550h out dx,ax mov dx,xga_reg_base ; (the manual doesn't explain...) add dx,0ah mov ax,1450h out dx,ax mov dx,xga_reg_base ; (the manual doesn't explain...) add dx,0ah mov ax,0051h out dx,ax mov dx,xga_reg_base ; (the manual doesn't explain...) add dx,0ah mov ax,0454h out dx,ax mov dx,xga_reg_base ; (the manual doesn't explain...) add dx,0ah mov ax,7f70h out dx,ax mov dx,xga_reg_base ; (the manual doesn't explain...) add dx,0ah mov ax,202ah out dx,ax mov dx,xga_reg_base ; (the manual doesn't explain...) ;; add dx,00h mov al,1 out dx,al mov dx,03c3h ; (the manual doesn't explain...) mov al,1 out dx,al mov ax,1202h ; select 400 scan lines mov bl,30h int screen mov ax,0+3 ; set video mode 3 int screen clc ; return success ret xgaman endp ; Routine to do keyclick if flag is set, no arguments vclick proc near test vtemu.vtflgop,vskeyclick ; is keyclick flag on? jz vclick1 ; z = no, just return push bx push di mov di,500 ; 500 Hertz mov bx,1 ; For 1 millisecond call vtsound ; Do it pop di ; Restore the ACs pop bx vclick1:ret vclick endp endif ; no_terminal ; Routine to do VT100-style bell, no arguments fvtbell proc far call vtbell ret fvtbell endp vtbell proc near cmp belltype,1 ; visual bell? je vtbell1 ; e = yes ja vtbell2 ; a = no bell push di ; audible bell push bx mov di,880 ; 880 Hertz mov bx,40 ; For 40 ms call vtsound ; Do it pop bx pop di ret vtbell1: ifndef no_terminal call revscn ; reverse screen push ax mov ax,40 ; for 40 milliseconds call pcwait pop ax call revscn ; put back endif ; no_terminal vtbell2:ret vtbell endp ; Routine to make noise of arbitrary frequency for arbitrary duration. ; Similar to routine (with typo removed) in "IBM PC Assembly Language: ; A Guide for Programmers", Leo J. Scanlon, 1983 Robert J. Brady Co., ; Bowie, MD., page 270. Modified by J R Doupnik to use 0.1 millsec interval. ; Call: di/ frequency in Hertz. ; bx/ duration in 1 millisecond units vtsound proc near push ax ; save regs push cx push dx mov al,0B6H ; write timer mode register out 43H,al mov dx,14H ; timer divisor is mov ax,4F38H ; 1331000/frequency div di out 42H,al ; write timer 2 count low byte mov al,ah out 42H,al ; write timer 2 count high byte in al,61H ; get current port B setting or al,3 ; turn speaker on out 61H,al mov ax,bx ; number of milliseconds to wait call pcwait ; do the calibrated wait in al,61H ; get current port B setting and al,0fch ; turn off speaker and timer out 61H,al pop dx ; restore regs pop cx pop ax ret vtsound endp code1 ends end