name msyv90 ; File MSYV90.ASM ; Last modification: 30 July 1986 ; Kermit system dependent module for VICTOR 9000/SIRIUS ; 30 July 1986 fill out prodecure DUMPSCR - it was borrowed from MSYIBM and ; modified to fit the Victor format. It required a modification of ; lclyini to get the character set base [bgp] ; Add global procedure Dumpscr, called by Ter in file msster, to dump screen ; to a file. Just does a beep for now. 3 May 1986 [jrd] ; ; edit history: ; 7-DEC-85 ORIGINAL BGP ; 20-FEB-86 CORRECTED FOR ERROR IN PUTMOD IN MSXV9000 (BGP) ; 22-FEB-86 ADDED CODE TO SWALLOW ANSI ESCAPE SEQUENCES (BGP) ; Added 'full' VT100 emulation using code by Andreas Stumpf ; (ZRZS@DS0RUS1I). The significant parts that are not emulated are ; esc c - reset terminal ; esc N - ?? ; esc O - ?? ; esc n - ?? ; esc l - ?? ; esc o - ?? ; esc < - go to ANSI mode (from VT52) ; esc [ q - fiddle with the LED's ; esc [ h - some modes not supported ; esc [ l - some modes not supported ; esc [ i - ?? ; esc [ p - ?? ; esc [ y - ?? ; and some codes that are not VT100 'standard' are supported ; esc [ E - ?? ; esc [ F - ?? ; esc [ G - ?? ; esc [ L - ?? ; esc [ M - ?? ; esc [ @ - ?? ; esc [ P - ?? ; esc [ X - ?? ; esc [ d - ?? ; esc [ e - ?? ; Last update 28 April 1986 ; Add global procedure Dumpscr, called by Ter in file msster, to dump screen ; to a file. Just does a beep for now. 3 May 1986 [jrd] ; public term, lclyini, vts, vtstat ; entry points public dumpscr ; [jrd] include mssdef.h SEG_CRTC EQU 0E800H ; segment for crt controller OFF_CRTC EQU 0 ; offset for crt controller modfrm struc ; format of mode line db ' Esc chr: ' m_echr db 2 dup (?) db ', Port: ' m_prt db 1 dup (?) db ', Speed: ' m_baud db 4 dup (?) db ', Parity: ' m_par db 4 dup (?) db ', Echo: ' m_echo db 3 dup (?) db ', Type ' m_hlp db 2 dup (?) db '? for Help' db ' $' ; must be dollar terminated modfrm ends DATAS segment public 'datas' extrn flags:byte ; to get access to emulation extrn filtst:byte, dmpname:byte ; for screen dumping [bgp] termhlp db CR,LF,'Terminal type of Heath-19 or VT100$' termtbl db 4 mkeyw 'Heath-19',TTHEATH mkeyw 'none',TTHEATH ; since none=heath on Victor mkeyw 'VT100',TTVT100 mkeyw 'VT102',TTVT100 ; stuff for screen routines wflags label word ; so we can push yflags yflags db ? ; status flags... db 0 ; extra byte for flags flags1 db 0 ; internal flags. prtscr equ 80h ; print screen pressed inited equ 08h ; been here before... esc_ch db ? argadr dw ? ; address of arg blk crt_cols db ? crt_lins db ? modbuf modfrm <> ; mode line buffer ; routine to call for captured output captrtn dw ? oldcur dw 0 ; save'd cursor position ; some static data for mode line unkbaud db 'Unk ' ; must be 4 chars... baudn db '45.5' db ' 50' db ' 75' db ' 110' db ' 135' db ' 150' db ' 300' db ' 600' db '1200' db '1800' db '2000' db '2400' db '4800' db '9600' db '19.2' db '38.4' baudnsiz equ 16 ; # of baud rates known (tbl size / 4) parnams db 'Even' db 'Mark' db 'None' db 'Odd ' ; must be 4 chars db 'Spc ' offmsg db 'Off' onmsg db 'On ' lclmsg db 'Lcl' remmsg db 'Rem' portno db ? screen dw 1920 dup (?) curloc db 2 dup (?) ; row,column scrseg dw 0F000H rptcur db 27,'n$' ; request cursor location escseq db 0 ; ANSI escape sequence indicator ; 0=none, 1=escape, 2=[ char_base dw 0 ; screen character base dmphand dw 0 ; handle for screen dump [bgp] dumpbuf db 80 dup (?),CR,LF ; line buffer for screen dump dumpsep db FF,CR,LF ; put in file between screen dumps dmperr db ' WARNING: CAN NOT OPEN THE SCREEN DUMP FILE $' ; stuff for ANSI emulation [as] SUPERBIOS equ 0dfh ; SuperBios-Interrupt tt struc ; structure of keyboardtable head dw 2 dup (?) kd0 db 104*3 dup (?) kd12 dw 104*3 dup (?) extrtabl db 256 dup (?) tt ends afirst db 0 ; Parameterblock for setting/getting of keyboard-table parmblock db 3 laenge dw 1196 ; length of table offs dw offset oldtable segm dw seg oldtable ; block for call to get Console-driver-address condev dw 1 drivadr dd 0 ; address of consoledriver ; oldtable tt <,,,> ; saved old keytable numtbl tt <,,,> ; Table with Num-Keypad apptbl tt <,,,> ; Table with Appl-Keypad ; In order to avoid smashing stuff that may already be in the multi-char ; sequence table for the keyboard (or as little as possible) put it near the ; end of the table - the following parameters tells how deep into the table ; to start putting stuff START_EXTRTBL EQU 160 ; Cursorsequences ANSI appcur db 0 ; flag for cursor key modes curseq db 3,ESC,'[A',3,ESC,'[B',3,ESC,'[D',3,ESC,'[C' curapp db 3,ESC,'OA',3,ESC,'OB',3,ESC,'OD',3,ESC,'OC' ; Applikationkeypad appkeys db 0 ; flag for keypad modes applik db 3,ESC,'[A',3,ESC,'[B',3,ESC,'[D',3,ESC,'[C' db 3,ESC,'OP',3,ESC,'OQ',3,ESC,'OR',3,ESC,'OS' db 3,ESC,'Ow',3,ESC,'Ox',3,ESC,'Oy',3,ESC,'Om' db 3,ESC,'Ot',3,ESC,'Ou',3,ESC,'Ov',3,ESC,'Ol' db 3,ESC,'Oq',3,ESC,'Or',3,ESC,'Os',3,ESC,'OM' db 3,ESC,'Op',3,ESC,'On' sesctbl db 'DEHMNOZn|o[>=78c<' ; table for characters following single ESC sesclen equ $-sesctbl ; now the table for routines to process those characters sescsub dw processD dw processE dw processH dw processM dw ignore dw ignore dw procc0 ; same as ESC [0c dw ignore dw ignore dw ignore dw processbra dw processgt dw processeq dw process7 dw process8 dw ignore dw ignore ; table for the last characters in a ESC'[' sequence mesctbl db '`EFGABCDHLM@PXKJfghilmrcnpyqde' mesclen equ $-mesctbl ; processing routine table for ESC'[' sequences mescsub dw proce dw proce dw procuf dw procug dw curmov dw curmov dw curmov dw curmov dw procH dw procL dw procM dw procAt dw procP dw procX dw procK dw procJ dw procH dw procg dw prochl dw ignore dw prochl dw proclm dw procr dw procc dw procn dw ignore dw ignore dw ignore dw procld dw procle ; top db 1 ; scrolling region margins bottom db 24 escpnt dw offset escstring escstring db 80 dup (?) ; save area for Escape sequence tabstops db 0,0,0,0,0,0,0,0 ; tabulator stops db 1,0,0,0,0,0,0,0 db 1,0,0,0,0,0,0,0 db 1,0,0,0,0,0,0,0 db 1,0,0,0,0,0,0,0 db 1,0,0,0,0,0,0,0 db 1,0,0,0,0,0,0,0 db 1,0,0,0,0,0,0,0 db 1,0,0,0,0,0,0,0 db 1,0,0,0,0,0,0,0 chrset_mask db 0 ; mask for selecting character set DATAS ends CODE segment public ; code segment extrn prtchr:near,outchr:near,sendbr:near,comnd:near extrn putmod:near,clrmod:near,cmblnk:near,poscur:near extrn beep:near, isfile:near ; [jrd] [bgp] assume cs:code,ds:datas,es:datas ; do initialization local to this module... ; mainly get console driver address to speed up screen access [as] ; 30 July 1986 added code to get character set base for dump [bgp] LCLYINI proc near mov ah,DCONIO mov dl,ESC ; to set nowrap int DOS mov dl,'w' int DOS mov ax,ds mov es,ax mov ax,14 ; function 'get driveraddress' mov bx,offset condev int SUPERBIOS ; address is now in drivadr push es mov ax,0F000H ; point at base of screen memory mov es,ax mov ax,word ptr es:3838 ; note: this should be the last character ; of the last line on the screen - if it was ; cleared as Kermit usually does when it starts ; up, this will be a space - it must be a space! and ax,7FFH ; strip off mode bits sub ax,' ' ; minus which char it is mov char_base,ax ; and save it pop es ret LCLYINI endp ; We need to save the arguments to TERM where they are a little more ; accessible than in the way they were passed ARGINI proc near ; read passed arguments mov bx,argadr ; base of argument block mov al,[bx].flgs ; get flags and al,capt+emheath+havtt+trnctl+lclecho+modoff+lnwrap mov yflags,al ; mask for allowable and save and flags1,not (prtscr) ; these are allowable ; (others remain). mov al,[bx].prt cmp al,portno ; using same port? je argin1 ; yes, go on and flags1,not inited ; else re-init stuff argin1: mov portno,al ; update port number mov al,[bx].cols mov crt_cols,al mov al,[bx].rows mov crt_lins,al ; init # of rows and cols mov ax,[bx].captr mov captrtn,ax ; buffer capture routine mov al,[bx].escc mov esc_ch,al ret ; that's it ARGINI endp ; We need to generate the mode line and output it MODLIN proc near ; turn on mode line push ds pop es ; make sure es is correct mov al,esc_ch mov modbuf.m_echr,' ' ; first char is initial space mov modbuf.m_hlp,' ' ; goes here too. cmp al,32 ; printable? jnb modl1 ; yes, keep going add al,40h ; made printable mov modbuf.m_echr,'^' ; note control char mov modbuf.m_hlp,'^' modl1: mov modbuf.m_echr+1,al ; fill in character mov modbuf.m_hlp+1,al mov bx,argadr ; get argument block mov al,[bx].baudb ; get baud bits mov si,offset unkbaud ; assume unknown baud cmp al,baudnsiz ; too big? jnb modl2 ; yes, use default mov cl,2 ; each is 4 bytes long shl al,cl mov ah,0 add ax,offset baudn mov si,ax modl2: mov cx,size m_baud ; length of baud space mov di,offset modbuf.m_baud rep movsb ; copy in baud rate mov al,[bx].parity ; get parity code mov cl,2 ; each is 4 bytes long... shl al,cl mov ah,0 add ax,offset parnams ; names of parity settings mov si,ax mov cx,4 ; each is 4 long mov di,offset modbuf.m_par rep movsb mov si,offset remmsg ; Assume remote echoing. test yflags,lclecho ; Is remote side echoing? jz modl4 ; Yes, keep going mov si,offset lclmsg ; Else it's local echoing. modl4: mov cx,3 ; size of on/off mov di,offset modbuf.m_echo rep movsb mov al,'1' cmp portno,1 ; port 1? je modl5 ; yes, keep going mov al,'2' modl5: mov modbuf.m_prt,al ; fill in port number mov dx,offset modbuf ; where it is call putmod ret MODLIN endp ; This is the entry point for terminal emulation ; Added option of VT100 emulation TERM proc near ; terminal emulator entry point mov argadr,ax ; save argument ptr push es ; save caller's extra segment address mov ax,seg datas mov es,ax call argini ; init options from arg address test flags1,inited ; have we run yet? jz term1 ; no, forget this part call restscr ; restore screen jmp term2 term1: call cmblnk ; clear it off term2: or flags1,inited ; remember we've run already. call clrmod ; empty mode line test yflags,modoff ; is mode line disabled? jnz term3 ; yes, skip it call modlin ; turn on mode line term3: cmp flags.vtflg,TTVT100 ; emulating VT100? jne lp call ansie jmp quit lp: call portchr ; char at port? jnc chkinp ; no, keep going ; we want to swallow any ANSI escapes that come for now ; they are all of the form ESC [ nn ; nn ; nn ; nn a ; where n is a numeric character, and a is a non-numeric character cmp escseq,0 ; escape sequence in progress? jne eat_esc_seq ; yes cmp al,ESC ; got an escape? jne no_esc ; no mov escseq,1 ; yes, flag it jmp chkinp eat_esc_seq: cmp escseq,1 ; got [? jne eat_esc_seq2 ; yes cmp al,'[' je eat_esc_seq1 push ax ; not [, print esc and char mov al,ESC call outtty ; send the escape pop ax ; and the following character mov escseq,0 ; no escape sequence jmp no_esc eat_esc_seq1: mov escseq,2 ; flag [ jmp chkinp eat_esc_seq2: cmp al,';' ; check for terminator je chkinp cmp al,'0' jl end_esc cmp al,'9' jg end_esc jmp chkinp ; no terminator, keep eating end_esc: mov escseq,0 ; end of sequence jmp chkinp no_esc: call outtty ; print on terminal chkinp: mov ah,DCONIO ; Get it with no checking mov dl,0FFH int DOS cmp al,0 ; anything there? je lp ; no... cmp al,esc_ch ; escape character? je quit ; yes, stop here call outprt jmp chkinp ; and keep going quit: call clrmod ; erase mode line call savescr ; save screen mov al,yflags mov bx,argadr mov [bx].flgs,al ; update flags in arg block pop es ; restore segment register ret ; and return to caller TERM endp ; ANSI, VT100 emulation by Andreas Stumpf ANSIE proc near cmp afirst,1 ; have we run yet? jnz ansi2 ; no, forget this part mov bx,ds ; now restore keyboard too mov es,bx mov bx,offset parmblock mov ax,18 int SUPERBIOS jmp ansi3 ansi2: call initansi ansi3: mov afirst,1 ; remember we've run already. portc: call portchr ; char at port? jnc achkinp ; no, get char from keyboard call doansi ; handle it somehow achkinp: mov ah,DCONIO ; Get it with no checking mov dl,0FFH int DOS cmp al,0 ; anything there? je portc ; no... cmp al,esc_ch ; escape character? je aquit ; yes, stop here call outprt ; send it jmp portc ; look for next char aquit: call finiansi ; fix keyboard up ret ANSIE endp ; DOANSI actually takes care of emulating the ANSI screen control stuff ; code by Andreas Stumpf - it expects the character to be in al DOANSI proc near cmp al,ESC ; got an escape? jne w00 jmp procesc0 ; escape terminates Escape-sequence, w00: ; so it has to be tested first cmp al,'X'-40h ; Control-X ? jne w0 jmp ignore w0: cmp al,'Z'-40h ; Control-Z jne w01 jmp ignore w01: cmp escseq,0 ; escape sequence in progress? je w02 jmp procesc ; yes w02: cmp al,' ' jl controls jmp noesc controls: cmp al,LF ; Linefeed,Formfeed and Vertical tab are ; processed as 'Scroll down, if at ; bottom margin, same function as ESC'D' jne w1 jmp processD ; perform scrolling if necessary w1: cmp al,FF jne w2 jmp processD w2: cmp al,11 ; vertical tab jne w3 jmp processD w3: cmp al,TAB ; horizontal tab jne w4 call get_cur_pos ; get cursor position mov al,dh ; work on it here mov cx,80 sub cl,al ; # of cols to search for tab cmp cl,0 ; already off the end? jg t0 ; no mov cl,0 jmp t1 ; go to right margin t0: xor ah,ah mov di,offset tabstops add di,ax ; address of first tabstop to look for cld mov ax,1 ; compare table with 1 repnz scasb ; cl=0 is right margin t1: sub cl,80 neg cl mov dh,cl ; set new col pos call set_cur_pos ; done... jmp ignore w4: cmp al,14 ; shift to extra set? jne w5 mov chrset_mask,80H ; set top bit on these jmp ignore w5: cmp al,15 ; shift to normal set? jne w6 mov chrset_mask,0 ; clear top bit jmp ignore w6: jmp noesc procesc0: ; start of escape sequence processing mov escpnt,offset escstring mov escseq,1 ; flag it jmp doansi_d ; done with it procesc: ; have just got an escape cmp escseq,1 ; single char ESCape ? je procesc1 ; yes process it inc escseq inc escpnt ; store escape sequence for mov bx,escpnt ; further processing mov [bx],al cmp escseq,3 jg proccont1 cmp al,'?' ; 1st char after ESC'[' may be a '?' jne proccont1 jmp doansi_d ; done with it proccont1: cmp al,';' jne proccont2 jmp doansi_d proccont2: cmp al,'-' ; may be first char of a number jne proccont3 ; continue checking mov bx,escpnt cmp byte ptr [bx-1],'0' ; preceding char in [0..9] ? jl procmin1 ; if yes, then syntax error => jmp ignore ; ignore Escapesequence procmin1: cmp byte ptr [bx-1],'9' jg procmin2 jmp ignore procmin2: jmp doansi_d proccont3: cmp al,'0' jl proccont cmp al,'9' jg proccont jmp doansi_d ; ESC-seq hasn't finished yet proccont: jmp procmulti ; other char than 0..9 ';' => process them procesc1: ; function dispatcher for single char Escapesequences mov di,offset sesctbl mov cx,sesclen cld repnz scasb ; search for legal char following ESC cmp al,[di-1] jnz notrecognized mov bx,sesclen sub bx,cx ; get offset in table dec bx shl bx,1 add bx,offset sescsub mov escseq,0 ; Escape sequence has finished jmp [bx] notrecognized: jmp noesc processbra: ; introduction of multi-char Escapesequence mov escseq,2 inc escpnt mov bx,escpnt mov [bx],al ; save that char jmp doansi_d ; and get next one processH: call get_cur_pos ; get cursor position mov al,dh ; get column here dec al ; range 0 to 79 mov bx,offset tabstops xor ah,ah add bx,ax mov byte ptr [bx],1 jmp ignore processD: call get_cur_pos ; get cursor position cmp dl,bottom ; is it last line? je delline ; yes, need to insert inc dl ; move down one line call set_cur_pos jmp ignore ; done delline: ; perform a scroll-up push dx ; save where we were mov dl,top mov dh,1 ; goto (top,1) call set_cur_pos mov al,ESC call outtty mov al,'M' ; delete line call outtty pop dx ; get back where we were push dx mov dh,1 ; column 1 call set_cur_pos mov al,ESC call outtty mov al,'L' ; insert line call outtty pop dx ; get it back again cmp dh,1 je processD1 ; done call set_cur_pos ; move to final position processD1: jmp ignore processE: mov al,CR ; same as ESC'D', but in col 1 call outtty ; so write out Carriage return jmp processD processM: call get_cur_pos ; get cursor position cmp dl,top je insline ; yes, jump to insert dec dl ; move up one call set_cur_pos jmp ignore insline: ; perform a scroll-down push dx ; save current position mov dl,bottom mov dh,1 ; 1. position to bottom margin call set_cur_pos mov al,ESC ; 2. delete line call outtty mov al,'M' call outtty mov dl,top mov dh,1 ; 3. position to top margin call set_cur_pos mov al,ESC call outtty mov al,'L' ; 4. insert line with ESC 'L' call outtty pop dx ; get back my position cmp dh,1 ; first col? je processM1 ; yes call set_cur_pos processM1: jmp ignore ; all done processeq: ; set applikation keypad mov ax,ds mov es,ax mov cx,8 mov di, offset apptbl.extrtabl add di,START_EXTRTBL ; don't want to start at the top cmp appcur,0 ; cursor keys application ? je peq1 mov si,offset curapp jmp peq2 peq1: mov si,offset curseq peq2: rep movsw ; move cursor keys to key-table mov appkeys,1 mov bx,offset parmblock mov byte ptr [bx],2 mov offs,offset apptbl mov ax,18 int SUPERBIOS ; set new keytable jmp ignore processgt: ; set numeric keypad mov ax,ds mov es,ax mov cx,8 mov di, offset numtbl.extrtabl add di,START_EXTRTBL ; don't want to start at the top cmp appcur,0 je pgt1 mov si,offset curapp jmp pgt2 pgt1: mov si,offset curseq pgt2: rep movsw mov appkeys,0 mov bx,offset parmblock mov byte ptr [bx],2 mov offs,offset numtbl mov ax,18 int SUPERBIOS jmp ignore process7: ; save cursor position mov al,ESC call outtty mov al,'j' jmp noesc process8: ; restore cursor position mov al,ESC call outtty mov al,'k' jmp noesc procmulti: ; function dispatcher for multi-character escape-sequences ; AL has terminating character mov cx,ds mov es,cx mov di,offset mesctbl mov cx,mesclen cld repnz scasb cmp al,[di-1] jnz notrec ; didn't find it in table mov bx,mesclen sub bx,cx ; get offset in table dec bx shl bx,1 add bx,offset mescsub jmp [bx] notrec: jmp noesc curmov: ; process Cursor movements cmp escseq,3 ; has no mumeric argument jne pars curmov0: mov al,ESC call outtty mov bx,escpnt mov al,[bx] jmp noesc ; print it without '[' pars: ; parse numeric argument mov bx,offset escstring+2 ; skip ESC'[' call getnum ; getnum returns the number in DL xor dh,dh cmp dl,80 jg curmovend cmp dl,0 jl curmovend je curmov0 mov cx,dx ; becomes loop counter mov bx,escpnt mov bl,[bx] ; put last char of sequence in bl parsl2: mov al,ESC call outtty mov al,bl call outtty loop parsl2 curmovend: jmp ignore ; ignore invalid positioning procg: mov bx,offset escstring+2 call getnum cmp dl,0 jne procg1 call get_cur_pos mov al,dh ; current col here dec al ; range 0 to 79 mov bx,offset tabstops xor ah,ah add bx,ax mov byte ptr [bx],0 jmp ignore procg1: cmp dl,3 jne procg3 mov cx,80 push es push ds pop es ; make sure in right segment mov di,offset tabstops xor ax,ax rep stosb pop es ; get old es back procg3: jmp ignore procE: mov al,CR ; go to col 1 call outtty procle: mov bx,escpnt mov byte ptr [bx],'B' ; process cursor down jmp curmov procuF: mov al,CR ; go to col 1 call outtty mov bx, escpnt mov byte ptr [bx],'A' ; cursor up jmp curmov procuG: mov bx,offset escstring+2 call getnum cmp dl,0 jg procug1 mov dl,1 procug1: cmp dl,80 jle procug2 mov dl,80 procug2: mov cl,dl call get_cur_pos mov dh,cl ; set new column call set_cur_pos jmp ignore procld: mov bx,offset escstring+2 call getnum cmp dl,0 jg procld1 mov dl,1 procld1: cmp dl,24 jle procld2 mov dl,24 procld2: mov cl,dl call get_cur_pos mov dl,cl call set_cur_pos jmp ignore procH: ; position cursor mov bx,offset escstring+2 call getnum cmp dl,1 jge procH0 mov dl,1 ; provide default for invalid address procH0: cmp dl,24 jg badH cmp byte ptr [bx],';' jne procH01 inc bx procH01: push dx ; save row value call getnum pop ax ; get it back here cmp dl,1 jge procH1 mov dl,1 procH1: cmp dl,80 jg badH mov dh,dl ; get in right places mov dl,al call set_cur_pos badH: jmp ignore procL: mov bx,offset escstring+2 call getnum mov cx,dx cmp cx,0 jg procL0 mov cx,1 jmp procL1 procL0: cmp cx,24 jle procL1 mov cx,1 procL1: call get_cur_pos mov bh,dl mov bl,dh ; save these procL2: ; perform a insert line mov dl,bottom mov dh,1 call set_cur_pos mov al,ESC call outtty mov al,'M' call outtty mov dl,bh ; get in right place mov dh,bl call set_cur_pos mov al,ESC call outtty mov al,'L' call outtty loop procL2 jmp ignore procM: mov bx,offset escstring+2 call getnum mov cx,dx cmp cx,0 jg procM0 mov cx,1 jmp procM1 procM0: cmp cx,24 jle procM1 mov cx,1 procM1: call get_cur_pos mov bh,dl mov bl,dh procM2: ; perform a delete line mov al,ESC call outtty mov al,'M' call outtty mov dl,bottom mov dh,1 call set_cur_pos mov al,ESC call outtty mov al,'L' call outtty mov dl,bh ; get in right places mov dh,bl call set_cur_pos loop procM2 jmp ignore procAt: ; insert blank characters mov bx,offset escstring+2 call getnum mov cx,dx sub cx,1 mov al,ESC call outtty mov al,'@' call outtty mov al,' ' call outtty mov al,BS call outtty cmp cx,0 jle procat1 procat2: mov al,' ' call outtty mov al,BS call outtty loop procat2 procat1: mov al,ESC call outtty mov al,'O' call outtty jmp ignore procP: procX: mov bx,offset escstring+2 call getnum mov cx,dx cmp cx,0 jg procX1 mov cx,1 procX1: mov al,ESC call outtty mov al,'N' call outtty loop procX1 jmp ignore procr: ; set margins mov top,1 mov bottom,24 mov bx,offset escstring+2 call getnum cmp dl,1 jl procr1 cmp dl,23 jg procr1 mov top,dl procr1: inc bx call getnum cmp dl,top jl procr2 cmp dl,24 jg procr2 mov bottom,dl procr2: mov dh,1 ; After inspecting what the VAX EDT editor does, mov dl,1 ; it appears that ESC [ Pn r should leave call set_cur_pos ; the cursor in the upper left corner [bgp] jmp ignore procc: ; Terminal status request mov bx,offset escstring+2 cmp byte ptr [bx],'>' je procc2 cmp byte ptr [bx],'0' je procc0 cmp byte ptr [bx],'c' je procc0 jmp ignore procc0: push wflags ; need to save these and yflags,not lclecho ; force no echo for these mov al,ESC call outprt mov al,'[' call outprt mov al,'?' call outprt mov al,'1' call outprt mov al,';' ; signal AVO option - we sort of have it call outprt mov al,'2' call outprt mov al,'c' call outprt pop wflags ; get back old flags procc2: jmp ignore procn: ; device status report mov bx,offset escstring+2 cmp byte ptr [bx],'5' je procn5 cmp byte ptr [bx],'6' je procn6 jmp ignore procn5: ; return operating status 'no malfunction' push wflags ; force no echo and yflags,not lclecho mov al,ESC call outprt mov al,'[' call outprt mov al,'0' call outprt mov al,'n' call outprt pop wflags jmp ignore procn6: ; report cursor position push wflags ; force no echo and yflags,not lclecho call get_cur_pos mov al,dh ; get column here sub al,1fh ; get binary column aam add ax,3030h ; change to ASCII push ax mov al,dl ; get line here now sub al,1fh ; convert to binary aam ; and to ... add ax,3030h ; ASCII mov bx,ax mov al,ESC ; put string out in form : ESC'['line';'col'R' call outprt mov al,'[' call outprt cmp bh,30h ; don't need leading zero je procc61 mov al,bh call outprt procc61: mov al,bl call outprt mov al,';' call outprt pop bx cmp bh,30h je procc62 mov al,bh call outprt procc62: mov al,bl call outprt mov al,'R' call outprt pop wflags ; get these back jmp ignore proclm: ; do screen attributes mov bx,offset escstring+2 proclm1: call getnum cmp dl,0 jne proclm2 mov al,ESC call outtty mov al,')' call outtty mov al,ESC call outtty mov al,'q' call outtty mov al,ESC call outtty mov al,'1' call outtty jmp proclm5 proclm2: cmp dl,1 jne proclm3 mov al,ESC call outtty mov al,'(' call outtty jmp proclm5 proclm3: cmp dl,4 jne proclm4 mov al,ESC call outtty mov al,'0' call outtty jmp proclm5 proclm4: cmp dl,7 jne proclm5 mov al,ESC call outtty mov al,'p' call outtty proclm5: cmp byte ptr [bx],'m' je proclm6 inc bx jmp proclm1 proclm6: jmp ignore procJ: cmp escseq,3 je procJ0 mov bx,offset escstring+2 ; skip ESC'[' call getnum cmp dl,0 je procJ0 cmp dl,1 je procJ1 cmp dl,2 je procJ2 jmp ignore ; ignore others procJ0: mov al,ESC call outtty mov al,'J' jmp noesc procJ1: mov al,ESC call outtty mov al,'b' jmp noesc procJ2: mov al,ESC call outtty mov al,'E' jmp noesc prochl: mov bx,offset escstring+2 ; skip ESC'[' call getnum cmp [escstring+2],'?' je quest mov bx,escpnt mov bl,[bx] ; contains 'h' or 'l' cmp dl,4 jne not4 mov al,ESC call outtty mov al,'@' cmp bl,'l' jne enterins mov al,'O' enterins: jmp noesc not4: ; ignore the others jmp ignore quest: ; sequence like ESC'[?'nn'h' mov bx,escpnt mov bl,[bx] cmp dl,1 jne not1 mov cx,8 cmp appkeys,0 je q1 mov offs,offset apptbl mov di, offset apptbl.extrtabl jmp q2 q1: mov offs,offset numtbl mov di, offset numtbl.extrtabl q2: add di,START_EXTRTBL ; don't want to start at the top cmp bl,'l' je q3 mov si,offset curapp mov appcur,1 jmp q4 q3: mov si,offset curseq mov appcur,0 q4: rep movsw mov bx,offset parmblock mov byte ptr [bx],2 mov ax,18 int SUPERBIOS jmp ignore not1: cmp dl,5 jne not5 mov al,ESC call outtty mov al,'p' cmp bl,'h' je isreverse mov al,'q' isreverse: jmp noesc not5: cmp dl,7 jne not7 mov al,ESC call outtty mov al,'v' cmp bl,'h' je autowrap mov al,'w' autowrap: jmp noesc not7: ; ignore the others jmp ignore procK: cmp escseq,3 je procK0 mov bx,offset escstring+2 ; skip ESC'[' call getnum cmp dl,0 je procK0 cmp dl,1 je procK1 cmp dl,2 je procK2 jmp ignore ; ignore others procK0: mov al,ESC call outtty mov al,'K' jmp noesc procK1: mov al,ESC call outtty mov al,'o' jmp noesc procK2: mov al,ESC call outtty mov al,'l' jmp noesc noesc: ; That wasn't valid! (or print last char) or al,chrset_mask ; set top bit right for specified set call outtty ; print it out... ignore: ; Here to flag end of escape or ignore mov escseq,0 ; one that we don't like doansi_d: ret ; Here when we have no more to do DOANSI endp ; GETNUM gets a number from escapestring, returns it in DL. ; Input: pointer in BX. Destroys BX, CX, DH. Finishes on first ; encounteder non-numeric char except '-'. Assumes correct syntax ; ('-' only as first char - checked in procmulti) GETNUM proc near xor dx,dx cmp bx,escpnt ; is it to end of string already? jge getn4 ; yes - just exit with zero xor ch,ch ; assume positive number cmp byte ptr [bx],'?' ; first char may be a questionmark jne getn1 inc bx getn1: mov cl,[bx] cmp cl,';' je getn3 cmp cl,'-' jne getn2 mov ch,-1 getn2: cmp cl,'0' jl getn3 cmp cl,'9' jg getn3 sub cl,'0' shl dl,1 ; multiply by 10 (=1010b) mov dh,dl shl dl,1 shl dl,1 add dl,dh add dl,cl inc bx cmp bx,escpnt jl getn1 getn3: cmp ch,-1 jne getn4 neg dx getn4: ret GETNUM endp ; initialize keyboard and tables to build it [as] INITANSI proc near cld mov bx,ds mov es,bx mov bx,offset parmblock mov ax,18 int SUPERBIOS ; get old keyboard or ax,ax jz ansi01 jmp aend ansi01: mov cx,598 ; copy it mov si,offset oldtable mov di,offset numtbl rep movsw mov si,offset numtbl ; Index in Table mov byte ptr [si].kd0+25,7fh ; DEL to Backspace-key ; set cursorkeys mov word ptr [si].kd12+2*88,0A000h ; mov word ptr [si].kd12+2*89,0A000h ; with auto-repeat mov word ptr [si].kd12+2*98,0A000h mov word ptr [si].kd12+2*99,0A000h mov byte ptr [si].kd0+88,START_EXTRTBL ; offset in EXTRtabl mov byte ptr [si].kd0+89,START_EXTRTBL+4 mov byte ptr [si].kd0+98,START_EXTRTBL+8 mov byte ptr [si].kd0+99,START_EXTRTBL+12 mov di,offset numtbl.extrtabl add di,START_EXTRTBL ; Don't want to overwrite stuff mov si,offset curseq mov cx,8 rep movsw ; move the new sequences to keytable ; copy complete table to build Applikation-keypad-table mov cx,598 mov si,offset numtbl mov di,offset apptbl rep movsw ; now build keypad mov si,offset apptbl mov word ptr [si].kd12+2*28,8000h mov word ptr [si].kd12+2*29,8000h mov word ptr [si].kd12+2*30,8000h mov word ptr [si].kd12+2*31,8000h mov word ptr [si].kd12+2*49,8000h mov word ptr [si].kd12+2*50,8000h mov word ptr [si].kd12+2*51,8000h mov word ptr [si].kd12+2*52,8000h mov word ptr [si].kd12+2*69,8000h mov word ptr [si].kd12+2*70,8000h mov word ptr [si].kd12+2*71,8000h mov word ptr [si].kd12+2*72,8000h mov word ptr [si].kd12+2*90,8000h mov word ptr [si].kd12+2*91,8000h mov word ptr [si].kd12+2*92,8000h mov word ptr [si].kd12+2*93,8000h mov word ptr [si].kd12+2*100,8000h mov word ptr [si].kd12+2*102,8000h mov byte ptr [si].kd0+28,START_EXTRTBL+16 ; offset in EXTRtabl mov byte ptr [si].kd0+29,START_EXTRTBL+20 mov byte ptr [si].kd0+30,START_EXTRTBL+24 mov byte ptr [si].kd0+31,START_EXTRTBL+28 mov byte ptr [si].kd0+49,START_EXTRTBL+32 mov byte ptr [si].kd0+50,START_EXTRTBL+36 mov byte ptr [si].kd0+51,START_EXTRTBL+40 mov byte ptr [si].kd0+52,START_EXTRTBL+44 mov byte ptr [si].kd0+69,START_EXTRTBL+48 mov byte ptr [si].kd0+70,START_EXTRTBL+52 mov byte ptr [si].kd0+71,START_EXTRTBL+56 mov byte ptr [si].kd0+72,START_EXTRTBL+60 mov byte ptr [si].kd0+90,START_EXTRTBL+64 mov byte ptr [si].kd0+91,START_EXTRTBL+68 mov byte ptr [si].kd0+92,START_EXTRTBL+72 mov byte ptr [si].kd0+93,START_EXTRTBL+76 mov byte ptr [si].kd0+100,START_EXTRTBL+80 mov byte ptr [si].kd0+102,START_EXTRTBL+84 mov di,offset apptbl.extrtabl add di,START_EXTRTBL ; avoid overwriting stuff... mov si,offset applik mov cx,44 rep movsw ; move new keycodes to table mov bx,offset parmblock mov byte ptr [bx],2 mov offs,offset numtbl ; set numeric keypad mov ax,18 int SUPERBIOS aend: ret INITANSI endp ; Save old keyboard stuff when exiting [as] FINIANSI proc near mov bx,offset parmblock mov byte ptr [bx],2 mov dx,offset oldtable xchg dx,offs ; save old keyboard-type in dx mov ax,18 int SUPERBIOS xchg dx,offs ; restore old keyboard-type ret FINIANSI endp ; Get the current cursor location - row in dl, col in dh ; (1,1) is upper left corner GET_CUR_POS proc near mov al,ESC ; request cursor location call outtty mov al,'n' call outtty mov ah,CONINQ ; input no check int DOS ; gets the ESC int DOS ; gets the Y int DOS sub al,31 mov dl,al int DOS sub al,31 mov dh,al ret GET_CUR_POS endp ; Set the cursor location - row in dl, col in dh ; (1,1) is upper left corner SET_CUR_POS proc near push dx ; save it to be sure mov al,ESC call outtty mov al,'Y' call outtty pop dx push dx mov al,dl ; row add al,31 call outtty pop dx push dx mov al,dh ; column add al,31 call outtty pop dx ret SET_CUR_POS endp ; Save the screen so we can restore it SAVESCR proc near call get_cur_pos ; get cursor location mov curloc,dl ; this is line number mov curloc+1,dh ; this is column number mov bx,SEG_CRTC ; where crt controller is mov es,bx mov bx,OFF_CRTC mov byte ptr es:[bx],12 mov ah,es:1[bx] and ah,7 ; only want bottom 3 bits mov byte ptr es:[bx],13 mov al,es:1[bx] shl ax,1 ; multiply by 2 (was word address) mov si,ax push ds pop es mov ds,scrseg mov di,offset screen mov cx,1920 rep movsw push es pop ds call cmblnk ; let them start with a blank one ret ; and return SAVESCR endp ; Restore screen from scrsav buffer RESTSCR proc near call cmblnk ; start with a clear screen mov si,offset screen mov es,scrseg xor di,di ; start at start mov cx,1920 ; 1920 words to go rep movsw mov dx,word ptr curloc ; get cursor location call set_cur_pos ret RESTSCR endp ; Save the screen to a buffer and then append buffer to a disk file. [jrd] ; Default filename is Kermit.scn; actual file can be a device too. Filename ; is determined by mssset and is passed as pointer dmpname. ; This reads the screen that was last saved by savescr - it is expected ; that savescr will be called just before this one ; 30 July 1986 Add this routine - it is pirated from the file MSYIBM and ; modified to match the Victor's needs [bgp] 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: mov ah,CREAT2 ; file did not exist mov cx,20H ; attributes, archive bit int DOS mov dmphand,ax ; save file handle jnc dmp1 ; nc = ok dmp0: call clrmod ; clear place for mode line mov dx,offset dmperr ; get string to put there call putmod ; on mode line... pop dx pop cx pop bx pop ax ret dmp1: push di ; read screen buffer, write lines push si push es push ds pop es ; make sure this is right mov cx,24 ; 24 lines in buffer mov si,offset screen ; where screen is saved dmp2: push cx ; save outer loop counter mov di,offset dumpbuf ; data segement memory mov cx,80 ; 80 columns dmp3: mov ax,word ptr es:[si] ; read char + attribute and ax,7FFH ; take off attributes sub ax,char_base ; minus base mov byte ptr [di],al ; store the char inc si ; update pointers inc si inc di loop dmp3 ; do for each column std ; set scan backward mov cx,80 ; 80 columns mov di,offset dumpbuf+79 ; end of line mov al,' ' ; thing to scan over repe scasb ; scan until non-space cld ; set direction forward jz dmp3a ; z = all spaces inc cx inc di dmp3a: mov word ptr [di+1],0A0Dh ; append cr/lf add cx,2 ; line count + cr/lf mov dx,offset dumpbuf ; array to be written mov bx,dmphand ; need file handle mov ah,WRITE2 ; write the line int DOS pop cx ; get line counter again loop dmp2 ; do next line mov dx,offset dumpsep ; put in formfeed/cr/lf mov cx,3 ; three bytes overall mov ah,WRITE2 ; write them mov bx,dmphand ; file handle int DOS mov ah,CLOSE2 ; close the file now int DOS dmp6: pop es pop si pop di pop dx pop cx pop bx pop ax ret DUMPSCR endp ; Send the character in al out to the serial port ; Handle echoing also... OUTPRT proc near test yflags,lclecho ; echoing? jz outpr1 ; no, forget it cmp flags.vtflg,TTVT100 ; doing VT100? jz outpr0 ; yes - echo it nicely push ax ; save char call outtty ; print it pop ax ; restore jmp outpr1 outpr0: push ax ; save char call doansi pop ax ; restore outpr1: mov ah,al ; this is where outchr expects it call outchr ; output to the port nop nop nop ; skip returns... ret OUTPRT endp ; Get a character from the serial port in al ; returns with carry on if a character is available PORTCHR proc near call prtchr ; character at port? jmp short portc1 ; yes, go handle nop ; skip return is stupid... clc ; no carry -> no character ret ; and return... portc1: and al,7fh ; we don't worry about parity here stc ; have a character ret ; and return PORTCHR endp ; Put the character in al to the screen ; Directly call the console-driver to get better speed (4 times, ~19200 ; baud) [as] OUTTTY proc near call capture push ax ; these are modified by the driver push bx push cx push dx push si push es mov cl,al mov ax,1 call dword ptr drivadr pop es pop si pop dx pop cx pop bx pop ax ret ; through OUTTTY endp ; Capture char in al to a file if we are supposed to CAPTURE proc near test yflags,CAPT ; capturing output? jz nocap ; no forget this part push ax ; save it call captrtn pop ax ; get char back nocap: test flags1,PRTSCR ; should we be printing? jz noprt ; no, go on push ax ; save char mov ah,LSTOUT mov dl,al int DOS ; out it goes pop ax noprt: ret CAPTURE endp ; Set heath emulation on/off. VTS proc near mov dx,offset termtbl mov bx,offset termhlp mov ah,CMKEY call comnd jmp vt1 push bx mov ah,CMCFM call comnd ; Get a confirm. jmp vt0 ; Didn't get a confirm. nop pop bx mov flags.vtflg,bl ; Set the emulation flag. ret vt0: pop bx vt1: ret VTS endp VTSTAT PROC NEAR ; For Status display [jrd] ret ; no emulator status to display VTSTAT ENDP CODE ends end