123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609 |
- {
- $Id$
- This file is part of the Free Pascal run time library.
- Copyright (c) 1999-2000 by the Free Pascal development team
- This include implements video mode management.
- See the file COPYING.FPC, 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.
- **********************************************************************}
- {-----------------------------------------------------------------------}
- { Internal routines }
- {-----------------------------------------------------------------------}
- {$ifndef nonewmodes}
- procedure res2Mode(x, y, maxColor: longint; var driver,mode: smallInt);
- var
- l: longint;
- begin
- case maxColor of
- 2: driver := D1bit;
- 4: driver := D2bit;
- 16: driver := D4bit;
- 64: driver := D6bit;
- 256: driver := D8bit;
- 4096: driver := D12bit;
- 32768: driver := D15bit;
- 65536: driver := D16bit;
- { not yet supported
- 65536*256: driver := D24bit;
- 65536*65536: driver := D32bit;}
- else
- begin
- driver := maxsmallint;
- exit;
- end;
- end;
- { Check whether this is known/predefined mode }
- for l := lowNewMode to highNewMode do
- if (resolutions[l].x = x) and
- (resolutions[l].y = y) then
- begin
- { Found! }
- mode := l;
- exit;
- end;
- { Not Found }
- mode := maxsmallint;
- end;
- function mode2res(modeNr: smallInt; var x,y: longint): boolean;
- begin
- if (modeNr < lowNewMode) or
- (modeNr > highNewMode) then
- begin
- mode2res := false;
- exit;
- end;
- mode2res := true;
- x := resolutions[modeNr].x;
- y := resolutions[modeNr].y;
- end;
- {$endif nonewmodes}
- procedure addmode(const mode: TModeInfo);
- {********************************************************}
- { Procedure AddMode() }
- {--------------------------------------------------------}
- { This routine adds <mode> to the list of recognized }
- { modes. Duplicates are allowed. }
- {********************************************************}
- var
- {$ifndef nonewmodes}
- i,driverNr, modeNr: smallint;
- prev: PModeInfo;
- {$endif nonewmodes}
- list: PModeInfo;
- newlst : PModeInfo;
- begin
- {$ifndef nonewmodes}
- res2Mode(mode.maxx+1,mode.maxy+1,mode.maxColor,driverNr,ModeNr);
- { bitdepth supported? }
- if (driverNr <> maxsmallint) then
- begin
- { Yes, add the mode }
- if not assigned(newModeList.modeinfo[driverNr]) then
- begin
- {$ifdef logging}
- logln('Adding resolution '+strf(modenr)+' for drivernr '+strf(drivernr)+
- ' ('+strf(mode.maxx)+'x'+strf(mode.maxy)+')');
- {$endif logging}
- new(newModeList.modeinfo[driverNr]);
- newModeList.modeinfo[driverNr]^ := mode;
- newModeList.modeinfo[driverNr]^.next:=nil;
- end
- else
- begin
- prev := nil;
- list := newModeList.modeinfo[driverNr];
- { sort first by x resolution, then by yresolution }
- while assigned(list) and
- ((list^.maxx < mode.maxx) or
- ((list^.maxx = mode.maxx) and
- (list^.maxy < mode.maxy))) do
- begin
- prev := list;
- list := list^.next;
- end;
- { mode already exists? -> replace (assume later added modes are }
- { better) }
- if assigned(list) and
- (list^.maxx = mode.maxx) and
- (list^.maxy = mode.maxy) then
- begin
- {$ifdef logging}
- logln('replacing resolution '+strf(modenr)+' for drivernr '+strf(drivernr)+
- ' ('+strf(mode.maxx)+'x'+strf(mode.maxy)+')');
- {$endif logging}
- { save/restore next, drivernr and drivermode in list }
- prev := list^.next;
- list^ := mode;
- list^.next := prev;
- end
- else
- begin
- new(newLst);
- { Increase the number of modes for this driver }
- newLst^ := mode;
- {$ifdef logging}
- logln('Adding resolution '+strf(modenr)+' for drivernr '+strf(drivernr)+
- ' ('+strf(mode.maxx)+'x'+strf(mode.maxy)+')');
- {$endif logging}
- if assigned(list) then
- newLst^.next := list^.next
- else
- newLst^.next := nil;
- if assigned(prev) then
- prev^.next := newLst
- else
- newModeList.modeinfo[driverNr] := newLst;
- end;
- end;
- { renumber internmodenumber }
- list := newModeList.modeinfo[driverNr];
- i:=0;
- while assigned(list) do
- begin
- inc(i);
- list^.internmodenumber:=i;
- list:=list^.next;
- end;
- newModeList.loHiModeNr[driverNr].lo:=1;
- newModeList.loHiModeNr[driverNr].hi:=i;
- end;
- {$endif nonewmodes}
- { TP-like mode stuff }
- if not assigned(ModeList) then
- begin
- new(ModeList);
- move(mode, ModeList^, sizeof(Mode));
- end
- else
- begin
- list := ModeList;
- { go to the end of the list }
- while assigned(list^.next) do
- list:=list^.next;
- new(NewLst);
- list^.next := NewLst;
- move(mode, NewLst^, sizeof(Mode));
- end;
- end;
- procedure initmode(var mode: TModeInfo);
- {********************************************************}
- { Procedure InitMode() }
- {--------------------------------------------------------}
- { This routine initialized the mode to default values. }
- {********************************************************}
- begin
- FillChar(mode,sizeof(Mode),#0);
- end;
- function searchmode(ReqDriver : smallint; var reqmode: smallint): PModeInfo;
- {********************************************************}
- { Procedure SearchMode() }
- {--------------------------------------------------------}
- { This routine searches the list of recognized modes, }
- { and tries to find the <reqmode> in the <reqdriver> }
- { return nil if not found, otherwise returns the found }
- { structure. }
- { note: if reqmode = -32768, the first mode available }
- { for reqdriver is returned (JM) }
- { if reqmode = -32767, the last mode available }
- { for reqdriver is returned (JM) }
- {********************************************************}
- var
- list, lastModeInfo: PModeInfo;
- {$ifndef nonewmodes}
- x,y: longint;
- {$endif}
- begin
- {$ifdef logging}
- LogLn('Searching for driver '+strf(reqdriver)+' and mode '+strf(reqmode));
- {$endif logging}
- {$ifndef nonewmodes}
- if (reqDriver >= lowNewDriver) and
- (reqDriver <= highNewDriver) then
- begin
- case reqMode of
- -32768:
- begin
- reqMode := newModeList.loHiModeNr[reqDriver].lo;
- searchMode := newModeList.modeinfo[reqDriver];
- end;
- -32767:
- begin
- reqMode := newModeList.loHiModeNr[reqDriver].hi;
- searchMode := nil;
- { Are there any modes available for this driver? }
- if reqMode <> -1 then
- begin
- list := newModeList.modeinfo[reqDriver];
- while assigned(list^.next) do
- list := list^.next;
- searchMode := list;
- end;
- end;
- else
- begin
- list := newModeList.modeinfo[reqDriver];
- searchMode := nil;
- if not assigned(list) then
- exit;
- if mode2res(reqMode,x,y) then
- begin
- x := pred(x);
- y := pred(y);
- while assigned(list) and
- ((list^.maxx < x) or
- ((list^.maxx = x) and
- (list^.maxy < y))) do
- list := list^.next;
- if not assigned(list) or
- (list^.maxx <> x) or
- (list^.maxy <> y) then
- list := nil;
- searchmode := list;
- end
- else
- begin
- while assigned(list) and
- (list^.internModeNumber <> reqMode) do
- list := list^.next;
- searchMode := list;
- end;
- end;
- end;
- exit;
- end;
- {$endif nonewmodes}
- searchmode := nil;
- list := ModeList;
- If assigned(list) then
- lastModeInfo := list;
- { go to the end of the list }
- while assigned(list) do
- begin
- {$ifdef logging}
- Log('Found driver '+strf(list^.DriverNumber)+
- ' and mode $'+hexstr(list^.ModeNumber,4)+'...');
- {$endif logging}
- if ((list^.DriverNumber = ReqDriver) and
- ((list^.ModeNumber = ReqMode) or
- { search for lowest mode }
- (reqMode = -32768))) or
- { search for highest mode }
- ((reqMode = -32767) and
- (lastModeInfo^.driverNumber = reqDriver) and
- ((list^.driverNumber <> lastModeInfo^.driverNumber) or
- not(assigned(list^.next)))) then
- begin
- {$ifdef logging}
- LogLn('Accepted!');
- {$endif logging}
- searchmode := list;
- If reqMode = -32768 then
- reqMode := list^.ModeNumber
- else if reqMode = -32767 then
- begin
- reqMode := lastModeInfo^.ModeNumber;
- searchMode := lastModeInfo;
- end;
- exit;
- end;
- {$ifdef logging}
- LogLn('Rejected.');
- {$endif logging}
- lastModeInfo := list;
- list:=list^.next;
- end;
- end;
- {-----------------------------------------------------------------------}
- { External routines }
- {-----------------------------------------------------------------------}
- function GetModeName(ModeNumber: smallint): string;
- {********************************************************}
- { Function GetModeName() }
- {--------------------------------------------------------}
- { Checks the known video list, and returns ModeName }
- { string. On error returns an empty string. }
- {********************************************************}
- var
- mode: PModeInfo;
- begin
- mode:=nil;
- GetModeName:='';
- { only search in the current driver modes ... }
- mode:=SearchMode(IntCurrentNewDriver,ModeNumber);
- if assigned(mode) then
- GetModeName:=Mode^.ModeName
- else
- _GraphResult := grInvalidMode;
- end;
- function GetGraphMode: smallint;
- begin
- GetGraphMode := IntCurrentMode;
- end;
- function GetMaxMode: word;
- { I know , i know, this routine is very slow, and it would }
- { be much easier to sort the linked list of possible modes }
- { instead of doing this, but I'm lazy!! And anyways, the }
- { speed of the routine here is not that important.... }
- var
- i: smallint;
- mode: PModeInfo;
- begin
- mode:=nil;
- i:=0;
- repeat
- inc(i);
- { mode 0 always exists... }
- { start search at 1.. }
- mode:=SearchMode(IntCurrentNewDriver,i);
- until not assigned(mode);
- GetMaxMode:=i;
- end;
- procedure GetModeRange(GraphDriver: smallint; var LoMode,
- HiMode: smallint);
- var
- mode : PModeInfo;
- begin
- {$ifdef logging}
- LogLn('GetModeRange : Enter ('+strf(GraphDriver)+')');
- {$endif}
- HiMode:=-1;
- mode := nil;
- { First search if the graphics driver is supported .. }
- { since mode zero is always supported.. if that driver }
- { is supported it should return something... }
- { not true, e.g. VESA doesn't have a mode 0. Changed so}
- { -32768 means "return lowest mode in second parameter }
- { also, under VESA some modes may not be supported }
- { (e.g. $108 here) while some with a higher number can }
- { be supported ($112 and onward), so I also added that }
- { -32767 means "return highest mode in second parameter}
- { This whole system should be overhauled though to work}
- { without such hacks (JM) }
- loMode := -32768;
- mode := SearchMode(GraphDriver, loMode);
- { driver not supported...}
- if not assigned(mode) then
- begin
- loMode := -1;
- exit;
- end;
- {$ifdef logging}
- LogLn('GetModeRange : Mode '+strf(lomode)+' found');
- {$endif}
- { now it exists... find highest available mode... }
- hiMode := -32767;
- mode:=SearchMode(GraphDriver,hiMode);
- end;
- procedure SetGraphMode(mode: smallint);
- var
- modeinfo: PModeInfo;
- begin
- { check if the mode exists... }
- { Depending on the modenumber, we search using the old or new }
- { graphdriver number (because once we entered graphmode, }
- { getgraphmode() returns the old mode number and }
- { both setgraphmode(getgraphmode) and setgraphmode(mAAAxBBB) }
- { have to work (JM) }
- case mode of
- detectMode:
- begin
- mode := -32767;
- modeInfo := searchmode(IntcurrentNewDriver,mode);
- end;
- lowNewMode..highNewMode:
- modeInfo := searchmode(IntcurrentNewDriver,mode);
- else
- modeinfo := searchmode(IntcurrentDriver,mode);
- end;
- if not assigned(modeinfo) then
- begin
- {$ifdef logging}
- LogLn('Mode setting failed in setgraphmode pos 1');
- {$endif logging}
- _GraphResult := grInvalidMode;
- exit;
- end;
- { reset all hooks...}
- DefaultHooks;
- { arccall not reset - tested against VGA BGI driver }
- { Setup all hooks if none, keep old defaults...}
- { required hooks - returns error if no hooks to these }
- { routines. }
- if assigned(modeinfo^.DirectPutPixel) then
- DirectPutPixel := modeinfo^.DirectPutPixel
- else
- begin
- {$ifdef logging}
- LogLn('Mode setting failed in setgraphmode pos 2');
- {$endif logging}
- DefaultHooks;
- _Graphresult := grInvalidMode;
- exit;
- end;
- if assigned(modeinfo^.PutPixel) then
- PutPixel := modeinfo^.PutPixel
- else
- begin
- {$ifdef logging}
- LogLn('Mode setting failed in setgraphmode pos 3');
- {$endif logging}
- DefaultHooks;
- _Graphresult := grInvalidMode;
- exit;
- end;
- if assigned(modeinfo^.GetPixel) then
- GetPixel := modeinfo^.GetPixel
- else
- begin
- {$ifdef logging}
- LogLn('Mode setting failed in setgraphmode pos 4');
- {$endif logging}
- DefaultHooks;
- _Graphresult := grInvalidMode;
- exit;
- end;
- if assigned(modeinfo^.SetRGBPalette) then
- SetRGBPalette := modeinfo^.SetRGBPalette
- else
- begin
- {$ifdef logging}
- LogLn('Mode setting failed in setgraphmode pos 5');
- {$endif logging}
- DefaultHooks;
- _Graphresult := grInvalidMode;
- exit;
- end;
- if assigned(modeinfo^.GetRGBPalette) then
- GetRGBPalette := modeinfo^.GetRGBPalette
- else
- begin
- {$ifdef logging}
- LogLn('Mode setting failed in setgraphmode pos 6');
- {$endif logging}
- DefaultHooks;
- _Graphresult := grInvalidMode;
- exit;
- end;
- { optional hooks. }
- if assigned(modeinfo^.SetAllPalette) then
- SetAllPalette := modeinfo^.SetAllPalette;
- if assigned(modeinfo^.ClearViewPort) then
- ClearViewPort := modeinfo^.ClearViewPort;
- if assigned(modeinfo^.PutImage) then
- PutImage := modeinfo^.PutImage;
- if assigned(modeinfo^.GetImage) then
- GetImage := modeinfo^.GetImage;
- if assigned(modeinfo^.ImageSize) then
- ImageSize := modeinfo^.ImageSize;
- if assigned(modeinfo^.GetScanLine) then
- GetScanLine := modeinfo^.GetScanLine;
- if assigned(modeinfo^.Line) then
- Line := modeinfo^.Line;
- if assigned(modeinfo^.InternalEllipse) then
- InternalEllipse := modeinfo^.InternalEllipse;
- if assigned(modeinfo^.PatternLine) then
- PatternLine := modeinfo^.PatternLine;
- if assigned(modeinfo^.HLine) then
- Hline := modeinfo^.Hline;
- if assigned(modeinfo^.Vline) then
- VLine := modeinfo^.VLine;
- if assigned(modeInfo^.SetVisualPage) then
- SetVisualPage := modeInfo^.SetVisualPage;
- if assigned(modeInfo^.SetActivePage) then
- SetActivePage := modeInfo^.SetActivePage;
- if assigned(modeInfo^.OutTextXY) then
- OutTextXY:=modeInfo^.OutTextXY;
- IntCurrentMode := modeinfo^.ModeNumber;
- IntCurrentDriver := modeinfo^.DriverNumber;
- {$ifdef logging}
- logln('Entering mode '+strf(intCurrentMode)+' of driver '+strf(intCurrentDriver));
- {$endif logging}
- XAspect := modeinfo^.XAspect;
- YAspect := modeinfo^.YAspect;
- MaxX := modeinfo^.MaxX;
- MaxY := modeinfo^.MaxY;
- {$ifdef logging}
- logln('maxx = '+strf(maxx)+', maxy = '+strf(maxy));
- {$endif logging}
- HardwarePages := modeInfo^.HardwarePages;
- MaxColor := modeinfo^.MaxColor;
- PaletteSize := modeinfo^.PaletteSize;
- { is this a direct color mode? }
- DirectColor := modeinfo^.DirectColor;
- { now actually initialize the video mode...}
- { check first if the routine exists }
- if not assigned(modeinfo^.InitMode) then
- begin
- {$ifdef logging}
- LogLn('Mode setting failed in setgraphmode pos 7');
- {$endif logging}
- DefaultHooks;
- _GraphResult := grInvalidMode;
- exit;
- end;
- modeinfo^.InitMode;
- if _GraphResult <> grOk then
- begin
- DefaultHooks;
- exit;
- end;
- isgraphmode := true;
- { It is very important that this call be made }
- { AFTER the other variables have been setup. }
- { Since it calls some routines which rely on }
- { those variables. }
- SetActivePage(0);
- SetVisualPage(0);
- SetViewPort(0,0,MaxX,MaxY,TRUE);
- GraphDefaults;
- end;
- procedure RestoreCrtMode;
- {********************************************************}
- { Procedure RestoreCRTMode() }
- {--------------------------------------------------------}
- { Returns to the video mode which was set before the }
- { InitGraph. Hardware state is set to the old values. }
- {--------------------------------------------------------}
- { NOTE: - }
- { - }
- {********************************************************}
- begin
- isgraphmode := false;
- RestoreVideoState;
- end;
- {
- $Log$
- Revision 1.5 2001-04-13 23:49:48 peter
- * fixes for the stricter compiler
- Revision 1.4 2000/08/12 12:27:14 jonas
- + setallpalette hook
- + setallpalette implemented for standard vga and VESA 2.0+
- Revision 1.3 2000/08/01 06:03:32 jonas
- * the defaulthooks are reset if setmode() fails at any point (merged
- from fixes branch)
- Revision 1.2 2000/07/13 11:33:47 michael
- + removed logs
- }
|