NAME ccyibm ; File CCYIBM.ASM ; Edit History: ; Mar.21,1991: ; * Add MASM Option /DCGA in serval places. The goal is to make ZUnet-PBX ; can be run in different CCDOS versions(Such as: CCDOS213,LIANXIAN, ; STCDOS,CGA17,etc.) on different video adapers( such as CGA,EGA,VGA ; and MDA). ; In this program Macro Conditions "IFDEF CGA ... ENDIF" and "IFNDEF CGA ; ... ENDIF" are used. ; Option CGA is used only when you want to build a program used in PC/XT ; (CGA or MDA adapter).Maybe it can be used in VGA adapter. [zqf] ; 1990: ; * Program is modified in many places to suit for different CCDOS versions. ; You can check them by indexing 'zqf' or 'CCDOS'. [zqf] ;CHINESE ifdef MSDOS include msyibm.dat else include ccyibm.dat endif 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 ifdef DEBG ; extrn debgp:near endif 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 ; ---------don't set cursor in CCDOS. Dec.12,1990 [zqf] IFDEF CGA ; Add Option CGA to servered screen.Mar.21,1991 [zqf] cmp isccdos,1 ; is in CCDOS ? je scrin6 ; e = yes, skip ENDIF int screen ; set cursor in case it moved scrin6: ; ----------- test flags1,inited ; have we run yet? jz scrin7 ; z = no, so no saved screen yet call restscr ; restore screen[zqf]Dec.13,1990 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 ; ************************** Change Connect Mode Line, Oct.8,1990 [zqf]. cmp isccdos, 0 ; if in MS-DOS or CC-DOS ? je modl0 ; e = in MS-DOS jmp cmodl0 ; in CC-DOS ; *** ; ******** in MS-DOS below modl0: 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 ; **** jmp modwrt ; ******** in CC-DOS below cmodl0: mov al,esc_ch mov cmodbuf.cm_echr,' ' ; first char is initial space mov cmodbuf.cm_hlp,' ' ; goes here too cmp al,32 ; printable? jnb cmodl1 ; yes, keep going add al,40h ; made printable mov cmodbuf.cm_echr,5eh ; caret, note control char mov cmodbuf.cm_hlp,5eh cmodl1: mov cmodbuf.cm_echr+1,al ; fill in character mov cmodbuf.cm_hlp+1,al mov bx,argadr ; get argument block mov al,[bx].baudb ; get baud bits mov si,offset cunkbaud ; assume unknown baud cmp al,baudnsiz ; too big? jnb cmodl2 ; nb = yes, use default mov cl,size cm_baud ; each is 5 bytes long mul cl mov ah,0 add ax,offset baudn mov si,ax cmodl2: mov cx,size cm_baud ; length of baud space mov di,offset cmodbuf.cm_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 cparnams ; names of parity settings mov si,ax mov cx,4 ; each is 4 long mov di,offset cmodbuf.cm_par rep movsb mov si,offset cremmsg ; Assume remote echoing test yflags,lclecho ; Is remote side echoing? jz cmodl4 ; Yes, keep going mov si,offset clclmsg ; Else it's local echoing. cmodl4: mov cx,4 ; size of on/off mov di,offset cmodbuf.cm_echo rep movsb mov al,portno ; communications port cmp al,' ' ; binary (non-printable)? jae cmodl5 ; ae = no, ascii add al,'0' ; convert to ascii cmodl5: mov cmodbuf.cm_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 cmodbuf.cm_term ; destination rep movsb ; copy it in mov cmodbuf.cm_prn,' ' ; assume not printing the screen mov cmodbuf.cm_prn+1,' ' mov cmodbuf.cm_prn+2,' ' test anspflg,prtscr ; doing a print the screen? jz cmodl5a ; z = no mov cmodbuf.cm_prn,'P' ; yes. display PRN at end of line mov cmodbuf.cm_prn+1,'R' mov cmodbuf.cm_prn+2,'N' cmodl5a: mov cx,size cmodfrm ; this is size of mode line mov si,offset cmodbuf ; mode line image pop es ; ************************** Oct.8,1990 [zqf]. ; 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 ;**** Modify to suit CCDOS. Sept 5,1990 [zqf] cmp isccdos,1 ; if in CCDOS ? jne modl5b ; ne = No, in MS-DOS mov ax,cx ; in CCDOS mov bx,dx call atsclr ; clear mode line in CC-DOS jmp modl5c modl5b: int screen ; clear mode line in MS-DOS modl5c: ;**** 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 ;**** Modify to suit CCDOS. June 25,1990 [zqf] mov ax,cx mov bx,dx call atsclr ; 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: nop ;****************** call savescr ; save screen in MS-DOS ;******************* 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 ;**** Modify to suit CCDOS. June 25,1990 [zqf] mov ax,cx mov bx,dx call atsclr ; int screen ; clear 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 ; ---------don't set cursor in CCDOS. Dec.12,1990 [zqf] IFDEF CGA ; Add Option CGA to servered screen.Mar.21,1991 [zqf] cmp isccdos,1 ; is in CCDOS ? je quit4 ; e = yes, skip ENDIF int screen ; Do it quit4: ; ----------- 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 ; ---------don't set cursor in CCDOS. Dec.12,1990 [zqf] IFDEF CGA ; Add Option CGA to servered screen.Mar.21,1991 [zqf] cmp isccdos,1 ; is in CCDOS ? je outnpa ; e = yes, skip ENDIF call endwnd ; restore screen before writing [dlk] outnpa: ; ----------- outnp6: cmp flags.vtflg,0 ; emulating a terminal? jne outnop1 ; ne = 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: push ax int screen pop ax 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 ; 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 jb pntchrx ; b = no, just return jmp pntflsh ; go flush the buffer pntchrx:clc ; clear carry bit 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 mcmsgsi pntmsg, cpntmsg mov cx,pntmsgl ; length cmp isccdos,0 je pntchk11 mov cx,cpntmsgl pntchk11: 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 ; ****************** if in CC-DOS mode? Nov.1990 [zqf] cmp isccdos,1 ; if CC-DOS ? jne savsc0 ; ne = No. IFNDEF CGA ; Add Option CGA to servered screen.Mar.21,1991 [zqf] call savccscr ; yes, call CCDOS screen save proc ENDIF jmp savsc4 ; return savsc0: ; ********************** 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 savsc4: 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 ; ****************** if in CC-DOS mode? Nov.1990 [zqf] cmp isccdos,1 ; if CC-DOS ? jne rstscr0 ; ne = No. IFNDEF CGA ; Add Option CGA to servered screen.Mar.21,1991 [zqf] call rstccscr ; yes, call CCDOS screen restore proc ENDIF ret ; return rstscr0: ; ********************** 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 ;**************************** used in CC-DOS Nov.28,1990 [zqf] ; SAVCCSCR ---- called by of module "ccyibm.asm". ; which save screen char & attr in buffer pointed ; by scrsav in CC-DOS. Nov 28,1990 [zqf] ; All registers are reserved. ;******************************** SAVCCSCR proc near push ax push bx push cx push dx push di push es mov ax,scrsav ; buffer segment address, offset is zero mov es,ax mov di,0 mov savadr+2,es mov savadr,di ; read current cursor mov bh,0 mov ah,3 int 10h ; read current cursor pos. & type. mov curpos,dx ; saved in mov curtyp,cx ; ; save screen mov bh,0 mov dx,0 savccscr1: mov ah,2 int 10h ; set cursor position --- mov ah,8 int 10h ; read char & attr in current cursor pos. mov es:[di],ax ; save in scrbuf inc dl cmp dl,crt_cols ; crt_cols:number of screen cols (typ 80) jl savccscr2 mov dl,0 inc dh cmp dh,crt_lins ; crt_lins:number of rows-1 (typ 24) jg savccscr3 savccscr2: inc di inc di jmp savccscr1 savccscr3: pop es pop di pop dx pop cx pop bx pop ax ret SAVCCSCR endp ;******************************* ;**************************** used in CC-DOS Nov.28,1990 [zqf] ; RSTCCSCR ---- called by of module "ccyibm.asm". ; which restore screen char & attr in buffer pointed ; by savadr in CC-DOS. Nov 28,1990 [zqf] ; All registers are reserved. ;******************************** RSTCCSCR proc push ax push bx push cx push dx push di push es mov ax,savadr+2 ; segment address of buffer mov es,ax mov di,savadr ; offset address of buffer ; restore screen mov bh,0 mov dx,0 rstccscr1:mov ah,2 int 10h ; set cursor position --- mov ax,es:[di] ; restore from scrbuf mov bl,ah mov cx,1 mov ah,9 int 10h ; write char & attr in current cursor pos. inc dl cmp dl,crt_cols ; crt_cols:number of screen cols (typ 80) jl rstccscr2 mov dl,0 inc dh cmp dh,crt_lins ; crt_lins:number of rows-1 (typ 24) jg rstccscr3 rstccscr2: inc di inc di ; adjust pointer jmp rstccscr1 rstccscr3: ; set original cursor pos &type mov bh,0 mov cx,curtyp mov ah,1 int 10h ; build cursor type mov bh,0 mov dx,curpos mov ah,2 int 10h ; set original cursor pos. pop es pop di pop dx pop cx pop bx pop ax ret RSTCCSCR 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 mcmsg dmperr, cdmperr 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 cmp crt_mode,18 ; end of ordinary 640x480 graphics ja scrse1 ; a = no, assume CGA segment mov ax,0A000H ; graphics scrse1: mov es,ax ; tell Topview our hardware address needs mov tv_segs,es ; save our hardware screen address mov tv_sego,di ; segment and offset form 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 CALL PATSCLR ; CALL PROC TO CLEAR LINE 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 ; Screen clearing routine.Ver 2.00 Dec. 15,1989 [ZU] ; (Screen clearing by scroll whole bolck between and ; Call ax/ corrdinates of upon left location to be cleared. ; -- ; bx/ corrdinates of down right location to be cleared. ; -- ; Cord: ah=row [0-24], al = col [0-79]. Preserves all registers. [zqf] patsclr proc near push ax push bx push cx push dx push si push di ; check if clear block or a line ? cmp bh,ah jg patsclr_b ; le= clear a block more than one line ; clear a block in one line ; read screen mode patsclr_l: push ax push bx mov ah,15 ;state int video mov activepage,bh ; mov cols,ah pop bx pop ax ; save current cursor push ax push bx mov bh,activepage mov ah,readcur int video mov currow,dh mov curcol,dl mov curtype,cx pop bx pop ax ; compute number of chars to clear in cx push ax xor cx,cx mov dx,0 patscl1: cmp bh,ah jle patscl2 mov dl,80 ;cols sub dl,al add cx,dx xor al,al inc ah jmp patscl1 patscl2: cmp bl,al jl patscl3 sub bl,al mov bh,0 add cx,bx inc cx patscl3: pop ax cmp cx,0 jle patscl10 ; set cursor at start location of clearing area mov dx,ax mov bh,activepage mov ah,setcur int video ; clear screen < CX__number of chars > mov al,' ' ;space mov bh,activepage mov bl,scbattr ; mov ah,writech ; ????? different with 'writeach' mov ah,writeach int video ; restore current cursor mov dh,currow mov dl,curcol mov bh,activepage mov ah,setcur int video patscl10: pop di pop si pop dx pop cx pop bx pop ax ret ; scroll window at location to patsclr_b: mov cx,ax mov dx,bx mov bh,scbattr mov al,0 mov ah,06h int video jmp patscl10 patsclr endp ; 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 cmp cx,0 jnz vscru0 jmp vscru3 ; z = nothing to do vscru0: cmp mar_top,0 ; scrolling the top screen line? ja vscru2 ; a = no. don't save anything push si push di ;******** test for CCDOS. Dec.12,1990 [zqf] IFDEF CGA ; Add Option CGA to servered screen.Mar.21,1991 [zqf] cmp isccdos,1 ; if CCDOS ? je vscru1a ; e = yes, in CCDOS, skip ENDIF 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 IFDEF CGA ; Add Option CGA to servered screen.Mar.21,1991 [zqf] vscru1a: ENDIF ;******** 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 ;******** test for CCDOS. Dec.12,1990 [zqf] IFDEF CGA ; Add Option CGA to servered screen.Mar.21,1991 [zqf] cmp isccdos,1 ; if CCDOS ? je vscru2c ; e = yes, in CCDOS, skip ENDIF int screen ; and do in parts IFDEF CGA ; Add Option CGA to servered screen.Mar.21,1991 [zqf] jmp vscru2d ; in MSDOS vscru2c: push dx mov dl,0dh mov ah,2 int 21h mov dl,0ah mov ah,2 int 21h pop dx vscru2d: ENDIF ;******** pop ax sub al,bl jmp short vscru2a ; do next part vscru2b: ;******** test for CCDOS. Dec.12,1990 [zqf] IFDEF CGA ; Add Option CGA to servered screen.Mar.21,1991 [zqf] cmp isccdos,1 ; if CCDOS ? je vscru2e ; e = yes, in CCDOS, skip ENDIF int screen ; and do in parts IFDEF CGA ; Add Option CGA to servered screen.Mar.21,1991 [zqf] jmp vscru2f ; in MSDOS vscru2e: push dx mov dl,0dh mov ah,2 int 21h mov dl,0ah mov ah,2 int 21h pop dx vscru2f: ENDIF ;******** 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 crt_lins,42 ; 43 lines active? jb cnv7fn2a ; b = no inc bx ; use bx = 52h for 132x43 cnv7fn2a: cmp al,10h ; analogue fixed freq (IBM 85xx)? je cnv7fx ; e = yes, no 132 columns cmp al,2 ; 1 = mono, 2 = color, above = ega jb cnv7fn3 ; b = mono or unknown mov bx,4fh ; presume med res color 132x25 je cnv7fn3 ; e = med res color, al = 2 mov bx,41h ; ega high res 132x25, enhanced mons cmp crt_lins,42 ; 43 lines active? jb cnv7fn3 ; b = no inc bx ; use bx = 42h for 132x43 cnv7fn3:mov ax,6f05h ; set special mode found in bl cmp byte ptr temp,0 ; resetting to 80 column mode? jne cnv7fn4 ; ne = no, setting 132x25 mov al,crt_norm ; get normal mode mov ah,0 ; set mode cmp crt_lins,42 ; 43 lines active? jb cnv7fn4 ; b = no mov bl,40h ; use Video 7 mode 40h 80x43 for color mov ax,6f05h ; and do special mode set cnv7fn4:int screen ; special mode is in bl mov cx,0f00h ; a nop screen bios command clc ret ckevrx: mov ax,0c000h ; seg addr for Everex EV-659 mov es,ax ; set into es register mov di,0047h ; offset of message in ROM lea si,evrxid ; offset of message here mov cx,evrxlen ; length of validation string cld repe cmpsb ; compare strings jne ckfnr2 ; ne = strings differ mov ah,crt_lins ; we recognize either 44 or 25 rows cmp ah,43 ; equal to 44-1 rows? jne ckfnr1 ; ne = no mov 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