1{
2    This file is part of the Free Pascal run time library.
3    Copyright (c) 1999-2000 by Florian Klaempfl
4    member of the Free Pascal development team
5
6    Video unit extension for VESA Modes for MS-DOS
7
8    See the file COPYING.FPC, included in this distribution,
9    for details about the copyright.
10
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14
15 **********************************************************************}
16unit vesamode;
17
18  interface
19
20  implementation
21
22    uses
23       dos,video,mouse;
24
25    type
26       PFarChar = ^Char; far;
27       twordarray = array[0..0] of word;
28
29       pwordarray = ^twordarray; far;
30       TVESAInfoBlock = packed record
31         VESASignature   : ARRAY[0..3] OF CHAR;
32         VESAVersion     : WORD;
33         OEMStringPtr    : PFarChar;
34         Capabilities    : LONGINT;
35         VideoModePtr    : pwordarray;
36         TotalMemory     : WORD;
37         Reserved        : ARRAY[1..242] OF BYTE;
38       end;
39
40       TVesaVideoMode = record
41         {Col,Row      : word;
42          Color        : boolean;}
43         V            : TVideoMode;
44         Mode         : word;
45       end;
46
47Const
48  VesaVideoModeCount = 5;
49  VesaVMD : Array[264..268] of TVesaVideoMode = (
50   (V : (Col: 80; Row : 60;  Color : True); Mode : 264),
51   (V : (Col: 132; Row : 25;  Color : True); Mode : 265),
52   (V : (Col: 132; Row : 43;  Color : True); Mode : 266),
53   (V : (Col: 132; Row : 50;  Color : True); Mode : 267),
54   (V : (Col: 132; Row : 60;  Color : True); Mode : 268)
55  );
56
57var
58  SupportedVesaVMD : Array[0..VesaVideoModeCount-1] of TVesaVideoMode;
59  SysGetVideoModeCount : function : word;
60  SysSetVideoMode : function (Const VideoMode : TVideoMode) : boolean;
61  SysGetVideoModeData : Function (Index : Word; Var Data : TVideoMode) : boolean;
62  VesaRegisteredModes : word = 0;
63
64    function ReturnSuperVGAInfo(var ib : TVESAInfoBLock) : Word;
65
66      var
67         regs : registers;
68
69      begin
70         FillChar(ib,SizeOf(ib),0);
71         regs.ax:=$4f00;
72         regs.es:=Seg(ib);
73         regs.di:=Ofs(ib);
74         intr($10,regs);
75         ReturnSuperVGAInfo:=regs.ax;
76      end;
77
78    function SetSuperVGAMode(m : word) : word;
79
80      var
81         regs : registers;
82
83      begin
84         regs.ax:=$4f02;
85         regs.bx:=m;
86         intr($10,regs);
87         SetSuperVGAMode:=regs.ax;
88      end;
89
90    function SetVESAMode(const VideoMode: TVideoMode): Boolean;
91
92      var
93         w : word;
94
95      begin
96         SetVESAMode:=false;
97         for w:=VesaRegisteredModes-1 downto 0 do
98           begin
99             if (VideoMode.col=SupportedVesaVMD[w].v.col) and
100                (VideoMode.row=SupportedVesaVMD[w].v.row) and
101                (VideoMode.color=SupportedVesaVMD[w].v.color) then
102               begin
103                 if SetSuperVGAMode(SupportedVesaVMD[w].mode) <> $4f then
104                   SetVESAMode:=false
105                 else
106                   begin
107                      SetVESAMode:=true;
108                      ScreenWidth:=VideoMode.Col;
109                      ScreenHeight:=VideoMode.Row;
110                      ScreenColor:=VideoMode.Color;
111                      // cheat to get a correct mouse
112                      {
113                      mem[$40:$84]:=ScreenHeight-1;
114                      mem[$40:$4a]:=ScreenWidth;
115                      memw[$40:$4c]:=ScreenHeight*((ScreenWidth shl 1)-1);
116                      }
117                      DoCustomMouse(true);
118                   end;
119               end;
120             if SetVESAMode then
121               exit;
122           end;
123         SetVESAMode:=SysSetVideoMode(VideoMode);
124      end;
125
126procedure InitializeVesaModes;
127var
128   infoblock : TVESAInfoBLock;
129   i : word;
130   m : word;
131begin
132   ReturnSuperVGAInfo(infoblock);
133   if not((infoblock.VESASignature[0]<>'V') or
134      (infoblock.VESASignature[1]<>'E') or
135      (infoblock.VESASignature[2]<>'S') or
136      (infoblock.VESASignature[3]<>'A')) then
137     begin
138{$R-}
139   i:=0;
140   while true do
141     begin
142        m := MemW[Seg(infoblock.VideoModePtr^):Ofs(infoblock.VideoModePtr^)+i*2];
143        case m of
144           264:
145             Begin
146               {RegisterVideoMode(80,60,true,@SetVESAMode,264);}
147               SupportedVesaVMD[VesaRegisteredModes]:=VesaVMD[m];
148               Inc(VesaRegisteredModes);
149             End;
150           265:
151             Begin
152               {RegisterVideoMode(132,25,true,@SetVESAMode,265);}
153               SupportedVesaVMD[VesaRegisteredModes]:=VesaVMD[m];
154               Inc(VesaRegisteredModes);
155             End;
156           266:
157             Begin
158               {RegisterVideoMode(132,43,true,@SetVESAMode,266);}
159               SupportedVesaVMD[VesaRegisteredModes]:=VesaVMD[m];
160               Inc(VesaRegisteredModes);
161             End;
162           267:
163             Begin
164               {RegisterVideoMode(132,50,true,@SetVESAMode,267);}
165               SupportedVesaVMD[VesaRegisteredModes]:=VesaVMD[m];
166               Inc(VesaRegisteredModes);
167             End;
168           268:
169             Begin
170               {RegisterVideoMode(132,60,true,@SetVESAMode,268);}
171               SupportedVesaVMD[VesaRegisteredModes]:=VesaVMD[m];
172               Inc(VesaRegisteredModes);
173             End;
174           $ffff:
175             break;
176        end;
177        inc(i);
178     end;
179   end;
180end;
181
182
183Function VesaGetVideoModeData (Index : Word; Var Data : TVideoMode) : boolean;
184Var
185  PrevCount : word;
186
187begin
188  PrevCount:=SysGetVideoModeCount();
189  VesaGetVideoModeData:=(Index<=PrevCount);
190  If VesaGetVideoModeData then
191    begin
192      SysGetVideoModeData(Index,Data);
193      exit;
194    end;
195  VesaGetVideoModeData:=(Index-PrevCount)<=VesaRegisteredModes;
196  If VesaGetVideoModeData then
197    Data:=SupportedVesaVMD[Index-PrevCount-1].V;
198end;
199
200Function VesaGetVideoModeCount : Word;
201
202begin
203  VesaGetVideoModeCount:=SysGetVideoModeCount()+VesaRegisteredModes;
204end;
205
206
207Var
208  Driver : TVideoDriver;
209(*
210Const
211  SysVideoDriver : TVideoDriver = (
212    InitDriver      : @SysInitVideo;
213    DoneDriver      : @SysDoneVideo;
214    UpdateScreen    : @SysUpdateScreen;
215    ClearScreen     : Nil;
216    SetVideoMode    : @SysSetVideoMode;
217    GetVideoModeCount : @SysGetVideoModeCount;
218    GetVideoModeData : @SysGetVideoModedata;
219    SetCursorPos    : @SysSetCursorPos;
220    GetCursorType   : @SysGetCursorType;
221    SetCursorType   : @SysSetCursorType;
222    GetCapabilities : @SysGetCapabilities
223  );
224*)
225initialization
226
227{ Get the videodriver to be used }
228  GetVideoDriver (Driver);
229  InitializeVesaModes;
230{ Change needed functions }
231  SysGetVideoModeCount:=Driver.GetVideoModeCount;
232  Driver.GetVideoModeCount:=@VesaGetVideoModeCount;
233  SysGetVideoModeData:=Driver.GetVideoModeData;
234  Driver.GetVideoModeData:=@VesaGetVideoModeData;
235  SysSetVideoMode:=Driver.SetVideoMode;
236  Driver.SetVideoMode:=@SetVESAMode;
237
238  SetVideoDriver (Driver);
239end.
240