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

  1. ;    VIDSAVE.COM -- Wrapper for ill-behaved programs that wipe out
  2. ;                   your 50- or 43-line video display mode
  3. ;
  4. ;    To use this program, copy it to the directory where the .EXE for
  5. ;    the target application lives. Rename this .COM file to have the
  6. ;    same filename (but still a .COM extension).
  7. ;
  8. ;    Copyright (c) 1991 by Walter Oney of Rational Systems, Inc.
  9. ;    All rights reserved
  10. ;
  11.  
  12.  
  13. pushall  macro
  14.          push  ax
  15.          push  bx
  16.          push  cx
  17.          push  dx
  18.          push  si
  19.          push  di
  20.          push  bp
  21.          endm
  22.  
  23. popall   macro
  24.          pop   bp
  25.          pop   di
  26.          pop   si
  27.          pop   dx
  28.          pop   cx
  29.          pop   bx
  30.          pop   ax
  31.          endm
  32.  
  33.          name  vidsave
  34.  
  35. vidsave  segment byte public 'code'
  36.          assume cs:vidsave, ds:vidsave
  37.          org   100h               ; required for .COM file usage
  38.  
  39. ;    Initialization. Establish reasonably sized stack and shrink
  40. ;    memory block down.
  41.  
  42. begin:   lea   sp, topsp          ; set new stack top
  43.          lea   bx, topsp+15       ; compute # para's in shrunk block
  44.          mov   cl,4
  45.          shr   bx, cl             ;   ..
  46.          mov   ah, 4Ah            ; resize memory block
  47.          int   21h                ;   ..
  48.  
  49.          mov   seg1, ds           ; set segment address where needed
  50.          mov   seg2, ds           ;   ..
  51.          mov   seg3, ds           ;   ..
  52.  
  53.      mov   ah,30h             ; test for DOS 3.3 or greater
  54.      int   21h
  55.          xchg  ah,al
  56.          cmp   ax,0303h
  57.          jae   dos_ok 
  58.  
  59.          lea   dx,old_dos_msg     ; indicate that we need DOS 3.3
  60.          mov   ah,9
  61.          int   21h
  62.          mov   ax,4c01h           ; terminate with error
  63.          int   21h
  64.  
  65. ;    Locate full pathname of executed command at the end of the
  66. ;    environment block. Replace the .COM extension with .EXE instead.
  67. dos_ok:  cld                      ; forward direction
  68.          mov   es, word ptr ds:[2Ch] ; point ES:DI to start of environment
  69.          xor   di, di                ;   ..
  70.          xor   al, al             ; get zero to compare against
  71.          xor   cx, cx             ; set practically infinite count
  72.          dec   cx                 ;   ..
  73.  
  74. skipvar: repne scasb              ; find end of environment variable
  75.          scasb                    ; compare next byte
  76.          jne   skipvar            ; if not another null, do it again
  77.  
  78.          add   di, 2              ; skip word count
  79.          mov   execpath, di       ; save ptr to start of program name
  80.          repne scasb              ; find end of name
  81.          mov   byte ptr es:[di-4], 'E' ; change extension to "EXE"
  82.          mov   byte ptr es:[di-3], 'X' ;   ..
  83.          mov   byte ptr es:[di-2], 'E' ;   ..
  84.  
  85.          mov   execpath+2, es     ; complete ptr to program name.
  86.          push  ds                 ; set ES back to our code/data segment
  87.          pop   es                 ;   ..
  88.  
  89. ;    Determine the current video characteristics (mode, page, font size)
  90.          mov   ah, 0Fh            ; get video mode
  91.          int   10h                ;   ..
  92.          mov   vidmode, al        ; save original mode
  93.          mov   vidpage, bh        ; save original display page
  94.          mov   ah, 03h            ; get cursor pos'n & shape
  95.          int   10h                ;   ..
  96.          mov   vidcurs, cx        ; save shape for later restore
  97.  
  98.          mov   ax, 1130h          ; get font information
  99.          xor   bh, bh             ; for current font
  100.          int   10h                ;   ..
  101.          mov   ax, 1112h          ; assume we're using small font
  102.          cmp   cx, 8              ; using 8 * 8 font?
  103.          je    setfont            ; if yes, good
  104.          mov   ax, 1114h          ; no. try for the 8 * 16 font
  105.          cmp   cx, 16             ;   ..
  106.          je    setfont            ;   ..
  107.          mov   ax, 1111h          ; no. must be the 8 * 14 font
  108. setfont: mov   vidfont, ax        ; save function code to restore this font
  109.  
  110. ;    If we're running on a VGA, we can determine the border color by reading
  111. ;    the palette register. With any sort of display, we can get the
  112. ;    attribute byte for any random location on the screen.
  113.          mov   ah, 08h            ; fcn 8: read char & attr at cursor
  114.          mov   bh, vidpage        ;   (for the current page)
  115.          int   10h                ;   ..
  116.          mov   charattr, ah       ; save attribute byte for later restore
  117.          mov   cl,4
  118.          shr   ah, cl             ; assume border color is same as
  119.          mov   border, ah         ;   background color of attribute
  120.  
  121.          mov   ax, 1A00h          ; issue fcn 1A (read configuration)
  122.          int   10h                ;   ..
  123.          cmp   al, 1Ah            ; if AL comes back != 1A, not a VGA
  124.          jne   notvga             ;   ..
  125.          cmp   bl, 8              ; is primary display a VGA with color?
  126.          jne   notvga             ; if not, don't try to read border color.
  127.  
  128.          mov   ax, 1008h          ; read border color
  129.          int   10h                ;   ..
  130.          mov   border, bh         ; save border color for later restore
  131.  
  132. notvga:
  133.  
  134. ;    Hook INT 10 so we can prevent the cursor from getting screwed up.
  135. ;    Hook INT 21 so we can monitor for EXEC calls and run them with
  136. ;    the original video mode.
  137.          mov   ax, 3510h            ; get current INT 10 & 21 vectors
  138.          int   21h                  ;   ..
  139.          mov   word ptr org10, bx   ;   ..
  140.          mov   word ptr org10+2, es ;   ..
  141.          mov   ax, 3521h            ;   ..
  142.          int   21h                  ;   ..
  143.          mov   word ptr org21, bx   ;   ..
  144.          mov   word ptr org21+2, es ;   ..
  145.          push  ds                   ; restore ES
  146.          pop   es                   ;   ..
  147.  
  148.          lea   dx, int10          ; hook INT 10
  149.          mov   ax, 2510h          ;   ..
  150.          int   21h                ;   ..
  151.  
  152.          lea   dx, int21          ; hook INT 21 also
  153.          mov   ax, 2521h          ;   ..
  154.          int   21h                ;   ..
  155.  
  156. ;    Execute the application whose filename is the same as our own filename.
  157.          lea   bx, execparm       ; es:bs -> parameter block
  158.          lds   dx, dword ptr execpath ; ds:dx -> pathname
  159.          assume ds:nothing
  160.          mov   ax, 4B00h          ; load & execute program
  161.          pushf                    ; don't go through our EXEC trap!
  162.          call  dword ptr cs:[org21];   ..
  163.  
  164.          mov   ax, cs             ; reset segment registers
  165.          mov   ds, ax             ;   ..
  166.          mov   es, ax             ;   ..
  167.          assume ds:vidsave         ;   ..
  168.  
  169. ;    Restore the environment and terminate
  170.          push  ds                 ; save DS across unhook
  171.          lds   dx, org10          ; unhook INT 10
  172.          mov   ax, 2510h          ;   ..
  173.          pushf                    ;   ..
  174.          call  dword ptr cs:[org21]  ;   ..
  175.          pop   ds                 ;   ..
  176.  
  177.          push  ds                 ; unhook INT 21 too
  178.          lds   dx, org21          ;   ..
  179.          mov   ax, 2521h          ;   ..
  180.          pushf                    ;   ..
  181.          call  dword ptr cs:[org21]  ;   ..
  182.          pop   ds                 ;   ..
  183.  
  184.          call  near ptr vidrest   ; restore video environment
  185.          mov   ax, 4C00h          ; terminate process
  186.          int   21h                ;   ..
  187.  
  188. ;    INT 10 handler (needed to prevent cursor from disappearing on
  189. ;    my home machine due to probable video BIOS bug):
  190.          assume nothing, cs:vidsave
  191. int10:   cmp   ah, 01h            ; look for Set Cursor Type call
  192.          je    setcur             ; stay here if so
  193.  
  194. chain10: jmp   dword ptr cs:[org10]; chain to original 6D handler
  195.  
  196. setcur:  cmp   cx, 0600h          ; check for start 6, end 0
  197.          je    fixcur             ;   ..
  198.          cmp   cx, 0200h          ; also for start 2, end 0
  199.          jne   chain10            ; ignore all other cursor sets
  200.          mov   cx, 0207h          ; set end row 7
  201.          jmp   chain10            ;   ..
  202.  
  203. fixcur:  mov   cx, 0507h          ; set end row 7
  204.          jmp   chain10            ; chain to original handler
  205.  
  206. ;    INT 21 handler (needed to restore video during EXEC from application):
  207. int21:   cmp   ah, 4Bh             ; EXEC function?
  208.          je    exec                ; if yes, stay here to deal with it
  209.          jmp   dword ptr cs:[org21]; no. chain to original handler
  210.  
  211. exec:    pushall                  ; save everything
  212.          push  ds                 ;   ..
  213.          push  es                 ;   ..
  214.          lds   dx, cs:org21       ; unhook ourselves during EXEC
  215.          mov   ax, 2521h          ;   ..
  216.          pushf                    ;   ..
  217.          call  dword ptr cs:[org21];   ..
  218.  
  219.          mov   ax, cs             ; get DS addressability for VIDREST
  220.          mov   ds, ax             ;   ..
  221.          call  near ptr vidrest   ; restore video to original
  222.  
  223.          pop   es                 ; restore everything
  224.          pop   ds                 ;   ..
  225.          popall                   ;   ..
  226.          int   21h                ; do EXEC from here
  227.          pushall                  ; save registers again
  228.          push  ds                 ;   ..
  229.          push  es                 ;   ..
  230.  
  231.          mov   ax, cs             ; rehook INT 21
  232.          mov   ds, ax             ;   ..
  233.          mov   dx, offset int21   ;   ..
  234.          mov   ax, 2521h          ;   ..
  235.          pushf                    ;   ..
  236.          call  dword ptr cs:[org21];   ..
  237.  
  238.          pop   es                 ; restore registers
  239.          pop   ds                 ;   ..
  240.          popall                   ;   ..
  241.          iret                     ; return to application
  242.  
  243. ;    Internal procedure to restore the video environment:
  244.          assume ds:vidsave
  245. vidrest  proc  near               
  246.          mov   al, vidmode        ; restore original video mode
  247.          xor   ah, ah             ;   ..
  248.          int   10h                ;   ..
  249.  
  250.          mov   ax, 0500h          ; force display page 0
  251.          int   10h                ;   ..
  252.  
  253.          mov   ax, vidfont        ; restore original font
  254.          xor   bl, bl             ; character block = 0
  255.          int   10h                ;   ..
  256.  
  257.          mov   ah, 03h            ; get cursor to reset MCGA
  258.          xor   bh, bh             ;   ..
  259.          int   10h                ;   ..
  260.  
  261.          mov   al, vidpage        ; restore original display page
  262.          mov   ah, 5              ;   ..
  263.          int   10h                ;   ..
  264.  
  265.          mov   cx, vidcurs        ; restore cursor shape
  266.          mov   ah, 01h            ;   ..
  267.          int   10h                ;   ..
  268.  
  269.          mov   ax, 1001h          ; fcn 10, subfcn 01: set border color
  270.          mov   bh, border         ;   ..
  271.          int   10h                ;   ..
  272.  
  273.          mov   ax, 0600h          ; fcn 06: scroll up, al=0: clear window
  274.          mov   bh, charattr       ; attribute to fill window with
  275.          xor   cx, cx             ; ch/cl = top/left
  276.          mov   dx, 40h            ; address BIOS data area at 40:
  277.          mov   es, dx             ;   ..
  278.          mov   dx, es:4Ah         ; set DL = right column
  279.          dec   dx                 ;   ..
  280.          mov   dh, es:84h         ; set DH = bottom row
  281.          int   10h                ; go clear the whole screen
  282.          ret                      ; return to local caller
  283. vidrest  endp
  284.  
  285. ;    Data:
  286.  
  287. execpath dw    0                  ; offset to name of program to execute
  288. execparm dw    0                  ; seg # of environment (also part of ptr)
  289.          dw    80h                ; segment:offset of command tail
  290. seg1     dw    ?                  ;   ..
  291.          dw    5Ch                ; segment:offset of 1st FCB
  292. seg2     dw    ?                  ;   ..
  293.          dw    6Ch                ; segment:offset of 2d FCB
  294. seg3     dw    ?                  ;   ..
  295.  
  296. vidfont  dw    ?                  ; INT 10 fcn to restore font
  297. vidpage  db    ?                  ; video page number
  298. vidmode  db    ?                  ; video mode
  299. vidcurs  dw    ?                  ; original cursor shape
  300. border   db    ?                  ; border color
  301. charattr db    ?                  ; character attribute to restore
  302.  
  303. org10    dd    0                  ; original INT 10 vector
  304. org21    dd    0                  ; original INT 21 vector
  305.  
  306.  
  307.          db    128 dup (0)        ; presumably enough stack . . .
  308. topsp    label byte
  309. old_dos_msg db 'This program requires DOS 3.3 or greater',0dh,0ah,'$'
  310. vidsave  ends
  311.          end   begin
  312.