mirror of
				https://gitlab.com/freepascal.org/fpc/source.git
				synced 2025-10-31 14:51:35 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			715 lines
		
	
	
		
			19 KiB
		
	
	
	
		
			ObjectPascal
		
	
	
	
	
	
			
		
		
	
	
			715 lines
		
	
	
		
			19 KiB
		
	
	
	
		
			ObjectPascal
		
	
	
	
	
	
| {
 | |
|     This file is part of the PinGUI - Platform Independent GUI Project
 | |
|     Copyright (c) 1999 by Berczi Gabor
 | |
| 
 | |
|     VESA support routines
 | |
| 
 | |
|     See the file COPYING.GUI, included in this distribution,
 | |
|     for details about the copyright.
 | |
| 
 | |
|     This program is distributed in the hope that it will be useful,
 | |
|     but WITHOUT ANY WARRANTY; without even the implied warranty of
 | |
|     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 | |
| 
 | |
|  **********************************************************************}
 | |
| unit VESA;
 | |
| 
 | |
| {$ifdef DEBUG}
 | |
| {$define TESTGRAPHIC}
 | |
| {$endif DEBUG}
 | |
| 
 | |
| interface
 | |
| 
 | |
| uses
 | |
|   Dos,
 | |
|   Objects,Strings,WUtils;
 | |
| 
 | |
| const
 | |
|      { Video Mode Attributes mask constants }
 | |
|      vesa_vma_CanBeSetInCurrentConfig = $0001;
 | |
|      vesa_vma_OptionalBlockPresent    = $0002;
 | |
|      vesa_vma_BIOSSupport             = $0004;
 | |
|      vesa_vma_ColorMode               = $0008; { else mono }
 | |
|      vesa_vma_GraphicsMode            = $0010; { else text }
 | |
|      { -- VBE 2.0 --- }
 | |
|      vesa_vma_VGACompatibleMode       = $0020;
 | |
|      vesa_vma_VGACompWindowedAvail    = $0040;
 | |
|      vesa_vma_LinearFrameBufferAvail  = $0080;
 | |
| 
 | |
|      { Windows Attributes mask constants }
 | |
|      vesa_wa_Present                  = $0001;
 | |
|      vesa_wa_Readable                 = $0002;
 | |
|      vesa_wa_Writeable                = $0004;
 | |
| 
 | |
|      { Memory Model value constants }
 | |
|      vesa_mm_Text                     = $0000;
 | |
|      vesa_mm_CGAGraphics              = $0001;
 | |
|      vesa_mm_HerculesGraphics         = $0002;
 | |
|      vesa_mm_4planePlanar             = $0003;
 | |
|      vesa_mm_PackedPixel              = $0004;
 | |
|      vesa_mm_NonChain4_256color       = $0005;
 | |
|      vesa_mm_DirectColor              = $0006;
 | |
|      vesa_mm_YUV                      = $0007;
 | |
| 
 | |
|      { Memory Window value constants }
 | |
|      vesa_mw_WindowA                  = $0000;
 | |
|      vesa_mw_WindowB                  = $0001;
 | |
| 
 | |
| type
 | |
|      {$ifdef FPC}tregisters=registers;{$endif}
 | |
|      {$ifdef TP}tregisters=registers;{$endif}
 | |
| 
 | |
|      PtrRec16 = record
 | |
|        Ofs,Seg: word;
 | |
|      end;
 | |
| 
 | |
|      TVESAInfoBlock = packed record
 | |
|        Signature    : longint; {  'VESA' }
 | |
|        Version      : word;
 | |
|        OEMString    : PString;
 | |
|        Capabilities : longint;
 | |
|        VideoModeList: PWordArray;
 | |
|        TotalMemory  : word; { in 64KB blocks }
 | |
|        Fill         : array[1..236] of byte;
 | |
|        VBE2Fill     : array[1..256] of byte;
 | |
|      end;
 | |
| 
 | |
|      TVESAModeInfoBlock = packed record
 | |
|        Attributes      : word;
 | |
|        WinAAttrs       : byte;
 | |
|        WinBAttrs       : byte;
 | |
|        Granularity     : word;
 | |
|        Size            : word;
 | |
|        ASegment        : word;
 | |
|        BSegment        : word;
 | |
|        FuncPtr         : pointer;
 | |
|        BytesPerLine    : word;
 | |
|      { optional }
 | |
|        XResolution     : word;
 | |
|        YResolution     : word;
 | |
|        XCharSize       : byte;
 | |
|        YCharSize       : byte;
 | |
|        NumberOfPlanes  : byte;
 | |
|        BitsPerPixel    : byte;
 | |
|        NumberOfBanks   : byte;
 | |
|        MemoryModel     : byte;
 | |
|        BankSize        : byte;
 | |
|        NumberOfImagePages: byte;
 | |
|        Reserved        : byte;
 | |
|      { direct color fields }
 | |
|        RedMaskSize     : byte;
 | |
|        RedFieldPosition: byte;
 | |
|        GreenMaskSize   : byte;
 | |
|        GreenFieldPosition: byte;
 | |
|        BlueMaskSize    : byte;
 | |
|        BlueFieldPosition: byte;
 | |
|        ReservedMaskSize: byte;
 | |
|        ReservedPosition: byte;
 | |
|        DirectColorModeInfo: byte;
 | |
|       { --- VBE 2.0 optional --- }
 | |
|        LinearFrameAddr : longint;
 | |
|        OffScreenAddr   : longint;
 | |
|        OffScreenSize   : word;
 | |
|        Reserved2       : array[1..216-(4+4+2)] of byte;
 | |
|      end;
 | |
| 
 | |
|      TVESAModeList = record
 | |
|        Count        : word;
 | |
|        Modes        : array[1..256] of word;
 | |
|      end;
 | |
| 
 | |
| function VESAInit: boolean;
 | |
| function VESAGetInfo(var B: TVESAInfoBlock): boolean;
 | |
| function VESAGetModeInfo(Mode: word; var B: TVESAModeInfoBlock): boolean;
 | |
| function VESAGetModeList(var B: TVESAModeList): boolean;
 | |
| function VESASearchMode(XRes,YRes,BPX: word; LFB: boolean; var Mode: word; var ModeInfo: TVESAModeInfoBlock): boolean;
 | |
| function VESAGetOemString: string;
 | |
| function VESASetMode(Mode: word): boolean;
 | |
| function VESAGetMode(var Mode: word): boolean;
 | |
| function VESASelectMemoryWindow(Window: byte; Position: word): boolean;
 | |
| function VESAReturnMemoryWindow(Window: byte; var Position: word): boolean;
 | |
| function RegisterVesaVideoMode(Mode : word) : boolean;
 | |
| Procedure FreeVesaModes;
 | |
| 
 | |
| implementation
 | |
| 
 | |
| uses
 | |
| {$ifdef FPC}
 | |
|   video, mouse,
 | |
| {$endif FPC}
 | |
| {$ifdef TESTGRAPHIC}
 | |
|   graph,
 | |
| {$endif TESTGRAPHIC}
 | |
|   pmode;
 | |
| 
 | |
| type
 | |
| 
 | |
|        PVesaVideoMode = ^TVesaVideoMode;
 | |
|        TVesaVideoMode = record
 | |
|          {Col,Row      : word;
 | |
|           Color        : boolean;}
 | |
|          V            : TVideoMode;
 | |
|          Mode         : word;
 | |
|          IsGraphic    : boolean;
 | |
|          { zero based vesa specific driver count }
 | |
|          VideoIndex   : word;
 | |
|          Next         : PVesaVideoMode;
 | |
|        end;
 | |
|        CursorBitMap = Record
 | |
|         width,height,size : longint;
 | |
|         colors : array[0..8*8-1] of word;
 | |
|        end;
 | |
| const
 | |
|   VesaVideoModeHead : PVesaVideoMode = nil;
 | |
|   VesaRegisteredModes : word = 0;
 | |
| {$ifdef TESTGRAPHIC}
 | |
|   IsGraphicMode : boolean = false;
 | |
|   GraphDriver   : integer = 0;
 | |
|   GraphMode     : Integer = 0;
 | |
|   FirstCallAfterSetVesaMode : boolean = false;
 | |
|   LastCursorX : word = $ffff;
 | |
|   LastCursorY : word = $ffff;
 | |
|   LastCursorType : word = crHidden;
 | |
| 
 | |
| var
 | |
|   UnderLineImage : CursorBitMap;
 | |
|   BlockImage : CursorBitMap;
 | |
|   HalfBlockImage : CursorBitMap;
 | |
| {$endif TESTGRAPHIC}
 | |
| 
 | |
| Var
 | |
|   SysGetVideoModeCount : function : word;
 | |
|   SysSetVideoMode      : function (Const VideoMode : TVideoMode) : boolean;
 | |
|   SysGetVideoModeData  : function (Index : Word; Var Data : TVideoMode) : boolean;
 | |
|   SysUpdateScreen      : procedure(Force : Boolean);
 | |
|   SysDoneVideo         : procedure;
 | |
|   SysInitVideo         : procedure;
 | |
|   SysSetCursorPos      : procedure(NewCursorX, NewCursorY: Word);
 | |
|   SysSetCursorType     : procedure(NewCurosrType : word);
 | |
| 
 | |
| 
 | |
| function VESAGetInfo(var B: TVESAInfoBlock): boolean;
 | |
| var r: registers;
 | |
|     OK: boolean;
 | |
|     M: MemPtr;
 | |
| begin
 | |
|   StrToMem('VBE2',B.Signature);
 | |
|   GetDosMem(M,SizeOf(B));
 | |
|   M.MoveDataTo(B,sizeof(B));
 | |
|   r.ah:=$4f; r.al:=0;
 | |
|   r.es:=M.DosSeg; r.di:=M.DosOfs;
 | |
|   realintr($10,r);
 | |
|   M.MoveDataFrom(sizeof(B),B);
 | |
|   FreeDosMem(M);
 | |
|   OK:=(r.ax=$004f){ and (MemToStr(B.Signature,4)='VESA')};
 | |
|   VESAGetInfo:=OK;
 | |
| end;
 | |
| 
 | |
| function VESAGetModeList(var B: TVESAModeList): boolean;
 | |
| var OK: boolean;
 | |
|     VI: TVESAInfoBlock;
 | |
| begin
 | |
|   FillChar(B,SizeOf(B),0);
 | |
|   OK:=VESAGetInfo(VI);
 | |
|   if OK then
 | |
|   begin
 | |
|     OK:=MoveDosToPM(VI.VideoModeList,@B.Modes,sizeof(B.Modes));
 | |
|     if OK then
 | |
|       while (B.Modes[B.Count+1]<>$ffff) and (B.Count<High(B.Modes)) do
 | |
|             Inc(B.Count);
 | |
|   end;
 | |
|   VESAGetModeList:=OK;
 | |
| end;
 | |
| 
 | |
| function VESASearchMode(XRes,YRes,BPX: word; LFB: boolean; var Mode: word; var ModeInfo: TVESAModeInfoBlock): boolean;
 | |
| var B: TVESAModeList;
 | |
|     OK: boolean;
 | |
|     I: integer;
 | |
|     MI: TVESAModeInfoBlock;
 | |
| begin
 | |
|   OK:=VESAGetModeList(B);
 | |
|   I:=1; Mode:=0;
 | |
|   repeat
 | |
|     OK:=VESAGetModeInfo(B.Modes[I],MI);
 | |
|     if OK and (MI.XResolution=XRes) and (MI.YResolution=YRes) and
 | |
|        (MI.BitsPerPixel=BPX) and
 | |
|        ((LFB=false) or ((MI.Attributes and vesa_vma_LinearFrameBufferAvail)<>0)) then
 | |
|       begin Mode:=B.Modes[I]; ModeInfo:=MI; end;
 | |
|     Inc(I);
 | |
|   until (OK=false) or (I>=B.Count) or (Mode<>0);
 | |
|   OK:=Mode<>0;
 | |
|   VESASearchMode:=OK;
 | |
| end;
 | |
| 
 | |
| function VESAGetOemString: string;
 | |
| var OK: boolean;
 | |
|     VI: TVESAInfoBlock;
 | |
|     S: array[0..256] of char;
 | |
| begin
 | |
|   FillChar(S,SizeOf(S),0);
 | |
|   OK:=VESAGetInfo(VI);
 | |
|   if OK then
 | |
|     OK:=MoveDosToPM(VI.OemString,@S,sizeof(S));
 | |
|   VESAGetOemString:=StrPas(@S);
 | |
| end;
 | |
| 
 | |
| function VESAGetModeInfo(Mode: word; var B: TVESAModeInfoBlock): boolean;
 | |
| var r : registers;
 | |
|     M : MemPtr;
 | |
|     OK: boolean;
 | |
| begin
 | |
|   r.ah:=$4f; r.al:=$01; r.cx:=Mode;
 | |
|   GetDosMem(M,sizeof(B));
 | |
|   r.es:=M.DosSeg; r.di:=M.DosOfs; {r.ds:=r.es;}
 | |
|   realintr($10,r);
 | |
|   M.MoveDataFrom(sizeof(B),B);
 | |
|   FreeDosMem(M);
 | |
|   OK:=(r.ax=$004f);
 | |
|   VESAGetModeInfo:=OK;
 | |
| end;
 | |
| 
 | |
| function RegisterVesaVideoMode(Mode : word) : boolean;
 | |
| var B: TVESAModeInfoBlock;
 | |
|     VH : PVesaVideoMode;
 | |
|     DoAdd : boolean;
 | |
| begin
 | |
|   if not VESAGetModeInfo(Mode,B) then
 | |
|     RegisterVesaVideoMode:=false
 | |
|   else
 | |
|     begin
 | |
|       VH:=VesaVideoModeHead;
 | |
|       DoAdd:=true;
 | |
|       RegisterVesaVideoMode:=false;
 | |
|       while assigned(VH) do
 | |
|         begin
 | |
|           if VH^.mode=mode then
 | |
|             DoAdd:=false;
 | |
|           VH:=VH^.next;
 | |
|         end;
 | |
|       if DoAdd then
 | |
|         begin
 | |
|           New(VH);
 | |
|           VH^.next:=VesaVideoModeHead;
 | |
|           VH^.mode:=mode;
 | |
|           VH^.IsGraphic:=(B.Attributes and vesa_vma_GraphicsMode)<>0;
 | |
|           VH^.v.color:=(B.Attributes and vesa_vma_ColorMode)<>0;
 | |
|           if VH^.IsGraphic then
 | |
|             begin
 | |
|               VH^.v.col:=B.XResolution div 8;
 | |
|               VH^.v.row:=B.YResolution div 8;
 | |
|             end
 | |
|           else
 | |
|             begin
 | |
|               VH^.v.col:=B.XResolution;
 | |
|               VH^.v.row:=B.YResolution;
 | |
|             end;
 | |
|           VH^.VideoIndex:=VesaRegisteredModes;
 | |
|           Inc(VesaRegisteredModes);
 | |
|           RegisterVesaVideoMode:=true;
 | |
|           VesaVideoModeHead:=VH;
 | |
|         end;
 | |
|     end;
 | |
| end;
 | |
| 
 | |
| function VESASetMode(Mode: word): boolean;
 | |
| var r: registers;
 | |
|     OK: boolean;
 | |
| begin
 | |
|   r.ah:=$4f; r.al:=$02; r.bx:=Mode;
 | |
|   dos.intr($10,r);
 | |
|   OK:=(r.ax=$004f);
 | |
|   VESASetMode:=OK;
 | |
| end;
 | |
| 
 | |
| function VESAGetMode(var Mode: word): boolean;
 | |
| var r : registers;
 | |
|     OK: boolean;
 | |
| begin
 | |
|   r.ah:=$4f; r.al:=$03;
 | |
|   dos.intr($10,r);
 | |
|   OK:=(r.ax=$004f);
 | |
|   if OK then Mode:=r.bx;
 | |
|   VESAGetMode:=OK;
 | |
| end;
 | |
| 
 | |
| function VESASelectMemoryWindow(Window: byte; Position: word): boolean;
 | |
| var r : registers;
 | |
|     OK : boolean;
 | |
| begin
 | |
|   r.ah:=$4f; r.al:=$05; r.bh:=0; r.bl:=Window; r.dx:=Position;
 | |
|   dos.intr($10,r);
 | |
|   OK:=(r.ax=$004f);
 | |
|   VESASelectMemoryWindow:=OK;
 | |
| end;
 | |
| 
 | |
| function VESAReturnMemoryWindow(Window: byte; var Position: word): boolean;
 | |
| var r  : registers;
 | |
|     OK : boolean;
 | |
| begin
 | |
|   r.ah:=$4f; r.al:=$05; r.bh:=1; r.bl:=Window;
 | |
|   dos.intr($10,r);
 | |
|   OK:=(r.ax=$004f);
 | |
|   if OK then Position:=r.dx;
 | |
|   VESAReturnMemoryWindow:=OK;
 | |
| end;
 | |
| 
 | |
| function VESAInit: boolean;
 | |
| var OK: boolean;
 | |
|     VI: TVESAInfoBlock;
 | |
| begin
 | |
|   OK:=VESAGetInfo(VI);
 | |
|   if OK then
 | |
| 
 | |
|   VESAInit:=OK;
 | |
| end;
 | |
| 
 | |
| {$ifdef FPC}
 | |
| Function VesaGetVideoModeData (Index : Word; Var Data : TVideoMode) : boolean;
 | |
| Var
 | |
|   PrevCount : word;
 | |
|   VH : PVesaVideoMode;
 | |
| 
 | |
| begin
 | |
|   PrevCount:=SysGetVideoModeCount();
 | |
|   VesaGetVideoModeData:=(Index<PrevCount);
 | |
|   If VesaGetVideoModeData then
 | |
|     begin
 | |
|       VesaGetVideoModeData:=SysGetVideoModeData(Index,Data);
 | |
|       exit;
 | |
|     end;
 | |
|   VesaGetVideoModeData:=(Index-PrevCount)<VesaRegisteredModes;
 | |
|   If VesaGetVideoModeData then
 | |
|     begin
 | |
|       VH:=VesaVideoModeHead;
 | |
|       while assigned(VH) and (VH^.VideoIndex<>Index-PrevCount) do
 | |
|         VH:=VH^.next;
 | |
|       if assigned(VH) then
 | |
|         Data:=VH^.v
 | |
|       else
 | |
|         VesaGetVideoModeData:=false;
 | |
|     end;
 | |
| end;
 | |
| 
 | |
| function SetVESAMode(const VideoMode: TVideoMode): Boolean;
 | |
| 
 | |
|   var
 | |
|      res : boolean;
 | |
|      VH : PVesaVideoMode;
 | |
| 
 | |
|   begin
 | |
|      res:=false;
 | |
|      VH:=VesaVideoModeHead;
 | |
|      while assigned(VH) do
 | |
|        begin
 | |
|          if (VideoMode.col=VH^.v.col) and
 | |
|             (VideoMode.row=VH^.v.row) and
 | |
|             (VideoMode.color=VH^.v.color) then
 | |
|            begin
 | |
| {$ifdef TESTGRAPHIC}
 | |
|              if VH^.IsGraphic then
 | |
|                begin
 | |
|                  if IsGraphicMode then
 | |
|                    CloseGraph;
 | |
|                  GraphDriver:=Graph.Vesa;
 | |
|                  if (VideoMode.col = 100) and (VideoMode.row = 75) then
 | |
|                    GraphMode:=m800x600x256
 | |
|                  else if (VideoMode.col = 80) and (VideoMode.row = 60) then
 | |
|                    GraphMode:=m640x480x256
 | |
|                  else if (VideoMode.col = 128) and (VideoMode.row = 96) then
 | |
|                    GraphMode:=m1024x768x256
 | |
|                  else
 | |
|                    GraphMode:=Graph.Detect;
 | |
|                  InitGraph(GraphDriver,GraphMode,'');
 | |
|                  res:=(GraphResult=grOK);
 | |
|                  if not res then
 | |
|                    begin
 | |
|                      SetVesaMode:=false;
 | |
|                      exit;
 | |
|                    end;
 | |
|                end
 | |
|              else
 | |
| {$endif TESTGRAPHIC}
 | |
|                res:=VESASetMode(VH^.mode);
 | |
|              if res then
 | |
|                begin
 | |
|                   ScreenWidth:=VideoMode.Col;
 | |
|                   ScreenHeight:=VideoMode.Row;
 | |
|                   ScreenColor:=VideoMode.Color;
 | |
| {$ifdef TESTGRAPHIC}
 | |
|                   IsGraphicMode:=VH^.IsGraphic;
 | |
|                   FirstCallAfterSetVesaMode:=true;
 | |
|                   LastCursorX:=$ffff;
 | |
|                   LastCursorY:=$ffff;
 | |
|                   LastCursorType:=crHidden;
 | |
|                   if IsGraphicMode then
 | |
|                     DoCustomMouse(false)
 | |
|                   else
 | |
| {$endif TESTGRAPHIC}
 | |
|                     DoCustomMouse(true);
 | |
|                end;
 | |
|            end;
 | |
|          if res then
 | |
|            begin
 | |
|              SetVesaMode:=true;
 | |
|              exit;
 | |
|            end;
 | |
|          VH:=VH^.next;
 | |
|        end;
 | |
|      SetVESAMode:=SysSetVideoMode(VideoMode);
 | |
|   end;
 | |
| 
 | |
| procedure VesaSetCursorPos(NewCursorX, NewCursorY: Word);
 | |
| begin
 | |
| {$ifdef TESTGRAPHIC}
 | |
|   if not IsGraphicMode then
 | |
| {$endif TESTGRAPHIC}
 | |
|     begin
 | |
|       SysSetCursorPos(NewCursorX,NewCursorY);
 | |
|       exit;
 | |
|     end;
 | |
| {$ifdef TESTGRAPHIC}
 | |
|   if (NewCursorX<>LastCursorX) or (NewCursorY<>LastCursorY) then
 | |
|     begin
 | |
|       Case GetCursorType of
 | |
|         crHidden  : ;
 | |
|         crUnderLine :
 | |
|           Begin
 | |
|             PutImage(LastCursorX*8,LastCursorY*8+7,UnderLineImage,XORPut);
 | |
|             PutImage(NewCursorX*8,NewCursorY*8+7,UnderLineImage,XORPut);
 | |
|           End;
 | |
|         crBlock     :
 | |
|           Begin
 | |
|             PutImage(LastCursorX*8,LastCursorY*8,BlockImage,XORPut);
 | |
|             PutImage(NewCursorX*8,NewCursorY*8,BlockImage,XORPut);
 | |
|           End;
 | |
|         crHalfBlock :
 | |
|           Begin
 | |
|             PutImage(LastCursorX*8,LastCursorY*8+4,HalfBlockImage,XORPut);
 | |
|             PutImage(NewCursorX*8,NewCursorY*8+4,HalfBlockImage,XORPut);
 | |
|           End;
 | |
|       end;
 | |
|       LastCursorX:=NewCursorX;
 | |
|       LastCursorY:=NewCursorY;
 | |
|     end;
 | |
| {$endif TESTGRAPHIC}
 | |
| end;
 | |
| 
 | |
| procedure VesaSetCursorType(NewType : Word);
 | |
| begin
 | |
| {$ifdef TESTGRAPHIC}
 | |
|   if not IsGraphicMode then
 | |
| {$endif TESTGRAPHIC}
 | |
|     begin
 | |
|       SysSetCursorType(NewType);
 | |
|       exit;
 | |
|     end;
 | |
| {$ifdef TESTGRAPHIC}
 | |
|   if (NewType<>LastCursorType) then
 | |
|     begin
 | |
|       Case LastCursorType of
 | |
|         crHidden  : ;
 | |
|         crUnderLine :
 | |
|           Begin
 | |
|             PutImage(LastCursorX*8,LastCursorY*8+7,UnderLineImage,XORPut);
 | |
|           End;
 | |
|         crBlock     :
 | |
|           Begin
 | |
|             PutImage(LastCursorX*8,LastCursorY*8,BlockImage,XORPut);
 | |
|           End;
 | |
|         crHalfBlock :
 | |
|           Begin
 | |
|             PutImage(LastCursorX*8,LastCursorY*8+4,HalfBlockImage,XORPut);
 | |
|           End;
 | |
|       end;
 | |
|       SysSetCursorType(NewType);
 | |
|       Case NewType of
 | |
|         crHidden  : ;
 | |
|         crUnderLine :
 | |
|           Begin
 | |
|             PutImage(LastCursorX*8,LastCursorY*8+7,UnderLineImage,XORPut);
 | |
|           End;
 | |
|         crBlock     :
 | |
|           Begin
 | |
|             PutImage(LastCursorX*8,LastCursorY*8,BlockImage,XORPut);
 | |
|           End;
 | |
|         crHalfBlock :
 | |
|           Begin
 | |
|             PutImage(LastCursorX*8,LastCursorY*8+4,HalfBlockImage,XORPut);
 | |
|           End;
 | |
|       end;
 | |
|       LastCursorType:=NewType;
 | |
|     end;
 | |
| {$endif TESTGRAPHIC}
 | |
| end;
 | |
| 
 | |
| procedure VesaUpdateScreen(Force: Boolean);
 | |
| {$ifdef TESTGRAPHIC}
 | |
| var
 | |
|   StoreDrawTextBackground,
 | |
|   MustUpdate : boolean;
 | |
|   x,y : longint;
 | |
|   w, prevcolor,
 | |
|   prevbkcolor, StoreCursorType : word;
 | |
|   Color,BkCol,Col : byte;
 | |
|   Ch : char;
 | |
| {$endif TESTGRAPHIC}
 | |
| begin
 | |
| {$ifdef TESTGRAPHIC}
 | |
|   if not IsGraphicMode then
 | |
| {$endif TESTGRAPHIC}
 | |
|     begin
 | |
|       SysUpdateScreen(Force);
 | |
|       exit;
 | |
|     end;
 | |
| {$ifdef TESTGRAPHIC}
 | |
|   if FirstCallAfterSetVesaMode then
 | |
|     begin
 | |
|       { Make sure to redraw all }
 | |
|       Fillchar(OldVideoBuf^,VideoBufSize,#0);
 | |
|       FirstCallAfterSetVesaMode:=false;
 | |
|     end;
 | |
|   if not force then
 | |
|    begin
 | |
|      MustUpdate:=false;
 | |
|      asm
 | |
|         movl    VideoBuf,%esi
 | |
|         movl    OldVideoBuf,%edi
 | |
|         movl    VideoBufSize,%ecx
 | |
|         shrl    $2,%ecx
 | |
|         repe
 | |
|         cmpsl
 | |
|         setne   MustUpdate
 | |
|      end;
 | |
|    end;
 | |
|   StoreDrawTextBackground:=DrawTextBackground;
 | |
|   DrawTextBackground:=true;
 | |
|   if Force or MustUpdate then
 | |
|    begin
 | |
|      PrevColor:=GetColor;
 | |
|      PrevBkColor:=GetBkColor;
 | |
| 
 | |
|      for y:=0 to ScreenHeight-1 do
 | |
|        for x:=0 to Screenwidth-1 do
 | |
|          begin
 | |
|            w:=VideoBuf^[x+y*ScreenWidth];
 | |
|            if Force or
 | |
|               (w<>OldVideoBuf^[x+y*ScreenWidth]) then
 | |
|              Begin
 | |
|                Color:=w shr 8;
 | |
|                Ch:=chr(w and $ff);
 | |
|                Col:=Color and $f;
 | |
|                if (Col = 0) and (GetMaxColor=255) then
 | |
|                  Col:=255;
 | |
|                SetColor(Col);
 | |
|                BkCol:=(Color shr 4) and 7;
 | |
|                if (BkCol = 0) and (GetMaxColor=255) then
 | |
|                  BkCol:=255;
 | |
|                SetBkColor(BkCol);
 | |
|                if (x=LastCursorX) and (Y=LastCursorY) then
 | |
|                  begin
 | |
|                    StoreCursorType:=LastCursorType;
 | |
|                    VesaSetCursorType(crHidden);
 | |
|                  end;
 | |
|                OutTextXY(x*8,y*8,Ch);
 | |
|                if (x=LastCursorX) and (Y=LastCursorY) then
 | |
|                  VesaSetCursorType(StoreCursorType);
 | |
|                if not force then
 | |
|                  OldVideoBuf^[x+y*ScreenWidth]:=w;
 | |
|              End;
 | |
|          end;
 | |
|      if Force then
 | |
|        move(videobuf^,oldvideobuf^,
 | |
|          VideoBufSize);
 | |
|      SetColor(PrevColor);
 | |
|      SetBkColor(GetBkColor);
 | |
|    end;
 | |
|   DrawTextBackground:=StoreDrawTextBackground;
 | |
| {$endif TESTGRAPHIC}
 | |
| end;
 | |
| 
 | |
| procedure VesaDoneVideo;
 | |
| begin
 | |
| {$ifdef TESTGRAPHIC}
 | |
|   if IsGraphicMode then
 | |
|     begin
 | |
|       CloseGraph;
 | |
|       IsGraphicMode:=false;
 | |
|     end;
 | |
| {$endif TESTGRAPHIC}
 | |
|   SysDoneVideo();
 | |
| end;
 | |
| 
 | |
| procedure VesaInitVideo;
 | |
| begin
 | |
| {$ifdef TESTGRAPHIC}
 | |
|   if IsGraphicMode then
 | |
|     begin
 | |
|       SysInitVideo();
 | |
|       InitGraph(GraphDriver,GraphMode,'');
 | |
|     end
 | |
|   else
 | |
| {$endif TESTGRAPHIC}
 | |
|     SysInitVideo();
 | |
| end;
 | |
| 
 | |
| Function VesaGetVideoModeCount : Word;
 | |
| 
 | |
| begin
 | |
|   VesaGetVideoModeCount:=SysGetVideoModeCount()+VesaRegisteredModes;
 | |
| end;
 | |
| 
 | |
| Procedure FreeVesaModes;
 | |
| var
 | |
|   VH : PVesaVideoMode;
 | |
| begin
 | |
|   VH:=VesaVideoModeHead;
 | |
|   While assigned(VH) do
 | |
|     begin
 | |
|       VesaVideoModeHead:=VH^.Next;
 | |
|       FreeMem(VH,Sizeof(TVesaVideoMode));
 | |
|       VH:=VesaVideoModeHead;
 | |
|     end;
 | |
| end;
 | |
| 
 | |
| Var
 | |
|   Driver : TVideoDriver;
 | |
| {$ifdef TESTGRAPHIC}
 | |
|   i : longint;
 | |
| {$endif TESTGRAPHIC}
 | |
| 
 | |
| BEGIN
 | |
| { Get the videodriver to be used }
 | |
|   GetVideoDriver (Driver);
 | |
| { Change needed functions }
 | |
|   SysGetVideoModeCount:=Driver.GetVideoModeCount;
 | |
|   Driver.GetVideoModeCount:=@VesaGetVideoModeCount;
 | |
|   SysGetVideoModeData:=Driver.GetVideoModeData;
 | |
|   Driver.GetVideoModeData:=@VesaGetVideoModeData;
 | |
|   SysSetVideoMode:=Driver.SetVideoMode;
 | |
|   Driver.SetVideoMode:=@SetVESAMode;
 | |
|   SysSetCursorPos:=Driver.SetCursorPos;
 | |
|   Driver.SetCursorPos:=@VESASetCursorPos;
 | |
|   SysSetCursorType:=Driver.SetCursorType;
 | |
|   Driver.SetCursorType:=@VESASetCursorType;
 | |
|   SysUpdateScreen:=Driver.UpdateScreen;
 | |
|   Driver.UpdateScreen:=@VesaUpdateScreen;
 | |
|   SysDoneVideo:=Driver.DoneDriver;
 | |
|   Driver.DoneDriver:=@VesaDoneVideo;
 | |
|   SysInitVideo:=Driver.InitDriver;
 | |
|   Driver.InitDriver:=@VesaInitVideo;
 | |
| 
 | |
| {$ifdef TESTGRAPHIC}
 | |
|   BlockImage.width:=7;
 | |
|   BlockImage.height:=7;
 | |
|   For i:=0 to 8*8-1 do
 | |
|     BlockImage.colors[i]:=White;
 | |
|   HalfBlockImage:=BlockImage;
 | |
|   HalfBlockImage.height:=3;
 | |
|   UnderLineImage:=BlockImage;
 | |
|   UnderLineImage.height:=0;
 | |
| {$endif TESTGRAPHIC}
 | |
| 
 | |
|   SetVideoDriver (Driver);
 | |
| {$endif FPC}
 | |
| END.
 | 
