home *** CD-ROM | disk | FTP | other *** search
/ Stars of Shareware: Programmierung / SOURCE.mdf / programm / msdos / pascal / video / video.pas < prev   
Encoding:
Pascal/Delphi Source File  |  1994-03-09  |  32.1 KB  |  835 lines

  1. {*********************************************************}
  2. {*                   VIDEO.PAS 1.00                      *}
  3. {*        Copyright (c) T P Systems, Inc. 1994.          *}
  4. {*                  All rights reserved.                 *}
  5. {*********************************************************}
  6.  
  7. (*
  8.     Implements a VideoManager object for handling EGA, VGA and SVGA modes.
  9.  
  10.     CAUTION: This is an experimental unit and still has some problems.
  11.     VideoManager has a problem in restoring SVGA modes. I don't know
  12.     whether this is a bug in my code or a problem with the VESA
  13.     implementations I have tested. Any help in sorting this out would be
  14.     appreciated.
  15.  
  16.     There are no screen writing methods which makes the use of graphics
  17.     modes problematical at this point.
  18.  
  19.     There are no palette handling methods so attributes in graphics modes
  20.     may not turn out to be what you intended.
  21.  
  22.     Remember there is no cursor in graphics modes and you have to specifically
  23.     emulate one if a cursor is important.  There seems to be a problem in
  24.     cursor positioning when in SVGA modes.
  25.  
  26. *)
  27.  
  28. {$A-,B-,E+,F+,I-,N-,O+,R-,S-,V-,X+}
  29.  
  30. Unit Video;
  31.  
  32. interface
  33.  
  34. uses
  35.   OpConst,
  36.   OpString,
  37.   OpInline,
  38.   OpCrt,
  39.   OpRoot,
  40.   Dos,
  41.   TsVga,
  42.   TsSvga;
  43.  
  44. type
  45.  
  46.   SetModeFunc       = function(Mode: word; Clear: boolean): word;
  47.   ReturnModeFunc    = function(var Mode: word): word;
  48.   ReturnBufSizeFunc = function(var Size: word; States: word): word;
  49.   SaveStateFunc     = function(Buf: pointer; States: word): word;
  50.   RestoreStateFunc  = function(Buf: pointer; States: word): word;
  51.  
  52. const
  53.   {VideoManager Option Flags -- first 4 options are not supported on EGA}
  54.   vmClearDisplay        = $0001; {if set video display memory cleared on}
  55.                                  {mode set - always cleared on EGA}
  56.   vmPreservePalette     = $0002; {if set palette is preserved on mode set}
  57.   vmSaveStateOnInit     = $0004; {if set saves initial state if possible}
  58.   vmRestoreStateOnDone  = $0008; {if set restores initial state if possible}
  59.   vmEnableHiBackground  = $0010; {if set turns blink bit off}
  60.   vmDisregardVesa       = $0020; {if set forces manager to treat display
  61.                                   as standard Vga even if Vesa installed}
  62.  
  63.   {the following option should not be set by user}
  64.   vmIsVesa              = $8000; {if set VESA is installed}
  65.  
  66. {***************************************************************
  67.  
  68.   VideoManager -- a descendant of Root to manage mode and font changes
  69.   for EGA, VGA and SVGA adapters.  It is intended primarily for applications
  70.   that need to present text in either text modes or graphics modes.
  71.   Checks for and uses VESA standard if installed. All font files must have the
  72.   name D:\Dir\8xNSuffix.Ext. The user may specify all elements except for the
  73.   8xN term where N is the height of the font. A single font directory, suffix
  74.   and extension may be specified. The object is primarily designed to handle
  75.   setting video modes for character based applications (text or graphics
  76.   modes), saving and restoring the video states on VGA and SVGA adapters to
  77.   take maximum advantage of the VGA standards. The saving and restoring
  78.   facilites are not supported on EGA. The general design philosophy is to use
  79.   the highest level routine available for the purpose at hand. This is to
  80.   insure no problems with unusual environments.
  81.  
  82.   Example of usage:
  83.  
  84.   var VM : VideoManager;
  85.  
  86.   if (CurrentDisplay = EGA) or (CurrentDisplay = VGA) then begin
  87.     if not VM.Init(vmClearDisplay, '', '', '', ssAllSvga) then begin
  88.       WriteLn('VideoManager initialization failed with error ',InitStatus
  89.       Exit;
  90.     end;
  91.     with VM do begin
  92.       if not SetScreenResolution(40, 100, 0, true, false) then
  93.         WriteLn('SetScreenResolution failed with error', GetStatus);
  94.     end;
  95.   end else begin
  96.     ...handle other cases...
  97.   end;
  98.   VM.Done;
  99.  
  100.   Enhancements: 1) a descendant that provided screen writing methods
  101.                    independent of mode (text or graphics) which could
  102.                    somehow be integrated with Opro's FastWrite routines
  103.                    (replacing them as necessary) would be very useful.
  104.                 2) think about incorporating Borland's BGI drivers for the
  105.                    graphics text writing.
  106.                 3) Support for EGA is weak for several reasons: not really
  107.                    interested, adpater has fewer capabilities, and don't
  108.                    have a model for testing.
  109.                 4) Palette handling methods should be added.
  110.                 5) Take advantage of additional 256 font characters for
  111.                    a total of 512 characters for special effects.
  112.  
  113. ***************************************************************}
  114.  
  115. type
  116.   VideoManagerPtr = ^VideoManager;
  117.   VideoManager = object(Root)
  118.     vmOptions          : word;
  119.     vmLastError        : word;
  120.     vmCurScrMode       : ScreenModeRec;
  121.     vmFontDir          : DirStr;  {dir for font files - defaults to same as program}
  122.     vmFontSuffix       : NameStr; {suffix to be appended to '8xN' - defaults to blank}
  123.     vmFontExt          : ExtStr;  {extension of font files including '.'- defaults to blank}
  124.     vmVgaState         : VgaStatePtr;
  125.     vmVgaInfo          : VgaInfoBlockPtr; {only valid during Init}
  126.     vmModeTable        : ModeNumTablePtr;
  127.     vmVgaModeInfo      : ModeInfoBlockPtr;
  128.     vmStates           : word;
  129.     vmUserModes        : ScreenModeArPtr;
  130.     vmSaveBuffer       : pointer;
  131.     vmSaveBufLen       : word;
  132.     vmFontBuffer       : pointer;
  133.     vmFontBufLen       : word;
  134.  
  135.     vmSetModeFunc      : SetModeFunc;
  136.     vmReturnModeFunc   : ReturnModeFunc;
  137.     vmReturnBufSizeFunc: ReturnBufSizeFunc;
  138.     vmSaveStateFunc    : SaveStateFunc;
  139.     vmRestoreStateFunc : RestoreStateFunc;
  140.     vmWinProc          : SvgaWinProc;
  141.  
  142.  
  143.     constructor Init(Options: word; FontDir: DirStr; FontSuffix: NameStr;
  144.                      FontExt: ExtStr; States: word; UserModes: ScreenModeArPtr);
  145.       {-Initializes VideoManager.  Options are selected from the VideoManager
  146.         options above.  FontDir, FontSuffix, and FontExt may be specified or
  147.         blank.  If FontDir is blank, font files are expected to be in same
  148.         directory as one from which program was loaded.  States is a bit
  149.         mapped value using Save State masks in VGA unit.  If ssSvgaAll is
  150.         specified and VESA is not supported, it is adjusted accordingly.
  151.         VESA is checked for and the appropriate functions are assigned the
  152.         various methods.  If a VGA or above is found, the appropriate info
  153.         block or state table are filled in. vmCurScrMode is updated.
  154.         If vmSaveStateOnInit in Options
  155.         is set, the states specified in States are saved on all but EGA.}
  156.  
  157.     destructor Done; virtual;
  158.       {-If vmSaveStateOnInit and vmRestoreStateOnDone are set in Options,
  159.         the initial state is restored.  All allocated data structures are
  160.         deallocated.}
  161.  
  162.     function SetScreenResolution(Rows, Cols: byte; Mode: word;
  163.                                  UserFont, TextOnly: boolean): boolean;
  164.       {-This is primary method for users and does most of the work for
  165.         which the object was created.  If SvgaMode is 0, the appropriate
  166.         ScreenModeArrays in VGA unit (StdEgaModes, SplEgaModes, StdVgaModes
  167.         SplVgaModes) are checked to locate a mode with the specifed Rows and
  168.         Cols.  If special fonts are not available, only the standard modes
  169.         can be used.  If UserFont is true, even if the mode is a standard
  170.         mode, the appropriate special font in the font directory will be
  171.         used.  If the mode is a special mode, a special font will be used
  172.         regardless of the setting of UserFont.  This methods sets the
  173.         appropriate scan lines, video mode, and font to achieve the requested
  174.         resolution.  Before exiting ReturnCurMode is called to set all of
  175.         the relevant data structures.  If Mode is not 0, that mode is set
  176.         regardless of Rows and Cols values; however an attempt is made to
  177.         achieve the specified Rows and Cols by selecting the appropriate
  178.         font if possible.  If UserFont is true, the appropriate special font
  179.         will be loaded even though a ROM based font exists.  If TextOnly is
  180.         true, only text modes will be used. Returns true if successful. If
  181.         returns false, check GetStatus for error.}
  182.  
  183.     function GetStatus: word;
  184.       {-Returns last error and resets error variable to zero.}
  185.  
  186.     procedure OptionsOn(Options: word);
  187.  
  188.     procedure OptionsOff(Options: word);
  189.  
  190.     function OptionIsOn(Options: word): boolean;
  191.  
  192.     function FindScreenMode(var ScrMode: ScreenModeRec;
  193.                             TextOnly: boolean): boolean;
  194.       {-Searches StdXxxModes, SplXxxModes, StdSvgaModes and vmUserModes for
  195.       matching resolution and video mode if smVidMode is non-zero in the
  196.       incoming ScrMode. smRows and smCols must be non-zero to distinguish
  197.       exactly which screen mode is wanted. Returns true if one is found with
  198.       the rest of ScrMode filled in. If no matching mode is found, returns
  199.       false.  The screen mode arrays are searched in the order listed above.}
  200.  
  201.     function ReturnInfo(Mode: word): EnhDisplayType;
  202.       {-Returns type of display: eEGA, eVGA, eVESA.  If eEGA, nothing else is
  203.         returned.  If eVGA, the VgaStateTable pointed to by vmVgaState
  204.         will be filled in.  If eVESA, in addition to the VgaStateTable the
  205.         ModeInfoBlock pointed to by vmVgaModeInfo will also be filled in.
  206.         Be sure to check miModeAttrs to see if optional date in ModeInfoBlock
  207.         is present before trying to use it.
  208.         GetStatus should be checked afterward to make sure there was no
  209.         error.}
  210.  
  211.     function SetMode(Mode: word): boolean;
  212.       {-Sets specified mode.  Returns true if successful.  Status should be
  213.         checked with GetStatus if it returns false.  GetStatus will return
  214.         ecVgaFuncFailed or ecSvgaFuncFailed.
  215.         Video display memory clearing, blink setting and palette preserving
  216.         depends on setting of Options. ReturnCurMode is called at end to make
  217.         sure data structures are current.}
  218.  
  219.     function ReturnCurMode: word;
  220.       {-Returns current video mode and sets data structures.}
  221.  
  222.     function SaveState: boolean;
  223.       {-Determines size of required save buffer depending on options specified
  224.         in States argument at initialization, allocates buffer and saves
  225.         states.  Returns true if successful.  This facility is not supported
  226.         on EGA's and will return false in that case.}
  227.  
  228.     function RestoreState: boolean;
  229.       {-Restores states previously saved with SaveState.  Will fail if states
  230.         not previously saved.}
  231.  
  232.     function SetFont(FontName: string; ScrMode: ScreenModeRec): boolean; virtual;
  233.       {-Used to load a font.  If FontName is blank a standard ROM based
  234.         font of appropriate size will be loaded. Otherwise FontName must
  235.         identify a complete font file of the appropriate size
  236.         for the current video mode and scan lines.  If the font buffer is
  237.         allocated, it will be deallocated if necessary and a new one of
  238.         appropriate size will be allocated.  Returns true if successful;
  239.         otherwise check GetStatus.}
  240.  
  241.  
  242.     {*** Internal methods that should not be necessary to use externally ***}
  243.  
  244.     function ReturnSaveBufferSize: word;
  245.       {-Returns status and size of save state buffer in Size (in bytes).  Must be
  246.         called before SaveVgaState to get size of required buffer. States is
  247.         bit mapped to indicate which states are to be saved.  See bit masks above.}
  248.  
  249.   end;
  250.  
  251.  
  252. {**********************************************************}
  253.  
  254. implementation
  255.  
  256. {*** VideoManager Methods ***}
  257.  
  258. constructor VideoManager.Init(Options: word; FontDir: DirStr;
  259.                               FontSuffix: NameStr;
  260.                               FontExt: ExtStr; States: word;
  261.                               UserModes: ScreenModeArPtr);
  262.   {-Initializes VideoManager.  Options are selected from the VideoManager
  263.     options above.  FontDir, FontSuffix, and FontExt may be specified or
  264.     blank.  If FontDir is blank, font files are expected to be in same
  265.     directory as one from which program was loaded.  States is a bit
  266.     mapped value using Save State masks in VGA unit.  If ssSvgaAll is
  267.     specified and VESA is not supported, it is adjusted accordingly.
  268.     VESA is checked for and the appropriate functions are assigned the
  269.     various methods.  If a VGA or above is found, the appropriate info
  270.     block or state table is filled in. If vmSaveStateOnInit in Options
  271.     is set, the states specified in States are saved on all but EGA.}
  272. begin
  273.   if not Root.Init then
  274.     Fail;
  275.   vmOptions          := Options;
  276.   if OptionIsOn(vmRestoreStateOnDone) and
  277.     (not OptionIsOn(vmSaveStateOnInit)) then begin
  278.     InitStatus := ecBadParam;
  279.     Fail;
  280.   end;
  281.   if OptionIsOn(vmSaveStateOnInit) and (CurrentDisplay = EGA) then
  282.     OptionsOff(vmSaveStateOnInit+vmRestoreStateOnDone);
  283.   OptionsOff(vmIsVesa);
  284.   vmLastError        := 0;
  285.   FillChar(vmCurScrMode, SizeOf(ScreenModeRec), 0);
  286.   vmFontDir          := FontDir;
  287.   if vmFontDir = '' then
  288.     vmFontDir := JustPathName(FExpand(ParamStr(0)));
  289.   vmFontSuffix       := FontSuffix;
  290.   if Length(vmFontSuffix) > 4 then begin
  291.     InitStatus := ecBadParam;
  292.     Fail;
  293.   end;
  294.   vmFontExt          := FontExt;
  295.   vmStates           := States;
  296.   vmUserModes        := UserModes;
  297.   vmVgaState         := nil;
  298.   vmVgaInfo          := nil;
  299.   vmModeTable        := nil;
  300.   vmVgaModeInfo      := nil;
  301.   vmSaveBuffer       := nil;
  302.   vmSaveBufLen       := 0;
  303.   vmFontBuffer       := nil;
  304.   vmFontBufLen       := 0;
  305.  
  306.   case CurrentDisplay of
  307.     EGA : begin
  308.       vmSetModeFunc := SetVgaMode;
  309.       vmReturnModeFunc := ReturnCurVgaMode;
  310.       OptionsOff(vmSaveStateOnInit+vmRestoreStateOnDone);
  311.       OptionsOn(vmClearDisplay);
  312.     end;
  313.     VGA : begin
  314.       if not OptionIsOn(vmDisregardVesa) then begin
  315.         if not GetMemCheck(vmVgaInfo, SizeOf(VgaInfoBlock)) then begin
  316.           InitStatus := ecOutOfMemory;
  317.           Fail;
  318.         end;
  319.         vmLastError := ReturnSvgaInfo(vmVgaInfo);
  320.       end;
  321.       if OptionIsOn(vmDisregardVesa) or
  322.          (vmLastError = ecVesaNotSupported) or
  323.          (vmVgaInfo^.viSign <> VesaSignature)  then begin
  324.         vmSetModeFunc    := SetVgaMode;
  325.         vmReturnModeFunc := ReturnCurVgaMode;
  326.         vmReturnBufSizeFunc := ReturnVgaSaveBufferSize;
  327.         vmSaveStateFunc  := SaveVgaState;
  328.         vmRestoreStateFunc := RestoreVgaState;
  329.         vmStates := vmStates and not ssSvga;
  330.         FreeMemCheck(vmVgaInfo, SizeOf(VgaInfoBlock));
  331.       end else begin
  332.         OptionsOn(vmIsVesa);
  333.         vmSetModeFunc    := SetSvgaMode;
  334.         vmReturnModeFunc := ReturnCurSvgaMode;
  335.         vmReturnBufSizeFunc := ReturnSvgaSaveBufferSize;
  336.         vmSaveStateFunc  := SaveSvgaState;
  337.         vmRestoreStateFunc := RestoreSvgaState;
  338.         vmModeTable := vmVgaInfo^.viModes;
  339.         FreeMemCheck(vmVgaInfo, SizeOf(VgaInfoBlock));
  340.         if not GetMemCheck(vmVgaModeInfo, SizeOf(ModeInfoBlock)) then begin
  341.           InitStatus := ecOutOfMemory;
  342.           Done;
  343.           Fail;
  344.         end;
  345.       end;
  346.       if not GetMemCheck(vmVgaState, SizeOf(VgaStateTable)) then begin
  347.         InitStatus := ecOutOfMemory;
  348.         Done;
  349.         Fail;
  350.       end;
  351.       vmLastError := 0;
  352.       if OptionIsOn(vmSaveStateOnInit) then begin
  353.         if not SaveState then begin
  354.           InitStatus := GetStatus;
  355.           Done;
  356.           Fail;
  357.         end;
  358.       end;
  359.     end;
  360.   end;
  361.   if ReturnCurMode = $FFFF then begin
  362.     InitStatus := GetStatus;
  363.     Done;
  364.     Fail;
  365.   end;
  366.   OrigBlinkOff := CurBlinkOff;
  367.   CurBlinkOff := OptionIsOn(vmEnableHiBackground);
  368.   SetBlink(not CurBlinkOff);
  369. end;
  370.  
  371. destructor VideoManager.Done;
  372.   {-If vmSaveStateOnInit and vmRestoreStateOnDone are set in Options,
  373.     the initial state is restored.  All allocated data structures are
  374.     deallocated.}
  375. begin
  376.   if OptionIsOn(vmRestoreStateOnDone) and (vmSaveBuffer <> nil) then
  377.     RestoreState;
  378.   FreeMemCheck(vmVgaState, SizeOf(VgaStateTable));
  379.   FreeMemCheck(vmVgaInfo, SizeOf(VgaInfoBlock));
  380.   FreeMemCheck(vmVgaModeInfo, SizeOf(ModeInfoBlock));
  381.   FreeMemCheck(vmSaveBuffer, vmSaveBufLen);
  382.   FreeMemCheck(vmFontBuffer, vmFontBufLen);
  383.   Root.Done;
  384. end;
  385.  
  386. function VideoManager.SetScreenResolution(Rows, Cols: byte; Mode: word;
  387.                                           UserFont, TextOnly: boolean): boolean;
  388.   {-This is primary method for users and does most of the work for
  389.     which the object was created.  If SvgaMode is 0, the appropriate
  390.     ScreenModeArrays in VGA unit (StdEgaModes, SplEgaModes, StdVgaModes
  391.     SplVgaModes) are checked to locate a mode with the specifed Rows and
  392.     Cols.  If special fonts are not available, only the standard modes
  393.     can be used.  If UserFont is true, even if the mode is a standard
  394.     mode, the appropriate special font in the font directory will be
  395.     used.  If the mode is a special mode, a special font will be used
  396.     regardless of the setting of UserFont.  This methods sets the
  397.     appropriate scan lines, video mode, and font to achieve the requested
  398.     resolution.  Before exiting ReturnCurMode is called to set all of
  399.     the relevant data structures.  If Mode is not 0, that mode is set
  400.     regardless of Rows and Cols values; however an attempt is made to
  401.     achieve the specified Rows and Cols by selecting the appropriate
  402.     font if possible.  If UserFont is true, the appropriate special font
  403.     will be loaded even though a ROM based font exists.  If TextOnly is
  404.     true, only text modes will be used. Returns true if successful. If
  405.     returns false, check GetStatus for error.}
  406.  
  407. var
  408.   ScrMode : ScreenModeRec;
  409.   Standard : boolean;
  410.   FontName : PathStr;
  411.   SvgaInfo : ModeInfoBlock;
  412. begin
  413.   SetScreenResolution := false;
  414.   with ScrMode do begin
  415.     smRows := Rows;
  416.     smCols := Cols;
  417.     smVidMode := Mode;
  418.     if Mode = 0 then begin
  419.       if not FindScreenMode(ScrMode, TextOnly) then begin
  420.         vmLastError := ecScrResolNotSupported;
  421.         Exit;
  422.       end;
  423.     end else begin
  424.       if not FindScreenMode(ScrMode, TextOnly) then begin
  425.         if Mode > $FF then begin
  426.           if not OptionIsOn(vmIsVesa) then begin
  427.             vmLastError := ecVesaNotSupported;
  428.             Exit;
  429.           end;
  430.           if not FindSvgaMode(Mode, vmModeTable) then begin
  431.             vmLastError := ecScrResolNotSupported;
  432.             Exit;
  433.           end;
  434.           vmLastError := ReturnSvgaModeInfo(Mode, @SvgaInfo);
  435.           if vmLastError <> 0 then Exit;
  436.           with SvgaInfo do begin
  437.             if not FlagIsSet(miModeAttrs, miHardwareSupport) then begin
  438.               vmLastError := ecScrResolNotSupported;
  439.               Exit;
  440.             end;
  441.             smIsText := not FlagIsSet(miModeAttrs, miGraphicsMode);
  442.             if FlagIsSet(miModeAttrs, miOptDataAvail) then begin
  443.               smFontSize := miYFontSize;
  444.               if smIsText then begin
  445.                 smRows   := miYResolution;
  446.                 smCols   := miXResolution;
  447.               end else begin
  448.                 smRows   := Byte(miYResolution div miYFontSize);
  449.                 smCols   := Byte(miXResolution div miXFontSize);
  450.               end;
  451.               smPixH     := miYResolution;
  452.               smPixW     := miXResolution;
  453.               smColors   := 1 shl miBitsPerPixel;
  454.             end else begin
  455.               vmLastError := ecScrResolNotSupported;
  456.               Exit;
  457.             end;
  458.           end;
  459.         end else begin
  460.           vmLastError := ecScrResolNotSupported;
  461.           Exit;
  462.         end;
  463.       end;
  464.     end;
  465.     case CurrentDisplay of
  466.       EGA : Standard := smFontSize in StdEgaFonts;
  467.       VGA : begin
  468.         Standard := smFontSize in StdVgaFonts;
  469.         if smIsText then begin
  470.           vmLastError := SetScanLines(smPixH);
  471.           if vmLastError <> 0 then Exit;
  472.         end;
  473.       end;
  474.     end;
  475.     if not SetMode(smVidMode) then Exit;
  476.     if (Standard and (not UserFont)) then
  477.       FontName := ''
  478.     else begin
  479.       FontName := AddBackSlash(vmFontDir)+'8x'+Long2Str(smFontSize)+
  480.         vmFontSuffix+vmFontExt;
  481.     end;
  482.     if not SetFont(FontName, ScrMode) then Exit;
  483.     SetScreenResolution := (ReturnCurMode = smVidMode);
  484.   end;
  485. end;
  486.  
  487.   {need to think about cursor and key repeat rate}
  488. (*
  489.     if IsText then begin
  490.       {make sure we have a good text cursor}
  491.       case Rows of
  492.         25 : if CurrentDisplay = EGA then
  493.              begin CH := $0B; CL := $0C; end else {VGA}
  494.              begin CH := $0D; CL := $0E; end;
  495.         43 : begin CH := $05; CL := $07; end;
  496.         50 : begin CH := $05; CL := $07; end;
  497.         else CH := 0;
  498.       end;
  499.       if CH <> 0 then begin
  500.         AH := $01;
  501.         Intr($10, Regs);
  502.         end;
  503.     end else begin
  504.       {There is no cursor in graphics modes; however DV generates one }
  505.       {and subsequent DV windows opened have a cursor in standard modes.}
  506.     end;
  507. *)
  508.  
  509. function VideoManager.GetStatus: word;
  510.   {-Returns last error and resets error variable to zero.}
  511. begin
  512.   GetStatus := vmLastError;
  513.   vmLastError := 0;
  514. end;
  515.  
  516. procedure VideoManager.OptionsOn(Options: word);
  517. begin
  518.   vmOptions := vmOptions or Options;
  519. end;
  520.  
  521. procedure VideoManager.OptionsOff(Options: word);
  522. begin
  523.   vmOptions := vmOptions and not Options;
  524. end;
  525.  
  526. function VideoManager.OptionIsOn(Options: word): boolean;
  527. begin
  528.   OptionIsOn := FlagIsSet(vmOptions, Options);
  529. end;
  530.  
  531. function VideoManager.FindScreenMode(var ScrMode: ScreenModeRec;
  532.                                      TextOnly: boolean): boolean;
  533.   {-Searches StdXxxModes, SplXxxModes and vmUserModes for matching resolution
  534.     and video mode if smVidMode is non-zero in the incoming ScrMode. smRows
  535.     and smCols must be non-zero to distinguish exactly which screen mode is
  536.     wanted.  Returns true if one is found with the rest of ScrMode filled in.
  537.     If no matching mode is found, returns false.}
  538. var
  539.   Mode : word;
  540. begin
  541.   FindScreenMode := false;
  542.   case CurrentDisplay of
  543.     EGA : begin
  544.       if ReturnScreenMode(@StdEgaModes, ScrMode) then begin
  545.         FindScreenMode := true;
  546.         Exit;
  547.       end;
  548.       if ReturnScreenMode(@SplEgaModes, ScrMode) then begin
  549.         FindScreenMode := true;
  550.         Exit;
  551.       end;
  552.     end;
  553.     VGA : begin
  554.       Mode := ScrMode.smVidMode;
  555.       if ReturnScreenMode(@StdVgaModes, ScrMode) then begin
  556.         if ((not TextOnly) or (TextOnly and ScrMode.smIsText)) then begin
  557.           FindScreenMode := true;
  558.           Exit;
  559.         end;
  560.         ScrMode.smVidMode := Mode;
  561.       end;
  562.       if ReturnScreenMode(@SplVgaModes, ScrMode) then begin
  563.         if ((not TextOnly) or (TextOnly and ScrMode.smIsText)) then begin
  564.           FindScreenMode := true;
  565.           Exit;
  566.         end;
  567.         ScrMode.smVidMode := Mode;
  568.       end;
  569.       if OptionIsOn(vmIsVesa) and ReturnScreenMode(@StdSvgaModes, ScrMode) then begin
  570.         if ((not TextOnly) or (TextOnly and ScrMode.smIsText)) then begin
  571.           if FindSvgaMode(Mode, vmModeTable) then begin
  572.             FindScreenMode := true;
  573.             Exit;
  574.           end;
  575.         end;
  576.         ScrMode.smVidMode := Mode;
  577.       end;
  578.       if (vmUserModes <> nil) and ReturnScreenMode(vmUserModes, ScrMode) then begin
  579.         if ((not TextOnly) or (TextOnly and ScrMode.smIsText)) then begin
  580.           FindScreenMode := true;
  581.           Exit;
  582.         end;
  583.       end;
  584.     end;
  585.   end;
  586. end;
  587.  
  588. function VideoManager.ReturnInfo(Mode: word): EnhDisplayType;
  589.   {-Returns type of display: eEGA, eVGA, eVESA.  If eEGA, nothing else is
  590.     returned.  If eVGA, the VgaStateTable pointed to by vmVgaState
  591.     will be filled in.  If eVESA, in addition to the VgaStateTable the
  592.     ModeInfoBlock pointed to by vmVgaModeInfo will also be filled in.
  593.     GetStatus should be checked afterward to make sure there was no
  594.     error.}
  595. begin
  596.   ReturnInfo := eEGA;
  597.   if CurrentDisplay = EGA then Exit;
  598.   if OptionIsOn(vmIsVesa) then begin
  599.     vmLastError := ReturnSvgaModeInfo(Mode, vmVgaModeInfo);
  600.     case vmLastError of
  601.       0 : begin
  602.         vmWinProc := vmVgaModeInfo^.miWinProc;
  603.         ReturnInfo := eVESA;
  604.       end;
  605.       ecVesaNotSupported : Exit;
  606.       ecVesaFuncFailed   : ReturnInfo := eVGA;  {not a VESA SVGA mode}
  607.     end;
  608.   end else
  609.     ReturnInfo := eVGA;
  610.   vmLastError := ReturnVgaInfo(vmVgaState);
  611. end;
  612.  
  613. function VideoManager.SetMode(Mode: word): boolean;
  614.   {-Sets specified mode.  Returns true if successful.  Status should be
  615.     checked with GetStatus if it returns false.  GetStatus will return
  616.     ecVgaFuncFailed or ecSvgaFuncFailed.
  617.     Video display memory clearing and palette preserving depends on
  618.     setting of Options.}
  619. var
  620.   MI : ModeInfoBlock;
  621. begin
  622.   SetMode := false;
  623.   if (OptionIsOn(vmIsVesa) and (Mode > $FF))then begin
  624.     if not FindSvgaMode(Mode, vmModeTable) then begin
  625.       vmLastError := ecVesaModeNotSupported;
  626.       Exit;
  627.     end;
  628.     vmLastError := ReturnSvgaModeInfo(Mode, @MI);
  629.     if vmLastError <> 0 then Exit;
  630.     if not FlagIsSet(MI.miModeAttrs, miHardwareSupport) then begin
  631.       vmLastError := ecVesaModeNotSupported;
  632.       Exit;
  633.     end;
  634.   end;
  635.   if (CurrentDisplay = VGA) then begin
  636.     vmLastError := PreservePalette(OptionIsOn(vmPreservePalette));
  637.     if vmLastError <> 0 then Exit;
  638.   end;
  639.   vmLastError := vmSetModeFunc(Mode, OptionIsOn(vmClearDisplay));
  640.   if vmLastError <> 0 then Exit;
  641.   SetMode := true;
  642. end;
  643.  
  644. function VideoManager.ReturnCurMode: word;
  645.   {-Returns current video mode and updates vmCurScrMode as well as global
  646.     variables CurVideoMode, CurScreenRows and CurScreenCols. If VESA is
  647.     installed, it also updates the ModeInfoBlock pointed to by vmVgaModeInfo.
  648.     If it fails for any reason, it returns mode $FFFF and GetStatus should
  649.     be checked.}
  650. var
  651.   Mode : word;
  652.   P : pointer;
  653.   Disp : EnhDisplayType;
  654. begin
  655.   ReturnCurMode := $FFFF;
  656.   vmLastError := vmReturnModeFunc(Mode);
  657.   if vmLastError <> 0 then Exit;
  658.   with vmCurScrMode do begin
  659.     smVidMode := Mode;
  660.     Disp := ReturnInfo(Mode);
  661.     if vmLastError <> 0 then Exit;
  662.     with vmVgaState^, vmVgaModeInfo^ do begin
  663.       case Disp of
  664.         eEGA : begin
  665.           smIsText   := (Byte(Mode) in StdTextModes);
  666.           smFontSize := BiosCharH;
  667.           smRows     := BiosRows+1;
  668.           smCols     := BiosCols;
  669.           smPixW     := 0;      {do not have good way of getting this}
  670.           if smIsText then
  671.             smPixH := 350
  672.           else
  673.             smPixH := 0;
  674.           {smColors := need way of getting this}
  675.         end;
  676.         eVGA : begin
  677.           smIsText   := (vsAddr <> $A000);  {this is not exactly true}
  678.           smFontSize := vsCharHigh;
  679.           smRows     := vsRows;
  680.           smCols     := vsCols;
  681.           smPixW     := 0;  {do not have good way of getting this}
  682.           if smIsText then
  683.             smPixH := ScanLines[vsNrScanLns]
  684.           else
  685.             smPixH := 0;    {do not have good way of getting this}
  686.           smColors := vsNrColors;
  687.           CurBlinkOff := (not FlagIsSet(vsMiscInfo, vsBlink));
  688.         end;
  689.         eVESA : begin
  690.           smIsText   := (not FlagIsSet(miModeAttrs, miGraphicsMode));
  691.           if FlagIsSet(miModeAttrs, miOptDataAvail) then begin
  692.             smFontSize := miYFontSize;
  693.             if smIsText then begin
  694.               smRows     := miYResolution;
  695.               smCols     := miXResolution;
  696.             end else begin
  697.               smRows     := Byte(miYResolution div miYFontSize);
  698.               smCols     := Byte(miXResolution div miXFontSize);
  699.             end;
  700.             smPixW     := miXResolution;
  701.             smPixH     := miYResolution;
  702.             smColors   := 1 shl miBitsPerPixel;
  703.           end else begin
  704.             smFontSize := vsCharHigh;
  705.             smRows     := vsRows;
  706.             smCols     := vsCols;
  707.             smPixW     := 0;
  708.             if smIsText then
  709.               smPixH := ScanLines[vsNrScanLns]
  710.             else
  711.               smPixH := 0;
  712.             smColors := vsNrColors;
  713.           end;
  714.           CurBlinkOff := (not FlagIsSet(vsMiscInfo, vsBlink));
  715.         end;
  716.       end;
  717.     end;
  718.     CurScreenRows := smRows;
  719.     CurScreenCols := smCols;
  720.     CurVideoMode  := Mode;
  721.   end;
  722.   ReturnCurMode := Mode;
  723. end;
  724.  
  725. function VideoManager.SaveState: boolean;
  726.   {-Determines size of required save buffer depending on options specified
  727.     in States argument at initialization, allocates buffer and saves
  728.     states.  Returns true if successful.  This facility is not supported
  729.     on EGA's and will return false in that case.}
  730. var
  731.   Bytes : word;
  732. begin
  733.   SaveState := false;
  734.   if CurrentDisplay = EGA then Exit;
  735.   Bytes := ReturnSaveBufferSize;
  736.   if vmLastError <> 0 then Exit;
  737.   if not GetMemCheck(vmSaveBuffer, Bytes) then begin
  738.     vmLastError := ecOutOfMemory;
  739.     Exit;
  740.   end;
  741.   DisableVideoRefresh(true);
  742.   vmSaveBufLen := Bytes;
  743.   {saving the Svga state if you are not in one seems to cause a problem}
  744.   if vmCurScrMode.smVidMode < $100 then
  745.     ClearFlag(vmStates, ssSvga);
  746.   vmLastError := vmSaveStateFunc(vmSaveBuffer, vmStates);
  747.   if vmLastError <> 0 then Exit;
  748.   {Phoenix AT Systems BIOS reference says saving modifies video registers}
  749.   vmLastError := vmRestoreStateFunc(vmSaveBuffer, vmStates);
  750.   DisableVideoRefresh(false);
  751.   SaveState := (vmLastError = 0);
  752. end;
  753.  
  754. function VideoManager.RestoreState: boolean;
  755.   {-Restores states previously saved with SaveState.  Will fail if states
  756.     not previously saved.}
  757. var
  758.   FontName : PathStr;
  759. begin
  760.   RestoreState := false;
  761.   if CurrentDisplay = EGA then Exit;
  762.   if vmSaveBuffer = nil then begin
  763.     vmLastError := ecStateNotSaved;
  764.     Exit;
  765.   end;
  766.   DisableVideoRefresh(true);
  767.   vmLastError := vmRestoreStateFunc(vmSaveBuffer, vmStates);
  768.   FreeMemCheck(vmSaveBuffer, vmSaveBufLen);
  769.   {unfortunately the restore functions do not restore a non-standard font}
  770.   {so must do it separately}
  771.   ReturnCurMode;
  772.   with vmCurScrMode do
  773.     if smFontSize in StdVgaFonts then
  774.       FontName := ''
  775.     else
  776.       FontName := AddBackSlash(vmFontDir)+'8x'+Long2Str(smFontSize)+vmFontExt;
  777.   SetFont(FontName, vmCurScrMode);
  778.   {at least on some systems video refresh is disabled in the above steps}
  779.   DisableVideoRefresh(false);
  780.   RestoreState := (vmLastError = 0);
  781. end;
  782.  
  783. function VideoManager.SetFont(FontName: string; ScrMode: ScreenModeRec): boolean;
  784.   {-Used to load a font.  If FontName is blank a standard ROM based
  785.     font of appropriate size will be loaded. Otherwise FontName must
  786.     identify a complete font file of the appropriate size
  787.     for the current video mode and scan lines.  If the font buffer is
  788.     allocated, it will be deallocated if necessary and a new one of
  789.     appropriate size will be allocated.  Returns true if successful;
  790.     otherwise check GetStatus.}
  791. begin
  792.   SetFont := false;
  793.   with ScrMode do begin
  794.     if vmFontBuffer <> nil then begin
  795.       if (vmFontBufLen div 256) <> smFontSize then
  796.         FreeMemCheck(vmFontBuffer, vmFontBufLen);
  797.     end;
  798.     if vmFontBuffer = nil then begin
  799.       vmFontBufLen := Word(256)*smFontSize;
  800.       if not GetMemCheck(vmFontBuffer, vmFontBufLen) then begin
  801.         vmLastError := ecOutOfMemory;
  802.         Exit;
  803.       end;
  804.     end;
  805.     vmLastError := SetVgaFont(FontName, ScrMode, vmFontBuffer);
  806.     if vmLastError <> 0 then begin
  807.       FreeMemCheck(vmFontBuffer, vmFontBufLen);
  808.       Exit;
  809.     end;
  810.     if smIsText then
  811.       FreeMemCheck(vmFontBuffer, vmFontBufLen);
  812.   end;
  813.   SetFont := true;
  814. end;
  815.  
  816. {*** Internal methods that should not be necessary to use externally ***}
  817.  
  818. function VideoManager.ReturnSaveBufferSize: word;
  819.   {-Returns size of save state buffer in bytes.  Called internally by
  820.     SaveState to get size of required buffer. Uses value of vmStates to
  821.     determine which states are to be saved.}
  822. var
  823.   Size : word;
  824. begin
  825.   ReturnSaveBufferSize := 0;
  826.   if CurrentDisplay = EGA then Exit;
  827.   vmLastError := vmReturnBufSizeFunc(Size, vmStates);
  828.   if vmLastError <> 0 then Exit;
  829.   ReturnSaveBufferSize := Size;
  830. end;
  831.  
  832. {**********************************************************}
  833.  
  834. end.
  835.