mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-04-09 17:08:34 +02:00
766 lines
20 KiB
ObjectPascal
766 lines
20 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
|
|
tregisters=registers;
|
|
|
|
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;
|
|
|
|
const
|
|
DisableVESA : boolean = false;
|
|
|
|
implementation
|
|
|
|
uses
|
|
video, mouse,
|
|
{$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
|
|
if disableVESA then
|
|
exit(false);
|
|
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);
|
|
if disableVESA then
|
|
exit(false);
|
|
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
|
|
if disableVESA then
|
|
begin
|
|
VESAGetOemString:='VESA disabled';
|
|
exit;
|
|
end;
|
|
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
|
|
if disableVESA then
|
|
exit(false);
|
|
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
|
|
if disableVESA then
|
|
exit(false);
|
|
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
|
|
if disableVESA then
|
|
exit(false);
|
|
if disableVESA then
|
|
exit(false);
|
|
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
|
|
if disableVESA then
|
|
exit(false);
|
|
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
|
|
if disableVESA then
|
|
exit(false);
|
|
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
|
|
if disableVESA then
|
|
OK:=false
|
|
else
|
|
OK:=VESAGetInfo(VI);
|
|
VESAInit:=OK;
|
|
end;
|
|
|
|
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;
|
|
if disableVESA then
|
|
exit(res);
|
|
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{$ifdef FPC}(){$endif};
|
|
|
|
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{$ifdef FPC}(){$endif});
|
|
end;
|
|
DrawTextBackground:=StoreDrawTextBackground;
|
|
{$endif TESTGRAPHIC}
|
|
end;
|
|
|
|
procedure VesaDoneVideo;
|
|
begin
|
|
{$ifdef TESTGRAPHIC}
|
|
if IsGraphicMode then
|
|
begin
|
|
CloseGraph;
|
|
IsGraphicMode:=false;
|
|
end;
|
|
{$endif TESTGRAPHIC}
|
|
SysDoneVideo();
|
|
end;
|
|
|
|
function SetVESAVideoDriver : boolean; forward;
|
|
|
|
procedure VesaInitVideo;
|
|
begin
|
|
if not SetVESAVideoDriver then
|
|
exit;
|
|
{$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}
|
|
|
|
function SetVESAVideoDriver : boolean;
|
|
BEGIN
|
|
if disableVESA then
|
|
exit(false);
|
|
{ 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);
|
|
SetVESAVideoDriver:=true;
|
|
END;
|
|
|
|
function ChkWinNT: boolean;
|
|
var
|
|
R: Registers;
|
|
begin
|
|
ChkWinNT := false;
|
|
R.AX := $3306;
|
|
RealIntr ($21, R);
|
|
if (R.AL = 255) or (R.BX <> 50 * 256 + 5) then
|
|
Exit;
|
|
R.AX := $3000;
|
|
RealIntr ($21, R);
|
|
if (R.AX = 5) and (R.BH = 255) then
|
|
ChkWinNT := true;
|
|
end;
|
|
|
|
begin
|
|
(* Let's disable VESA functions by default if running under MS Windows NT+ *)
|
|
if ChkWinNT then
|
|
DisableVESA := true;
|
|
END.
|