home *** CD-ROM | disk | FTP | other *** search
- ; VIDSAVE.COM -- Wrapper for ill-behaved programs that wipe out
- ; your 50- or 43-line video display mode
- ;
- ; To use this program, copy it to the directory where the .EXE for
- ; the target application lives. Rename this .COM file to have the
- ; same filename (but still a .COM extension).
- ;
- ; Copyright (c) 1991 by Walter Oney of Rational Systems, Inc.
- ; All rights reserved
- ;
-
-
- pushall macro
- push ax
- push bx
- push cx
- push dx
- push si
- push di
- push bp
- endm
-
- popall macro
- pop bp
- pop di
- pop si
- pop dx
- pop cx
- pop bx
- pop ax
- endm
-
- name vidsave
-
- vidsave segment byte public 'code'
- assume cs:vidsave, ds:vidsave
- org 100h ; required for .COM file usage
-
- ; Initialization. Establish reasonably sized stack and shrink
- ; memory block down.
-
- begin: lea sp, topsp ; set new stack top
- lea bx, topsp+15 ; compute # para's in shrunk block
- mov cl,4
- shr bx, cl ; ..
- mov ah, 4Ah ; resize memory block
- int 21h ; ..
-
- mov seg1, ds ; set segment address where needed
- mov seg2, ds ; ..
- mov seg3, ds ; ..
-
- mov ah,30h ; test for DOS 3.3 or greater
- int 21h
- xchg ah,al
- cmp ax,0303h
- jae dos_ok
-
- lea dx,old_dos_msg ; indicate that we need DOS 3.3
- mov ah,9
- int 21h
- mov ax,4c01h ; terminate with error
- int 21h
-
- ; Locate full pathname of executed command at the end of the
- ; environment block. Replace the .COM extension with .EXE instead.
- dos_ok: cld ; forward direction
- mov es, word ptr ds:[2Ch] ; point ES:DI to start of environment
- xor di, di ; ..
- xor al, al ; get zero to compare against
- xor cx, cx ; set practically infinite count
- dec cx ; ..
-
- skipvar: repne scasb ; find end of environment variable
- scasb ; compare next byte
- jne skipvar ; if not another null, do it again
-
- add di, 2 ; skip word count
- mov execpath, di ; save ptr to start of program name
- repne scasb ; find end of name
- mov byte ptr es:[di-4], 'E' ; change extension to "EXE"
- mov byte ptr es:[di-3], 'X' ; ..
- mov byte ptr es:[di-2], 'E' ; ..
-
- mov execpath+2, es ; complete ptr to program name.
- push ds ; set ES back to our code/data segment
- pop es ; ..
-
- ; Determine the current video characteristics (mode, page, font size)
- mov ah, 0Fh ; get video mode
- int 10h ; ..
- mov vidmode, al ; save original mode
- mov vidpage, bh ; save original display page
- mov ah, 03h ; get cursor pos'n & shape
- int 10h ; ..
- mov vidcurs, cx ; save shape for later restore
-
- mov ax, 1130h ; get font information
- xor bh, bh ; for current font
- int 10h ; ..
- mov ax, 1112h ; assume we're using small font
- cmp cx, 8 ; using 8 * 8 font?
- je setfont ; if yes, good
- mov ax, 1114h ; no. try for the 8 * 16 font
- cmp cx, 16 ; ..
- je setfont ; ..
- mov ax, 1111h ; no. must be the 8 * 14 font
- setfont: mov vidfont, ax ; save function code to restore this font
-
- ; If we're running on a VGA, we can determine the border color by reading
- ; the palette register. With any sort of display, we can get the
- ; attribute byte for any random location on the screen.
- mov ah, 08h ; fcn 8: read char & attr at cursor
- mov bh, vidpage ; (for the current page)
- int 10h ; ..
- mov charattr, ah ; save attribute byte for later restore
- mov cl,4
- shr ah, cl ; assume border color is same as
- mov border, ah ; background color of attribute
-
- mov ax, 1A00h ; issue fcn 1A (read configuration)
- int 10h ; ..
- cmp al, 1Ah ; if AL comes back != 1A, not a VGA
- jne notvga ; ..
- cmp bl, 8 ; is primary display a VGA with color?
- jne notvga ; if not, don't try to read border color.
-
- mov ax, 1008h ; read border color
- int 10h ; ..
- mov border, bh ; save border color for later restore
-
- notvga:
-
- ; Hook INT 10 so we can prevent the cursor from getting screwed up.
- ; Hook INT 21 so we can monitor for EXEC calls and run them with
- ; the original video mode.
- mov ax, 3510h ; get current INT 10 & 21 vectors
- int 21h ; ..
- mov word ptr org10, bx ; ..
- mov word ptr org10+2, es ; ..
- mov ax, 3521h ; ..
- int 21h ; ..
- mov word ptr org21, bx ; ..
- mov word ptr org21+2, es ; ..
- push ds ; restore ES
- pop es ; ..
-
- lea dx, int10 ; hook INT 10
- mov ax, 2510h ; ..
- int 21h ; ..
-
- lea dx, int21 ; hook INT 21 also
- mov ax, 2521h ; ..
- int 21h ; ..
-
- ; Execute the application whose filename is the same as our own filename.
- lea bx, execparm ; es:bs -> parameter block
- lds dx, dword ptr execpath ; ds:dx -> pathname
- assume ds:nothing
- mov ax, 4B00h ; load & execute program
- pushf ; don't go through our EXEC trap!
- call dword ptr cs:[org21]; ..
-
- mov ax, cs ; reset segment registers
- mov ds, ax ; ..
- mov es, ax ; ..
- assume ds:vidsave ; ..
-
- ; Restore the environment and terminate
- push ds ; save DS across unhook
- lds dx, org10 ; unhook INT 10
- mov ax, 2510h ; ..
- pushf ; ..
- call dword ptr cs:[org21] ; ..
- pop ds ; ..
-
- push ds ; unhook INT 21 too
- lds dx, org21 ; ..
- mov ax, 2521h ; ..
- pushf ; ..
- call dword ptr cs:[org21] ; ..
- pop ds ; ..
-
- call near ptr vidrest ; restore video environment
- mov ax, 4C00h ; terminate process
- int 21h ; ..
-
- ; INT 10 handler (needed to prevent cursor from disappearing on
- ; my home machine due to probable video BIOS bug):
- assume nothing, cs:vidsave
- int10: cmp ah, 01h ; look for Set Cursor Type call
- je setcur ; stay here if so
-
- chain10: jmp dword ptr cs:[org10]; chain to original 6D handler
-
- setcur: cmp cx, 0600h ; check for start 6, end 0
- je fixcur ; ..
- cmp cx, 0200h ; also for start 2, end 0
- jne chain10 ; ignore all other cursor sets
- mov cx, 0207h ; set end row 7
- jmp chain10 ; ..
-
- fixcur: mov cx, 0507h ; set end row 7
- jmp chain10 ; chain to original handler
-
- ; INT 21 handler (needed to restore video during EXEC from application):
- int21: cmp ah, 4Bh ; EXEC function?
- je exec ; if yes, stay here to deal with it
- jmp dword ptr cs:[org21]; no. chain to original handler
-
- exec: pushall ; save everything
- push ds ; ..
- push es ; ..
- lds dx, cs:org21 ; unhook ourselves during EXEC
- mov ax, 2521h ; ..
- pushf ; ..
- call dword ptr cs:[org21]; ..
-
- mov ax, cs ; get DS addressability for VIDREST
- mov ds, ax ; ..
- call near ptr vidrest ; restore video to original
-
- pop es ; restore everything
- pop ds ; ..
- popall ; ..
- int 21h ; do EXEC from here
- pushall ; save registers again
- push ds ; ..
- push es ; ..
-
- mov ax, cs ; rehook INT 21
- mov ds, ax ; ..
- mov dx, offset int21 ; ..
- mov ax, 2521h ; ..
- pushf ; ..
- call dword ptr cs:[org21]; ..
-
- pop es ; restore registers
- pop ds ; ..
- popall ; ..
- iret ; return to application
-
- ; Internal procedure to restore the video environment:
- assume ds:vidsave
- vidrest proc near
- mov al, vidmode ; restore original video mode
- xor ah, ah ; ..
- int 10h ; ..
-
- mov ax, 0500h ; force display page 0
- int 10h ; ..
-
- mov ax, vidfont ; restore original font
- xor bl, bl ; character block = 0
- int 10h ; ..
-
- mov ah, 03h ; get cursor to reset MCGA
- xor bh, bh ; ..
- int 10h ; ..
-
- mov al, vidpage ; restore original display page
- mov ah, 5 ; ..
- int 10h ; ..
-
- mov cx, vidcurs ; restore cursor shape
- mov ah, 01h ; ..
- int 10h ; ..
-
- mov ax, 1001h ; fcn 10, subfcn 01: set border color
- mov bh, border ; ..
- int 10h ; ..
-
- mov ax, 0600h ; fcn 06: scroll up, al=0: clear window
- mov bh, charattr ; attribute to fill window with
- xor cx, cx ; ch/cl = top/left
- mov dx, 40h ; address BIOS data area at 40:
- mov es, dx ; ..
- mov dx, es:4Ah ; set DL = right column
- dec dx ; ..
- mov dh, es:84h ; set DH = bottom row
- int 10h ; go clear the whole screen
- ret ; return to local caller
- vidrest endp
-
- ; Data:
-
- execpath dw 0 ; offset to name of program to execute
- execparm dw 0 ; seg # of environment (also part of ptr)
- dw 80h ; segment:offset of command tail
- seg1 dw ? ; ..
- dw 5Ch ; segment:offset of 1st FCB
- seg2 dw ? ; ..
- dw 6Ch ; segment:offset of 2d FCB
- seg3 dw ? ; ..
-
- vidfont dw ? ; INT 10 fcn to restore font
- vidpage db ? ; video page number
- vidmode db ? ; video mode
- vidcurs dw ? ; original cursor shape
- border db ? ; border color
- charattr db ? ; character attribute to restore
-
- org10 dd 0 ; original INT 10 vector
- org21 dd 0 ; original INT 21 vector
-
-
- db 128 dup (0) ; presumably enough stack . . .
- topsp label byte
- old_dos_msg db 'This program requires DOS 3.3 or greater',0dh,0ah,'$'
- vidsave ends
- end begin
-