home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Power-Programmierung
/
CD1.mdf
/
magazine
/
progjour
/
1991
/
06
/
vidsave.asm
< prev
next >
Wrap
Assembly Source File
|
1991-10-01
|
13KB
|
312 lines
; 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