home *** CD-ROM | disk | FTP | other *** search
/ Simtel MSDOS - Coast to Coast / simteldosarchivecoasttocoast.iso / pcmag / vol9n21.zip / DGCRT.PAS < prev    next >
Pascal/Delphi Source File  |  1990-09-25  |  28KB  |  918 lines

  1. {
  2.  ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄
  3.  █                                                                         █
  4.  █        TITLE :      DGCRT.TPU                                           █
  5.  █      PURPOSE :      Useful screen handling routines.                    █
  6.  █       AUTHOR :      David Gerrold, CompuServe ID:  70307,544            █
  7.  █  _____________________________________________________________________  █
  8.  █                                                                         █
  9.  █   Written in Turbo Pascal, Version 5.5,                                 █
  10.  █   with routines from TurboPower, Object Professional.                   █
  11.  █                                                                         █
  12.  █   Turbo Pascal is a product of Borland International.                   █
  13.  █   Object Professional is a product of TurboPower Software.              █
  14.  █  _____________________________________________________________________  █
  15.  █                                                                         █
  16.  █   This is not public domain software.                                   █
  17.  █   This software is copyright 1990, by David Gerrold.                    █
  18.  █   Permission is hereby granted for personal use.                        █
  19.  █                                                                         █
  20.  █        The Brass Cannon Corporation                                     █
  21.  █        9420 Reseda Blvd., #804                                          █
  22.  █        Northridge, CA  91324-2932.                                      █
  23.  █                                                                         █
  24.  ▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀
  25.                                                                             }
  26. { Compiler Directives ===================================================== }
  27.  
  28. {$A-}    {Switch word alignment off, necessary for cloning}
  29. {$R-}    {Range checking off}
  30. {$B-}    {Boolean complete evaluation off}
  31. {$S-}    {Stack checking off}
  32. {$I-}    {I/O checking off}
  33. {$N+,E+} {Simulate numeric coprocessor}
  34. {$M 16384,0,327680} {stack and heap}
  35. {$V-}    {Variable range checking off}
  36.  
  37. { Name ==================================================================== }
  38.  
  39. UNIT DgCrt;
  40. {
  41.   Screen-handling routines.
  42. }
  43.  
  44. { ========================================================================= }
  45. { Interface =============================================================== }
  46.  
  47. INTERFACE
  48.  
  49. USES
  50. { Turbo Pascal Units}
  51.   Dos,
  52.  
  53. { Object Professional Units }
  54.   OpCrt,
  55.   OpWindow,
  56.   OpMouse,
  57.  
  58. { DG Units }
  59.   DgDec,
  60.   DgBit;
  61.  
  62. { ========================================================================= }
  63. { Declarations ============================================================ }
  64.  
  65. TYPE
  66.   EgaRegArray = array [0..16] of byte;
  67.   { byte 16 is the overscan (border) area }
  68.  
  69.   VgaRegArray = array [0..16, 1..3] of byte;
  70.   { Vga register values for assignment to standard colors. }
  71.  
  72. CONST
  73.   StandardColors  : EgaRegArray =
  74.     (0, 1, 2, 3, 4, 5, 20, 7, 56, 57, 58, 59, 60, 61, 62, 63, 0);
  75.   FadeToBlackFlag : boolean = false;
  76.   FadeRate        : byte = 12;                   { steps to dissolve }
  77.  
  78. VAR
  79.   StoreEgaPal  : EgaRegArray;                    { Ega palette }
  80.   StoreVgaPal  : VgaRegArray;                    { Vga palette }
  81.   StoreKeyStateByte : byte;                      { store shift key status }
  82.   StoreScreenHeight : byte;                      { how many rows? }
  83.   StoreScreenWidth  : byte;                      { how many cols? }
  84.  
  85.   EgaPal       : EgaRegArray;                    { working palette }
  86.   VgaPal       : VgaRegArray;                    { working palette }
  87.  
  88.   DissolveProc     : procedure;                  { for dissolve process }
  89.   FinalFadeOutProc : procedure;                  { for final fade out }
  90.  
  91. { Procs and Funcs ========================================================= }
  92.  
  93. FUNCTION Attribute (FG, BG : Byte) : Byte;
  94.  
  95. PROCEDURE DisableUV;
  96. { Disables UltraVision. }
  97.  
  98. PROCEDURE DispPackedWindow (PackedWindow : Pointer);
  99. { Display a packed window. }
  100.  
  101. PROCEDURE Dissolve (Hither, Yon : VgaRegArray);
  102. { Dissolves registers from one palette to another }
  103.  
  104. FUNCTION EgaVal (Red, Green, Blue : byte) : byte;
  105. { Returns single byte containing red, green, and blue color values. }
  106.  
  107. PROCEDURE EnableUV (Mode : byte);
  108. { Enables UltraVision. }
  109.  
  110. PROCEDURE FadeIn (FadeInProc : Proc;  Mode : byte);
  111. { Fades in to screen painted by FadeInProc. }
  112.  
  113. PROCEDURE FadeOut;
  114. { Fades out to black }
  115.  
  116. PROCEDURE FadeStart (FadeInProc : Proc;  Mode : byte);
  117. { Fades out DOS to black, fades in program. }
  118.  
  119. (*
  120. FUNCTION GetMode : byte;
  121. { Returns EGA display mode.  If UltraVision installed, returns UV mode. }
  122. *)
  123. PROCEDURE GetEgaPalette (VAR P : EgaRegArray);
  124. { Gets current EGA palette, returns it in P. }
  125.  
  126. FUNCTION GetEgaRegister (ColorNum : byte) : byte;
  127. { Returns Ega register of ColorNum (0..15).  Returns 0..64. }
  128.  
  129. FUNCTION GetUvMode : byte;
  130. { Gets UltraVision mode. }
  131.  
  132. PROCEDURE GetVgaPalette (VAR P : VgaRegArray);
  133. { Gets current VGA palette, stores it in P. }
  134.  
  135. PROCEDURE GetVgaRegister (ColorReg : byte;  VAR Red, Green, Blue : byte);
  136. { Gets R, G, and B values of Color Register Number (0-64). }
  137.  
  138. PROCEDURE ReadAtCursor (VAR Ch : char;  VAR Attr : byte);
  139. { Reads char and attr at cursor loc }
  140.  
  141. PROCEDURE SaveDosScreen;
  142. {
  143.   Sets ExitProc to automatically restore DOS screen on exit.
  144.   MUST be first statement in program.
  145. }
  146.  
  147. PROCEDURE SetMode (Mode : byte);
  148. { Sets EGA mode.  If UltraVision installed, sets UV mode. }
  149.  
  150. PROCEDURE SetEgaPalette (VAR P : EgaRegArray);
  151. { Load a palette into Ega registers (0-64). }
  152.  
  153. PROCEDURE SetEgaRegister (ColorNum, EgaReg : byte);
  154. { Resets ColorNum (0-15) with number of EGA register.  64-color palette. }
  155.  
  156. PROCEDURE SetUvMode (Mode : byte);
  157. { Sets UltraVision mode. }
  158.  
  159. PROCEDURE SetVgaPalette (P : VgaRegArray);
  160. { Loads a VGA palette into whatever EGA registers are active. }
  161.  
  162. PROCEDURE SetVgaRegister (ColorReg, Red, Green, Blue : byte);
  163. { Resets Color Register Number (0-64) with R, G, B values 0-63. }
  164.  
  165. FUNCTION UVactive : boolean;
  166. { Is UltraVision on? }
  167.  
  168. FUNCTION UVinstalled : boolean;
  169. { Is UltraVision present? }
  170.  
  171. { ========================================================================= }
  172. { Implementation ========================================================== }
  173.  
  174. IMPLEMENTATION
  175.  
  176. { ========================================================================= }
  177.  
  178. CONST
  179.   StoreDosScreen  : pointer = nil;               { saved DOS screen }
  180.  
  181. VAR
  182.   StoreCheckBreak : boolean;                     { DOS BREAK status }
  183.   StoreCursorLoc  : word;                        { DOS cursor loc }
  184.   StoreCursorSize : word;                        { DOS cursor size }
  185.   StoreDosMode    : byte;                        { DOS mode at start }
  186.   StoreUvMode     : byte;                        { Ultra Vision mode }
  187.   StoreDosPalette : EgaRegArray;                 { store system palette }
  188.  
  189.   BlinkByte  : byte absolute $40:$65;            { system blink is bit 5 }
  190.   BlinkFlag  : boolean;                          { system blink on or off? }
  191.   ScreenFlag : boolean;                          { restore DOS screen? }
  192.   FadeFlag   : boolean;                          { fade in DOS screen? }
  193.  
  194. { ========================================================================= }
  195. { Attribute =============================================================== }
  196.  
  197. FUNCTION Attribute (FG, BG : Byte) : Byte;
  198. { Translates Foreground and Background colors into a video attribute. }
  199.  
  200. BEGIN
  201. Attribute := (FG + BG Shl 4) And $7F;
  202.  
  203. { "And $7F" turns off the high bit, which triggers blinking.  Blinking
  204. can be turned on by adding 128 to the result of this function. }
  205. END;
  206.  
  207. { DisableUV =============================================================== }
  208.  
  209. PROCEDURE DisableUV;
  210. { Disables UltraVision. }
  211.  
  212. VAR
  213.   R : registers;
  214.  
  215. BEGIN
  216.   if not UVinstalled then exit;
  217.   with R do begin
  218.     AH := $CC;
  219.     AL := $01;
  220.     end;
  221.   Intr ($10, R);                                 { turns off UV }
  222.   with R do begin
  223.     AH := $0;
  224.     AL := $03;                                   { set color text mode }
  225.     end;
  226.   Intr ($10, R);
  227. END;
  228.  
  229. { DispPackedWindow ======================================================== }
  230.  
  231. PROCEDURE DispPackedWindow (PackedWindow : Pointer);
  232. VAR
  233.   P : PackedWindowPtr;
  234.  
  235. BEGIN
  236.   New (P, InitFromMemory (PackedWindow));
  237.   P^.Display;
  238.   Dispose (P, Done);
  239. END;
  240.  
  241. { Dissolve ================================================================ }
  242.  
  243. PROCEDURE Dissolve (Hither, Yon : VgaRegArray);
  244. { Dissolves registers from one palette to another }
  245. VAR
  246.   EgaPal    : EgaRegArray;
  247.   Transfer,
  248.   Factor    : array [0..16, 1..3] of real;
  249.   Loop,
  250.   Color,
  251.   Number    : byte;
  252.  
  253. BEGIN
  254.   if CurrentDisplay < Vga then exit;
  255.   GetEgaPalette (EgaPal);
  256.  
  257.   if FadeRate = 0 then begin
  258.     SetVgaPalette (Yon);
  259.     DissolveProc;
  260.     exit;
  261.     end;
  262.  
  263. {
  264.   If FadeRate > 0 then do a real dissolve.
  265. }
  266.   for Loop := 0 to 15 do
  267.     for color := 1 to 3 do begin
  268.       Transfer [Loop, Color] := Hither [Loop, Color];
  269.       Factor [Loop, Color] :=
  270.         (Yon [Loop, Color] - Hither [Loop, Color])/FadeRate;
  271.       end;
  272.   for Loop := 0 to pred (FadeRate) do begin
  273.     for Number := 0 to 15 do begin
  274.       for Color := 1 to 3 do
  275.         Transfer [Number, Color] :=
  276.           Transfer [Number, Color] + Factor [Number, Color];
  277.       SetVgaRegister (EgaPal [Number],
  278.                       round (Transfer [Number, 1]),
  279.                       round (Transfer [Number, 2]),
  280.                       round (Transfer [Number, 3]));
  281.       end;
  282.     DissolveProc;
  283.     end;
  284. END;
  285.  
  286. { EgaVal ================================================================ }
  287.  
  288. FUNCTION EgaVal (Red, Green, Blue : byte) : byte;
  289. {
  290.   Returns single byte containing red, green, and blue color values.
  291.   Red, Green, and Blue must be in range [0..3].
  292. }
  293.  
  294. CONST
  295.   R : array [0..3] of byte = (0, 32, 4, 36);
  296.   G : array [0..3] of byte = (0, 16, 2, 18);
  297.   B : array [0..3] of byte = (0,  8, 1,  9);
  298. {
  299.   Colors are stored as six bit numbers:
  300.  
  301.     rgbRGB
  302.     001001  =  both blue bits on  =  9.
  303.     010010  =  both green bits on = 18.
  304.     100100  =  both red bits on   = 36.
  305.  
  306.   Bits 5, 4, and 3 are secondary red, green, and blue.
  307.   Bits 2, 1, and 0 are primary red, green, and blue.
  308.  
  309.   Primary  blue = 1, secondary  blue =  8;  if both are on, value is 9.
  310.   Primary green = 2, secondary green = 16;  if both are on, value is 18.
  311.   Primary   red = 4, secondary   red = 32;  if both are on, value is 36.
  312. }
  313.  
  314. BEGIN
  315.   EgaVal := R [Red] + G [Green] + B [Blue];
  316. END;
  317.  
  318. { EnableUV ================================================================ }
  319.  
  320. PROCEDURE EnableUV (Mode : byte);
  321. { Enables UltraVision. }
  322.  
  323. VAR
  324.   R : registers;
  325. BEGIN
  326.   if not UVinstalled then exit;
  327.   with R do begin
  328.     AH := $CC;
  329.     AL := $02;
  330.     end;
  331.   Intr ($10, R);                                 { turns on UV }
  332.   with R do begin
  333.     AH := $0;
  334.     AL := Mode;
  335.     end;
  336.   Intr ($10, R);                                 { restore video mode }
  337. END;
  338.  
  339. { FadeIn ================================================================== }
  340.  
  341. PROCEDURE FadeIn (FadeInProc : Proc;  Mode : byte);
  342. { Fades in to screen painted by FadeInProc. }
  343.  
  344. VAR
  345.   BlackPal  : VgaRegArray;
  346.   ColorReg  : array [1 .. 3] of byte;
  347.   Loop,
  348.   InnerLoop : byte;
  349. BEGIN
  350.   if CurrentDisplay < Vga then exit;
  351.   SetMode (Mode);
  352.   HiddenCursor;
  353.   ClrScr;
  354.   if FadeToBlackFlag then
  355.     for InnerLoop := 1 to 3 do
  356.       ColorReg [InnerLoop] := 0
  357.   else
  358.     GetVgaRegister (0, ColorReg [1], ColorReg [2], ColorReg [3]);
  359.   For Loop := 0 to 15 do
  360.     For InnerLoop := 1 to 3 do
  361.       BlackPal [Loop, InnerLoop] := ColorReg [InnerLoop];
  362.   SetVgaPalette (BlackPal);
  363.   FadeInProc;                                    { set up fade in screen }
  364.   Dissolve (BlackPal, VgaPal);
  365. END;
  366.  
  367. { FadeOut ================================================================= }
  368.  
  369. PROCEDURE FadeOut;
  370. { Fades out to black }
  371. VAR
  372.   BlackPal,
  373.   VgaPal    : VgaRegArray;
  374.   ColorReg  : array [1 .. 3] of byte;
  375.   Loop,
  376.   InnerLoop : byte;
  377. BEGIN
  378.   if CurrentDisplay < Vga then exit;
  379.   GetVgaPalette (VgaPal);
  380.   if FadeToBlackFlag then
  381.     for InnerLoop := 1 to 3 do
  382.       ColorReg [InnerLoop] := 0
  383.   else
  384.     for InnerLoop := 1 to 3 do
  385.       ColorReg [InnerLoop] := VgaPal [0, InnerLoop];
  386.   For Loop := 0 to 15 do
  387.     For InnerLoop := 1 to 3 do
  388.       BlackPal [Loop, InnerLoop] := ColorReg [InnerLoop];
  389.   Dissolve (VgaPal, BlackPal);
  390. END;
  391.  
  392. { FadeStart =============================================================== }
  393.  
  394. PROCEDURE FadeStart (FadeInProc : Proc;  Mode : byte);
  395. { Fades out DOS to black, fades in program. }
  396.  
  397. BEGIN
  398.   FadeOut;
  399.   SaveDosScreen;
  400. {
  401.   If fading in to a different palette, set Vpal to new palette
  402.   in FadeInProc.
  403. }
  404.   FadeIn (FadeInProc, Mode);
  405.   FadeFlag := true;
  406. END;
  407.  
  408. { GetEgaPalette =========================================================== }
  409.  
  410. PROCEDURE GetEgaPalette (VAR P : EgaRegArray);
  411. { Gets current EGA palette, returns it in P. }
  412.  
  413. VAR
  414.   R    : registers;
  415.   Loop : byte;
  416.  
  417. BEGIN
  418.   if CurrentDisplay < Ega then exit;
  419.   for Loop := 0 to 15 do
  420.     P [Loop] := GetEgaRegister (Loop);
  421. END;
  422.  
  423. { GetEgaRegister ========================================================== }
  424.  
  425. FUNCTION GetEgaRegister (ColorNum : byte) : byte;
  426. { Returns Ega register of ColorNum (0..15).  Returns 0..64. }
  427.  
  428. VAR
  429.   R : registers;
  430.  
  431. BEGIN
  432.   with R do begin
  433.     AH := $10;
  434.     AL := $7;
  435.     BL := ColorNum;
  436.     intr ($10, R);
  437.     GetEgaRegister := BH;
  438.     end;
  439. END;
  440.  
  441. { GetUvMode =============================================================== }
  442.  
  443. FUNCTION GetUvMode : byte;
  444. { Gets UltraVision mode. }
  445.  
  446. VAR
  447.   R : registers;
  448. BEGIN
  449.   if not UVactive then
  450.     GetUvMode := 255
  451.   else
  452.     with R do begin
  453.       AH := $CD;
  454.       AL := $04;
  455.       Intr ($10, R);
  456.       GetUvMode := AL;
  457.       end;
  458. END;
  459.  
  460. { GetVgaPalette =========================================================== }
  461.  
  462. PROCEDURE GetVgaPalette (VAR P : VgaRegArray);
  463. {
  464.   Gets current VGA palette, stores it in P.
  465.  
  466.   This procedure does not get the Vga registers stored in 0-15.
  467.   It gets the Vga registers pointed to by EgaPal [0..15] which
  468.   can be any value in the range 0..64.
  469. }
  470.  
  471. VAR
  472.   Loop   : byte;
  473.   EgaPal : EgaRegArray;
  474.  
  475. BEGIN
  476.   if CurrentDisplay < Vga then exit;
  477.   GetEgaPalette (EgaPal);
  478.   for Loop := 0 to 15 do
  479.     GetVgaRegister (EgaPal [Loop],
  480.                     P [Loop, 1],
  481.                     P [Loop, 2],
  482.                     P [Loop, 3]);
  483. END;
  484.  
  485. { GetVgaRegister ========================================================== }
  486.  
  487. PROCEDURE GetVgaRegister (ColorReg : byte;  VAR Red, Green, Blue : byte);
  488. {
  489.   Gets R, G, and B values of Color Register Number (0-64).
  490.   Values will be in range of 0-63.
  491. }
  492.  
  493. VAR
  494.   R : registers;
  495.  
  496. BEGIN
  497.   with R do begin
  498.     AX := $1015;
  499.     BX := ColorReg;
  500.     Intr ($10, R);
  501.     Red := DH;
  502.     Green := CH;
  503.     Blue := CL;
  504.     end;
  505. END;
  506.  
  507. { ReadAtCursor ============================================================ }
  508.  
  509. PROCEDURE ReadAtCursor (VAR Ch : char;  VAR Attr : byte);
  510. { Reads char and attr at cursor loc }
  511.  
  512. VAR
  513.   R : registers;
  514.  
  515. BEGIN
  516.   with R do begin
  517.     AH := $08;
  518.     BH := $00;
  519.     end;
  520.   Intr ($10, R);
  521.   Ch := chr (R.AL);
  522.   Attr := R.AH;
  523. END;
  524.  
  525. { RestoreDosScreen ======================================================== }
  526.  
  527. {$F+}  PROCEDURE RestoreDosScreen; {$F-}
  528. BEGIN
  529.   SetMode (StoreDosMode);
  530.   SetUvMode (StoreUvMode);
  531.   HiddenCursor;
  532.   RestoreWindow
  533.     (1, 1, StoreScreenWidth, StoreScreenHeight, true, StoreDosScreen);
  534. END;
  535.  
  536. { SaveDosScreen =========================================================== }
  537.  
  538. {$F+} PROCEDURE SaveDosScreen; {$F-}
  539. {
  540.   Sets ExitProc to automatically restore DOS screen on exit.
  541.   MUST be first statement in program.
  542. }
  543.  
  544. BEGIN
  545.   Case StoreDosMode of
  546.     Bw40 : begin
  547.            textmode (bw80);
  548.            StoreDosMode := CurrentMode;
  549.            end;
  550.     Co40 : begin
  551.            textmode (co80);
  552.            StoreDosMode := CurrentMode;
  553.            end;
  554.     end;  { case }
  555.  
  556.   ScreenFlag := SaveWindow (1, 1,
  557.                             StoreScreenWidth, StoreScreenHeight,
  558.                             true, StoreDosScreen);
  559.   { false means not enough heap space to store saved window }
  560.   { true will force restoring this screen on exit }
  561.  
  562.   if Font8x8Selected then                     { turn off graphics }
  563.     SelectFont8x8 (false);
  564.   if DefColorChoice = ForceMono then
  565.     SetMode (bw80)                            { force b/w 25 line mode }
  566.   else begin
  567.     SetMode (co80);
  568.     if ScreenHeight <> 25 then SetUvMode ($11);
  569.     end;
  570.  
  571.   ReinitCrt;                                     { restore OpCrt variables }
  572.   InitializeMouse;                               { restore mouse limits }
  573.   HiddenCursor;
  574. END;
  575.  
  576. { SetEgaPalette =========================================================== }
  577.  
  578. PROCEDURE SetEgaPalette (VAR P : EgaRegArray);
  579. VAR
  580.   Loop   : byte;
  581.  
  582. BEGIN
  583.   if CurrentDisplay < Ega then exit;
  584.   for Loop := 0 to 15 do
  585.     SetEgaRegister (Loop, P [Loop]);
  586. END;
  587.  
  588. { SetEgaRegister ========================================================== }
  589.  
  590. PROCEDURE SetEgaRegister (ColorNum, EgaReg : byte);
  591. { Resets ColorNum (0-15) with number of EGA register.  64-color palette. }
  592.  
  593. VAR
  594.   R : registers;
  595.  
  596. BEGIN
  597.   with R do begin
  598.     AX := $1000;
  599.     BL := ColorNum;
  600.     BH := EgaReg;
  601.     end;
  602.   intr ($10, R);
  603. END;
  604.  
  605. { SetMode ================================================================= }
  606.  
  607. PROCEDURE SetMode (Mode : byte);
  608. {
  609.   Sets EGA mode.  If UltraVision installed, sets UV mode.
  610.   UV modes are a superset of EGA modes.
  611. }
  612.  
  613. VAR
  614.   R : registers;
  615. BEGIN
  616.   if CurrentDisplay < Ega then exit;
  617.   if CurrentMode = Mode then exit;
  618.   with R do begin
  619.     AH := $00;                                   { EGA mode }
  620.     AL := Mode;
  621.     end;
  622.   Intr ($10, R);
  623.   ReinitCrt;
  624.   InitializeMouse;                               { reset mouse limits }
  625. END;
  626.  
  627. { SetUvMode =============================================================== }
  628.  
  629. PROCEDURE SetUvMode (Mode : byte);
  630. { Sets UltraVision mode. }
  631.  
  632. VAR
  633.   R : registers;
  634. BEGIN
  635.   if not UVactive then exit;
  636.   if GetUvMode = Mode then exit;
  637.   with R do begin
  638.     AH := $CD;
  639.     AL := Mode;
  640.     end;
  641.   Intr ($10, R);
  642.   ReinitCrt;
  643.   InitializeMouse;                               { reset mouse limits }
  644. END;
  645.  
  646. { SetVgaPalette =========================================================== }
  647.  
  648. PROCEDURE SetVgaPalette (P : VgaRegArray);
  649. {
  650.   Loads a VGA palette into whatever EGA registers are active.
  651.  
  652.   This procedure does not load Vga registers 0-15.
  653.   It loads the Vga registers pointed to by EgaPal [0..15] which
  654.   can be any value in the range 0..64.
  655. }
  656. VAR
  657.   Loop   : byte;
  658.   EgaPal : EgaRegArray;
  659.  
  660. BEGIN
  661.   if CurrentDisplay < Vga then exit;
  662.   GetEgaPalette (EgaPal);
  663.   for Loop := 0 to 15 do
  664.     SetVgaRegister (EgaPal [Loop],
  665.                     P [Loop, 1],
  666.                     P [Loop, 2],
  667.                     P [Loop, 3]);
  668. END;
  669.  
  670. { SetVgaRegister ========================================================== }
  671.  
  672. PROCEDURE SetVgaRegister (ColorReg, Red, Green, Blue : byte);
  673. { Resets Color Register Number (0-64) with R, G, B values 0-63. }
  674.  
  675. VAR
  676.   R : registers;
  677.  
  678. BEGIN
  679.   with R do begin
  680.     AX := $1010;
  681.     BX := ColorReg;
  682.     DH := Red;
  683.     CH := Green;
  684.     CL := Blue;
  685.     end;
  686.   Intr ($10, R);
  687. END;
  688.  
  689. { UVactive ================================================================ }
  690.  
  691. FUNCTION UVactive : boolean;
  692. { Is UltraVision on? }
  693.  
  694. VAR
  695.   R : registers;
  696. BEGIN
  697.   With R do begin
  698.     AH := $CC;
  699.     AL := $00;
  700.     end;
  701.   Intr ($10, R);
  702.   if (R.CX = $ABCD) and (R.AL = $00) then        { UV installed?  active? }
  703.     UVactive := true
  704.   else
  705.     UVactive := false;
  706. END;
  707.  
  708. { UVinstalled ============================================================= }
  709.  
  710. FUNCTION UVinstalled : boolean;
  711. { Is UltraVision present? }
  712.  
  713. VAR
  714.   R : registers;
  715. BEGIN
  716.   With R do begin
  717.     AH := $CC;
  718.     AL := $00;
  719.     end;
  720.   Intr ($10, R);
  721.   if R.CX = $ABCD then
  722.     UVinstalled := true
  723.   else
  724.     UVinstalled := false;
  725. END;
  726.  
  727. { ========================================================================= }
  728. { Exit Process Variable =================================================== }
  729.  
  730. VAR
  731.   ExitSave : pointer;                            { for ExitProc }
  732.  
  733. { ExitUnit ================================================================ }
  734.  
  735. {$F+} PROCEDURE ExitUnit; {$F-}
  736.  
  737. BEGIN
  738.   ExitProc := ExitSave;                          { reset original address }
  739.  
  740.   HiddenMouseCursor;                             { ATI VGA-wonder bug? }
  741.   HideMouse;                                     { no more mouse cursor }
  742.  
  743. {
  744.   Restore a saved screen.  ScreenFlag is true if the system screen
  745.   has been saved.
  746. }
  747.   if FadeFlag then begin
  748.     FadeOut;
  749.     DissolveProc := Zen;                       { reinstall dummy }
  750.     FinalFadeOutProc;                          { user proc }
  751.     VgaPal := StoreVgaPal;
  752.     end;
  753.  
  754.   if BlinkFlag then                              { restore system blink }
  755.     SetBlink (true)                              { to what it was before }
  756.   else
  757.     SetBlink (false);
  758.  
  759.   if ScreenFlag and (StoreDosScreen <> nil) then begin
  760.     if FadeFlag then
  761.       FadeIn (RestoreDosScreen, StoreDosMode)
  762.     else
  763.       RestoreDosScreen;
  764.     end
  765.   else begin
  766.     SetMode (StoreDosMode);
  767.     SetUvMode (StoreUvMode);
  768.     SetEgaPalette (StoreEgaPal);
  769.     SetVgaPalette (StoreVgaPal);
  770.     end;
  771.  
  772.   if ScreenFlag then
  773.     RestoreCursorState (StoreCursorLoc, StoreCursorSize)   { cursor on }
  774.   else
  775.     SetCursorSize (hi (StoreCursorSize), lo (StoreCursorSize));
  776.   KeyStateByte := StoreKeyStateByte;             { restore shift keys }
  777.   NormVideo;                                     { resets original TextAttr }
  778.   CheckBreak := StoreCheckBreak;                 { restore BREAK }
  779. END;
  780.  
  781. { Initialization ========================================================== }
  782.  
  783. BEGIN
  784.   ExitSave := ExitProc;                          { save old exit address }
  785.   ExitProc := @ExitUnit;                         { get new exit address }
  786.  
  787.   StoreKeyStateByte := KeyStateByte;             { save shift key states }
  788.   StoreScreenHeight := ScreenHeight;             { save number of rows }
  789.   StoreScreenWidth  := ScreenWidth;              { save number of cols }
  790.   StoreCheckBreak := CheckBreak;                 { save state of BREAK }
  791.  
  792.   CheckBreak := false;                           { no BREAK allowed }
  793.   ScreenFlag := false;                           { don't restore DOS screen }
  794.   FadeFlag   := false;                           { don't fade DOS back in }
  795.  
  796. {
  797.   If Ega or Vga is installed and running, save the existing Ega and Vga
  798.   palettes so they can be restored in the Exit unit if the program messes
  799.   around with them.
  800.  
  801.   GetEgaPalette and GetVgaPalette will test for presence of Ega/Vga.
  802. }
  803.   StoreDosMode := CurrentMode;                   { save existing mode }
  804.   StoreUvMode  := GetUvMode;                     { save existing mode }
  805.   GetEgaPalette (StoreEgaPal);                   { save Ega palette }
  806.   GetVgaPalette (StoreVgaPal);                   { save Vga palette }
  807.   EgaPal := StoreEgaPal;                         { working palette }
  808.   VgaPal := StoreVgaPal;                         { working palette }
  809.  
  810. { Check for mono, get existing DOS mode ----------------------------------- }
  811. {
  812.   If the current display is not capable of color or the user has set
  813.   his display to mono mode, we need to force mono attributes.
  814. }
  815.   Case CurrentDisplay of
  816.     MonoHerc : DefColorChoice := ForceMono;      { force b/w? }
  817.     end;  {case}
  818.  
  819. {
  820.   If system is running in mono, force mono.  The user has his own
  821.   reasons for running in mono mode.
  822. }
  823.   Case StoreDosMode of
  824.     bw40,
  825.     bw80,
  826.     Mono : DefColorChoice := ForceMono;
  827.     end;  {case}
  828.  
  829.   if DefColorChoice = ForceMono then
  830.     FadeToBlackFlag := true;
  831.  
  832.   TextAttr := ColorMono (Yellow, LightGray);     { set new attributes }
  833.  
  834. { Initialize the cursor  -------------------------------------------------- }
  835.  
  836.   GetCursorState
  837.     (StoreCursorLoc, StoreCursorSize);           { save cursor loc, size }
  838.   dec (StoreCursorLoc, 256);                     { adjust cursor row up 1 }
  839.  
  840. {
  841.   There are some very obscure situations in which DOS will hide the
  842.   cursor.  This happens when the scan lines are set for 32 and 0, or
  843.   13 and 14.  This code will detect that situation and will restore
  844.   the cursor to a normal size for the DOS text mode.  It may be
  845.   incompatible with TSR routines that turn the cursor off and fake
  846.   a non-blinking cursor.  I haven't tested it.  Feedback would be
  847.   appreciated.
  848. }
  849.   case StoreCursorSize of                        { disappearing cursor }
  850.     8192,                                        { lines 0, 32 }
  851.     3342  : StoreCursorSize := 1543;             { lines 13, 14 }
  852.     end;
  853.  
  854.   HiddenCursor;
  855.  
  856. { Check for blinking ------------------------------------------------------ }
  857.  
  858.   BlinkFlag := BlinkByte and $20 = $20;          { system blink on? }
  859.  
  860. { Misc -------------------------------------------------------------------- }
  861.  
  862.   DissolveProc     := Zen;                       { install dummy proc }
  863.   FinalFadeOutProc := Zen;                       { install dummy proc }
  864.   Randomize;
  865. END.
  866.  
  867. { ========================================================================= }
  868. { ========================================================================= }
  869.  
  870. VERSION HISTORY:
  871.   9005.05
  872.     Completely restructured for consistency with Object Professional.
  873.  
  874.   9006.01
  875.     Added routine to check system blink status and restore it.
  876.  
  877.   9006.20
  878.     Added Dissolve, FadeIn, FadeOut procedures.  VGA only.
  879.  
  880. { ========================================================================= }
  881.  
  882. ACKNOWLEDGMENTS:
  883.  
  884.   9006.01
  885.     UltraVision is a product of Personics Corporation.
  886.     63 Great Road, Maynard, MA  01754.
  887.     Copyright 1987-1990 by M+H Consulting and John Jurewicz.
  888.  
  889.     UltraVision compatible routines are derived from the Ultra Vision
  890.     manual, Appendix C:  Bios Interface.
  891.  
  892.   9006.01
  893.     GetVgaRegister and SetVgaRegister routines are both from code
  894.     supplied by Michael Covington, contributing editor of PC Techniques
  895.     magazine.  Additional help by Tom Gryder and Steve Sneed.
  896.  
  897.   9006.22
  898.     FadeIn, FadeOut, and FadeStart procedures added.
  899.  
  900.     When using graphics mode, always begin with FadeStart or
  901.     SaveDosScreen, as this will restore the DOS screen on exit.  If
  902.     you do not want to restore the DOS screen on exit, precede the
  903.     call to SaveDosScreen with ClrScr.
  904.  
  905.     The idea behind these procedures is to automate the process
  906.     of restoring DOS to its previous state when exiting the program.
  907.  
  908. { ========================================================================= }
  909.  
  910. NEED TO FIX:
  911.   When in 50-line mode, even if not changing mode, there's a flicker as
  912.   the mode is reset.  Why?
  913.  
  914.  
  915. { ========================================================================= }
  916. { ========================================================================= }
  917.  
  918.