123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254 |
- {
- This file is part of the Free Pascal run time library.
- Copyright (c) 1993,99 by Carl Eric Codere
- This include implements VESA basic access.
- 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.
- **********************************************************************}
- type
- pModeList = ^tModeList;
- tModeList = Array [0..255] of word; {list of modes terminated by -1}
- {VESA modes are >=100h}
- palrec = packed record { record used for set/get DAC palette }
- red: byte;
- green: byte;
- blue : byte;
- align: byte;
- end;
- const
- { VESA attributes }
- attrSwitchDAC = $01; { DAC is switchable (1.2) }
- attrNotVGACompatible = $02; { Video is NOT VGA compatible (2.0) }
- attrSnowCheck = $04; { Video must use snow checking(2.0) }
- { mode attribute bits }
- modeAvail = $01; { Hardware supports this mode (1.0) }
- modeExtendInfo = $02; { Extended information (1.0) }
- modeBIOSSupport = $04; { TTY BIOS Support (1.0) }
- modeColor = $08; { This is a color mode (1.0) }
- modeGraphics = $10; { This is a graphics mode (1.0) }
- modeNotVGACompatible = $20; { this mode is NOT I/O VGA compatible (2.0)}
- modeNoWindowed = $40; { This mode does not support Windows (2.0) }
- modeLinearBuffer = $80; { This mode supports linear buffers (2.0) }
- { window attributes }
- winSupported = $01;
- winReadable = $02;
- winWritable = $04;
- { memory model }
- modelText = $00;
- modelCGA = $01;
- modelHerc = $02;
- model4plane = $03;
- modelPacked = $04;
- modelModeX = $05;
- modelRGB = $06;
- modelYUV = $07;
- TYPE
- TVESAinfo = packed record { VESA Information request }
- signature : array [1..4] of char; { This should be VESA }
- version : word; { VESA revision }
- str : pChar; { pointer to OEM string }
- caps : longint; { video capabilities }
- modeList : pModeList; { pointer to SVGA modes }
- pad : array [18..260] of byte; { extra padding more then }
- end; { VESA standard because of bugs on }
- { some video cards. }
- TVESAModeInfo = packed record
- attr : word; { mode attributes (1.0) }
- winAAttr,
- winBAttr : byte; { window attributes (1.0) }
- winGranularity : word; {in K} { Window granularity (1.0) }
- winSize : word; {in K} { window size (1.0) }
- winASeg, { Window A Segment address (1.0) }
- winBSeg : word; { Window B Segment address (1.0) }
- winFunct : procedure; { Function to swtich bank }
- BytesPerScanLine: word; {bytes per scan line (1.0) }
- { extended information }
- extendedInfo : packed record
- xRes, yRes : word; {pixels}
- xCharSize,
- yCharSize : byte;
- planes : byte;
- bitsPixel : byte;
- banks : byte;
- memModel : byte;
- bankSize : byte; {in K}
- NumberOfPages: byte;
- end;
- pad : array [29..260] of byte; { always put some more space then required}
- end;
- var
- VESAInfo : TVESAInfo; { VESA Driver information }
- ModeInfo : TVESAModeInfo; { Current Mode information }
- BytesPerLine: word; { Number of bytes per scanline }
- { window management }
- ReadWindow : byte; { Window number for reading. }
- WriteWindow: byte; { Window number for writing. }
- winReadSeg : word; { Address of segment for read }
- winWriteSeg: word; { Address of segment for writes}
- CurrentReadBank : integer; { active read bank }
- CurrentWriteBank: integer; { active write bank }
- BankShift : word; { address to shift by when switching banks. }
- funct : procedure;
- function hexstr(val : longint;cnt : byte) : string;
- const
- HexTbl : array[0..15] of char='0123456789ABCDEF';
- var
- i : longint;
- begin
- hexstr[0]:=char(cnt);
- for i:=cnt downto 1 do
- begin
- hexstr[i]:=hextbl[val and $f];
- val:=val shr 4;
- end;
- end;
- {$IFDEF DPMI}
- function getVESAInfo(var VESAInfo: TVESAInfo) : boolean;
- var
- ptrlong : longint;
- VESAPtr : ^TVESAInfo;
- regs : TDPMIRegisters;
- ModeSel: word;
- offs: longint;
- { added... }
- modelist: PmodeList;
- modeptr : pointer;
- i: longint;
- RealSeg : word;
- begin
- { Allocate real mode buffer }
- Ptrlong:=GlobalDosAlloc(sizeof(TVESAInfo));
- { Get selector value }
- VESAPtr := pointer(longint(Ptrlong and $0000ffff) shl 16);
- { Get segment value }
- RealSeg := word((Ptrlong and $ffff0000) shr 16);
- if not assigned(VESAPtr) then
- RunError(203);
- FillChar(regs, sizeof(TDPMIRegisters), #0);
- { Get VESA Mode information ... }
- regs.eax := $4f00;
- regs.es := RealSeg;
- regs.edi := $00;
- RealIntr($10, regs);
- if VESAPtr^.Signature <> 'VESA' then
- begin
- getVesaInfo := FALSE;
- GlobalDosFree(word(longint(VESAPtr) shr 16));
- exit;
- end
- else
- getVesaInfo := TRUE;
- { The mode pointer buffer points to a real mode memory }
- { Therefore steps to get the modes: }
- { 1. Allocate Selector and SetLimit to max number of }
- { of possible modes. }
- ModeSel := AllocSelector(0);
- SetSelectorLimit(ModeSel, 256*sizeof(word));
- { 2. Set Selector linear address to the real mode pointer }
- { returned. }
- offs := longint((longint(VESAPtr^.ModeList) and $ffff0000) shr 16) shl 4;
- offs:= offs OR word(VESAPtr^.ModeList);
- SetSelectorBase(ModeSel, offs);
- { copy VESA mode information to a protected mode buffer and }
- { then free the real mode buffer... }
- Move(VESAPtr^, VESAInfo, sizeof(TVESAInfo));
- GlobalDosFree(word(longint(VESAPtr) shr 16));
- { ModeList points to the mode list }
- { We must copy it somewhere... }
- ModeList := Ptr(ModeSel, 0);
- i:=0;
- new(VESAInfo.ModeList);
- while ModeList^[i]<> $ffff do
- begin
- VESAInfo.ModeList^[i] := ModeList^[i];
- Inc(i);
- end;
- VESAInfo.ModeList^[i]:=$ffff;
- { Free the temporary selector used to get mode information }
- FreeSelector(ModeSel);
- end;
- function getModeInfo(var ModeInfo: TVESAModeInfo;mode:word):boolean;
- var
- Ptr: longint;
- VESAPtr : ^TModeInfo;
- regs : TDPMIRegisters;
- RealSeg: word;
- begin
- { Alllocate real mode buffer }
- Ptr:=GlobalDosAlloc(sizeof(TModeInfo));
- { get the selector and segment values }
- VESAPtr := pointer(longint(Ptr and $0000ffff) shl 16);
- RealSeg := word((Ptr and $ffff0000) shr 16);
- if not assigned(VESAPtr) then
- RunError(203);
- { setup interrupt registers }
- FillChar(regs, sizeof(TDPMIRegisters), #0);
- { call VESA mode information...}
- regs.eax := $4f01;
- regs.es := RealSeg;
- regs.edi := $00;
- regs.ecx := mode;
- RealIntr($10, regs);
- if word(regs.eax) <> $4f then
- getModeInfo := FALSE
- else
- getModeInfo := TRUE;
- { copy to protected mode buffer ... }
- Move(VESAPtr^, ModeInfo, sizeof(TModeInfo));
- { free real mode memory }
- GlobalDosFree(word(longint(VESAPtr) shr 16));
- end;
- {$ELSE}
- function getVESAInfo(var VESAInfo: TVESAInfo) : boolean; assembler;
- asm
- mov ax,4F00h
- les di,VESAInfo
- int 10h
- sub ax,004Fh {make sure we got 004Fh back}
- cmp ax,1
- sbb al,al
- cmp word ptr es:[di],'V'or('E'shl 8) {signature should be 'VESA'}
- jne @@ERR
- cmp word ptr es:[di+2],'S'or('A'shl 8)
- je @@X
- @@ERR:
- mov al,0
- @@X:
- end;
- function getModeInfo(var ModeInfo: TVESAModeInfo;mode:word):boolean;assembler;
- asm
- mov ax,4F01h
- mov cx,mode
- les di,ModeInfo
- int 10h
- sub ax,004Fh {make sure it's 004Fh}
- cmp ax,1
- sbb al,al
- end;
- {$ENDIF}
- function SearchVESAModes(mode: Word): boolean;
- {********************************************************}
- { Searches for a specific DEFINED vesa mode. If the mode }
- { is not available for some reason, then returns FALSE }
- { otherwise returns TRUE. }
- {********************************************************}
- var
- i: word;
- ModeSupported : Boolean;
- begin
- i:=0;
- { let's assume it's not available ... }
- ModeSupported := FALSE;
- { This is a STUB VESA implementation }
- if VESAInfo.ModeList^[0] = $FFFF then exit;
- repeat
- if VESAInfo.ModeList^[i] = mode then
- begin
- { we found it, the card supports this mode... }
- ModeSupported := TRUE;
- break;
- end;
- Inc(i);
- until VESAInfo.ModeList^[i] = $ffff;
- { now check if the hardware supports it... }
- If ModeSupported then
- begin
- { we have to init everything to zero, since VBE < 1.1 }
- { may not setup fields correctly. }
- FillChar(ModeInfo, sizeof(ModeInfo), #0);
- GetModeInfo(ModeInfo, Mode);
- if (ModeInfo.attr and modeAvail) <> 0 then
- ModeSupported := TRUE
- else
- ModeSupported := FALSE;
- end;
- SearchVESAModes := ModeSupported;
- end;
- procedure SetBankIndex(win: byte; BankNr: Integer); assembler;
- asm
- mov ax,4f05h
- mov bh,00h
- mov bl,[Win]
- mov dx,[BankNr]
- int 10h
- end;
- {********************************************************}
- { There are two routines for setting banks. This may in }
- { in some cases optimize a bit some operations, if the }
- { hardware supports it, because one window is used for }
- { reading and one window is used for writing. }
- {********************************************************}
- procedure SetReadBank(BankNr: Integer);
- begin
- { check if this is the current bank... if so do nothing. }
- if BankNr = CurrentReadBank then exit;
- CurrentReadBank := BankNr; { save current bank number }
- BankNr := BankNr shl BankShift; { adjust to window granularity }
- { we set both banks, since one may read only }
- SetBankIndex(ReadWindow, BankNr);
- { if the hardware supports only one window }
- { then there is only one single bank, so }
- { update both bank numbers. }
- if ReadWindow = WriteWindow then
- CurrentWriteBank := CurrentReadBank;
- end;
- procedure SetWriteBank(BankNr: Integer);
- begin
- { check if this is the current bank... if so do nothing. }
- if BankNr = CurrentWriteBank then exit;
- CurrentWriteBank := BankNr; { save current bank number }
- BankNr := BankNr shl BankShift; { adjust to window granularity }
- { we set both banks, since one may read only }
- SetBankIndex(WriteWindow, BankNr);
- { if the hardware supports only one window }
- { then there is only one single bank, so }
- { update both bank numbers. }
- if ReadWindow = WriteWindow then
- CurrentReadBank := CurrentWriteBank;
- end;
- {************************************************************************}
- {* 8-bit pixels VESA mode routines *)
- {************************************************************************}
- procedure PutPixVESA256(x, y : integer; color : word);
- var
- bank : word;
- offs : longint;
- begin
- X:= X + StartXViewPort;
- Y:= Y + StartYViewPort;
- { convert to absolute coordinates and then verify clipping...}
- if ClipPixels then
- Begin
- if (X < StartXViewPort) or (X > (StartXViewPort + ViewWidth)) then
- exit;
- if (Y < StartYViewPort) or (Y > (StartYViewPort + ViewHeight)) then
- exit;
- end;
- offs := longint(y) * BytesPerLine + x;
- SetWriteBank(integer(offs shr 16));
- mem[WinWriteSeg : word(offs)] := byte(color);
- end;
- procedure DirectPutPixVESA256(x, y : integer);
- var
- bank : word;
- offs : longint;
- begin
- offs := longint(y) * BytesPerLine + x;
- SetWriteBank(integer(offs shr 16));
- mem[WinWriteSeg : word(offs)] := byte(CurrentColor);
- end;
- function GetPixVESA256(x, y : integer): word;
- var
- bank : word;
- offs : longint;
- begin
- X:= X + StartXViewPort;
- Y:= Y + StartYViewPort;
- offs := longint(y) * BytesPerLine + x;
- SetReadBank(integer(offs shr 16));
- GetPixVESA256:=mem[WinWriteSeg : word(offs)];
- end;
- {************************************************************************}
- {* 15/16bit pixels VESA mode routines *)
- {************************************************************************}
- procedure PutPixVESA32k(x, y : integer; color : word);
- var
- bank : word;
- offs : longint;
- begin
- X:= X + StartXViewPort;
- Y:= Y + StartYViewPort;
- { convert to absolute coordinates and then verify clipping...}
- if ClipPixels then
- Begin
- if (X < StartXViewPort) or (X > (StartXViewPort + ViewWidth)) then
- exit;
- if (Y < StartYViewPort) or (Y > (StartYViewPort + ViewHeight)) then
- exit;
- end;
- offs := longint(y) * BytesPerLine + 2*x;
- SetWriteBank(integer(offs shr 16));
- memW[WinWriteSeg : word(offs)] := color;
- end;
- procedure PutPixVESA64k(x, y : integer; color : word);
- var
- bank : word;
- offs : longint;
- begin
- X:= X + StartXViewPort;
- Y:= Y + StartYViewPort;
- { convert to absolute coordinates and then verify clipping...}
- if ClipPixels then
- Begin
- if (X < StartXViewPort) or (X > (StartXViewPort + ViewWidth)) then
- exit;
- if (Y < StartYViewPort) or (Y > (StartYViewPort + ViewHeight)) then
- exit;
- end;
- offs := longint(y) * BytesPerLine + 2*x;
- SetWriteBank(integer(offs shr 16));
- memW[WinWriteSeg : word(offs)] := color;
- end;
- function GetPixVESA32k(x, y : integer): word;
- var
- bank : word;
- offs : longint;
- begin
- X:= X + StartXViewPort;
- Y:= Y + StartYViewPort;
- offs := longint(y) * BytesPerLine + 2*x;
- SetReadBank(integer(offs shr 16));
- GetPixVESA32k:=memW[WinWriteSeg : word(offs)];
- end;
- function GetPixVESA64k(x, y : integer): word;
- var
- bank : word;
- offs : longint;
- begin
- X:= X + StartXViewPort;
- Y:= Y + StartYViewPort;
- offs := longint(y) * BytesPerLine + 2*x;
- SetReadBank(integer(offs shr 16));
- GetPixVESA64k:=memW[WinWriteSeg : word(offs)];
- end;
- procedure DirectPutPixVESA32k(x, y : integer);
- var
- bank : word;
- offs : longint;
- begin
- offs := longint(y) * BytesPerLine + 2*x;
- SetWriteBank(integer((offs shr 16) and $ff));
- memW[WinWriteSeg : word(offs)] := CurrentColor;
- end;
- procedure DirectPutPixVESA64k(x, y : integer);
- var
- bank : word;
- offs : longint;
- begin
- offs := longint(y) * BytesPerLine + 2*x;
- SetWriteBank(integer(offs shr 16));
- memW[WinWriteSeg : word(offs)] := CurrentColor;
- end;
- {************************************************************************}
- {* 4-bit pixels VESA mode routines *)
- {************************************************************************}
- procedure PutPixVESA16(x, y : integer; color : word);
- var
- bank : word;
- offs : longint;
- dummy_read : byte;
- begin
- X:= X + StartXViewPort;
- Y:= Y + StartYViewPort;
- { convert to absolute coordinates and then verify clipping...}
- if ClipPixels then
- Begin
- if (X < StartXViewPort) or (X > (StartXViewPort + ViewWidth)) then
- exit;
- if (Y < StartYViewPort) or (Y > (StartYViewPort + ViewHeight)) then
- exit;
- end;
- { this can be done only once at InitGraph }
- PortW[$3C4] := $0f02;
- PortW[$3CE] := $0003;
- PortW[$3CE] := $0205;
- { }
- offs := longint(y) * BytesPerLine + (x div 8);
- SetWriteBank(integer(offs shr 16));
- port[$3CE] := $08;
- port[$3CF] := ($80 shr (x and 7));
- dummy_read := mem[WinWriteSeg : word(offs)];
- mem[winWriteSeg : offs] := byte(color);
- { this can be done only once at DoneGraph..}
- PortW[$3CE] := $FF08;
- PortW[$3CE] := $0005;
- { }
- end;
- procedure DirectPutPixVESA16(x, y : integer);
- var
- bank : word;
- offs : longint;
- dummy_read : byte;
- begin
- { this can be done only once at InitGraph }
- PortW[$3C4] := $0f02;
- PortW[$3CE] := $0003;
- PortW[$3CE] := $0205;
- { }
- offs := longint(y) * BytesPerLine + (x div 8);
- SetWriteBank(integer(offs shr 16));
- port[$3CE] := $08;
- port[$3CF] := ($80 shr (x and 7));
- dummy_read := mem[WinWriteSeg : word(offs)];
- mem[winWriteSeg : offs] := byte(CurrentColor);
- { this can be done only once at DoneGraph..}
- PortW[$3CE] := $FF08;
- PortW[$3CE] := $0005;
- { }
- end;
- {************************************************************************}
- {* VESA Palette entries *)
- {************************************************************************}
- { BIG PROBLEM: The routines seems to be wrong, with Function 09h on my ATI }
- { technologies MACH64 - the palrec record seems to be at the END of the }
- { record, contrary to the VBE 2 specification!!! To verify with other video}
- { cards. }
- {$IFDEF DPMI}
- Procedure SetVESARGBPalette(ColorNum, RedValue, GreenValue,
- BlueValue : Integer);
- var
- FunctionNr : byte; { use blankbit or normal RAMDAC programming? }
- pal: palrec;
- Error : boolean; { VBE call error }
- regs: TDPMIRegisters;
- Ptr: longint;
- PalPtr : ^PalRec;
- RealSeg: word;
- begin
- if DirectColor then
- Begin
- _GraphResult := grError;
- exit;
- end;
- Error := TRUE;
- pal.align := 0;
- pal.red := byte(RedValue);
- pal.green := byte(GreenValue);
- pal.blue := byte(BlueValue);
- { use the set/get palette function }
- if VESAInfo.Version >= $0200 then
- Begin
- { check if blanking bit must be set when programming }
- { the RAMDAC. }
- if (VESAInfo.caps and attrSnowCheck) <> 0 then
- FunctionNr := $80
- else
- FunctionNr := $00;
- { Alllocate real mode buffer }
- Ptr:=GlobalDosAlloc(sizeof(palrec));
- { get the selector and segment values }
- PalPtr := pointer(longint(Ptr and $0000ffff) shl 16);
- RealSeg := word((Ptr and $ffff0000) shr 16);
- if not assigned(PalPtr) then
- RunError(203);
- { setup interrupt registers }
- FillChar(regs, sizeof(TDPMIRegisters), #0);
- { copy palette values to real mode buffer }
- move(pal, palptr^, sizeof(palrec));
- regs.eax := $4F09;
- regs.ebx := FunctionNr;
- regs.ecx := $01;
- regs.edx := ColorNum;
- regs.es := RealSeg;
- regs.edi := 0; { offset is always zero }
- RealIntr($10, regs);
- { free real mode memory }
- GlobalDosFree(word(longint(PalPtr) shr 16));
- if word(regs.eax) <> $004F then
- begin
- _GraphResult := grError;
- exit;
- end;
- end
- else
- { assume it's fully VGA compatible palette-wise. }
- Begin
- SetVGARGBPalette(ColorNum, RedValue, GreenValue, BlueValue);
- end;
- end;
- Procedure GetVESARGBPalette(ColorNum: integer; Var
- RedValue, GreenValue, BlueValue : integer);
- var
- pal: PalRec;
- Error: boolean;
- palptr : ^PalRec;
- regs : TDPMIRegisters;
- RealSeg: word;
- ptr: longint;
- begin
- if DirectColor then
- Begin
- _GraphResult := grError;
- exit;
- end;
- { use the set/get palette function }
- if VESAInfo.Version >= $0200 then
- Begin
- { Alllocate real mode buffer }
- Ptr:=GlobalDosAlloc(sizeof(palrec));
- { get the selector and segment values }
- PalPtr := pointer(longint(Ptr and $0000ffff) shl 16);
- RealSeg := word((Ptr and $ffff0000) shr 16);
- if not assigned(PalPtr) then
- RunError(203);
- { setup interrupt registers }
- FillChar(regs, sizeof(TDPMIRegisters), #0);
- regs.eax := $4F09;
- regs.ebx := $01; { get palette data }
- regs.ecx := $01;
- regs.edx := ColorNum;
- regs.es := RealSeg;
- regs.edi := 0; { offset is always zero }
- RealIntr($10, regs);
- { copy to protected mode buffer ... }
- Move(PalPtr^, Pal, sizeof(palrec));
- { free real mode memory }
- GlobalDosFree(word(longint(PalPtr) shr 16));
- if word(regs.eax) <> $004F then
- begin
- _GraphResult := grError;
- exit;
- end
- else
- begin
- RedValue := Integer(pal.Red);
- GreenValue := Integer(pal.Green);
- BlueValue := Integer(pal.Blue);
- end;
- end
- else
- GetVGARGBPalette(ColorNum, RedValue, GreenValue, BlueValue);
- end;
- {$ELSE}
- Procedure SetVESARGBPalette(ColorNum, RedValue, GreenValue,
- BlueValue : Integer);
- var
- FunctionNr : byte; { use blankbit or normal RAMDAC programming? }
- pal: ^palrec;
- Error : boolean; { VBE call error }
- begin
- if DirectColor then
- Begin
- _GraphResult := grError;
- exit;
- end;
- Error := FALSE;
- new(pal);
- if not assigned(pal) then RunError(203);
- pal^.align := 0;
- pal^.red := byte(RedValue);
- pal^.green := byte(GreenValue);
- pal^.blue := byte(BlueValue);
- { use the set/get palette function }
- if VESAInfo.Version >= $0200 then
- Begin
- { check if blanking bit must be set when programming }
- { the RAMDAC. }
- if (VESAInfo.caps and attrSnowCheck) <> 0 then
- FunctionNr := $80
- else
- FunctionNr := $00;
- asm
- mov ax, 4F09h { Set/Get Palette data }
- mov bl, [FunctionNr] { Set palette data }
- mov cx, 01h { update one palette reg. }
- mov dx, [ColorNum] { register number to update }
- les di, [pal] { get palette address }
- int 10h
- cmp ax, 004Fh { check if success }
- jz @noerror
- mov [Error], TRUE
- @noerror:
- end;
- if not Error then
- Dispose(pal)
- else
- begin
- _GraphResult := grError;
- exit;
- end;
- end
- else
- { assume it's fully VGA compatible palette-wise. }
- Begin
- SetVGARGBPalette(ColorNum, RedValue, GreenValue, BlueValue);
- end;
- end;
- Procedure GetVESARGBPalette(ColorNum: integer; Var
- RedValue, GreenValue, BlueValue : integer);
- var
- Error: boolean;
- pal: ^palrec;
- begin
- if DirectColor then
- Begin
- _GraphResult := grError;
- exit;
- end;
- Error := FALSE;
- new(pal);
- if not assigned(pal) then RunError(203);
- FillChar(pal^, sizeof(palrec), #0);
- { use the set/get palette function }
- if VESAInfo.Version >= $0200 then
- Begin
- asm
- mov ax, 4F09h { Set/Get Palette data }
- mov bl, 01h { Set palette data }
- mov cx, 01h { update one palette reg. }
- mov dx, [ColorNum] { register number to update }
- les di, [pal] { get palette address }
- int 10h
- cmp ax, 004Fh { check if success }
- jz @noerror
- mov [Error], TRUE
- @noerror:
- end;
- if not Error then
- begin
- RedValue := Integer(pal^.Red);
- GreenValue := Integer(pal^.Green);
- BlueValue := Integer(pal^.Blue);
- Dispose(pal);
- end
- else
- begin
- _GraphResult := grError;
- exit;
- end;
- end
- else
- GetVGARGBPalette(ColorNum, RedValue, GreenValue, BlueValue);
- end;
- {$ENDIF}
- procedure SetupLinear(var ModeInfo: TVESAModeInfo);
- begin
- { !!!!!!!!!!!!!!!!!!!!!!!!!!!!!! }
- end;
- procedure SetupWindows(var ModeInfo: TVESAModeInfo);
- begin
- { now we check the windowing scheme ...}
- if (ModeInfo.WinAAttr and WinSupported) <> 0 then
- { is this window supported ... }
- begin
- { now check if the window is R/W }
- if (ModeInfo.WinAAttr and WinReadable) <> 0 then
- begin
- ReadWindow := 0;
- WinReadSeg := ModeInfo.WinASeg;
- end;
- if (ModeInfo.WinAAttr and WinWritable) <> 0 then
- begin
- WriteWindow := 0;
- WinWriteSeg := ModeInfo.WinASeg;
- end;
- end;
- if (ModeInfo.WinBAttr and WinSupported) <> 0 then
- { is this window supported ... }
- begin
- { OPTIMIZATION ... }
- { if window A supports both read/write, then we try to optimize }
- { everything, by using a different window for Read and/or write.}
- if (WinReadSeg <> 0) and (WinWriteSeg <> 0) then
- begin
- { check if winB supports read }
- if (ModeInfo.WinBAttr and winReadable) <> 0 then
- begin
- WinReadSeg := ModeInfo.WinBSeg;
- ReadWindow := 1;
- end
- else
- { check if WinB supports write }
- if (ModeInfo.WinBAttr and WinWritable) <> 0 then
- begin
- WinWriteSeg := ModeInfo.WinBSeg;
- WriteWindow := 1;
- end;
- end
- else
- { Window A only supported Read OR Write, no we have to make }
- { sure that window B supports the other mode. }
- if (WinReadSeg = 0) and (WinWriteSeg<>0) then
- begin
- if (ModeInfo.WinBAttr and WinReadable <> 0) then
- begin
- ReadWindow := 1;
- WinReadSeg := ModeInfo.WinBSeg;
- end
- else
- { impossible, this VESA mode is WRITE only! }
- begin
- WriteLn('Invalid VESA Window attribute.');
- Halt(255);
- end;
- end
- else
- if (winWriteSeg = 0) and (WinReadSeg<>0) then
- begin
- if (ModeInfo.WinBAttr and WinWritable) <> 0 then
- begin
- WriteWindow := 1;
- WinWriteSeg := ModeInfo.WinBSeg;
- end
- else
- { impossible, this VESA mode is READ only! }
- begin
- WriteLn('Invalid VESA Window attribute.');
- Halt(255);
- end;
- end
- else
- if (winReadSeg = 0) and (winWriteSeg = 0) then
- { no read/write in this mode! }
- begin
- WriteLn('Invalid VESA Window attribute.');
- Halt(255);
- end;
- end;
- { if both windows are not supported, then we can assume }
- { that there is ONE single NON relocatable window. }
- if (WinWriteSeg = 0) and (WinReadSeg = 0) then
- begin
- WinWriteSeg := ModeInfo.WinASeg;
- WinReadSeg := ModeInfo.WinASeg;
- end;
- { 16-bit Protected mode checking code... }
- { change segment values to protected mode }
- { selectors. }
- if WinReadSeg = $A000 then
- WinReadSeg := SegA000
- else
- if WinReadSeg = $B000 then
- WinReadSeg := SegB000
- else
- if WinReadSeg = $B800 then
- WinReadSeg := SegB800
- else
- begin
- WriteLn('Invalid segment address.');
- Halt(255);
- end;
- if WinWriteSeg = $A000 then
- WinWriteSeg := SegA000
- else
- if WinWriteSeg = $B000 then
- WinWriteSeg := SegB000
- else
- if WinWriteSeg = $B800 then
- WinWriteSeg := SegB800
- else
- begin
- WriteLn('Invalid segment address.');
- Halt(255);
- end;
- end;
- function setVESAMode(mode:word):boolean;
- var i:word;
- begin
- { Init mode information, for compatibility with VBE < 1.1 }
- FillChar(ModeInfo, sizeof(ModeInfo), #0);
- { get the video mode information }
- if getModeInfo(modeinfo, mode) then
- begin
- { checks if the hardware supports the video mode. }
- if (ModeInfo.attr and modeAvail) <> 0 then
- begin
- SetVESAMode := TRUE;
- end
- else
- begin
- SetVESAmode := TRUE;
- _GraphResult := grError;
- exit;
- end;
- BankShift := 0;
- while (64 shl BankShift) <> ModeInfo.WinGranularity do
- Inc(BankShift);
- CurrentWriteBank := -1;
- CurrentReadBank := -1;
- BytesPerLine := ModeInfo.BytesPerScanLine;
- { These are the window adresses ... }
- WinWriteSeg := 0; { This is the segment to use for writes }
- WinReadSeg := 0; { This is the segment to use for reads }
- ReadWindow := 0;
- WriteWindow := 0;
- { VBE 2.0 and higher supports >= non VGA linear buffer types...}
- { this is backward compatible. }
- if ((ModeInfo.Attr and ModeNoWindowed) <> 0) and
- ((ModeInfo.Attr and ModeLinearBuffer) <> 0) then
- SetupLinear(ModeInfo)
- else
- { if linear and windowed is supported, then use windowed }
- { method. }
- SetUpWindows(ModeInfo);
- asm
- mov ax,4F02h
- mov bx,mode
- int 10h
- sub ax,004Fh
- cmp ax,1
- sbb al,al
- mov @RESULT,al
- end;
- end;
- end;
- function getVESAMode:word;assembler;
- asm {return -1 if error}
- mov ax,4F03h
- int 10h
- cmp ax,004Fh
- je @@OK
- mov ax,-1
- jmp @@X
- @@OK:
- mov ax,bx
- @@X:
- end;
- {************************************************************************}
- {* VESA Modes inits *)
- {************************************************************************}
- procedure Init1280x1024x64k;
- begin
- SetVesaMode(m1280x1024x64k);
- end;
- procedure Init1280x1024x32k;
- begin
- SetVESAMode(m1280x1024x32k);
- end;
- procedure Init1280x1024x256;
- begin
- SetVESAMode(m1280x1024x256);
- end;
- procedure Init1280x1024x16;
- begin
- SetVESAMode(m1280x1024x16);
- end;
- procedure Init1024x768x64k;
- begin
- SetVESAMode(m1024x768x64k);
- end;
- procedure Init640x480x32k;
- begin
- SetVESAMode(m640x480x32k);
- end;
- procedure Init1024x768x256;
- begin
- SetVESAMode(m1024x768x256);
- end;
- procedure Init1024x768x16;
- begin
- SetVESAMode(m1024x768x16);
- end;
- procedure Init800x600x64k;
- begin
- SetVESAMode(m800x600x64k);
- end;
- procedure Init800x600x32k;
- begin
- SetVESAMode(m800x600x32k);
- end;
- procedure Init800x600x256;
- begin
- SetVESAMode(m800x600x256);
- end;
- procedure Init800x600x16;
- begin
- SetVesaMode(m800x600x16);
- end;
- procedure Init640x480x64k;
- begin
- SetVESAMode(m640x480x64k);
- end;
- procedure Init640x480x256;
- begin
- SetVESAMode(m640x480x256);
- end;
- procedure Init640x400x256;
- begin
- SetVESAMode(m640x400x256);
- end;
- procedure Init320x200x64k;
- begin
- SetVESAMode(m320x200x64k);
- end;
- procedure Init320x200x32k;
- begin
- SetVESAMode(m320x200x32k);
- end;
- {$IFDEF DPMI}
- Procedure SaveStateVESA;
- var
- PtrLong: longint;
- regs: TDPMIRegisters;
- begin
- SaveSupported := FALSE;
- SavePtr := nil;
- { Get the video mode }
- asm
- mov ah,0fh
- int 10h
- mov [VideoMode], al
- end;
- { Prepare to save video state...}
- asm
- mov ax, 4F04h { get buffer size to save state }
- mov dx, 00h
- mov cx, 00001111b { Save DAC / Data areas / Hardware states }
- int 10h
- mov [StateSize], bx
- cmp al,04fh
- jnz @notok
- mov [SaveSupported],TRUE
- @notok:
- end;
- if SaveSupported then
- begin
- PtrLong:=GlobalDosAlloc(64*StateSize); { values returned in 64-byte blocks }
- if PtrLong = 0 then
- RunError(203);
- SavePtr := pointer(longint(PtrLong and $0000ffff) shl 16);
- RealStateSeg := word((PtrLong and $ffff0000) shr 16);
- if not assigned(SavePtr) then
- RunError(203);
- FillChar(regs, sizeof(regs), #0);
- { call the real mode interrupt ... }
- regs.eax := $4F04; { save the state buffer }
- regs.ecx := $0F; { Save DAC / Data areas / Hardware states }
- regs.edx := $01; { save state }
- regs.es := RealStateSeg;
- regs.ebx := 0;
- RealIntr($10,regs);
- FillChar(regs, sizeof(regs), #0);
- { restore state, according to Ralph Brown Interrupt list }
- { some BIOS corrupt the hardware after a save... }
- regs.eax := $4F04; { restore the state buffer }
- regs.ecx := $0F; { rest DAC / Data areas / Hardware states }
- regs.edx := $02;
- regs.es := RealStateSeg;
- regs.ebx := 0;
- RealIntr($10,regs);
- end;
- end;
- procedure RestoreStateVESA;
- var
- regs:TDPMIRegisters;
- begin
- { go back to the old video mode...}
- asm
- mov ah,00
- mov al,[VideoMode]
- int 10h
- end;
- { then restore all state information }
- if assigned(SavePtr) and (SaveSupported=TRUE) then
- begin
- FillChar(regs, sizeof(regs), #0);
- { restore state, according to Ralph Brown Interrupt list }
- { some BIOS corrupt the hardware after a save... }
- regs.eax := $4F04; { restore the state buffer }
- regs.ecx := $0F; { rest DAC / Data areas / Hardware states }
- regs.edx := $02; { restore state }
- regs.es := RealStateSeg;
- regs.ebx := 0;
- RealIntr($10,regs);
- if GlobalDosFree(longint(SavePtr) shr 16)<>0 then
- RunError(216);
- SavePtr := nil;
- end;
- end;
- {$ELSE}
- {**************************************************************}
- {* Real mode routines *}
- {**************************************************************}
- Procedure SaveStateVESA;
- begin
- SavePtr := nil;
- SaveSupported := FALSE;
- { Get the video mode }
- asm
- mov ah,0fh
- int 10h
- mov [VideoMode], al
- end;
- { Prepare to save video state...}
- asm
- mov ax, 1C00h { get buffer size to save state }
- mov cx, 00000111b { Save DAC / Data areas / Hardware states }
- int 10h
- mov [StateSize], bx
- cmp al,01ch
- jnz @notok
- mov [SaveSupported],TRUE
- @notok:
- end;
- if SaveSupported then
- Begin
- GetMem(SavePtr, 64*StateSize); { values returned in 64-byte blocks }
- if not assigned(SavePtr) then
- RunError(203);
- asm
- mov ax, 4F04h { save the state buffer }
- mov cx, 00001111b { Save DAC / Data areas / Hardware states }
- mov dx, 01h
- mov es, WORD PTR [SavePtr+2]
- mov bx, WORD PTR [SavePtr]
- int 10h
- end;
- { restore state, according to Ralph Brown Interrupt list }
- { some BIOS corrupt the hardware after a save... }
- asm
- mov ax, 4F04h { save the state buffer }
- mov cx, 00001111b { Save DAC / Data areas / Hardware states }
- mov dx, 02h
- mov es, WORD PTR [SavePtr+2]
- mov bx, WORD PTR [SavePtr]
- int 10h
- end;
- end;
- end;
- procedure RestoreStateVESA;
- begin
- { go back to the old video mode...}
- asm
- mov ah,00
- mov al,[VideoMode]
- int 10h
- end;
- { then restore all state information }
- if assigned(SavePtr) and (SaveSupported=TRUE) then
- begin
- { restore state, according to Ralph Brown Interrupt list }
- asm
- mov ax, 4F04h { save the state buffer }
- mov cx, 00001111b { Save DAC / Data areas / Hardware states }
- mov dx, 02h { restore state }
- mov es, WORD PTR [SavePtr+2]
- mov bx, WORD PTR [SavePtr]
- int 10h
- end;
- FreeMem(SavePtr, 64*StateSize);
- SavePtr := nil;
- end;
- end;
- {$ENDIF DPMI}
|