3 This file is part of the Free Pascal run time library.
4 Copyright (c) 1999-2000 by Carl Eric Codere
6 This include implements VESA basic access.
8 See the file COPYING.FPC, included in this distribution,
9 for details about the copyright.
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.
15 **********************************************************************}
18 palrec = packed record { record used for set/get DAC palette }
19 blue, green, red, align: byte;
24 attrSwitchDAC = $01; { DAC is switchable (1.2) }
25 attrNotVGACompatible = $02; { Video is NOT VGA compatible (2.0) }
26 attrSnowCheck = $04; { Video must use snow checking(2.0) }
28 { mode attribute bits }
29 modeAvail = $01; { Hardware supports this mode (1.0) }
30 modeExtendInfo = $02; { Extended information (1.0) }
31 modeBIOSSupport = $04; { TTY BIOS Support (1.0) }
32 modeColor = $08; { This is a color mode (1.0) }
33 modeGraphics = $10; { This is a graphics mode (1.0) }
34 modeNotVGACompatible = $20; { this mode is NOT I/O VGA compatible (2.0)}
35 modeNoWindowed = $40; { This mode does not support Windows (2.0) }
36 modeLinearBuffer = $80; { This mode supports linear buffers (2.0) }
55 { otherwise it's already included in graph.pp }
60 BytesPerLine: word; { Number of bytes per scanline }
61 YOffset : word; { Pixel offset for VESA page flipping }
64 ReadWindow : byte; { Window number for reading. }
65 WriteWindow: byte; { Window number for writing. }
66 winReadSeg : word; { Address of segment for read }
67 winWriteSeg: word; { Address of segment for writes}
68 CurrentReadBank : integer; { active read bank }
69 CurrentWriteBank: integer; { active write bank }
71 BankShift : word; { address to shift by when switching banks. }
73 { linear mode specific stuff }
74 InLinear : boolean; { true if in linear mode }
75 LinearPageOfs : longint; { offset used to set active page }
76 FrameBufferLinearAddress : longint;
78 ScanLines: word; { maximum number of scan lines for mode }
80 function hexstr(val : longint;cnt : byte) : string;
82 HexTbl : array[0..15] of char='0123456789ABCDEF';
87 for i:=cnt downto 1 do
89 hexstr[i]:=hextbl[val and $f];
97 function getVESAInfo(var VESAInfo: TVESAInfo) : boolean;
100 VESAPtr : ^TVESAInfo;
102 regs : TDPMIRegisters;
112 { Allocate real mode buffer }
114 Ptrlong:=GlobalDosAlloc(sizeof(TVESAInfo));
115 { Get selector value }
116 VESAPtr := pointer(Ptrlong shl 16);
118 Ptrlong:=Global_Dos_Alloc(sizeof(TVESAInfo));
121 { Get segment value }
122 RealSeg := word(Ptrlong shr 16);
123 if not assigned(VESAPtr) then
125 FillChar(regs, sizeof(regs), #0);
127 { Get VESA Mode information ... }
133 { no far pointer support in FPC yet, so move the vesa info into a memory }
134 { block in the DS slector space (JM) }
135 dosmemget(RealSeg,0,VesaPtr^,SizeOf(TVESAInfo));
137 St:=Vesaptr^.signature;
141 LogLn('No VESA detected.');
143 getVesaInfo := FALSE;
145 GlobalDosFree(word(PtrLong and $ffff));
147 If not Global_Dos_Free(word(PtrLong and $ffff)) then
149 { also free the extra allocated buffer }
158 { The mode pointer buffer points to a real mode memory }
159 { Therefore steps to get the modes: }
160 { 1. Allocate Selector and SetLimit to max number of }
161 { of possible modes. }
162 ModeSel := AllocSelector(0);
163 SetSelectorLimit(ModeSel, 256*sizeof(word));
165 { 2. Set Selector linear address to the real mode pointer }
167 offs := longint(longint(VESAPtr^.ModeList) shr 16) shl 4;
168 {shouldn't the OR in the next line be a + ?? (JM)}
169 offs := offs OR (Longint(VESAPtr^.ModeList) and $ffff);
170 SetSelectorBase(ModeSel, offs);
172 { copy VESA mode information to a protected mode buffer and }
173 { then free the real mode buffer... }
174 Move(VESAPtr^, VESAInfo, sizeof(VESAInfo));
175 GlobalDosFree(word(PtrLong and $ffff));
177 { ModeList points to the mode list }
178 { We must copy it somewhere... }
179 ModeList := Ptr(ModeSel, 0);
182 { No far pointer support, so the Ptr(ModeSel, 0) doesn't work. }
183 { Immediately copy everything to a buffer in the DS selector space }
185 { The following may copy data from outside the VESA buffer, but it }
186 { shouldn't get past the 1MB limit, since that would mean the buffer }
187 { has been allocated in the BIOS or high memory region, which seems }
188 { impossible to me (JM)}
189 DosMemGet(word(longint(VESAPtr^.ModeList) shr 16),
190 word(longint(VESAPtr^.ModeList) and $ffff), ModeList^,256*sizeof(word));
192 { copy VESA mode information to a protected mode buffer and }
193 { then free the real mode buffer... }
194 Move(VESAPtr^, VESAInfo, sizeof(VESAInfo));
195 If not Global_Dos_Free(word(PtrLong and $ffff)) then
201 new(VESAInfo.ModeList);
202 while ModeList^[i]<> $ffff do
205 LogLn('Found mode $'+hexstr(ModeList^[i],4));
207 VESAInfo.ModeList^[i] := ModeList^[i];
210 VESAInfo.ModeList^[i]:=$ffff;
211 { Free the temporary selector used to get mode information }
213 LogLn(strf(i) + ' modes found.');
216 FreeSelector(ModeSel);
222 function getVESAModeInfo(var ModeInfo: TVESAModeInfo;mode:word):boolean;
226 VESAPtr : ^TVESAModeInfo;
228 regs : TDPMIRegisters;
231 { Alllocate real mode buffer }
233 Ptr:=GlobalDosAlloc(sizeof(TVESAModeInfo));
234 { get the selector value }
235 VESAPtr := pointer(longint(Ptr shl 16));
236 if not assigned(VESAPtr) then
239 Ptr:=Global_Dos_Alloc(sizeof(TVESAModeInfo));
241 { get the segment value }
242 RealSeg := word(Ptr shr 16);
243 { setup interrupt registers }
244 FillChar(regs, sizeof(regs), #0);
245 { call VESA mode information...}
251 if word(regs.eax) <> $4f then
252 getVESAModeInfo := FALSE
254 getVESAModeInfo := TRUE;
255 { copy to protected mode buffer ... }
257 Move(VESAPtr^, ModeInfo, sizeof(ModeInfo));
259 DosMemGet(RealSeg,0,ModeInfo,sizeof(ModeInfo));
261 { free real mode memory }
263 GlobalDosFree(Word(Ptr and $ffff));
265 If not Global_Dos_Free(Word(Ptr and $ffff)) then
271 function getVESAInfo(var VESAInfo: TVESAInfo) : boolean; assembler;
276 sub ax,004Fh {make sure we got 004Fh back}
279 cmp word ptr es:[di],'V'or('E'shl 8) {signature should be 'VESA'}
281 cmp word ptr es:[di+2],'S'or('A'shl 8)
289 function getVESAModeInfo(var ModeInfo: TVESAModeInfo;mode:word):boolean;assembler;
295 sub ax,004Fh {make sure it's 004Fh}
302 function SearchVESAModes(mode: Word): boolean;
303 {********************************************************}
304 { Searches for a specific DEFINED vesa mode. If the mode }
305 { is not available for some reason, then returns FALSE }
306 { otherwise returns TRUE. }
307 {********************************************************}
310 ModeSupported : Boolean;
313 { let's assume it's not available ... }
314 ModeSupported := FALSE;
315 { This is a STUB VESA implementation }
316 if VESAInfo.ModeList^[0] = $FFFF then exit;
318 if VESAInfo.ModeList^[i] = mode then
320 { we found it, the card supports this mode... }
321 ModeSupported := TRUE;
325 until VESAInfo.ModeList^[i] = $ffff;
326 { now check if the hardware supports it... }
327 If ModeSupported then
329 { we have to init everything to zero, since VBE < 1.1 }
330 { may not setup fields correctly. }
331 FillChar(VESAModeInfo, sizeof(VESAModeInfo), #0);
332 If GetVESAModeInfo(VESAModeInfo, Mode) And
333 ((VESAModeInfo.attr and modeAvail) <> 0) then
334 ModeSupported := TRUE
336 ModeSupported := FALSE;
338 SearchVESAModes := ModeSupported;
343 procedure SetBankIndex(win: byte; BankNr: Integer); assembler;
358 {********************************************************}
359 { There are two routines for setting banks. This may in }
360 { in some cases optimize a bit some operations, if the }
361 { hardware supports it, because one window is used for }
362 { reading and one window is used for writing. }
363 {********************************************************}
364 procedure SetReadBank(BankNr: Integer);
366 { check if this is the current bank... if so do nothing. }
367 if BankNr = CurrentReadBank then exit;
369 { LogLn('Setting read bank to '+strf(BankNr));}
371 CurrentReadBank := BankNr; { save current bank number }
372 BankNr := BankNr shl BankShift; { adjust to window granularity }
373 { we set both banks, since one may read only }
374 SetBankIndex(ReadWindow, BankNr);
375 { if the hardware supports only one window }
376 { then there is only one single bank, so }
377 { update both bank numbers. }
378 if ReadWindow = WriteWindow then
379 CurrentWriteBank := CurrentReadBank;
382 procedure SetWriteBank(BankNr: Integer);
384 { check if this is the current bank... if so do nothing. }
385 if BankNr = CurrentWriteBank then exit;
387 { LogLn('Setting write bank to '+strf(BankNr));}
389 CurrentWriteBank := BankNr; { save current bank number }
390 BankNr := BankNr shl BankShift; { adjust to window granularity }
391 { we set both banks, since one may read only }
392 SetBankIndex(WriteWindow, BankNr);
393 { if the hardware supports only one window }
394 { then there is only one single bank, so }
395 { update both bank numbers. }
396 if ReadWindow = WriteWindow then
397 CurrentReadBank := CurrentWriteBank;
400 {************************************************************************}
401 {* 8-bit pixels VESA mode routines *}
402 {************************************************************************}
404 procedure PutPixVESA256(x, y : integer; color : word); {$ifndef fpc}far;{$endif fpc}
408 X:= X + StartXViewPort;
409 Y:= Y + StartYViewPort;
410 { convert to absolute coordinates and then verify clipping...}
413 if (X < StartXViewPort) or (X > (StartXViewPort + ViewWidth)) then
415 if (Y < StartYViewPort) or (Y > (StartYViewPort + ViewHeight)) then
418 Y := Y + YOffset; { adjust pixel for correct virtual page }
419 offs := longint(y) * BytesPerLine + x;
421 SetWriteBank(integer(offs shr 16));
422 mem[WinWriteSeg : word(offs)] := byte(color);
426 procedure DirectPutPixVESA256(x, y : integer); {$ifndef fpc}far;{$endif fpc}
431 offs := (longint(y) + YOffset) * BytesPerLine + x;
432 Case CurrentWriteMode of
435 SetReadBank(integer(offs shr 16));
436 col := mem[WinReadSeg : word(offs)] xor byte(CurrentColor);
440 SetReadBank(integer(offs shr 16));
441 col := mem[WinReadSeg : word(offs)] And byte(CurrentColor);
445 SetReadBank(integer(offs shr 16));
446 col := mem[WinReadSeg : word(offs)] or byte(currentcolor);
450 If CurrentWriteMode <> NotPut then
451 col := Byte(CurrentColor)
452 else col := Not(Byte(CurrentColor));
455 SetWriteBank(integer(offs shr 16));
456 mem[WinWriteSeg : word(offs)] := Col;
459 function GetPixVESA256(x, y : integer): word; {$ifndef fpc}far;{$endif fpc}
463 X:= X + StartXViewPort;
464 Y:= Y + StartYViewPort + YOffset;
465 offs := longint(y) * BytesPerLine + x;
466 SetReadBank(integer(offs shr 16));
467 GetPixVESA256:=mem[WinReadSeg : word(offs)];
470 Procedure GetScanLineVESA256(x1, x2, y: integer; var data); {$ifndef fpc}far;{$endif}
472 l, amount, bankrest, index, pixels: longint;
475 inc(x1,StartXViewPort);
476 inc(x2,StartXViewPort);
478 LogLn('getscanline256 '+strf(x1)+' - '+strf(x2)+' at '+strf(y+StartYViewPort));
482 Offs:=(Longint(y)+StartYViewPort+YOffset)*bytesperline+x1;
484 curbank := integer(offs shr 16);
485 SetReadBank(curbank);
487 LogLn('set bank '+strf(curbank)+' for offset '+hexstr(offs,8));
489 If ((amount >= 4) and
490 ((offs and 3) = 0)) or
491 (amount >= 4+4-(offs and 3)) Then
494 If (offs and 3) <> 0 then
495 { this cannot go past a window boundary bacause the }
496 { size of a window is always a multiple of 4 }
499 LogLn('Alligning by reading '+strf(4-(offs and 3))+' pixels');
501 for l := 1 to 4-(offs and 3) do
502 WordArray(Data)[index+l-1] :=
503 Mem[WinReadSeg:word(offs)+l-1];
509 LogLn('Offset is now '+hexstr(offs,8)+', amount left: '+strf(amount));
511 { offs is now 4-bytes alligned }
512 If amount <= ($10000-(Offs and $ffff)) Then
514 else {the rest won't fit anymore in the current window }
515 bankrest := $10000 - (Offs and $ffff);
516 { it is possible that by aligning, we ended up in a new }
517 { bank, so set the correct bank again to make sure }
518 setreadbank(offs shr 16);
520 LogLn('Rest to be read from this window: '+strf(bankrest));
522 For l := 0 to (Bankrest div 4)-1 Do
524 pixels := MemL[WinWriteSeg:word(offs)+l*4];
525 WordArray(Data)[index+l*4] := pixels and $ff;
526 pixels := pixels shr 8;
527 WordArray(Data)[index+l*4+1] := pixels and $ff;
528 pixels := pixels shr 8;
529 WordArray(Data)[index+l*4+2] := pixels and $ff;
530 pixels := pixels shr 8;
531 WordArray(Data)[index+l*4+3] := pixels{ and $ff};
537 LogLn('Offset is now '+hexstr(offs,8)+', amount left: '+strf(amount));
543 LogLn('Leftover: '+strf(amount)+' at offset '+hexstr(offs,8));
545 For l := 0 to amount - 1 do
547 { this may cross a bank at any time, so adjust }
548 { because this loop alwys runs for very little pixels, }
549 { there's little gained by splitting it up }
550 setreadbank(offs shr 16);
551 WordArray(Data)[index+l] := mem[WinReadSeg:word(offs)];
559 procedure HLineVESA256(x,x2,y: integer); {$ifndef fpc}far;{$endif fpc}
562 mask, l, bankrest: longint;
563 curbank, hlength: integer;
565 { must we swap the values? }
572 { First convert to global coordinates }
573 X := X + StartXViewPort;
574 X2 := X2 + StartXViewPort;
575 Y := Y + StartYViewPort;
578 if LineClipped(x,y,x2,y,StartXViewPort,StartYViewPort,
579 StartXViewPort+ViewWidth, StartYViewPort+ViewHeight) then
583 LogLn('hline '+strf(x)+' - '+strf(x2)+' on '+strf(y)+' in mode '+strf(currentwritemode));
585 HLength := x2 - x + 1;
587 LogLn('length: '+strf(hlength));
591 Offs:=(Longint(y)+YOffset)*bytesperline+x;
593 LogLn('Offs: '+strf(offs)+' -- '+hexstr(offs,8));
595 Mask := byte(CurrentColor)+byte(CurrentColor) shl 8;
596 Mask := Mask + Mask shl 16;
597 Case CurrentWriteMode of
601 curbank := integer(offs shr 16);
602 SetWriteBank(curbank);
603 SetReadBank(curbank);
605 LogLn('set bank '+strf(curbank)+' for offset '+hexstr(offs,8));
607 If ((HLength >= 4) and
608 ((offs and 3) = 0)) or
609 (HLength >= 4+4-(offs and 3)) Then
613 If (offs and 3) <> 0 then
614 { this cannot go past a window boundary bacause the }
615 { size of a window is always a multiple of 4 }
618 LogLn('Alligning by drawing '+strf(4-(offs and 3))+' pixels');
620 for l := 1 to 4-(offs and 3) do
621 Mem[WinWriteSeg:word(offs)+l-1] :=
622 Mem[WinReadSeg:word(offs)+l-1] And Byte(CurrentColor);
627 LogLn('Offset is now '+hexstr(offs,8)+', length left: '+strf(hlength));
629 { offs is now 4-bytes alligned }
630 If HLength <= ($10000-(Offs and $ffff)) Then
632 else {the rest won't fit anymore in the current window }
633 bankrest := $10000 - (Offs and $ffff);
634 { it is possible that by aligningm we ended up in a new }
635 { bank, so set the correct bank again to make sure }
636 setwritebank(offs shr 16);
637 setreadbank(offs shr 16);
639 LogLn('Rest to be drawn in this window: '+strf(bankrest));
641 For l := 0 to (Bankrest div 4)-1 Do
642 MemL[WinWriteSeg:word(offs)+l*4] :=
643 MemL[WinReadSeg:word(offs)+l*4] And Mask;
647 LogLn('Offset is now '+hexstr(offs,8)+', length left: '+strf(hlength));
653 LogLn('Drawing leftover: '+strf(HLength)+' at offset '+hexstr(offs,8));
655 For l := 0 to HLength - 1 do
657 { this may cross a bank at any time, so adjust }
658 { becauese this loop alwys runs for very little pixels, }
659 { there's little gained by splitting it up }
660 setreadbank(offs shr 16);
661 setwritebank(offs shr 16);
662 Mem[WinWriteSeg:word(offs)] :=
663 Mem[WinReadSeg:word(offs)] And byte(currentColor);
673 curbank := integer(offs shr 16);
674 SetWriteBank(curbank);
675 SetReadBank(curbank);
677 LogLn('set bank '+strf(curbank)+' for offset '+hexstr(offs,8));
679 If ((HLength >= 4) and
680 ((offs and 3) = 0)) or
681 (HLength >= 4+4-(offs and 3)) Then
685 If (offs and 3) <> 0 then
686 { this cannot go past a window boundary bacause the }
687 { size of a window is always a multiple of 4 }
690 LogLn('Alligning by drawing '+strf(4-(offs and 3))+' pixels');
692 for l := 1 to 4-(offs and 3) do
693 Mem[WinWriteSeg:word(offs)+l-1] :=
694 Mem[WinReadSeg:word(offs)+l-1] Xor Byte(CurrentColor);
699 LogLn('Offset is now '+hexstr(offs,8)+', length left: '+strf(hlength));
701 { offs is now 4-bytes alligned }
702 If HLength <= ($10000-(Offs and $ffff)) Then
704 else {the rest won't fit anymore in the current window }
705 bankrest := $10000 - (Offs and $ffff);
706 { it is possible that by aligningm we ended up in a new }
707 { bank, so set the correct bank again to make sure }
708 setwritebank(offs shr 16);
709 setreadbank(offs shr 16);
711 LogLn('Rest to be drawn in this window: '+strf(bankrest));
713 For l := 0 to (Bankrest div 4)-1 Do
714 MemL[WinWriteSeg:word(offs)+l*4] :=
715 MemL[WinReadSeg:word(offs)+l*4] Xor Mask;
719 LogLn('Offset is now '+hexstr(offs,8)+', length left: '+strf(hlength));
725 LogLn('Drawing leftover: '+strf(HLength)+' at offset '+hexstr(offs,8));
727 For l := 0 to HLength - 1 do
729 { this may cross a bank at any time, so adjust }
730 { because this loop alwys runs for very little pixels, }
731 { there's little gained by splitting it up }
732 setreadbank(offs shr 16);
733 setwritebank(offs shr 16);
734 Mem[WinWriteSeg:word(offs)] :=
735 Mem[WinReadSeg:word(offs)] xor byte(currentColor);
745 curbank := integer(offs shr 16);
746 SetWriteBank(curbank);
747 SetReadBank(curbank);
749 LogLn('set bank '+strf(curbank)+' for offset '+hexstr(offs,8));
751 If ((HLength >= 4) and
752 ((offs and 3) = 0)) or
753 (HLength >= 4+4-(offs and 3)) Then
757 If (offs and 3) <> 0 then
758 { this cannot go past a window boundary bacause the }
759 { size of a window is always a multiple of 4 }
762 LogLn('Alligning by drawing '+strf(4-(offs and 3))+' pixels');
764 for l := 1 to 4-(offs and 3) do
765 Mem[WinWriteSeg:word(offs)+l-1] :=
766 Mem[WinReadSeg:word(offs)+l-1] Or Byte(CurrentColor);
770 { it is possible that by aligningm we ended up in a new }
771 { bank, so set the correct bank again to make sure }
772 setwritebank(offs shr 16);
773 setreadbank(offs shr 16);
775 LogLn('Offset is now '+hexstr(offs,8)+', length left: '+strf(hlength));
777 { offs is now 4-bytes alligned }
778 If HLength <= ($10000-(Offs and $ffff)) Then
780 else {the rest won't fit anymore in the current window }
781 bankrest := $10000 - (Offs and $ffff);
783 LogLn('Rest to be drawn in this window: '+strf(bankrest));
785 For l := 0 to (Bankrest div 4)-1 Do
786 MemL[WinWriteSeg:offs+l*4] :=
787 MemL[WinReadSeg:word(offs)+l*4] Or Mask;
791 LogLn('Offset is now '+hexstr(offs,8)+', length left: '+strf(hlength));
797 LogLn('Drawing leftover: '+strf(HLength)+' at offset '+hexstr(offs,8));
799 For l := 0 to HLength - 1 do
801 { this may cross a bank at any time, so adjust }
802 { because this loop alwys runs for very little pixels, }
803 { there's little gained by splitting it up }
804 setreadbank(offs shr 16);
805 setwritebank(offs shr 16);
806 Mem[WinWriteSeg:word(offs)] :=
807 Mem[WinReadSeg:word(offs)] And byte(currentColor);
816 If CurrentWriteMode = NotPut Then
819 curbank := integer(offs shr 16);
820 SetWriteBank(curbank);
822 LogLn('set bank '+strf(curbank)+' for offset '+hexstr(offs,8)+' -- '+strf(offs));
824 If ((HLength >= 4) and
825 ((offs and 3) = 0)) or
826 (HLength >= 4+4-(offs and 3)) Then
830 If (offs and 3) <> 0 then
831 { this cannot go past a window boundary bacause the }
832 { size of a window is always a multiple of 4 }
835 LogLn('Alligning by drawing '+strf(4-(offs and 3))+' pixels');
837 for l := 1 to 4-(offs and 3) do
838 Mem[WinWriteSeg:word(offs)+l-1] := Byte(Mask);
843 LogLn('Offset is now '+hexstr(offs,8)+', length left: '+strf(hlength));
845 { offs is now 4-bytes alligned }
846 If HLength <= ($10000-(Offs and $ffff)) Then
848 else {the rest won't fit anymore in the current window }
849 bankrest := $10000 - (Offs and $ffff);
850 { it is possible that by aligningm we ended up in a new }
851 { bank, so set the correct bank again to make sure }
852 setwritebank(offs shr 16);
854 LogLn('Rest to be drawn in this window: '+strf(bankrest)+' -- '+hexstr(bankrest,8));
856 For l := 0 to (Bankrest div 4)-1 Do
857 MemL[WinWriteSeg:word(offs)+l*4] := Mask;
861 LogLn('Offset is now '+hexstr(offs,8)+', length left: '+strf(hlength));
867 LogLn('Drawing leftover: '+strf(HLength)+' at offset '+hexstr(offs,8));
869 For l := 0 to HLength - 1 do
871 { this may cross a bank at any time, so adjust }
872 { because this loop alwys runs for very little pixels, }
873 { there's little gained by splitting it up }
874 setwritebank(offs shr 16);
875 Mem[WinWriteSeg:word(offs)] := byte(mask);
886 procedure VLineVESA256(x,y,y2: integer); {$ifndef fpc}far;{$endif fpc}
889 l, bankrest: longint;
890 curbank, vlength: integer;
893 { must we swap the values? }
900 { First convert to global coordinates }
901 X := X + StartXViewPort;
902 Y := Y + StartYViewPort;
903 Y2 := Y2 + StartYViewPort;
906 if LineClipped(x,y,x,y2,StartXViewPort,StartYViewPort,
907 StartXViewPort+ViewWidth, StartYViewPort+ViewHeight) then
910 Col := Byte(CurrentColor);
912 LogLn('vline '+strf(y)+' - '+strf(y2)+' on '+strf(x)+' in mode '+strf(currentwritemode));
914 VLength := y2 - y + 1;
916 LogLn('length: '+strf(vlength));
920 Offs:=(Longint(y)+YOffset)*bytesperline+x;
922 LogLn('Offs: '+strf(offs)+' -- '+hexstr(offs,8));
924 Case CurrentWriteMode of
928 curbank := integer(offs shr 16);
929 SetWriteBank(curbank);
930 SetReadBank(curbank);
932 LogLn('set bank '+strf(curbank)+' for offset '+hexstr(offs,8));
934 If (VLength-1)*bytesperline <= ($10000-(Offs and $ffff)) Then
936 else {the rest won't fit anymore in the current window }
937 bankrest := (($10000 - (Offs and $ffff)) div bytesperline)+1;
939 LogLn('Rest to be drawn in this window: '+strf(bankrest));
941 For l := 0 to Bankrest-1 Do
943 Mem[WinWriteSeg:word(offs)] :=
944 Mem[WinReadSeg:word(offs)] And Col;
945 inc(offs,bytesperline);
949 LogLn('Offset is now '+hexstr(offs,8)+', length left: '+strf(vlength));
956 curbank := integer(offs shr 16);
957 SetWriteBank(curbank);
958 SetReadBank(curbank);
960 LogLn('set bank '+strf(curbank)+' for offset '+hexstr(offs,8));
962 If (VLength-1)*bytesperline <= ($10000-(Offs and $ffff)) Then
964 else {the rest won't fit anymore in the current window }
965 bankrest := (($10000 - (Offs and $ffff)) div bytesperline)+1;
967 LogLn('Rest to be drawn in this window: '+strf(bankrest));
969 For l := 0 to Bankrest-1 Do
971 Mem[WinWriteSeg:word(offs)] :=
972 Mem[WinReadSeg:word(offs)] Xor Col;
973 inc(offs,bytesperline);
977 LogLn('Offset is now '+hexstr(offs,8)+', length left: '+strf(vlength));
984 curbank := integer(offs shr 16);
985 SetWriteBank(curbank);
986 SetReadBank(curbank);
988 LogLn('set bank '+strf(curbank)+' for offset '+hexstr(offs,8));
990 If (VLength-1)*bytesperline <= ($10000-(Offs and $ffff)) Then
992 else {the rest won't fit anymore in the current window }
993 bankrest := (($10000 - (Offs and $ffff)) div bytesperline)+1;
995 LogLn('Rest to be drawn in this window: '+strf(bankrest));
997 For l := 0 to Bankrest-1 Do
999 Mem[WinWriteSeg:word(offs)] :=
1000 Mem[WinReadSeg:word(offs)] Or Col;
1001 inc(offs,bytesperline);
1005 LogLn('Offset is now '+hexstr(offs,8)+', length left: '+strf(vlength));
1011 If CurrentWriteMode = NotPut Then
1014 curbank := integer(offs shr 16);
1015 SetWriteBank(curbank);
1017 LogLn('set bank '+strf(curbank)+' for offset '+hexstr(offs,8));
1019 If (VLength-1)*bytesperline <= ($10000-(Offs and $ffff)) Then
1021 else {the rest won't fit anymore in the current window }
1022 bankrest := (($10000 - (Offs and $ffff)) div bytesperline)+1;
1024 LogLn('Rest to be drawn in this window: '+strf(bankrest));
1026 For l := 0 to Bankrest-1 Do
1028 Mem[WinWriteSeg:word(offs)] := Col;
1029 inc(offs,bytesperline);
1033 LogLn('Offset is now '+hexstr(offs,8)+', length left: '+strf(vlength));
1041 procedure PatternLineVESA256(x1,x2,y: smallint); {$ifndef fpc}far;{$endif fpc}
1042 {********************************************************}
1043 { Draws a horizontal patterned line according to the }
1044 { current Fill Settings. }
1045 {********************************************************}
1046 { Important notes: }
1047 { - CurrentColor must be set correctly before entering }
1049 {********************************************************}
1051 TVESA256Fill = Record
1053 0: (data1, data2: longint);
1054 1: (pat: array[0..7] of byte);
1059 bankrest, l : longint;
1060 offs, amount: longint;
1063 OldWriteMode : word;
1064 TmpFillPattern, patternPos : byte;
1066 { convert to global coordinates ... }
1067 x1 := x1 + StartXViewPort;
1068 x2 := x2 + StartXViewPort;
1069 y := y + StartYViewPort;
1070 { if line was fully clipped then exit...}
1071 if LineClipped(x1,y,x2,y,StartXViewPort,StartYViewPort,
1072 StartXViewPort+ViewWidth, StartYViewPort+ViewHeight) then
1074 OldWriteMode := CurrentWriteMode;
1075 CurrentWriteMode := NormalPut;
1076 { Get the current pattern }
1077 TmpFillPattern := FillPatternTable
1078 [FillSettings.Pattern][((y + startYViewPort) and $7)+1];
1080 LogLn('patternline '+strf(x1)+' - '+strf(x2)+' on '+strf(y));
1082 { how long is the line }
1083 amount := x2 - x1 + 1;
1084 { offset to start at }
1085 offs := (longint(y)+yoffset)*bytesperline+x1;
1086 { convert the pattern data into the actual color sequence }
1088 FillChar(fill,sizeOf(fill),byte(currentBkColor));
1091 if TmpFillPattern and j <> 0 then
1092 fill.pat[7-i] := currentColor;
1095 {$define overflowOn}
1104 SetWriteBank(integer(offs shr 16));
1106 (((offs and 7) = 0) or
1107 (amount > 7+8-(offs and 7))) Then
1111 If (offs and 7) <> 0 then
1112 { this cannot go past a window boundary bacause the }
1113 { size of a window is always a multiple of 8 }
1115 { position in the pattern where to start }
1116 patternPos := offs and 7;
1118 LogLn('Aligning by drawing '+strf(8-(offs and 7))+' pixels');
1120 for l := 1 to 8-(offs and 7) do
1122 Mem[WinWriteSeg:word(offs)+l-1] := fill.pat[patternPos and 7];
1129 LogLn('Offset is now '+hexstr(offs,8)+', length left: '+strf(amount));
1131 { offs is now 8-bytes alligned }
1132 If amount <= ($10000-(Offs and $ffff)) Then
1134 else {the rest won't fit anymore in the current window }
1135 bankrest := $10000 - (Offs and $ffff);
1136 { it is possible that by aligningm we ended up in a new }
1137 { bank, so set the correct bank again to make sure }
1138 setwritebank(offs shr 16);
1140 LogLn('Rest to be drawn in this window: '+strf(bankrest));
1142 for l := 0 to (bankrest div 8)-1 Do
1144 MemL[WinWriteSeg:word(offs)+l*8] := fill.data1;
1145 MemL[WinWriteSeg:word(offs)+l*8+4] := fill.data2;
1150 LogLn('Offset is now '+hexstr(offs,8)+', length left: '+strf(amount));
1156 LogLn('Drawing leftover: '+strf(amount)+' at offset '+hexstr(offs,8));
1158 patternPos := offs and 7;
1159 For l := 0 to amount - 1 do
1161 { this may cross a bank at any time, so adjust }
1162 { because this loop alwys runs for very little pixels, }
1163 { there's little gained by splitting it up }
1164 setwritebank(offs shr 16);
1165 Mem[WinWriteSeg:word(offs)] := fill.pat[patternPos and 7];
1172 currentWriteMode := oldWriteMode;
1176 {************************************************************************}
1177 {* 256 colors VESA mode routines Linear mode *}
1178 {************************************************************************}
1184 procedure DirectPutPixVESA256Linear(x, y : integer); {$ifndef fpc}far;{$endif fpc}
1189 offs := longint(y) * BytesPerLine + x;
1190 Case CurrentWriteMode of
1193 if UseNoSelector then
1194 col:=pbyte(LFBPointer+offs+LinearPageOfs)^
1196 seg_move(WinWriteSeg,offs+LinearPageOfs,get_ds,longint(@col),1);
1197 col := col xor byte(CurrentColor);
1201 if UseNoSelector then
1202 col:=pbyte(LFBPointer+offs+LinearPageOfs)^
1204 seg_move(WinWriteSeg,offs+LinearPageOfs,get_ds,longint(@col),1);
1205 col := col and byte(CurrentColor);
1209 if UseNoSelector then
1210 col:=pbyte(LFBPointer+offs+LinearPageOfs)^
1212 seg_move(WinWriteSeg,offs+LinearPageOfs,get_ds,longint(@col),1);
1213 col := col or byte(CurrentColor);
1217 If CurrentWriteMode <> NotPut then
1218 col := Byte(CurrentColor)
1219 else col := Not(Byte(CurrentColor));
1222 if UseNoSelector then
1223 pbyte(LFBPointer+offs+LinearPageOfs)^:=col
1225 seg_move(get_ds,longint(@col),WinWriteSeg,offs+LinearPageOfs,1);
1228 procedure PutPixVESA256Linear(x, y : integer; color : word); {$ifndef fpc}far;{$endif fpc}
1232 X:= X + StartXViewPort;
1233 Y:= Y + StartYViewPort;
1234 { convert to absolute coordinates and then verify clipping...}
1237 if (X < StartXViewPort) or (X > (StartXViewPort + ViewWidth)) then
1239 if (Y < StartYViewPort) or (Y > (StartYViewPort + ViewHeight)) then
1242 offs := longint(y) * BytesPerLine + x;
1244 logln('putpix offset: '+hexstr(offs,8)+', color: '+strf(color)+', lpo: $'+
1245 hexstr(LinearPageOfs,8));
1247 if UseNoSelector then
1248 pbyte(LFBPointer+offs+LinearPageOfs)^:=byte(color)
1250 seg_move(get_ds,longint(@color),WinWriteSeg,offs+LinearPageOfs,1);
1253 function GetPixVESA256Linear(x, y : integer): word; {$ifndef fpc}far;{$endif fpc}
1258 X:= X + StartXViewPort;
1259 Y:= Y + StartYViewPort;
1260 offs := longint(y) * BytesPerLine + x;
1262 logln('getpix offset: '+hexstr(offs,8)+', lpo: $'+
1263 hexstr(LinearPageOfs,8));
1265 if UseNoSelector then
1266 col:=pbyte(LFBPointer+offs+LinearPageOfs)^
1268 seg_move(WinWriteSeg,offs+LinearPageOfs,get_ds,longint(@col),1);
1269 GetPixVESA256Linear:=col;
1272 function SetVESADisplayStart(PageNum : word;x,y : integer):Boolean;
1276 if PageNum>VesaModeInfo.NumberOfPages then
1280 writeln(stderr,'Setting Display Page ',PageNum);
1282 dregs.RealEBX:=0{ $80 for Wait for retrace };
1284 dregs.RealEDX:=y+PageNum*maxy;
1287 dregs.RealEAX:=$4F07; RealIntr($10,dregs);
1288 { idem as above !!! }
1289 if (dregs.RealEAX and $1FF) <> $4F then
1292 writeln(stderr,'Set Display start error');
1294 SetVESADisplayStart:=false;
1297 SetVESADisplayStart:=true;
1303 {************************************************************************}
1304 {* 15/16bit pixels VESA mode routines *}
1305 {************************************************************************}
1307 procedure PutPixVESA32kOr64k(x, y : integer; color : word); {$ifndef fpc}far;{$endif fpc}
1312 logln('putpixvesa32kor64k('+strf(x)+','+strf(y)+')');
1314 X:= X + StartXViewPort;
1315 Y:= Y + StartYViewPort;
1316 { convert to absolute coordinates and then verify clipping...}
1319 if (X < StartXViewPort) or (X > (StartXViewPort + ViewWidth)) then
1321 if (Y < StartYViewPort) or (Y > (StartYViewPort + ViewHeight)) then
1324 Y := Y + YOffset; { adjust pixel for correct virtual page }
1325 offs := longint(y) * BytesPerLine + 2*x;
1326 SetWriteBank(integer(offs shr 16));
1328 logln('putpixvesa32kor64k offset: '+strf(word(offs)));
1330 memW[WinWriteSeg : word(offs)] := color;
1333 function GetPixVESA32kOr64k(x, y : integer): word; {$ifndef fpc}far;{$endif fpc}
1337 X:= X + StartXViewPort;
1338 Y:= Y + StartYViewPort + YOffset;
1339 offs := longint(y) * BytesPerLine + 2*x;
1340 SetReadBank(integer(offs shr 16));
1341 GetPixVESA32kOr64k:=memW[WinReadSeg : word(offs)];
1344 procedure DirectPutPixVESA32kOr64k(x, y : integer); {$ifndef fpc}far;{$endif fpc}
1350 logln('directputpixvesa32kor64k('+strf(x)+','+strf(y)+')');
1353 offs := longint(y) * BytesPerLine + 2*x;
1354 SetWriteBank(integer((offs shr 16) and $ff));
1355 Case CurrentWriteMode of
1358 SetReadBank(integer(offs shr 16));
1359 memW[WinWriteSeg : word(offs)] := memW[WinReadSeg : word(offs)] xor currentcolor;
1363 SetReadBank(integer(offs shr 16));
1364 memW[WinWriteSeg : word(offs)] := memW[WinReadSeg : word(offs)] And currentcolor;
1368 SetReadBank(integer(offs shr 16));
1369 memW[WinWriteSeg : word(offs)] := memW[WinReadSeg : word(offs)] or currentcolor;
1373 If CurrentWriteMode <> NotPut Then
1375 Else col := Not(CurrentColor);
1377 logln('directputpixvesa32kor64k offset: '+strf(word(offs)));
1379 memW[WinWriteSeg : word(offs)] := Col;
1385 {************************************************************************}
1386 {* 15/16bit pixels VESA mode routines Linear mode *}
1387 {************************************************************************}
1389 procedure PutPixVESA32kor64kLinear(x, y : integer; color : word); {$ifndef fpc}far;{$endif fpc}
1393 X:= X + StartXViewPort;
1394 Y:= Y + StartYViewPort;
1395 { convert to absolute coordinates and then verify clipping...}
1398 if (X < StartXViewPort) or (X > (StartXViewPort + ViewWidth)) then
1400 if (Y < StartYViewPort) or (Y > (StartYViewPort + ViewHeight)) then
1403 offs := longint(y) * BytesPerLine + 2*x;
1404 if UseNoSelector then
1405 pword(LFBPointer+offs+LinearPageOfs)^:=color
1407 seg_move(get_ds,longint(@color),WinWriteSeg,offs+LinearPageOfs,2);
1410 function GetPixVESA32kor64kLinear(x, y : integer): word; {$ifndef fpc}far;{$endif fpc}
1415 X:= X + StartXViewPort;
1416 Y:= Y + StartYViewPort;
1417 offs := longint(y) * BytesPerLine + 2*x;
1418 if UseNoSelector then
1419 color:=pword(LFBPointer+offs+LinearPageOfs)^
1421 seg_move(WinWriteSeg,offs+LinearPageOfs,get_ds,longint(@color),2);
1422 GetPixVESA32kor64kLinear:=color;
1425 procedure DirectPutPixVESA32kor64kLinear(x, y : integer); {$ifndef fpc}far;{$endif fpc}
1430 offs := longint(y) * BytesPerLine + 2*x;
1431 Case CurrentWriteMode of
1434 if UseNoSelector then
1435 col:=pword(LFBPointer+offs+LinearPageOfs)^
1437 seg_move(WinWriteSeg,offs+LinearPageOfs,get_ds,longint(@col),2);
1438 col := col xor currentcolor;
1442 if UseNoSelector then
1443 col:=pword(LFBPointer+offs+LinearPageOfs)^
1445 seg_move(WinWriteSeg,offs+LinearPageOfs,get_ds,longint(@col),2);
1446 col := col and currentcolor;
1450 if UseNoSelector then
1451 col:=pword(LFBPointer+offs+LinearPageOfs)^
1453 seg_move(WinWriteSeg,offs+LinearPageOfs,get_ds,longint(@col),2);
1454 col := col or currentcolor;
1458 If CurrentWriteMode <> NotPut Then
1460 Else col := Not(CurrentColor);
1463 if UseNoSelector then
1464 pword(LFBPointer+offs+LinearPageOfs)^:=col
1466 seg_move(get_ds,longint(@col),WinWriteSeg,offs+LinearPageOfs,2);
1471 {************************************************************************}
1472 {* 4-bit pixels VESA mode routines *}
1473 {************************************************************************}
1475 procedure PutPixVESA16(x, y : integer; color : word); {$ifndef fpc}far;{$endif fpc}
1480 X:= X + StartXViewPort;
1481 Y:= Y + StartYViewPort;
1482 { convert to absolute coordinates and then verify clipping...}
1485 if (X < StartXViewPort) or (X > (StartXViewPort + ViewWidth)) then
1487 if (Y < StartYViewPort) or (Y > (StartYViewPort + ViewHeight)) then
1490 Y := Y + YOffset; { adjust pixel for correct virtual page }
1492 offs := longint(y) * BytesPerLine + (x div 8);
1493 SetWriteBank(integer(offs shr 16));
1495 PortW[$3ce] := $0f01; { Index 01 : Enable ops on all 4 planes }
1496 PortW[$3ce] := color shl 8; { Index 00 : Enable correct plane and write color }
1498 Port[$3ce] := 8; { Index 08 : Bitmask register. }
1499 Port[$3cf] := $80 shr (x and $7); { Select correct bits to modify }
1501 dummy := Mem[WinWriteSeg: offs]; { Latch the data into host space. }
1502 Mem[WinWriteSeg: offs] := dummy; { Write the data into video memory }
1503 PortW[$3ce] := $ff08; { Enable all bit planes. }
1504 PortW[$3ce] := $0001; { Index 01 : Disable ops on all four planes. }
1509 Function GetPixVESA16(X,Y: Integer):word; {$ifndef fpc}far;{$endif fpc}
1510 Var dummy, offset: Word;
1513 X:= X + StartXViewPort;
1514 Y:= Y + StartYViewPort + YOffset;
1515 offset := longint(Y) * BytesPerLine + (x div 8);
1516 SetReadBank(integer(offset shr 16));
1518 shift := 7 - (X and 7);
1520 dummy := (Mem[WinReadSeg:offset] shr shift) and 1;
1522 dummy := dummy or (((Mem[WinReadSeg:offset] shr shift) and 1) shl 1);
1524 dummy := dummy or (((Mem[WinReadSeg:offset] shr shift) and 1) shl 2);
1526 dummy := dummy or (((Mem[WinReadSeg:offset] shr shift) and 1) shl 3);
1527 GetPixVESA16 := dummy;
1531 procedure DirectPutPixVESA16(x, y : integer); {$ifndef fpc}far;{$endif fpc}
1538 case CurrentWriteMode of
1541 { getpixel wants local/relative coordinates }
1542 Color := GetPixVESA16(x-StartXViewPort,y-StartYViewPort);
1543 Color := CurrentColor Xor Color;
1547 { getpixel wants local/relative coordinates }
1548 Color := GetPixVESA16(x-StartXViewPort,y-StartYViewPort);
1549 Color := CurrentColor Or Color;
1553 { getpixel wants local/relative coordinates }
1554 Color := GetPixVESA16(x-StartXViewPort,y-StartYViewPort);
1555 Color := CurrentColor And Color;
1562 Color := CurrentColor;
1564 offs := longint(y) * BytesPerLine + (x div 8);
1565 SetWriteBank(integer(offs shr 16));
1566 PortW[$3ce] := $0f01; { Index 01 : Enable ops on all 4 planes }
1567 PortW[$3ce] := color shl 8; { Index 00 : Enable correct plane and write color }
1569 Port[$3ce] := 8; { Index 08 : Bitmask register. }
1570 Port[$3cf] := $80 shr (x and $7); { Select correct bits to modify }
1572 dummy := Mem[WinWriteSeg: offs]; { Latch the data into host space. }
1573 Mem[WinWriteSeg: offs] := dummy; { Write the data into video memory }
1574 PortW[$3ce] := $ff08; { Enable all bit planes. }
1575 PortW[$3ce] := $0001; { Index 01 : Disable ops on all four planes. }
1581 {************************************************************************}
1582 {* VESA Palette entries *}
1583 {************************************************************************}
1587 Procedure SetVESARGBPalette(ColorNum, RedValue, GreenValue,
1588 BlueValue : Integer);
1591 regs: TDPMIRegisters;
1597 FunctionNr : byte; { use blankbit or normal RAMDAC programming? }
1602 logln('setvesargbpalette called with directcolor = true');
1604 _GraphResult := grError;
1608 pal.red := byte(RedValue);
1609 pal.green := byte(GreenValue);
1610 pal.blue := byte(BlueValue);
1611 { use the set/get palette function }
1612 if VESAInfo.Version >= $0200 then
1614 { check if blanking bit must be set when programming }
1616 if (VESAInfo.caps and attrSnowCheck) <> 0 then
1621 { Alllocate real mode buffer }
1623 Ptr:=GlobalDosAlloc(sizeof(palrec));
1624 { get the selector values }
1625 PalPtr := pointer(Ptr shl 16);
1626 if not assigned(PalPtr) then
1629 Ptr:=Global_Dos_Alloc(sizeof(palrec));
1631 {get the segment value}
1632 RealSeg := word(Ptr shr 16);
1633 { setup interrupt registers }
1634 FillChar(regs, sizeof(regs), #0);
1635 { copy palette values to real mode buffer }
1637 move(pal, palptr^, sizeof(pal));
1639 DosMemPut(RealSeg,0,pal,sizeof(pal));
1642 regs.ebx := FunctionNr;
1644 regs.edx := ColorNum;
1646 regs.edi := 0; { offset is always zero }
1647 RealIntr($10, regs);
1649 { free real mode memory }
1651 GlobalDosFree(word(Ptr and $ffff));
1653 If not Global_Dos_Free(word(Ptr and $ffff)) then
1657 if word(regs.eax) <> $004F then
1660 logln('setvesargbpalette failed while directcolor = false!');
1662 _GraphResult := grError;
1667 { assume it's fully VGA compatible palette-wise. }
1669 SetVGARGBPalette(ColorNum, RedValue, GreenValue, BlueValue);
1674 Procedure GetVESARGBPalette(ColorNum: integer; Var
1675 RedValue, GreenValue, BlueValue : integer);
1681 regs : TDPMIRegisters;
1688 logln('getvesargbpalette called with directcolor = true');
1690 _GraphResult := grError;
1693 { use the set/get palette function }
1694 if VESAInfo.Version >= $0200 then
1696 { Alllocate real mode buffer }
1698 Ptr:=GlobalDosAlloc(sizeof(palrec));
1699 { get the selector value }
1700 PalPtr := pointer(longint(Ptr and $0000ffff) shl 16);
1701 if not assigned(PalPtr) then
1704 Ptr:=Global_Dos_Alloc(sizeof(palrec));
1706 { get the segment value }
1707 RealSeg := word(Ptr shr 16);
1708 { setup interrupt registers }
1709 FillChar(regs, sizeof(regs), #0);
1712 regs.ebx := $01; { get palette data }
1714 regs.edx := ColorNum;
1716 regs.edi := 0; { offset is always zero }
1717 RealIntr($10, regs);
1719 { copy to protected mode buffer ... }
1721 Move(PalPtr^, Pal, sizeof(pal));
1723 DosMemGet(RealSeg,0,Pal,sizeof(pal));
1725 { free real mode memory }
1727 GlobalDosFree(word(Ptr and $ffff));
1729 If not Global_Dos_Free(word(Ptr and $ffff)) then
1733 if word(regs.eax) <> $004F then
1736 logln('getvesargbpalette failed while directcolor = false!');
1738 _GraphResult := grError;
1743 RedValue := Integer(pal.Red);
1744 GreenValue := Integer(pal.Green);
1745 BlueValue := Integer(pal.Blue);
1749 GetVGARGBPalette(ColorNum, RedValue, GreenValue, BlueValue);
1753 Procedure SetVESARGBPalette(ColorNum, RedValue, GreenValue,
1754 BlueValue : Integer); far;
1756 FunctionNr : byte; { use blankbit or normal RAMDAC programming? }
1758 Error : boolean; { VBE call error }
1762 _GraphResult := grError;
1767 if not assigned(pal) then RunError(203);
1769 pal^.red := byte(RedValue);
1770 pal^.green := byte(GreenValue);
1771 pal^.blue := byte(BlueValue);
1772 { use the set/get palette function }
1773 if VESAInfo.Version >= $0200 then
1775 { check if blanking bit must be set when programming }
1777 if (VESAInfo.caps and attrSnowCheck) <> 0 then
1782 mov ax, 4F09h { Set/Get Palette data }
1783 mov bl, [FunctionNr] { Set palette data }
1784 mov cx, 01h { update one palette reg. }
1785 mov dx, [ColorNum] { register number to update }
1786 les di, [pal] { get palette address }
1788 cmp ax, 004Fh { check if success }
1797 _GraphResult := grError;
1802 { assume it's fully VGA compatible palette-wise. }
1804 SetVGARGBPalette(ColorNum, RedValue, GreenValue, BlueValue);
1811 Procedure GetVESARGBPalette(ColorNum: integer; Var RedValue, GreenValue,
1812 BlueValue : integer); far;
1819 _GraphResult := grError;
1824 if not assigned(pal) then RunError(203);
1825 FillChar(pal^, sizeof(palrec), #0);
1826 { use the set/get palette function }
1827 if VESAInfo.Version >= $0200 then
1830 mov ax, 4F09h { Set/Get Palette data }
1831 mov bl, 01h { Set palette data }
1832 mov cx, 01h { update one palette reg. }
1833 mov dx, [ColorNum] { register number to update }
1834 les di, [pal] { get palette address }
1836 cmp ax, 004Fh { check if success }
1843 RedValue := Integer(pal^.Red);
1844 GreenValue := Integer(pal^.Green);
1845 BlueValue := Integer(pal^.Blue);
1850 _GraphResult := grError;
1855 GetVGARGBPalette(ColorNum, RedValue, GreenValue, BlueValue);
1860 heaperrorproc=function(size:longint):integer;
1863 HeapErrorIsHooked : boolean = false;
1864 OldHeapError : HeapErrorProc = nil;
1865 DsLimit : dword = 0;
1867 function NewHeapError(size : longint) : integer;
1869 set_segment_limit(get_ds,DsLimit);
1870 NewHeapError:=OldHeapError(size);
1871 DsLimit:=get_segment_limit(get_ds);
1872 { The base of ds can be changed
1873 we need to compute the address again PM }
1874 LFBPointer:=pointer(FrameBufferLinearAddress-get_segment_base_address(get_ds));
1875 if dword(LFBPointer)+dword(VESAInfo.TotalMem shl 16)-1 > DsLimit then
1876 set_segment_limit(get_ds,dword(LFBPointer)+dword(VESAInfo.TotalMem shl 16)-1);
1879 procedure HookHeapError;
1881 if HeapErrorIsHooked then
1883 DsLimit:=get_segment_limit(get_ds);
1884 OldHeapError:=HeapErrorProc(HeapError);
1885 HeapError:=@NewHeapError;
1886 HeapErrorIsHooked:=true;
1889 procedure UnHookHeapError;
1891 if not HeapErrorIsHooked then
1894 set_segment_limit(get_ds,DsLimit);
1895 HeapError:=OldHeapError;
1896 HeapErrorIsHooked:=false;
1899 function SetupLinear(var ModeInfo: TVESAModeInfo;mode : word) : boolean;
1915 DirectPutPixel:=@DirectPutPixVESA32kor64kLinear;
1916 PutPixel:=@PutPixVESA32kor64kLinear;
1917 GetPixel:=@GetPixVESA32kor64kLinear;
1918 { linear mode for lines not yet implemented PM }
1919 HLine:=@HLineDefault;
1920 VLine:=@VLineDefault;
1921 GetScanLine := @GetScanLineDefault;
1922 PatternLine := @PatternLineDefault;
1930 DirectPutPixel:=@DirectPutPixVESA256Linear;
1931 PutPixel:=@PutPixVESA256Linear;
1932 GetPixel:=@GetPixVESA256Linear;
1933 { linear mode for lines not yet implemented PM }
1934 HLine:=@HLineDefault;
1935 VLine:=@VLineDefault;
1936 GetScanLine := @GetScanLineDefault;
1937 PatternLine := @PatternLineDefault;
1942 FrameBufferLinearAddress:=Get_linear_addr(VESAModeInfo.PhysAddress and $FFFF0000,
1943 VESAInfo.TotalMem shl 16);
1945 logln('framebuffer linear address: '+hexstr(FrameBufferLinearAddress div (1024*1024),8));
1946 logln('total mem shl 16: '+strf(vesainfo.totalmem shl 16));
1948 if int31error<>0 then
1951 logln('Unable to get linear address for '+hexstr(VESAModeInfo.PhysAddress,8));
1953 writeln(stderr,'Unable to get linear address for ',hexstr(VESAModeInfo.PhysAddress,8));
1956 if UseNoSelector then
1959 LFBPointer:=pointer(FrameBufferLinearAddress-get_segment_base_address(get_ds));
1960 if dword(LFBPointer)+dword(VESAInfo.TotalMem shl 16)-1 > dword(get_segment_limit(get_ds)) then
1961 set_segment_limit(get_ds,dword(LFBPointer)+dword(VESAInfo.TotalMem shl 16)-1);
1965 WinWriteSeg:=allocate_ldt_descriptors(1);
1967 logln('writeseg1: '+hexstr(winwriteseg,8));
1969 set_segment_base_address(WinWriteSeg,FrameBufferLinearAddress);
1970 set_segment_limit(WinWriteSeg,(VESAInfo.TotalMem shl 16)-1);
1971 lock_linear_region(FrameBufferLinearAddress,(VESAInfo.TotalMem shl 16));
1972 if int31error<>0 then
1975 logln('Error in linear memory selectors creation');
1977 writeln(stderr,'Error in linear memory selectors creation');
1984 { WinSize:=(VGAInfo.TotalMem shl 16);
1985 WinLoMask:=(VGAInfo.TotalMem shl 16)-1;
1987 Temp:=VGAInfo.TotalMem;
1996 procedure SetupWindows(var ModeInfo: TVESAModeInfo);
1999 { now we check the windowing scheme ...}
2000 if (ModeInfo.WinAAttr and WinSupported) <> 0 then
2001 { is this window supported ... }
2003 { now check if the window is R/W }
2004 if (ModeInfo.WinAAttr and WinReadable) <> 0 then
2007 WinReadSeg := ModeInfo.WinASeg;
2009 if (ModeInfo.WinAAttr and WinWritable) <> 0 then
2012 WinWriteSeg := ModeInfo.WinASeg;
2015 if (ModeInfo.WinBAttr and WinSupported) <> 0 then
2016 { is this window supported ... }
2019 { OPTIMIZATION ... }
2020 { if window A supports both read/write, then we try to optimize }
2021 { everything, by using a different window for Read and/or write.}
2022 if (WinReadSeg <> 0) and (WinWriteSeg <> 0) then
2024 { check if winB supports read }
2025 if (ModeInfo.WinBAttr and winReadable) <> 0 then
2027 WinReadSeg := ModeInfo.WinBSeg;
2031 { check if WinB supports write }
2032 if (ModeInfo.WinBAttr and WinWritable) <> 0 then
2034 WinWriteSeg := ModeInfo.WinBSeg;
2039 { Window A only supported Read OR Write, no we have to make }
2040 { sure that window B supports the other mode. }
2041 if (WinReadSeg = 0) and (WinWriteSeg<>0) then
2043 if (ModeInfo.WinBAttr and WinReadable <> 0) then
2046 WinReadSeg := ModeInfo.WinBSeg;
2049 { impossible, this VESA mode is WRITE only! }
2051 WriteLn('Invalid VESA Window attribute.');
2056 if (winWriteSeg = 0) and (WinReadSeg<>0) then
2058 if (ModeInfo.WinBAttr and WinWritable) <> 0 then
2061 WinWriteSeg := ModeInfo.WinBSeg;
2064 { impossible, this VESA mode is READ only! }
2066 WriteLn('Invalid VESA Window attribute.');
2071 if (winReadSeg = 0) and (winWriteSeg = 0) then
2072 { no read/write in this mode! }
2074 WriteLn('Invalid VESA Window attribute.');
2079 { if both windows are not supported, then we can assume }
2080 { that there is ONE single NON relocatable window. }
2081 if (WinWriteSeg = 0) and (WinReadSeg = 0) then
2083 WinWriteSeg := ModeInfo.WinASeg;
2084 WinReadSeg := ModeInfo.WinASeg;
2087 { 16-bit Protected mode checking code... }
2088 { change segment values to protected mode }
2090 if WinReadSeg = $A000 then
2091 WinReadSeg := SegA000
2093 if WinReadSeg = $B000 then
2094 WinReadSeg := SegB000
2096 if WinReadSeg = $B800 then
2097 WinReadSeg := SegB800
2100 WriteLn('Invalid segment address.');
2103 if WinWriteSeg = $A000 then
2104 WinWriteSeg := SegA000
2106 if WinWriteSeg = $B000 then
2107 WinWriteSeg := SegB000
2109 if WinWriteSeg = $B800 then
2110 WinWriteSeg := SegB800
2113 WriteLn('Invalid segment address.');
2121 function setVESAMode(mode:word):boolean;
2125 { Init mode information, for compatibility with VBE < 1.1 }
2126 FillChar(VESAModeInfo, sizeof(TVESAModeInfo), #0);
2127 { get the video mode information }
2128 if getVESAModeInfo(VESAmodeinfo, mode) then
2130 { checks if the hardware supports the video mode. }
2131 if (VESAModeInfo.attr and modeAvail) = 0 then
2133 SetVESAmode := FALSE;
2135 logln(' vesa mode '+strf(mode)+' not supported!!!');
2137 _GraphResult := grError;
2141 SetVESAMode := TRUE;
2143 while (64 shr BankShift) <> VESAModeInfo.WinGranularity do
2145 CurrentWriteBank := -1;
2146 CurrentReadBank := -1;
2147 BytesPerLine := VESAModeInfo.BytesPerScanLine;
2149 { These are the window adresses ... }
2150 WinWriteSeg := 0; { This is the segment to use for writes }
2151 WinReadSeg := 0; { This is the segment to use for reads }
2155 { VBE 2.0 and higher supports >= non VGA linear buffer types...}
2156 { this is backward compatible. }
2157 if (((VESAModeInfo.Attr and ModeNoWindowed) <> 0) or UseLFB) and
2158 ((VESAModeInfo.Attr and ModeLinearBuffer) <> 0) then
2160 if not SetupLinear(VESAModeInfo,mode) then
2161 SetUpWindows(VESAModeInfo);
2164 { if linear and windowed is supported, then use windowed }
2166 SetUpWindows(VESAModeInfo);
2169 LogLn('Entering vesa mode '+strf(mode));
2170 LogLn('Read segment: $'+hexstr(winreadseg,4));
2171 LogLn('Write segment: $'+hexstr(winwriteseg,4));
2172 LogLn('Window granularity: '+strf(VESAModeInfo.WinGranularity)+'kb');
2173 LogLn('Window size: '+strf(VESAModeInfo.winSize)+'kb');
2174 LogLn('Bytes per line: '+strf(bytesperline));
2176 { Select the correct mode number if we're going to use linear access! }
2196 _GraphResult := GrNotDetected
2197 else _GraphResult := grOk;
2202 function getVESAMode:word;assembler;
2203 asm {return -1 if error}
2224 {************************************************************************}
2225 {* VESA Modes inits *}
2226 {************************************************************************}
2230 {******************************************************** }
2231 { Function GetMaxScanLines() }
2232 {-------------------------------------------------------- }
2233 { This routine returns the maximum number of scan lines }
2234 { possible for this mode. This is done using the Get }
2235 { Scan Line length VBE function. }
2236 {******************************************************** }
2237 function GetMaxScanLines: word;
2239 regs : TDPMIRegisters;
2241 FillChar(regs, sizeof(regs), #0);
2242 { play it safe, call the real mode int, the 32-bit entry point }
2243 { may not be defined as stated in VBE v3.0 }
2244 regs.eax := $4f06; {_ setup function }
2245 regs.ebx := $0001; { get scan line length }
2246 RealIntr($10, regs);
2247 GetMaxScanLines := (regs.edx and $0000ffff);
2252 function GetMaxScanLines: word; assembler;
2262 procedure Init1280x1024x64k; {$ifndef fpc}far;{$endif fpc}
2264 SetVesaMode(m1280x1024x64k);
2265 { Get maximum number of scanlines for page flipping }
2266 ScanLines := GetMaxScanLines;
2269 procedure Init1280x1024x32k; {$ifndef fpc}far;{$endif fpc}
2271 SetVESAMode(m1280x1024x32k);
2272 { Get maximum number of scanlines for page flipping }
2273 ScanLines := GetMaxScanLines;
2276 procedure Init1280x1024x256; {$ifndef fpc}far;{$endif fpc}
2278 SetVESAMode(m1280x1024x256);
2279 { Get maximum number of scanlines for page flipping }
2280 ScanLines := GetMaxScanLines;
2284 procedure Init1280x1024x16; {$ifndef fpc}far;{$endif fpc}
2286 SetVESAMode(m1280x1024x16);
2287 { Get maximum number of scanlines for page flipping }
2288 ScanLines := GetMaxScanLines;
2291 procedure Init1024x768x64k; {$ifndef fpc}far;{$endif fpc}
2293 SetVESAMode(m1024x768x64k);
2294 { Get maximum number of scanlines for page flipping }
2295 ScanLines := GetMaxScanLines;
2298 procedure Init640x480x32k; {$ifndef fpc}far;{$endif fpc}
2300 SetVESAMode(m640x480x32k);
2301 { Get maximum number of scanlines for page flipping }
2302 ScanLines := GetMaxScanLines;
2305 procedure Init1024x768x256; {$ifndef fpc}far;{$endif fpc}
2307 SetVESAMode(m1024x768x256);
2308 { Get maximum number of scanlines for page flipping }
2309 ScanLines := GetMaxScanLines;
2312 procedure Init1024x768x16; {$ifndef fpc}far;{$endif fpc}
2314 SetVESAMode(m1024x768x16);
2315 { Get maximum number of scanlines for page flipping }
2316 ScanLines := GetMaxScanLines;
2319 procedure Init800x600x64k; {$ifndef fpc}far;{$endif fpc}
2321 SetVESAMode(m800x600x64k);
2322 { Get maximum number of scanlines for page flipping }
2323 ScanLines := GetMaxScanLines;
2326 procedure Init800x600x32k; {$ifndef fpc}far;{$endif fpc}
2328 SetVESAMode(m800x600x32k);
2329 { Get maximum number of scanlines for page flipping }
2330 ScanLines := GetMaxScanLines;
2333 procedure Init800x600x256; {$ifndef fpc}far;{$endif fpc}
2335 SetVESAMode(m800x600x256);
2336 { Get maximum number of scanlines for page flipping }
2337 ScanLines := GetMaxScanLines;
2340 procedure Init800x600x16; {$ifndef fpc}far;{$endif fpc}
2342 SetVesaMode(m800x600x16);
2343 { Get maximum number of scanlines for page flipping }
2344 ScanLines := GetMaxScanLines;
2347 procedure Init640x480x64k; {$ifndef fpc}far;{$endif fpc}
2349 SetVESAMode(m640x480x64k);
2350 { Get maximum number of scanlines for page flipping }
2351 ScanLines := GetMaxScanLines;
2355 procedure Init640x480x256; {$ifndef fpc}far;{$endif fpc}
2357 SetVESAMode(m640x480x256);
2358 { Get maximum number of scanlines for page flipping }
2359 ScanLines := GetMaxScanLines;
2362 procedure Init640x400x256; {$ifndef fpc}far;{$endif fpc}
2364 SetVESAMode(m640x400x256);
2365 { Get maximum number of scanlines for page flipping }
2366 ScanLines := GetMaxScanLines;
2369 procedure Init320x200x64k; {$ifndef fpc}far;{$endif fpc}
2371 SetVESAMode(m320x200x64k);
2372 { Get maximum number of scanlines for page flipping }
2373 ScanLines := GetMaxScanLines;
2376 procedure Init320x200x32k; {$ifndef fpc}far;{$endif fpc}
2378 SetVESAMode(m320x200x32k);
2379 { Get maximum number of scanlines for page flipping }
2380 ScanLines := GetMaxScanLines;
2386 Procedure SaveStateVESA; {$ifndef fpc}far;{$endif fpc}
2389 regs: TDPMIRegisters;
2391 SaveSupported := FALSE;
2394 LogLn('Get the video mode...');
2396 { Get the video mode }
2409 LogLn('Prepare to save VESA video state');
2411 { Prepare to save video state...}
2413 mov ax, 4F04h { get buffer size to save state }
2415 mov cx, 00001111b { Save DAC / Data areas / Hardware states }
2426 mov [SaveSupported],TRUE
2432 RealIntr($10, regs);
2433 StateSize := word(regs.ebx);
2434 if byte(regs.eax) = $4f then
2435 SaveSupported := TRUE;
2436 if SaveSupported then
2439 LogLn('allocating VESA save buffer of '+strf(64*StateSize));
2442 PtrLong:=GlobalDosAlloc(64*StateSize); { values returned in 64-byte blocks }
2444 PtrLong:=Global_Dos_Alloc(64*StateSize); { values returned in 64-byte blocks }
2448 SavePtr := pointer(longint(PtrLong and $0000ffff) shl 16);
2450 { In FPC mode, we can't do anything with this (no far pointers) }
2451 { However, we still need to keep it to be able to free the }
2452 { memory afterwards. Since this data is not accessed in PM code, }
2453 { there's no need to save it in a seperate buffer (JM) }
2454 if not assigned(SavePtr) then
2457 RealStateSeg := word(PtrLong shr 16);
2459 FillChar(regs, sizeof(regs), #0);
2460 { call the real mode interrupt ... }
2461 regs.eax := $4F04; { save the state buffer }
2462 regs.ecx := $0F; { Save DAC / Data areas / Hardware states }
2463 regs.edx := $01; { save state }
2464 regs.es := RealStateSeg;
2467 FillChar(regs, sizeof(regs), #0);
2468 { restore state, according to Ralph Brown Interrupt list }
2469 { some BIOS corrupt the hardware after a save... }
2470 regs.eax := $4F04; { restore the state buffer }
2471 regs.ecx := $0F; { rest DAC / Data areas / Hardware states }
2473 regs.es := RealStateSeg;
2479 procedure RestoreStateVESA; {$ifndef fpc}far;{$endif fpc}
2481 regs:TDPMIRegisters;
2483 { go back to the old video mode...}
2495 { then restore all state information }
2497 if assigned(SavePtr) and (SaveSupported=TRUE) then
2499 { No far pointer support, so it's possible that that assigned(SavePtr) }
2500 { would return false under FPC. Just check if it's different from nil. }
2501 if (SavePtr <> nil) and (SaveSupported=TRUE) then
2504 FillChar(regs, sizeof(regs), #0);
2505 { restore state, according to Ralph Brown Interrupt list }
2506 { some BIOS corrupt the hardware after a save... }
2507 regs.eax := $4F04; { restore the state buffer }
2508 regs.ecx := $0F; { rest DAC / Data areas / Hardware states }
2509 regs.edx := $02; { restore state }
2510 regs.es := RealStateSeg;
2513 (* Done in exitproc (Jonas)
2515 if GlobalDosFree(longint(SavePtr) shr 16)<>0 then
2517 if Not(Global_Dos_Free(longint(SavePtr) shr 16)) then
2527 {**************************************************************}
2528 {* Real mode routines *}
2529 {**************************************************************}
2531 Procedure SaveStateVESA; far;
2534 SaveSupported := FALSE;
2535 { Get the video mode }
2541 { Prepare to save video state...}
2543 mov ax, 4f04h { get buffer size to save state }
2544 mov cx, 00001111b { Save DAC / Data areas / Hardware states }
2550 mov [SaveSupported],TRUE
2553 if SaveSupported then
2555 GetMem(SavePtr, 64*StateSize); { values returned in 64-byte blocks }
2556 if not assigned(SavePtr) then
2559 mov ax, 4F04h { save the state buffer }
2560 mov cx, 00001111b { Save DAC / Data areas / Hardware states }
2562 mov es, WORD PTR [SavePtr+2]
2563 mov bx, WORD PTR [SavePtr]
2566 { restore state, according to Ralph Brown Interrupt list }
2567 { some BIOS corrupt the hardware after a save... }
2569 mov ax, 4F04h { save the state buffer }
2570 mov cx, 00001111b { Save DAC / Data areas / Hardware states }
2572 mov es, WORD PTR [SavePtr+2]
2573 mov bx, WORD PTR [SavePtr]
2579 procedure RestoreStateVESA; far;
2581 { go back to the old video mode...}
2588 { then restore all state information }
2589 if assigned(SavePtr) and (SaveSupported=TRUE) then
2591 { restore state, according to Ralph Brown Interrupt list }
2593 mov ax, 4F04h { save the state buffer }
2594 mov cx, 00001111b { Save DAC / Data areas / Hardware states }
2595 mov dx, 02h { restore state }
2596 mov es, WORD PTR [SavePtr+2]
2597 mov bx, WORD PTR [SavePtr]
2600 { Done in exitproc (JM)
2601 FreeMem(SavePtr, 64*StateSize); }
2607 {************************************************************************}
2608 {* VESA Page flipping routines *}
2609 {************************************************************************}
2610 { Note: These routines, according to the VBE3 specification, will NOT }
2611 { work with the 24 bpp modes, because of the alignment. }
2612 {************************************************************************}
2614 {******************************************************** }
2615 { Procedure SetVisualVESA() }
2616 {-------------------------------------------------------- }
2617 { This routine changes the page which will be displayed }
2618 { on the screen, since the method has changed somewhat }
2619 { between VBE versions , we will use the old method where }
2620 { the new pixel offset is used to display different pages }
2621 {******************************************************** }
2622 procedure SetVisualVESA(page: word); {$ifndef fpc}far;{$endif fpc}
2624 newStartVisible : word;
2626 if page > HardwarePages then exit;
2627 newStartVisible := (MaxY+1)*page;
2628 if newStartVisible > ScanLines then exit;
2631 mov bx, 0000h { set display start }
2632 mov cx, 0000h { pixel zero ! }
2633 mov dx, [NewStartVisible] { new scanline }
2644 procedure SetActiveVESA(page: word); {$ifndef fpc}far;{$endif fpc}
2646 { video offset is in pixels under VESA VBE! }
2647 { This value is reset after a mode set to page ZERO = YOffset = 0 ) }
2648 YOffset := (MaxY+1)*page;
2653 Revision 1.1 2002/02/19 08:25:17 sasu
2656 Revision 1.1.2.3 2000/12/16 15:57:16 jonas
2657 * removed 64bit evaluations when range checking is on
2659 Revision 1.1.2.2 2000/08/01 05:58:49 jonas
2660 * set _graphresult to grnotdetected if the vesa setmode interrupt
2661 call returns an error
2663 Revision 1.1.2.1 2000/07/16 07:47:01 jonas
2664 * fixed several savevideo/restorevideostate related problems
2665 * moved exitsave pointer from graphh.inc to grap.inc to avoid name
2666 conflicts with people using this name in their own programs
2668 Revision 1.1 2000/07/13 06:30:40 michael
2671 Revision 1.25 2000/07/08 07:48:38 jonas
2672 * LFB modes finally work! You have to add $4000 to the mode number
2673 if you use LFB access!
2675 Revision 1.24 2000/06/07 07:41:44 jonas
2676 * always set SetupLinear to false at the start of the routine (there
2677 were some "exit" statements which returned without the function
2678 result being set otherwise)
2680 Revision 1.23 2000/05/13 14:08:42 jonas
2681 * set some more procedures back to the defaults when using linear
2682 VESA modes because they only work for windowed VESA modes
2684 Revision 1.22 2000/03/19 11:20:13 peter
2685 * graph unit include is now independent and the dependent part
2687 * ggigraph unit for linux added
2689 Revision 1.21 2000/03/12 22:32:22 pierre
2690 + UseLFB and UseNoSelector vars to force LinearFrameBuffer use
2691 with or without specific selector.
2693 Revision 1.20 2000/03/09 22:32:22 pierre
2694 * fixes for LFB mode
2696 Revision 1.19 2000/02/12 13:39:19 jonas
2697 + new, faster fillpoly from Thomas Schatzl
2698 * some logging commands in vesa.inc disabled
2700 Revision 1.18 2000/01/07 16:41:32 daniel
2703 Revision 1.17 2000/01/07 16:32:24 daniel
2704 * copyright 2000 added
2706 Revision 1.16 2000/01/06 15:19:42 jonas
2707 * fixed bug in getscanlinevesa256 and hlinevesa256 for short lines (<8 pixels)
2709 Revision 1.15 2000/01/02 18:51:05 jonas
2710 * again small fix to patternline-, hline- and getscanlinevesa256
2712 Revision 1.14 1999/12/29 12:15:41 jonas
2713 * fixed small bug in hlinevesa256, getscanlinevesa25 and patternlinevesa256
2714 * small speed-up in the above procedures
2716 Revision 1.13 1999/12/27 12:10:57 jonas
2717 * fixed VESA palrec structure
2719 Revision 1.12 1999/12/26 10:36:00 jonas
2720 * finished patternlineVESA256 and enabled it
2721 * folded (direct)put/getpixVESA32k and 64k into one procedure since
2722 they were exactly the same code
2724 Revision 1.11 1999/12/25 22:31:09 jonas
2725 + patternlineVESA256, not yet used because I'm not yet sure it's
2726 already working 100%
2727 * changed {$ifdef logging} to {$ifdef logging2} for vlineVESA256 and
2728 hlineVESA256 (they're used a lot a working properly afaik)
2730 Revision 1.10 1999/12/21 17:42:17 jonas
2731 * changed vesa.inc so it doesn't try to use linear modes anymore (doesn't work
2733 * fixed mode detection so the low modenumber of a driver doesn't have to be zero
2734 anymore (so VESA autodetection now works)
2736 Revision 1.9 1999/12/12 13:34:20 jonas
2737 * putimage now performs the lipping itself and uses directputpixel
2738 (note: this REQUIRES or/and/notput support in directputpixel,
2739 this is not yet the case in the assembler versions!)
2740 * YOffset addition moved in hlinevesa256 and vlinevesa256
2741 because it uses still putpixel afterwards
2743 Revision 1.8 1999/12/11 23:41:39 jonas
2744 * changed definition of getscanlineproc to "getscanline(x1,x2,y:
2745 integer; var data);" so it can be used by getimage too
2746 * changed getimage so it uses getscanline
2747 * changed floodfill, getscanline16 and definitions in Linux
2748 include files so they use this new format
2749 + getscanlineVESA256 for 256 color VESA modes (banked)
2751 Revision 1.7 1999/12/10 12:52:54 pierre
2752 * some LinearFrameBuffer code, not finished
2754 Revision 1.6 1999/12/09 02:06:00 carl
2755 + page flipping for all VESA modes.
2756 (important note: The VESAModeInfo structure returns the MAXIMUM
2757 number of image pages, and not the actual available number of
2758 pages (cf. VBE 3.0 specification), that is the reason why
2759 SetVisualPage() has so much checking).
2761 Revision 1.5 1999/12/02 22:34:14 pierre
2762 * avoid FPC problem in array of char comp
2764 Revision 1.4 1999/11/30 02:25:15 carl
2765 * GetPixVESA16 bugfix with read segment.
2767 Revision 1.3 1999/11/28 12:18:39 jonas
2768 + all available mode numbers are logged if you compile the unit with
2771 Revision 1.2 1999/11/27 21:48:01 jonas
2772 * fixed VlineVESA256 and re-enabled it in graph.inc
2773 * added procedure detectgraph to interface of graph unit
2775 Revision 1.1 1999/11/08 11:15:21 peter
2776 * move graph.inc to the target dir
2778 Revision 1.21 1999/11/03 20:23:01 florian
2779 + first release of win32 gui support
2781 Revision 1.20 1999/10/24 15:50:23 carl
2782 * Bugfix in TP mode SaveStateVESA
2784 Revision 1.19 1999/10/24 03:37:15 carl
2785 + GetPixVESA16 (not tested yet...)
2787 Revision 1.18 1999/09/28 13:56:31 jonas
2788 * reordered some local variables (first 4 byte vars, then 2 byte vars
2790 * font data is now disposed in exitproc, exitproc is now called
2791 GraphExitProc (was CleanModes) and resides in graph.pp instead of in
2794 Revision 1.17 1999/09/27 23:34:42 peter
2795 * new graph unit is default for go32v2
2796 * removed warnings/notes
2798 Revision 1.16 1999/09/26 13:31:07 jonas
2799 * changed name of modeinfo variable to vesamodeinfo and fixed
2800 associated errors (fillchar(modeinfo,sizeof(tmodeinfo),#0) instead
2801 of sizeof(TVesamodeinfo) etc)
2802 * changed several sizeof(type) to sizeof(varname) to avoid similar
2803 errors in the future
2805 Revision 1.15 1999/09/24 22:52:39 jonas
2806 * optimized patternline a bit (always use hline when possible)
2807 * isgraphmode stuff cleanup
2808 * vesainfo.modelist now gets disposed in cleanmode instead of in
2809 closegraph (required moving of some declarations from vesa.inc to
2811 * queryadapter gets no longer called from initgraph (is called from
2812 initialization of graph unit)
2813 * bugfix for notput in 32k and 64k vesa modes
2814 * a div replaced by / in fillpoly
2816 Revision 1.14 1999/09/23 14:00:42 jonas
2817 * -dlogging no longer required to fuction correctly
2820 Revision 1.13 1999/09/20 09:34:30 florian
2823 Revision 1.12 1999/09/18 22:21:11 jonas
2824 + hlinevesa256 and vlinevesa256
2825 + support for not/xor/or/andput in vesamodes with 32k/64k colors
2826 * lots of changes to avoid warnings under FPC
2828 Revision 1.11 1999/09/15 11:40:30 jonas
2829 * fixed PutPixVESA256
2831 Revision 1.10 1999/09/11 19:43:02 jonas
2832 * FloodFill: did not take into account current viewport settings
2833 * GetScanLine: only get line inside viewport, data outside of it
2835 * InternalEllipseDefault: fix for when xradius or yradius = 0 and
2836 increase xradius and yradius always by one (TP does this too)
2837 * fixed conlict in vesa.inc from last update
2838 * some conditionals to avoid range check and overflow errors in
2839 places where it doesn't matter
2841 Revision 1.9 1999/08/01 14:51:07 jonas
2842 * removed and/or/xorput support from vesaputpix256 (not in TP either)
2843 * added notput support to directputpix256
2845 Revision 1.8 1999/07/18 15:07:21 jonas
2846 + xor-, and- and orput support for VESA256 modes
2847 * compile with -dlogging if you wnt some info to be logged to grlog.txt
2849 Revision 1.7 1999/07/14 15:21:49 jonas
2850 * fixed initialization of bankshift var ('64 shr banshift' instead of shl)
2852 Revision 1.6 1999/07/14 13:17:29 jonas
2853 * bugfix in getmodeinfo (SizeOf(TModeInfo) -> SizeOf(TVESAModeInfo))
2854 * as the result of the above bugfix, the graph unit doesn't crash
2855 anymore under FPC if compiler with -dsupportVESA, but it doesn't
2858 Revision 1.5 1999/07/12 13:28:33 jonas
2859 * forgot log tag in previous commit