|
DataMuseum.dkPresents historical artifacts from the history of: DKUUG/EUUG Conference tapes |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about DKUUG/EUUG Conference tapes Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - downloadIndex: T m
Length: 116489 (0x1c709) Types: TextFile Names: »msyibm.asm«
└─⟦9ae75bfbd⟧ Bits:30007242 EUUGD3: Starter Kit └─⟦71044c191⟧ »EurOpenD3/misc/kermit.ms-2.32.tar.Z« └─⟦31f2d420d⟧ └─⟦this⟧ »msyibm.asm«
NAME msyibm ; File MSYIBM.ASM ; edit history: ; Last edit 30 Nov 1988 ; 30 Nov 1988 Add SET TERM CLEAR screen clearing support. ; 28 Nov 1988 Accomodate Tseng Labs UltraPAK mono/Herc board w/132 cols. ; 132 column mode is 18h. Requires Tseng's BIGSCR.COM (use BIGSCR /R:25 ; to enable 132x25 feature). Thanks to Tseng Labs for technical support. ; 21 Nov 1988 Version 2.32 ; 14 Nov 1988 Write a space during lclini to obtain default screen colors. ; 12 Nov 1988 Add procs vtrmac and vtsmac to allow exit from Connect mode and ; invokation of macros TERMINALR and TERMINALS by reception of escape seqs ; in file mszibm.asm or by keyboard verbs. ; 7 Oct 1988 Reverse left/right arrow key codes when writing right to left. ; 24 Sept 1988 Make output to printer be buffered and flow controlled. ; 1 July 1988 Version 2.31 ; 19 June 1988 Add Everex EVGA support, from Terry Kennedy. ; 10 June 1988 Add oldsp and procedure endcon to exit Connect mode if output ; fails, mostly for networking (but we don't know that here). ; 23 May 1988 Add Everex EV-659 ega board test from Alex Zliu. Fixed incorrect ; screen width assumption at startup. ; 29 March 1988 Include flag ttyact to group string bytes into one net packet, ; thanks to Paul Fox of AT&T. ; 23 March 1988 Add "fairness" word to let serial port deliver max chars ; between kbd reads, for connect mode only. [jrd] ; 10 Feb 1988 Revise getcirc and vtscrX routines to do proper scrolling with ; MS Window 1.0x/2.0x [jrd]. ; 9 Feb 1988 Mode line again. Make flags.modflg 0 for off, 1 for on and owned ; by Kermit, and 2 for on and owned by remote host (toggling suppressed). ; 25 Jan 1988 Add global byte SCROLL, set in msz, to control emulator screen ; scrolling for higher speeds. [jrd] ; 5 Jan 1988 Restore cursor codes broken by Tek code additions. [jrd] ; 1 Jan 1988 version 2.30 public term, lclyini ; entry points public prtbout, prtnout, csrtype, scrmod, scrseg, scrsync public scroff, scron, atsclr, vtscru, vtscrd, scrloc, trnmod, telmsy public chgdsp, vtroll, crt_lins, crt_cols, getflgs, tv_mode, vtclear ; 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, modwrt, snull public klogon, klogof, cdos, chang, khold, vtrmac, vtsmac public vtemu, crt_mode, scbattr, refresh, low_rgt ; data public savescr, restscr, pntchr, pntchk, pntflsh ; code include mssdef.h ; some definitions ; 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 biostty equ 0eh ; Bios screen tty write mode modfrm struc ; format of mode (status) line db 'Esc-chr: ' ; do not write in last column m_echr db 2 dup (?) db ' help: ' m_hlp db 2 dup (?) db '? port:' m_prt db 1 dup (?) db ' speed:' m_baud db 5 dup (?) db ' parity:' m_par db 4 dup (?) db ' echo:' m_echo db 3 dup (?) m_term db 13 dup (' ') ; 13 bytes for term type m_prn db 3 dup (' ') ; show PRN when printer is on modfrm ends datas segment public 'datas' extrn flags:byte, mar_top:byte, mar_bot:byte, portval:word extrn filtst:byte, dmpname:byte, kbdflg:byte, rxtable:byte extrn anspflg:byte, tekflg:byte, scroll:byte, ttyact:byte extrn holdscr:byte, taklev:byte, takadr:word, mcctab:byte ; stuff for screen routines yflags db 0 ; status flags flags1 db 0 ; internal flags (but used in mszibm) prtscr equ 1 ; print screen pressed inited equ 08h ; been here before vtinited db 0 ; flag for emulator having been inited vtclear db 0 ; nonzero to clear emulator screen cursor dw 0 esc_ch db 0 parmsk db 0 ; 8/7 bit parity mask, for reception argadr dw ? ; address of arg blk 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 tsngid db 'Tseng' ; Tseng Labs EVA (& Orchid Designer) tsnglen equ $-tsngid evrxid db 'Everex' ; Everex Micro Enhancer Deluxe EGA evrxlen equ $-evrxid evgid db 'VGA EV673' ; Everex EVGA EV-673 evglen equ $-evgid 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 ? ; Topview virtual screen, segment tv_sego dw ? ; and offset tv_mode db 0 ; flag, 0 = no Topview savadr dw 2 dup (?) ; offset then segment of saved screen savflg dw 0 ; low_rgt at time of screen save ; The following are used to turn the display back on (after scrolling etc.) msets db 2CH,28H,2DH,29H,2AH,2EH,1EH,29H vtemu emulst <> ; emulator flags ansflgs db 0 ; ANSI flags trmtyp db 0 ; most recent terminal type mtty db ' TTY ' ; no terminal type (mode line) fairness dw 0 lincur dw ? ; cursor type save area scbattr db ? ; Screen background attribute oldattr db ? ; screen attributes at init time curattr db ? ; current attribute oldsp dw 0 ; offset to longjmp to for i/o failure temp dw ? ; scratch storage modtemp db 0 ; temp to hold Kermit modeline status captrtn dw ? ; routine to call for captured output dmphand dw -1 ; screen dump file handle dumplen equ 132 dumpbuf db dumplen dup (?), cr, lf ; 134 byte dump work buffer dumpsep db FF,cr,lf ; screen image separators dmperr db ' Cannot open file to save screen to disk $' crlf db cr,lf,'$' flowon db 0 ; flow control chars xon flowoff db 0 ; and xoff (or both null if none) pntmsg db 'Printer not ready, printing request skipped.' pntmsgl equ $-pntmsg ; length of pntmsg pntptr dw dumpbuf ; pointer to next free byte in buffer ; some static data for mode line modbuf modfrm <> ; mode line buffer unkbaud db 'unkwn' ; must be 5 chars baudn db ' 45.5',' 50 ',' 75 ',' 110 ','134.5',' 150 ',' 300 ',' 600 ' db ' 1200',' 1800',' 2000',' 2400',' 4800',' 9600','19200','38400' db '57.6K','115 K' baudnsiz equ 18 ; # of baud rates known (tbl size / 4) parnams db 'even','mark','none','odd ','spc ' lclmsg db 'loc' remmsg db 'rem' portno db ? ; storage for multi-window stuff swidth equ 80 ; max screen width slen equ 24 ; and length of text npages equ 10 ; # of pages of scrolling on each side crt_norm db ? ; video mode for normal screen crt_mode db ? ; video mode (typ 3, must be text) crt_cols db ? ; number of screen columns (typ 80) crt_lins db 24 ; number of screen rows - 1 (typ 24) low_rgt dw ? ; lower right corner of text window ; high = row address (typ 23) ; low = column address (typ 79) inipara dw ? ; initial paragraphs of scroll memory scrsav dw ? ; segment address of save area refresh db 0 ; screen refresh (0=wait for retrace) vtroll db 0 ; auto roll back allowed (0 = no) ; circular buffer for screen roll back. cbuf struc pp dw ? ; place ptr in buffer bend dw ? ; end of buffer orig dw ? ; buffer origin lcnt dw 0 ; # of lines in buffer lmax dw ? ; max lines of buffer cbuf ends twnd cbuf <> ; top screen spill-buffer struct bwnd cbuf <> ; bottom screen spill buffer struct vtrname db 'TERMINALR' ; a macro name, must be Upper Case vtrlen equ $-vtrname vtsname db 'TERMINALS' ; a macro name, must be Upper Case vtslen equ $-vtsname vtmacname dw vtrname ; pointer to selected macro name vtmaclen db vtrlen datas ends code segment public 'code' extrn beep:near, prtchr:near, outchr:near, sbrk:near, pcwait:near extrn isfile:near, strlen:near, strcpy:near ; in mssfil extrn anstty:near,ansini:near,ansrei:near ; in mszibm extrn anstat:near,anskbi:near,ansdsl:near ; in mszibm extrn ans52t:near, vsinit:near ; in mszibm extrn msuinit:near, keybd:near ; in msuibm extrn tekini:near,tekcls:near,tekemu:near,tekend:near ;in msgibm extrn tekrint:near assume cs:code, ds:datas, es:datas ; 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. [jrd] lclyini proc near call msuinit ; initialize keyboard module msuxxx mov ax,swidth*(slen+1)*2 ; (80 char + 80 attr) * 25 lines call sbrk ; memory allocation routine (mssker) ;if we get here them we have the lines mov scrsav,ax ; memory segment for save screens ; screen roll back buffers 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 ax,24000D/16 ; space for Command.com copy #2 jbe lclyin1 ; be = not enough for it. [ebb] cmp ax,(swidth*slen+15)/16 ; minimum roll back space left over? jbe lclyin1 ; be = not even that much cmp ax,(swidth*slen*npages+7)/8 ; paragraphs wanted for roll back jbe lclyin2 ; be = enough but not more than needed mov ax,(swidth*slen*npages+7)/8 ; limit to our actual needs jmp short lclyin2 ; ask for all we really want lclyin1:mov ax,(4*swidth+15)/16 ; use minimum needed paragraphs lclyin2:mov inipara,ax ; save for later resizing of buffers mov cl,4 ; convert paragraphs to bytes shl ax,cl ; for sbrk call sbrk ; ask for that many bytes ;if we get here them we have the space mov bwnd.orig,ax ; memory segment, bottom window area mov twnd.orig,ax ; top. same place for both buffers! call scrseg ; test running in an Environment call scrmod ; read video state, get crt_mode mov ax,low_rgt ; lower right corner of screen mov al,crt_mode mov crt_norm,al ; save as normal mode mov savflg,ax mov ah,conout ; output a space to set background mov dl,' ' ; and foreground screen colors int dos mov ah,3 ; get current cursor position into dx mov bh,0 int screen dec dl ; backup to the space mov ah,2 ; set cursor int screen mov ah,8 ; read current attributes xor bh,bh ; page 0 int screen mov scbattr,ah ; save video attributes mov oldattr,ah ; and here too mov ax,inipara ; # paragraphs allocated by DOS mov cl,3 ; 2**3 = 8 shl ax,cl ; paragraphs to words (char + attrib) xor dx,dx ; clear extended size mov ch,0 mov cl,byte ptr low_rgt inc cl ; number of chars per line in buffer div cx ; ax = number of lines in buffer mov bwnd.lmax,ax ; max lines per buffer (quotient) mov twnd.lmax,ax ; max lines per buffer add cx,cx ; count char and attribute per item xor dx,dx ; clear extended numerator mul cx ; ax = effective # bytes per buffer dec ax ; adjust for counting from zero mov bwnd.bend,ax ; offset of last byte in buffer mov twnd.bend,ax ; offset of last byte in buffer mov bwnd.pp,0 ; offset of first byte in buffer mov twnd.pp,0 ; offset of first byte in buffer mov bwnd.lcnt,0 ; number of lines occupied in buffer mov twnd.lcnt,0 ; number of lines occupied in buffer call vsinit ; init terminal emulator module MSZ 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 lclyin3 ; 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 lclyin3 ; nz = no mov ega_mode,1 ; yes, set flag to say so mov crt_norm,3 ; assume color monitor is attached cmp bh,0 ; is color mode in effect? je lclyin3 ; e = yes mov crt_norm,7 ; else use mode 7 for mono lclyin3:ret lclyini endp scrini proc near ; init screen stuff call scrseg ; update screen segment tv_seg(s/o) call scrmod ; get screen mode, low_rgt mov ah,3 ; get cursor position and type xor bh,bh ; page 0 int screen mov lincur,cx ; save cursor type (scan line #'s) mov ax,low_rgt ; present screen text size cmp ax,savflg ; vs size of saved screen jne scrin1 ; ne = different, initialize jmp scrin3 ; same, skip initialization ; Re-initialize screen buffers scrin1: mov ax,inipara ; paragraphs allotted to roll back mov cl,3 ; 2**3 = 8 shl ax,cl ; paragraphs to words (char + attrib) xor dx,dx ; clear extended size mov cl,byte ptr low_rgt ; number of chars per line in buffer inc cl ; chars per line xor ch,ch ; clear high byte div cx ; ax = number of lines in buffer mov bwnd.lmax,ax ; max lines per buffer (quotient) mov twnd.lmax,ax ; max lines per buffer add cx,cx ; count char and attribute per item xor dx,dx ; clear extended numerator mul cx ; ax = effective # bytes per buffer dec ax ; adjust for counting from zero mov bwnd.bend,ax ; offset of last byte in buffer mov twnd.bend,ax ; offset of last byte in buffer mov bwnd.pp,0 ; offset of first byte in buffer mov twnd.pp,0 ; offset of first byte in buffer mov bwnd.lcnt,0 ; number of lines occupied in buffer mov twnd.lcnt,0 ; number of lines occupied in buffer 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 scrin2 ; 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 scrin2 ; nz = no mov ega_mode,1 ; yes, set flag to say so mov crt_norm,3 ; assume color monitor is attached cmp bh,0 ; is color mode in effect? je scrin2 ; e = yes mov crt_norm,7 ; else use mode 7 for mono scrin2: mov ah,oldattr ; get init time attributes mov curattr,ah ; and set nice screen attribute mov scbattr,ah mov cursor,0 ; cursor to upper left corner cmp flags.vtflg,0 ; terminal type of None? ja scrin3 ; a = no, emulating mov dh,byte ptr low_rgt+1 inc dh ; bottom mov dl,0 ; left corner jmp short scrin5 ; Common finish code scrin3: mov dx,cursor ; use old cursor, if any cmp flags.vtflg,0 ; emulating? je scrin4 ; e = no cmp dh,byte ptr low_rgt+1 ; past logical end of screen? jbe scrin4 ; be = no, keep going mov dh,byte ptr low_rgt+1 ; yes, just use lower right corner scrin4: cmp dl,byte ptr low_rgt ; maybe past right margin jbe scrin5 ; be = no, use the way it is mov dl,byte ptr low_rgt scrin5: mov cursor,dx ; init cursor mov ah,2 ; set cursor position xor bh,bh ; page zero int screen ; set cursor in case it moved test flags1,inited ; have we run yet? jz scrin7 ; z = no, so no saved screen yet call restscr ; restore screen scrin7: or flags1,inited ; remember we've run already cmp flags.modflg,1 ; is mode line on and locally owned? ja scrin10 ; a = host owned, leave intact cmp flags.vtflg,0 ; emulating a terminal? jne scrin8 ; ne = yes, can have mode line or yflags,modoff ; for no emulation say toggled off cmp trmtyp,0 ; previous terminal type = none? jne scrin9 ; ne = no. need to clear mode line jmp scrin10 ; yes, let 25th line be intact scrin8: cmp flags.modflg,0 ; is mode line disabled? je scrin9 ; e = yes, clear it test yflags,modoff ; is mode line toggled off? jnz scrin9 ; nz = yes, clear the line call modlin ; turn on mode line jmp short scrin10 scrin9: call clrmod ; ensure its off scrin10:cmp flags.vtflg,0 ; current terminal type = None? je scrin12 ; e = yes, nothing to init mov al,yflags ; tell emulator we are back cmp vtclear,0 ; screen need clearing? jne scrin10a ; yes, do emulator reinit now cmp vtinited,inited ; inited emulator yet? je scrin11 ; e = yes cmp tekflg,0 ; Tek mode still active? jne scrin12 ; ne = yes, no re-init here scrin10a:call vtinit ; init it now mov vtclear,0 ; say screen is clear jmp short scrin12 scrin11:call ansrei ; reinit the emulator call ansflg ; and get its flags scrin12:mov al,flags.vtflg ; current terminal type mov trmtyp,al ; place to remember it til next time cmp flags.vtflg,tttek ; Tek mode? je scrin13 ; e = yes cmp tekflg,0 ; Tek mode active within DEC stuff? je scrin14 ; e = no scrin13:call tekini ; reinit to get graphics screen scrin14:ret scrini endp ; Routine to initialize VT102/52/Heath-19 terminal emulator. vtinit proc near mov holdscr,0 ; clear holdscreen cmp flags.vtflg,0 ; doing emulation? je vtinix ; e = no cmp tekflg,0 ; Tek mode active? jne vtini2 ; ne = yes, do it's reinit or vtinited,inited call ansflg ; update ansi flags mov bx,argadr ; Get address of argument block mov dl,[bx].flgs and dl,lclecho and yflags,not lclecho or yflags,dl mov al,yflags ; Pass the flags 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: call ansini ; call startup routine in mszibm vtinix: clc ret vtini2: call tekrint ; reinitialize Tek emulator clc ret vtinit endp 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 mov al,[bx].prt mov portno,al ; update port number 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 mov parmsk,0ffh ; parity mask, assume parity = None cmp [bx].parity,parnon ; is parity None? je argini1 ; e = yes, keep all 8 bits mov parmsk,07fh ; else keep lower 7 bits argini1:ret ; that's it argini endp modlin proc near ; turn on mode line 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,5eh ; caret, note control char mov modbuf.m_hlp,5eh 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 ; nb = yes, use default mov cl,size m_baud ; each is 5 bytes long mul cl mov ah,0 add ax,offset baudn mov si,ax modl2: mov cx,size m_baud ; length of baud space mov di,offset modbuf.m_baud push es ; save es push ds pop es ; set es to datas segment cld rep movsb ; copy in baud rate mov al,[bx].parity ; get parity code shl al,1 ; each is 4 bytes long shl al,1 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,portno ; communications port cmp al,' ' ; binary (non-printable)? jae modl5 ; ae = no, ascii add al,'0' ; convert to ascii modl5: mov modbuf.m_prt,al ; fill in port number 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 modbuf.m_prn,' ' ; assume not printing the screen mov modbuf.m_prn+1,' ' mov modbuf.m_prn+2,' ' test anspflg,prtscr ; doing a print the screen? jz modl5a ; z = no mov modbuf.m_prn,'P' ; yes. display PRN at end of line mov modbuf.m_prn+1,'R' mov modbuf.m_prn+2,'N' modl5a: mov cx,size modfrm ; this is size of mode line mov si,offset modbuf ; mode line image pop es ; alternate entry to write an alternate mode line modwrt: push cx push si ; save mode line and size mov ah,3 ; read cursor position xor bx,bx ; screen page 0 int screen mov cursor,dx ; save cursor position call trmatt ; Get terminal attributes and ah,77h ; omit blinking/bold attributes mov bh,ah ; get video attribute mov dx,low_rgt ; right most column inc dh ; refer to status line mov ch,dh ; bottom line [dlk] mov cl,0 ; left col = 0 (first) [dlk] mov ax,600h ; scroll to clear the line int screen mov dh,byte ptr low_rgt+1 ; refer to status line inc dh xor dl,dl ; left most column mov bh,0 mov ah,2 ; set cursor position int screen pop si pop cx ; restore these cmp cl,crt_cols ; mode line longer than screen? jbe modl6 ; le = no mov cl,crt_cols ; else do just one line's worth dec cx ; don't let screen scroll modl6: cld lodsb ; get a byte mov ah,14 ; write to terminal mov bh,0 ; page 0 int screen loop modl6 ; write out entire mode line cmp flags.vtflg,0 ; emulating? je modl7 ; e = no and yflags,not modoff ; update local flags (mode line on) mov al,yflags ; Yes - update flags also call ansdsl ; get extras from emulator modl7: mov dx,cursor mov ah,2 mov bh,0 int screen ; put cursor back where it belongs ret modlin endp clrmod proc near ; clear mode line call trmatt ; Get terminal screen attributes mov bh,al ; Use screen background attribute mov ax,600h ; blank window mov dx,low_rgt ; right most column inc dh ; refer to status line mov cx,dx ; bottom line [dlk] xor cl,cl ; left most column int screen ; clear mode line or yflags,modoff ; turn on flag ret clrmod endp ; Fetch screen attributes from emulator (if emulating). It exists mainly ; so that the reverse video will work. Returns the current mode ; line background attribute in ah, the current screen background in al, ; and the current "cursor" (foreground) attribute in bl. (Note: anstat ; returns status yflags in bh). trmatt proc near ; Get attributes cmp flags.vtflg,0 ; emulating? je trmat1 ; No, just do simple stuff mov al,yflags ; anstat expects flags byte in al call anstat ; Fetch emulator status/attributes ret trmat1: mov al,scbattr ; Background attributes mov bl,curattr ; And cursor attribute mov ah,al ; where modlin needs them and ah,77h ; get colors part, no blink/bold rol ah,1 ; reverse them rol ah,1 rol ah,1 rol ah,1 ret trmatt endp ; Get byte yflags of terminal emulator passed in AL. Used in mode line ; handling when 25th line is used by the emulator. [jrd] telmsy proc near mov yflags,al ; get the updated flags call ansflg ; and any other emulator info ret telmsy endp ;[IU2] This routine updates the ANSI status flags from the emulator, ; and passes the "yflags" byte to the VT100 emulator also. ansflg proc near push ax ; save regs push bx mov al,yflags call anstat ; Get status and attributes mov ansflgs,bh ; Save test ansflgs,dececho ; does host want us to do local echo? jz ansflg1 ; z = no, use working default or yflags,lclecho ; turn on local echoing ansflg1:pop bx pop ax ret ansflg endp getflgs proc near ; supply yflags for terminal emulators mov al,yflags ret getflgs endp term proc near ; terminal mode entry point mov argadr,ax ; save argument ptr call argini ; init options from arg address call scrini ; init screen stuff mov bx,portval ; port data structure address mov bx,[bx].flowc ; get flow control chars (bl=xoff) mov flowon,bh mov flowoff,bl ; save for later mov oldsp,sp ; remember stack for i/o failure, ; used by procedure endcon lp: call prtchr ; char at port? jmp short lpinp ; yes, go handle nop ; else look at kbd lpkbd: mov fairness,0 ; say kbd was examined call keybd ; call keyboard translator in msu jnc lp ; nc = no char or have processed it jmp short quit ; carry set = quit connect mode 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: call pntflsh ; flush printer buffer call tekend ; cleanup Tektronix mode [bjh] mov ah,3 ; get cursor position into dx xor bh,bh ; page 0 int screen mov cursor,dx ; save position cmp flags.vtflg,0 ; terminal type of none? ja quit1 ; a = yes test yflags,modoff ; is modeline still toggled off? jnz quit1 ; nz = yes call clrmod ; clear it before storing screen quit1: call savescr ; save screen mov ax,0600h ; clear mode line with old attributes mov bh,oldattr ; attributes mov dx,low_rgt ; right most column inc dh ; refer to status line mov cx,dx ; bottom line [dlk] xor cl,cl ; left most column int screen ; clear the mode line mov ah,oldattr ; attributes at init time mov scbattr,ah ; background = original state ; for ega in non-standard # lines 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 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 ah,2 ; Position cursor mov bh,0 ; Page 0 mov dx,low_rgt ; bottom line inc dh ; status line position xor dl,dl ; left most column int screen ; Do it mov al,yflags and al,not lclecho ; don't copy host's echo flag mov bx,argadr mov ah,[bx].flgs ; get user's flag settings and ah,lclecho ; clear all but local echo bit or [bx].flgs,al ; update flags in arg block ret term endp ; put the character in al to the screen outtty proc near cmp flags.vtflg,0 ; emulating a terminal? jne outnoc ; ne = yes, emulator handles printing 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 outnop ; no, keep going call pntchr ; queue char for printer jnc outnop ; nc = successful print push ax call beep ; else make a noise and call trnprs ; turn off printing pop ax outnop: test yflags,capt ; capturing output? jz outnoc ; no, forget this part push ax ; save char call captrtn ; give it captured character pop ax ; restore character and keep going outnoc: cmp vtroll,0 ; auto roll back allowed? jz outnp6 ; z = no, leave screen as is cmp tekflg,0 ; Tek mode active? jne outnp6 ; ne = yes, skip screen rolling cmp bwnd.lcnt,0 ; is screen rolled back? [dlk] je outnp6 ; e = no call endwnd ; restore screen before writing [dlk] outnp6: cmp flags.vtflg,0 ; emulating a terminal? jnz outnop1 ; nz = yup, go do something smart test yflags,trnctl ; debug? if so use Bios tty mode jz outnp4 ; z = no mov ah,biostty ; Bios tty 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 al,7eh ; output a tilde for 8th bit int screen 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 al,5eh ; caret int screen ; display it pop ax ; recover the non-printable char outnp3: int screen ret outnp4: cmp al,bell ; bell (Control G)? jne outnp5 ; ne = no jmp beep ; use short beep, avoid char loss outnp5: mov dl,al ; write without intervention mov ah,conout int dos ; else let dos display char ret outnop1:cmp flags.vtflg,tttek ; doing Tektronix emulation? je outnop2 ; e = yes, use Tek emulator cmp tekflg,0 ; Tek submode active? jne outnop2 ; ne = yes, use Tek emulator jmp anstty ; call terminal emulator routine & ret outnop2:jmp tekemu ; use Tek emulator and return outtty endp ;[IU2] Here to output character to port with no echo (like escape sequences ; sent by PF keys, responses to requests from the host, etc. It is ; wrong thinking to echo these). prtbout proc near ; Global routine now mov ah,al ; This is where outchr expects it call outchr jmp endcon ; failure, end connection nop clc ; carry clear for success ret prtbout endp ;[IU2] Here to output an unsigned 8-bit number (in al) to the port without ; echoing. Used by terminal emulator escape sequence output. prtnout proc near mov bl,10 ; Output in base 10 jmp prtno2 ; Ensure at least a zero prtno1: cmp al,0 jne prtno2 ; Yes - do more digits ret ; No - return from recursive call prtno2: mov ah,0 ; Clear previous remainder div bl ; Divide off a digit push ax ; Push remainder (in ah) on stack call prtno1 ; Recur pop ax ; Pop off a digit add ah,'0' ; Make it ASCII call outchr ; send to port jmp endcon ; failure, end connection nop clc ; carry clear for success ret 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 test yflags,lclecho ; echoing? jz outpr1 ; z = no, forget it push ax ; save char call outtty ; print it pop ax ; restore outpr1: mov ah,al ; this is where outchr expects it call outchr ; output to the port jmp endcon ; failure, end connection nop clc ; carry clear for success ret outprt endp ; Jump here to exit Connect mode and execute macros 'TERMINALR' (vtrmac) or ; 'TERMINALS' (vtsmac). Does nothing if macro does not exist. ; Preserves registers except ax. Returns to TELNET caller with 'C' in kbdflg. vtrmac proc near ; RESET macro mov ax,offset vtrname ; select macro name mov vtmacname,ax mov vtmaclen,vtrlen ; and its length jmp short vtmacro ; finish in common code vtrmac endp vtsmac proc near ; SET macro mov ax,offset vtsname mov vtmacname,ax mov vtmaclen,vtslen jmp short vtmacro vtsmac endp ; ; Reference Macro structure for db number of entries (mac names) ; is file table mcctab |-> db length of macroname, excl '$' ; mssset.asm each entry |-> db 'macroname','$' ; where these |-> dw offset of definition string ; are stored. ; Definition string in db length of <string with null> ; buffer macbuf db 'string with trailing null' ; vtmacro proc near ; common code for macros vtsmac,vtrmac push bx push cx push si mov bx,offset mcctab ; table of macro names mov cl,[bx] ; number of names in table xor ch,ch jcxz vtmacx ; z = empty table, do nothing inc bx ; point to length of first name vtmac2: mov al,[bx] ; length of this name xor ah,ah cmp al,vtmaclen ; length same as desired keyword? jne vtmac3 ; ne = no, search again mov si,bx inc si ; point at first char of name push cx ; save name counter push di ; save reg mov cl,vtmaclen ; length of name, excluding '$' xor ch,ch mov di,vtmacname ; point at desired macro name push es ; save reg push ds pop es ; make es use datas segment cld repe cmpsb ; match strings pop es ; need current si below pop cx pop di ; recover saved regs je vtmac4 ; e = matched vtmac3: add bx,ax ; step to next name, add name length add bx,4 ; + count, dollar sign, def word ptr loop vtmac2 ; try next name vtmacx: pop si ; no macro, return to Connect mode pop cx pop bx ret vtmac4: cmp taklev,maxtak ; room in Take level? jge vtmacx ; ge = no, exit with no action inc taklev ; increment take level add takadr,size takinfo ; make a new Take entry/macro mov bx,takadr ; point to current macro structure inc si ; skip dollar sign after name mov si,[si] ; get definition address mov [bx].takbuf,si ; address of definition string struc mov cl,[si] ; length byte of definition xor ch,ch mov [bx].takcnt,cx ; number of chars in definition inc si ; address of definition text proper mov [bx].takptr,si ; where to read next command char mov [bx].taktyp,0ffh ; flag as a macro pop si pop cx pop bx jmp endcon ; exit Connect mode vtmacro endp ; Error recovery routine used when outchr reports unable to send character ; or when vtmacro requests exiting Connect mode. ; Exit Connect mode cleanly, despite layers of intermediate calls. endcon proc near mov kbdflg,'C' ; report 'C' to TERM's caller mov sp,oldsp ; recover startup stack pointer ; TERM caller's return address is now ; on the top of stack. A longjmp. jmp quit ; exit Connect mode cleanly endcon endp ;;; 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: push ax ; save final char mov ttyact,0 ; network, group chars for packet mov al,escape ; Output an escape call outprt ; Output, echo permitted cmp flags.vtflg,tttek ; Tek terminal? je comar0 ; e = yes, use VT100 codes cmp flags.vtflg,ttvt100 ; VT100 terminal emulation? jne comar2 ; No, do VT52/HEATH-19 sequence comar0: call ansflg ; Update flags all around mov al,'[' ; Maybe this next? test ansflgs,decckm ; Cursor key mode reset? je comar1 ; Yes, output the "[" mov al,'O' ; No, set, use the "O" comar1: call outprt ; Output it (echo permitted) comar2: pop ax ; recover final char mov ttyact,1 ; network, restore tty active flag call outprt ; Output to port (echo permitted) ret pf1: mov al,'P' ; keypad function keys 1-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 ; Output an escape call prtbout call ansflg ; get emulator flags test ansflgs,decanm ; ansi mode? jz short compf1 ; z = no mov al,'O' ; send an "O" call prtbout ; Output it compf1: pop ax ; Get the saved char back mov ttyact,1 ; network, restore tty active flag call prtbout ; Output to port 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 ansflgs,deckpam ; keypad application mode active? jnz comkp3 ; nz = yes, use escape sequences sub al,40h ; deduct offset to numeric symbols jmp comkp0 ; and send that single char comkp3: push ax ; save final char mov ttyact,0 ; network, group chars for packet mov al,escape ; Output an escape call prtbout mov al,'O' ; Output the "O" cmp flags.vtflg,ttvt100 ; VT100 mode? je comkp1 ; e = yes, use "O" code cmp flags.vtflg,tttek ; Tek terminal je comkp1 ; e = yes, use VT100 codes test ansflgs,decanm ; ANSI (alt application keypad) mode? jnz comkp1 ; nz = yes, use "O" comkp2: mov al,'?' ; else use "?" instead of "O" comkp1: call prtbout pop ax ; recover final char comkp0: mov ttyact,1 ; network, restore tty active flag call prtbout ; send it ret klogon proc near ; resume logging (if any) test flags.capflg,logses ; session logging enabled? jz klogn ; z = no, forget it or argadr.flgs,capt ; turn on capture flag or yflags,capt ; set local msy flag as well call ansflg ; tell emulator klogn: clc ret klogon endp klogof proc near ; suspend logging (if any) and argadr.flgs,not capt ; stop capturing and yflags,not capt ; reset local msy flag as well call ansflg ; tell emulator klogo: clc ret klogof endp snull proc near ; send a null byte mov al,0 ; the null jmp prtbout ; send without logging and local echo snull endp khold: xor holdscr,1 ; toggle Hold screen byte for msx clc ret ; general character out for emulator chrout: cmp flags.vtflg,0 ; emulating? je chrou5 ; e = no call anskbi ; Yes, say we had keyboard input cmp al,cr ; A CR? jne chrou5 ; No - just output it and return call ansflg ; Yes - update VT100 flags test ansflgs,anslnm ; ANSI new-line mode set? jz chrou5 ; No - just send the cr call outprt ; Yes - output a carriage-return mov al,lf ; Followed by a line feed chrou5: call outprt ret ; 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 dmpscn proc near ; dump screen to file call savescr ; save screen to buffer call dumpscr ; do buffer to file clc ; do not exit Connect mode ret dmpscn endp ;[IU2] Routine to toggle VT100/VT52/Heath-19 modes in VT100 emulator. vtans52 proc near cmp flags.vtflg,0 ; emulating? je vtans5 ; e = no call ans52t ; Call MSZ toggle-it routine call ansflg ; Update flags clc ; clear c bit so don't exit Connect vtans5: ret vtans52 endp ; Toggle Mode Line trnmod: cmp flags.modflg,1 ; mode line enabled and owned by us? jne trnm2 ; ne = no, don't touch it cmp flags.vtflg,tttek ; Tek mode? je trnm2 ; yes cmp tekflg,0 ; Tek submode? jne trnm2 ; ne = yes, no mode line changes test yflags,modoff ; mode line already off? jnz trnm1 ; yes, go turn on call clrmod ; no, clear mode line here or yflags,modoff ; turn on flag call ansflg ; Update flags all around clc ; clear c bit so don't exit Connect ret trnm1: and yflags,not modoff ; Clear flag first cmp flags.vtflg,0 ; terminal type of none? ja trnm3 push dx ; scroll screen to save bottom line mov ah,prstr ; for terminal type none mov dx,offset crlf int dos pop dx trnm3: call modlin ; Then turn on mode line call ansflg ; Update flags all around trnm2: clc ret trnprs: push ax ; toggle ^ PrtSc screen to printer test anspflg,prtscr ; are we currently printing? jnz trnpr2 ; nz = yes, its on and going off mov ah,ioctl mov al,7 ; get output status of printer push bx mov bx,4 ; file handle for system printer int dos pop bx jc trnpr1 ; c = printer not ready cmp al,0ffh ; Ready status? je trnpr2 ; e = Ready trnpr1: call beep ; Not Ready, complain jmp trnpr3 ; and ignore request trnpr2: xor anspflg,prtscr ; flip the flag test yflags,modoff ; mode line off? jnz trnpr3 ; nz = yes call modlin ; else rewrite mode line trnpr3: pop ax clc ; return carry clear (don't quit) ret ; Print on PRN the char in register al. On success return with C bit clear. ; On failure do procedure pntchk and return its C bit (typically C set). ; Uses buffer dumpbuf (screen dump). pntchr proc near push bx ; buffer the character mov bx,pntptr ; offset of next free byte in buffer mov [bx],al ; store the character inc bx ; update pointer mov pntptr,bx ; save pointer cmp bx,offset dumpbuf+dumplen ; buffer full yet? pop bx clc ; clear carry bit jb pntchrx ; b = no, just return jmp pntflsh ; go flush the buffer pntchrx:ret pntchr endp ; Flush printer buffer. Return carry clear if success. ; On failure do procedure pntchk and return its C bit (typically C set). ; Uses buffer dumpbuf (screen dump). pntflsh proc near cmp pntptr,offset dumpbuf ; any text in buffer? jne pntfls1 ; ne = yes ret ; else nothing to do pntfls1:push ax push bx push cx push dx mov bx,portval mov bx,[bx].flowc ; get flow control chars (bl=xoff) mov flowon,bh mov flowoff,bl ; save for later mov al,bl ; get flow control char cmp al,0 ; flow control active? je pntfls2 ; e = no, not using xoff call prtbout ; output xoff (al), no echo pntfls2:mov ah,write2 mov bx,4 ; file handle for DOS printer PRN mov cx,pntptr ; next free byte in buffer mov dx,offset dumpbuf ; start of buffer mov pntptr,dx ; reset buffer pointer sub cx,dx ; cx = current byte count jcxz pntfls3 ; z = empty, do nothing int dos ; write buffer to printer pntfls3:pushf ; save carry status bit mov al,flowon cmp al,0 ; flow control active? je pntfls4 ; e = no, not using xon call prtbout ; output xon (al), no echo pntfls4:popf pop dx pop cx pop bx pop ax jnc pntflsx ; nc = success call pntchk ; c = error (printer not ready) pntflsx:ret pntflsh endp ; Check for PRN (DOS's printer) being ready. If ready, return with C clear ; Otherwise, write Not Ready msg on mode line and return with C bit set. ; N.B. DOS Critical Error will occur here if PRN is not ready. [jrd] pntchk proc near push dx push cx push ax mov cx,10 ; ten retries before declaring error pntchk0:mov ah,ioctl ; get printer status, via DOS mov al,7 ; status for output push bx mov bx,4 ; std handle for DOS system printer int dos pop bx jc pntchk1 ; c = call failed cmp al,0ffh ; code for Ready? je pntchk3 ; e = yes, assume printer is ready pntchk1:push cx ; save counter, just in case mov ax,100 ; wait 100 millisec call pcwait pop cx loop pntchk0 ; and try a few more times ; get here when printer is not ready test yflags,modoff ; is mode line off? jnz pntchk2 ; nz = off, skip msg push bx push si mov si,offset pntmsg ; say printer not ready mov cx,pntmsgl ; length call modwrt ; write alternate mode line pop si pop bx pntchk2:pop ax pop cx pop dx stc ; say printer not ready ret pntchk3:pop ax pop cx pop dx clc ; say printer is ready ret pntchk endp ;;;;; General screen management routines for IBM PC ; computes screen location to ax, given row and col in [dh,dl], resp. scrloc proc near mov al,dh ; get row mul crt_cols ; multiply by number of columns add al,dl ; plus current column number adc ah,0 ; ripple carry shl ax,1 ; double for attributes ret scrloc endp ; Routine to set cursor type. Pass cursor type in al: 0 = No cursor, ; 1 = Underline cursor, 2 = Block cursor. All cursors blink due to hardware. ; Routine frags any ac that video ints frag. ; 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 ah,1 ; Video fxn for set cursor type mov cx,0F00H ; Assume no cursor cmp al,0 ; No cursor? je csrty2 ; Right - set it and be done with it cmp crt_mode,7 ; B&W card? je csrty3 ; Yes - different sizes cmp crt_mode,18h ; Tseng UltraPAK mono board? je csrty3 ; e = yes, use mono cursor mov cx,0607H ; No, use CGA underline cursor cmp al,2 ; Block? jne csrty2 ; No - set it now csrty1: xor ch,ch ; Yes - make it a block csrty2: cmp ega_mode,0 ; ega board active? je csrty4 ; e = no cmp byte ptr low_rgt+1,23 ; 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 fxn for set cursor type int screen pop es:[87h] ; restore Info byte pop es ; and our work register pop cx ret csrty4: int screen ; regular cursor shape setting pop cx ret csrty3: mov cx,0B0CH ; Assume B&W underline cursor cmp al,2 ; Block? jne csrty2 ; No - set it now jmp csrty1 ; Yes - make it a block csrtype endp ; Save the entire screen in a buffer so we can restore and/or dump it. ; Saves regular (80x25) screens to memory buffer scrsav and other sized ; screens to video memory page 1. Resultant save place put into savadr ; (offset then segment) and current low_rgt size info in savflg. Note, ; some Environments (TopView/Windows etc) may not permit use of page 1. [jrd] savescr proc near push es push ds push ax push cx push si push di call scrseg ; get screen segment in ax and es:di push ax ; save screen segment mov si,0 mov di,scrsav ; place to put screen (memory buff) mov savadr+2,di ; working seg address for restore mov savadr,0 ; and no offset for memory buffer call scrmod ; ascertain video mode and screen mov ax,low_rgt ; text screen lower right (typ 23,79) mov savflg,ax ; save it for screen restore inc al ; number of columns add ah,2 ; plus status line = number of rows cmp al,swidth ; same as preset screen space (80)? ja savsc1 ; a = no, use screen video page 1 cmp ah,slen+1 ; same as preset screen length (24)? je savsc3 ; e = yes, use our memory buffer savsc1: mul ah ; times rows = characters on screen shl ax,1 ; times two for attributes = page 1 mov cx,ax ; cx = working copy of screen size and cx,000fh ; get lower four bits for offset part mov savadr,cx ; save offset in this word mov cl,4 shr ax,cl ; compute number of paragraphs pop di ; source screen address push di ; restore again add di,ax ; add paragraphs, point di to page 1 mov savadr+2,di ; and save segment in this word savsc3: mov es,savadr+2 ; segment of storage area mov di,savadr ; offset of same mov ax,low_rgt ; lower right of text screen inc al ; number of columns on screen add ah,2 ; number of rows on screen mul ah ; number of characters on the screen mov cx,ax ; save this in counter cx call scroff ; turn off screen [dt] pop ds ; address screen cld rep movsw ; save the screen pop di pop si pop cx pop ax pop ds ; restore this call scron ; turn on screen [dt] pop es ret savescr endp ; restore screen from buffer (offset and seg in savadr, text coord in savflg). ; Restores all screen lines. [jrd] restscr proc near push es mov ax,savflg ; saved low_rgt text screen coord add ah,2 ; number of screen lines inc al ; number of screen columns mul ah ; columns time lines = # characters mov cx,ax ; save this in counter cx push cx ; save count call scrseg ; get address of screen in es:di call scroff ; turn off screen [dt] push ds ; save original data segment mov si,savadr ; offset of storage area push savadr+2 ; segment of same pop ds ; put storage segment into ds cld rep movsw ; restore data to screen pop ds ; recover original data segment call scron ; turn on screen [dt] pop cx ; recover count call scrsync ; synch Topview with new screen pop es 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. ; Dumpscr reads the screen image saved by savescr so call savescr call first. 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 bx,bx ; 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 ; position cursor int screen mov dx,offset dmperr ; say no can do mov ah,prstr int dos pop dx ; get original cursor position mov ah,2 ; position cursor xor bx,bx ; 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 mov si,savadr ; offset in storage area dmp2: push cx ; save outer loop counter mov es,savadr+2 ; get storage segment mov di,offset dumpbuf ; data segment memory mov cl,byte ptr savflg ; number of columns on screen - 1 inc cl ; number of columns on screen xor ch,ch dmp3: mov ax,word ptr es:[si] ; read char + attribute 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 std ; set scan backward mov cl,byte ptr savflg ; number of columns on screen - 1 inc cl ; number of columns on screen xor ch,ch push es mov ax,ds mov es,ax ; set es to data segment for es:di mov di,offset dumpbuf ; start of line add di,cx ; plus length of line dec di ; minus 1 equals end of line mov al,' ' ; thing to scan over repe scasb ; scan until non-space cld ; set direction forward pop es 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 jc dmp3b ; c = error 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 dmp3b: 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 clc ret dumpscr 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. [jrd] scrmod proc near push ax push dx mov ah,15 ; Get current video state int screen 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 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 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 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,0B000H ; Assume B&W card cmp crt_mode,7 ; Is it? je scrse1 ; e = yes cmp crt_mode,18h ; Tseng UltraPAK mono in 132 col? je scrse1 ; e = yes, use seg B000H mov ax,0B800H ; No - video memory is here on color cmp crt_mode,12 ; graphics set? jb scrse1 ; b = no 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 mov 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 mov tv_mode,0 ; 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. scrsync proc near cmp tv_mode,0 ; Topview mode active? je scrsyn1 ; e = no, skip DOS call below 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 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 refresh,0 ; slow refresh? jne scrofx ; ne = no wait 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 ; Yes - just return 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 ; Dumb, but card is too 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 refresh,0 ; slow refresh? jne scronx ; ne = no wait 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 ; Yes - just return 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 ; restore regs pop dx pop ax scronx: ret scron endp ; Screen clearing routine. [IU] ; ; 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-79]. Preserves all registers. [jrd] atsclr: push ax ; save regs push cx push dx mov dx,bx ; Compute last screen offset in ax push ax call scrmod ; update column length pop ax ; scrmod zaps ax 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 sar cx,1 ; Make byte count a word count jle atscl2 ; If nothing to clear, then vamos push di ; save regs push es ; save es push ax ; save around call call scrseg ; Get address of screen in ax, es:di pop ax ; recover displacement add di,ax ; displacement memory address mov ah,scbattr ; Use current screen background attr mov al,' ' ; Use space for fill mov dl,byte ptr low_rgt ; line length - 1 inc dl ; line length xor dh,dh ;;;;; cmp cx,dx ; Blanking a line or less?? ;;;;; jg atscl1 ; No - make scroff disable display atscl1: call scroff ; Turn screen off if color card push cx ; save word count for Topview cld rep stosw ; Blit... (excuse PDP-10ese please) pop cx ; recover word count call scrsync ; synch Topview call scron ; Turn screen back on if color card pop es ; Restore segment register pop di ; And destination index atscl2: pop dx ; restore regs pop cx pop ax ret ; Scrolling routines. vtscru scrolls up, vtscrd scrolls down 'scroll' ; rows. The top line is 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. [jrd] ; All registers are preserved. ; Screen-roll down. Move text down one line, for terminal emulator only. vtscrd: push ax ; Upgraded by [jrd] push bx push cx push dx mov ah,7 ; scroll down mov ch,mar_top ; top margin line mov cl,0 ; left most column mov dh,mar_bot ; bottom margin line mov dl,byte ptr low_rgt ; right most column mov bh,scbattr ; attributes mov bl,dh sub bl,ch ; region size - 1 line mov al,scroll ; number of lines to scroll, from msz vscrd1: 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 vscrd1 ; do next part vscrd2: int screen ; scroll it down pop dx pop cx pop bx pop ax ret ; Screen scroll up one line (text moves up) for terminal emulator use. ; When running under an Environment control number of line positions moved ; to be less than scrolling region. [jrd] vtscru: push ax ; Upgraded by [jrd] push bx push cx push dx mov cl,scroll ; number of lines to scroll mov ch,0 jcxz vscru3 ; z = nothing to do cmp mar_top,0 ; scrolling the top screen line? ja vscru2 ; a = no. don't save anything push si push di call scroff ; turn off color screen mov si,tv_sego ; screen offset for es:si mov bx,offset twnd ; put lines in top window buffer vscru1: push cx ; save count call putcirc ; put screen line in circular buffer pop cx loop vscru1 ; save 'scroll' number of lines call scron ; turn on screen again pop di pop si ; now scroll the visible screen vscru2: mov ah,6 ; scroll up mov dh,mar_bot ; bottom row mov dl,byte ptr low_rgt ; right most column mov ch,mar_top ; top row of scrolling region mov cl,0 ; left most column mov bh,scbattr ; attributes mov bl,dh sub bl,ch ; region size - 1 line 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 jmp short vscru2a ; do next part vscru2b:int screen ; scroll up that region vscru3: pop dx ; Restore the rest of the regs pop cx pop bx pop ax ret ;screen text roll up, version for manual scrolling only mscru: push ax ; Upgraded by [jrd] push bx push cx push dx push si push di cmp bwnd.lcnt,0 ; any lines in bottom window? je mscru2 ; e = no, so ignore request call scroff ; turn off color screen mov bx,offset twnd ; this is where it goes mov si,tv_sego ; screen offset for es:si call putcirc ; put screen line in circular buffer mov ax,601H ; scroll up one line mov dx,low_rgt ; lower right corner xor cx,cx ; top row of scrolling region mov bh,scbattr ; background attributes int screen ; scroll up that region mov dx,low_rgt mov dl,0 ; location is lower left corner call scrloc ; get count from display start mov di,ax push es mov bx,tv_segs ; get screen's segment into, es:di mov es,bx ; segment add di,tv_sego ; destination memory address (es:di) mov bx,offset bwnd ; source of lines call getcirc ; get line from circ buf to screen pop es ; restore es call scron ; turn on the screen mscru2: pop di ; Restore the rest of the regs pop si pop dx pop cx pop bx pop ax ret ;screen text scroll down, for manual mode only mscrd: push ax ; Upgraded by [jrd] push bx push cx push dx push si push di cmp twnd.lcnt,0 ; any lines left in top window? je mscrd1 ; e = no, ingore request call scroff ; turn off screen mov dx,low_rgt ; from screen location, row mov dl,0 ; starting in col 0 call scrloc ; get offset in display buffer in ax mov si,tv_sego ; screen offset for es:di add si,ax ; source addr in display buffer es:si mov bx,offset bwnd ; buffer to use (bottom window) call putcirc ; copy bottom screen line to circ buf mov ax,701H ; scroll down one line xor cx,cx ; top left corner mov dx,low_rgt ; bottom right corner mov bh,scbattr ; attributes int screen ; scroll it down push es mov di,tv_segs ; screen segment mov es,di mov di,tv_sego ; screen offset, for es:di mov bx,offset twnd ; buffer to use (top window) call getcirc ; copy from circ buf to screen pop es call scron ; turn on display again mscrd1: pop di ; Restore the rest of the regs pop si pop dx pop cx pop bx pop ax ret ; move viewing window down as much as possible (text moves up) endwnd proc near ; go to end of scrolling text push cx mov cx,bwnd.lcnt ; all bottom window lines [dlk] jmp dnwp0 ; and enter dwnpg endwnd endp dnone proc near ; move text up one line [jrd] push cx mov cx,1 jmp dnwp0 dnone endp ; scroll viewing window down (text moves up) one page (24 lines) dnwpg proc near push cx mov cl,byte ptr low_rgt+1 ; number of rows, excl status inc cl ; count from 1, not 0 mov ch,0 dnwp0: ; additional entry point cmp bwnd.lcnt,cx ; enough lines in bottom line buffer? jge dnwp1 ; ge = we have that many lines stored mov cx,bwnd.lcnt ; do as many as we have dnwp1: jcxz dnwp2 ; z = nothing to do cmp tekflg,0 ; Tek mode active? jne dnwp2 ; ne = yes, no scrolling call mscru ; scroll up text one line loop dnwp1 dnwp2: pop cx clc ret dnwpg endp ; home viewing window homwnd proc near push cx mov cx,twnd.lcnt ; all top window lines [dlk] jmp upwp0 ; join upwpg homwnd endp upone proc near ; move text down one line [jrd] push cx mov cx,1 jmp upwp0 upone endp ; scroll viewing window up (text moves down) a page (24 lines) upwpg proc near push cx mov cl,byte ptr low_rgt+1 ; number of rows, excl status line inc cl ; count from 1, not 0 mov ch,0 upwp0: ; additional entry point cmp twnd.lcnt,cx ; enough lines in top line buffer? jae upwp1 ; ae = at least as many as requested mov cx,twnd.lcnt ; do only as many as are stored upwp1: jcxz upwp2 ; z = no lines to scroll cmp tekflg,0 ; Tek mode active? jne upwp2 ; ne = yes, no scrolling call mscrd ; roll down text one line loop upwp1 upwp2: pop cx clc ret upwpg endp ; Put a line into the circular buffer. Pass the buffer structure in bx. ; Source is tv_segs:si which is the current screen address. ; Rewritten by [jrd] putcirc proc near push es mov cl,crt_cols ; number of columns xor ch,ch mov es,[bx].orig ; get segment of memory area cmp bx,offset bwnd ; bottom buffer? je putci6 ; e = yes mov di,twnd.pp ; pick up buffer ptr (offset from es) add di,cx ; increment to next available slot add di,cx ; char and attribute cmp di,twnd.bend ; would line extend beyond buffer? jb putci1 ; b = not beyond end mov di,0 ; else start at the beginning putci1: mov twnd.pp,di ; update ptr cld ; set direction to forward push ds ; save regular datas seg reg mov ds,tv_segs ; use screen segment for ds:si rep movsw ; copy into buffer pop ds ; restore regular datas segment mov cx,twnd.lmax ; line capacity of buffer dec cx ; minus one work space line cmp twnd.lcnt,cx ; can we increment line count? jae putci1b ; ae = no, keep going inc twnd.lcnt ; else count this line putci1b:cmp bwnd.lcnt,0 ; any lines in bottom buffer? je putci2 ; e = no mov cx,bwnd.pp ; see if we overlap bot buf cmp cx,twnd.pp ; is this line in bot buf area? jne putci2 ; ne = no add cl,crt_cols ; move bottom pointer one slot earlier adc ch,0 add cl,crt_cols ; words adc ch,0 cmp cx,bwnd.bend ; beyond end of buffer? jb putci1a ; b = no mov cx,0 ; yes, start at beginning of buffer putci1a:mov bwnd.pp,cx ; new bottom pointer dec bwnd.lcnt ; one less line in bottom buffer putci2: pop es ret putci6: ; bottom buffer add cx,cx ; words worth cmp bwnd.lcnt,0 ; any lines in the buffer yet? jne putci7 ; ne = yes mov di,twnd.pp ; get latest used slot of top buff add di,cx ; where first free (?) slot starts cmp di,bwnd.bend ; are we now beyond the buffer? jb putci6a ; b = no mov di,0 ; yes, start at beginning of buffer putci6a:add di,cx ; start of second free (?) slot cmp di,bwnd.bend ; are we now beyond the buffer? jb putci6b ; b = no mov di,0 ; yes, start at beginning of buffer putci6b:mov cx,twnd.lmax ; buffer line capacity sub cx,twnd.lcnt ; minus number used by top buffer sub cx,2 ; minus one work slot and one we need cmp cx,0 ; overused some slots? jge putci8 ; ge = enough to share add twnd.lcnt,cx ; steal these from top window beginning jmp short putci8 putci7: mov es,bwnd.orig ; get segment of memory area mov di,bwnd.pp ; pick up buffer ptr (offset from es) cmp di,0 ; would line start before buffer? jne putci7a ; ne = after start of buffer mov di,bwnd.bend ; else start at the end minus one slot inc di putci7a:sub di,cx putci8: mov bwnd.pp,di ; update ptr (this is latest used slot) mov cl,crt_cols xor ch,ch cld ; set direction to forward push ds ; save regular datas seg reg mov ds,tv_segs ; use screen segment for ds:si rep movsw ; copy into buffer pop ds ; restore regular datas segment mov cx,bwnd.lmax ; line capacity of buffer cmp bwnd.lcnt,cx ; can we increment line count? jae putci8b ; ae = no, keep going inc bwnd.lcnt ; else count this line putci8b:cmp twnd.lcnt,0 ; any lines in top line buf? je putci9 ; e = no mov cx,twnd.pp ; yes, see if we used last top line cmp cx,bwnd.pp ; where we just wrote jne putci9 ; not same place, so all is well dec twnd.lcnt ; one less line in top window cmp cx,0 ; currently at start of buffer? jne putci8a ; ne = no mov cx,twnd.bend ; yes inc cx putci8a:sub cl,crt_cols ; back up top window sbb ch,0 sub cl,crt_cols ; by one line sbb ch,0 mov twnd.pp,cx ; next place to read putci9: pop es ret putcirc endp ; Get a line from the circular buffer, removing it from the buffer. ; returns with carry on if the buffer is empty. ; Pass the buffer structure in bx. ; Destination preset in es:di which is the current screen address. ; Rewritten by [jrd] getcirc proc near cmp [bx].lcnt,0 ; any lines in buffer? jne getci1 ; ne = yes, ok to take one out stc ; else set carry ret getci1: ; top and bottom window common code mov cl,crt_cols ; # of chars to copy xor ch,ch mov si,[bx].pp ; this is source push si ; save around calls push cx ; save around calls cld ; set direction to forward push ds ; save original ds mov ax,[bx].orig ; use seg address of buffer for si mov ds,ax rep movsw ; destination = screen at es:di pop ds ; recover original data segment pop cx ; recover word count call scrsync ; synch Topview pop si ; get ptr again add cx,cx ; words cmp bx,offset bwnd ; bottom window? je getci7 ; e = yes sub si,cx ; top window, move back jnc getci6 ; nc = still in buffer, continue mov si,twnd.bend ; else use end of buffer sub si,cx ; minus length of a piece inc si getci6: mov twnd.pp,si ; update ptr dec twnd.lcnt ; decrement # of lines in buffer clc ; make sure no carry ret getci7: ; bottom window add si,cx ; words, move back (bot buf = reverse) cmp si,bwnd.bend ; still in buffer? jb getci8 ; b = yes mov si,0 ; else use beginning of buffer getci8: mov bwnd.pp,si ; update ptr dec bwnd.lcnt ; decrement # of lines in buffer clc ; make sure no carry ret getcirc endp ; ; CHKDSP - procedure to check for hardware support of 132 cols [dlk] ; ; Supported hardware: EVA board from Tseng Labs w/132-col kit installed ; Tseng Labs UltraPAK mono/Herc board w/132 column modes. ; Video 7 Vega Deluxe w/ 132X25.COM driver installed [tmk] ; and VGA board, ATI EGA Wonder, Everex ev-659 and fvga-673. ; The routine checks for the presence of a 132-column-capable adapter. If ; one is found, its handler returns the proper video mode in [CX]. The main- ; line code then moves this to [AX] and issues the video interrupt. ; chgdsp proc near 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 ah,flowoff ; get xoff cmp ah,0 ; flow control? je chgds0 ; e = none call outchr ; send it nop ; avoid serial port interrupts while nop ; doing many rep scasb's below nop call savescr ; save current screen mov ax,40 ; wait 40 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 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 jmp chgdsx ; if not, exit ; Perform mode change chgds1: mov ax,cx ; get returned value in proper reg int screen ; call the bios cmp flags.modflg,1 ; is mode line enabled? jbe chgds2 ; be = yes, and off or locally owned mov flags.modflg,1 ; remove foreign ownership chgds2: call scrini ; reset parameters chgdsx: mov ah,flowon ; get flowon byte cmp ah,0 ; using flow control? je chgdsx1 ; e = no call outchr ; send it nop nop nop chgdsx1:pop di ; restore what we saved pop si pop dx pop cx pop bx pop ax pop es ret ; return to caller chgdsp endp ; Individual tests for various 132-column boards ; ; Tseng LABS EVA and UltraPAK 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 chnoad ; ne = no mov cx,7 ; default to mono (7) for this board cmp byte ptr temp,0 ; setting 132 columns? je ckteva1 ; e = resetting to normal mov cx,18h ; set to 132 cols (Set Mode 18H) ckteva1:clc ; carry clear means found ret ckteva2: ; an EVA board - check for 132 col kit cmp byte ptr es:099h,0 ; check 132 col kit installed je chnoad ; e=0=not installed jmp catfnd ; do the mode change chnoad: stc ; indicate adapter not present ret ; and exit ; ; 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 jne chnoad ; ne = strings differ ; catfnd: mov cx,0003h ; prepare to reset video mode cmp byte ptr temp,0 ; are we setting or resetting? je ckexit ; e is reset, exit mov cx,0023h ; set to 132 cols (Set Mode 23H) ckexit: clc ; carry clear means found 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 cnv7fn0 ; 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: jmp chnoad ; ne = strings are different ; cnv7fn0:test byte ptr es:[03ffeh],1 ; is this a 'Deluxe' Vega? jz chnoad ; 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 cnv7fn1:repe cmpsb ; Look for repeat of msg by 132X25.COM jne cnv7fn2 ; if different mov cl,crt_mode ; prepare to reset video mode mov ch,0 cmp byte ptr temp,0 ; are we setting or resetting? je ckexit ; e is reset, exit mov cx,0000h ; set to 132 cols (old 40x25) jmp short ckexit ; and exit 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 al,2 ; 1 = mono, 2 = color, above = ega jb cnv7fn3 ; b = mono mov bx,4fh ; presume med res color 132x25 je cnv7fn3 ; e = med res color mov bx,41h ; ega high res 132x25 cnv7fn3:push bx mov ah,0eh ; get current mode int screen 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 mov ah,0 ; set mode cnv7fn4:pop bx ; recover special mode int screen mov cx,0f00h ; a nop screen bios command jmp ckexit 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 cx,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 jmp ckexit ckfnr1: cmp ah,24 ; equal to 25-1 rows? je ckfnr3 ; e = yes ckfnr2: jmp chnoad ; ne = no ckfnr3: mov cx,0003h ; prepare to reset video mode cmp byte ptr temp,0 ; are we setting or resetting? je ckfnr4 ; e is reset, exit mov cx,0070h ; Everex extended mode ident mov bl,0ah ; 132x25 ckfnr4: jmp ckexit ckevga: mov ax,0c000h ; Everex FVGA-673, 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? jne ckevg2 ; ne = no mov cx,3 ; prepare to reset video mode cmp byte ptr temp,0 ; setting or resetting mode? je ckevg1 ; e = resetting, exit mov cx,0070h ; mode for 132x25 mov bl,0ah ; Everex mode 0ah ckevg1: clc ret ckevg2: stc ; say board not found ret ; Jumping to this location is like retskp. It assumes the instruction ; after the call is a jmp addr. RSKP PROC NEAR pop bp add bp,3 push bp ret RSKP ENDP ; Jumping here is the same as a ret R PROC NEAR ret R ENDP code ends if1 %out [End of pass 1] else %out [End of assembly] endif end