mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-04-17 08:39:33 +02:00
435 lines
10 KiB
PHP
435 lines
10 KiB
PHP
{************************************************************************}
|
|
{* 4-bit planar VGA mode routines *}
|
|
{************************************************************************}
|
|
|
|
|
|
const
|
|
|
|
VideoOfs = 0;
|
|
|
|
|
|
var
|
|
|
|
VidMem: PByteArray;
|
|
ScrWidth: SmallInt;
|
|
|
|
|
|
procedure bytemove(var source, dest; count: SmallInt);
|
|
var
|
|
s, d: PByte;
|
|
begin
|
|
s := PByte(@source);
|
|
d := PByte(@dest);
|
|
while count > 0 do begin
|
|
d^ := s^;
|
|
Inc(d);
|
|
Inc(s);
|
|
Dec(count);
|
|
end;
|
|
end;
|
|
|
|
|
|
|
|
procedure PutPixel16(X,Y : SmallInt; Pixel: Word);
|
|
var
|
|
offset: word;
|
|
dummy: byte;
|
|
begin
|
|
Inc(x, StartXViewPort);
|
|
Inc(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;
|
|
offset := y * 80 + (x shr 3) + VideoOfs;
|
|
WritePortW($3ce, $0f01); { Index 01 : Enable ops on all 4 planes }
|
|
WritePortW($3ce, (Pixel and $ff) shl 8); { Index 00 : Enable correct plane and write color }
|
|
|
|
WritePortW($3ce, 8 or ($8000 shr (x and $7)));{ Select correct bits to modify }
|
|
dummy := VidMem^[offset]; { Read data byte into VGA latch register }
|
|
VidMem^[offset] := dummy; { Write the data into video memory }
|
|
end;
|
|
|
|
|
|
function GetPixel16(X,Y: SmallInt):word;
|
|
var
|
|
dummy, offset: Word;
|
|
shift: byte;
|
|
begin
|
|
Inc(x, StartXViewPort);
|
|
Inc(y, StartYViewPort);
|
|
offset := Y * 80 + (x shr 3) + VideoOfs;
|
|
WritePortW($3ce, 4);
|
|
shift := 7 - (X and 7);
|
|
dummy := (VidMem^[offset] shr shift) and 1;
|
|
WritePortB($3cf, 1);
|
|
dummy := dummy or (((VidMem^[offset] shr shift) and 1) shl 1);
|
|
WritePortB($3cf, 2);
|
|
dummy := dummy or (((VidMem^[offset] shr shift) and 1) shl 2);
|
|
WritePortB($3cf, 3);
|
|
dummy := dummy or (((VidMem^[offset] shr shift) and 1) shl 3);
|
|
GetPixel16 := dummy;
|
|
end;
|
|
|
|
|
|
procedure GetScanLine16(x1, x2, y: SmallInt; var data);
|
|
var
|
|
dummylong: longint;
|
|
Offset, count, count2, amount, index: word;
|
|
plane: byte;
|
|
begin
|
|
inc(x1,StartXViewPort);
|
|
inc(x2,StartXViewPort);
|
|
{$ifdef logging}
|
|
LogLn('GetScanLine16 start, length to get: '+strf(x2-x1+1)+' at y = '+strf(y));
|
|
{$Endif logging}
|
|
offset := (Y + StartYViewPort) * 80 + (x1 shr 3) + VideoOfs;
|
|
{$ifdef logging}
|
|
LogLn('Offset: '+HexStr(offset,4)+' - ' + strf(offset));
|
|
{$Endif logging}
|
|
{ first get enough pixels so offset is 32bit aligned }
|
|
amount := 0;
|
|
index := 0;
|
|
If ((x1 and 31) <> 0) Or
|
|
((x2-x1+1) < 32) Then
|
|
Begin
|
|
If ((x2-x1+1) >= 32+32-(x1 and 31)) Then
|
|
amount := 32-(x1 and 31)
|
|
Else amount := x2-x1+1;
|
|
{$ifdef logging}
|
|
LogLn('amount to align to 32bits or to get all: ' + strf(amount));
|
|
{$Endif logging}
|
|
For count := 0 to amount-1 do
|
|
WordArray(Data)[Count] := getpixel16(x1-StartXViewPort+Count,y);
|
|
index := amount;
|
|
Inc(Offset,(amount+7) shr 3);
|
|
{$ifdef logging}
|
|
LogLn('offset now: '+HexStr(offset,4)+' - ' + strf(offset));
|
|
LogLn('index now: '+strf(index));
|
|
{$Endif logging}
|
|
End;
|
|
amount := x2-x1+1 - amount;
|
|
{$ifdef logging}
|
|
LogLn('amount left: ' + strf(amount));
|
|
{$Endif logging}
|
|
If amount = 0 Then Exit;
|
|
WritePortB($3ce, 4);
|
|
{ first get everything from plane 3 (4th plane) }
|
|
WritePortB($3cf, 3);
|
|
Count := 0;
|
|
For Count := 1 to (amount shr 5) Do
|
|
Begin
|
|
dummylong := PLongInt(@VidMem^[offset+(Count-1)*4])^;
|
|
dummylong :=
|
|
((dummylong and $ff) shl 24) or
|
|
((dummylong and $ff00) shl 8) or
|
|
((dummylong and $ff0000) shr 8) or
|
|
((dummylong and $ff000000) shr 24);
|
|
For Count2 := 31 downto 0 Do
|
|
Begin
|
|
WordArray(Data)[index+Count2] := DummyLong and 1;
|
|
DummyLong := DummyLong shr 1;
|
|
End;
|
|
Inc(Index, 32);
|
|
End;
|
|
{ Now get the data from the 3 other planes }
|
|
plane := 3;
|
|
Repeat
|
|
Dec(Index,Count*32);
|
|
Dec(plane);
|
|
WritePortB($3cf, plane);
|
|
Count := 0;
|
|
For Count := 1 to (amount shr 5) Do
|
|
Begin
|
|
dummylong := PLongInt(@VidMem^[offset+(Count-1)*4])^;
|
|
dummylong :=
|
|
((dummylong and $ff) shl 24) or
|
|
((dummylong and $ff00) shl 8) or
|
|
((dummylong and $ff0000) shr 8) or
|
|
((dummylong and $ff000000) shr 24);
|
|
For Count2 := 31 downto 0 Do
|
|
Begin
|
|
WordArray(Data)[index+Count2] :=
|
|
(WordArray(Data)[index+Count2] shl 1) or (DummyLong and 1);
|
|
DummyLong := DummyLong shr 1;
|
|
End;
|
|
Inc(Index, 32);
|
|
End;
|
|
Until plane = 0;
|
|
amount := amount and 31;
|
|
Dec(index);
|
|
{$ifdef Logging}
|
|
LogLn('Last array index written to: '+strf(index));
|
|
LogLn('amount left: '+strf(amount)+' starting at x = '+strf(index+1));
|
|
{$Endif logging}
|
|
For Count := 1 to amount Do
|
|
WordArray(Data)[index+Count] := getpixel16(index+Count,y);
|
|
{$ifdef logging}
|
|
LogLn('First 32 bytes gotten with getscanline16: ');
|
|
If x2-x1+1 >= 32 Then
|
|
Count2 := 32
|
|
Else Count2 := x2-x1+1;
|
|
For Count := 0 to Count2-1 Do
|
|
Log(strf(WordArray(Data)[Count])+' ');
|
|
LogLn('');
|
|
If x2-x1+1 >= 32 Then
|
|
Begin
|
|
LogLn('Last 32 bytes gotten with getscanline16: ');
|
|
For Count := 31 downto 0 Do
|
|
Log(strf(WordArray(Data)[x2-x1-Count])+' ');
|
|
End;
|
|
LogLn('');
|
|
GetScanLineDefault(x1-StartXViewPort,x2-StartXViewPort,y,Data);
|
|
LogLn('First 32 bytes gotten with getscanlinedef: ');
|
|
If x2-x1+1 >= 32 Then
|
|
Count2 := 32
|
|
Else Count2 := x2-x1+1;
|
|
For Count := 0 to Count2-1 Do
|
|
Log(strf(WordArray(Data)[Count])+' ');
|
|
LogLn('');
|
|
If x2-x1+1 >= 32 Then
|
|
Begin
|
|
LogLn('Last 32 bytes gotten with getscanlinedef: ');
|
|
For Count := 31 downto 0 Do
|
|
Log(strf(WordArray(Data)[x2-x1-Count])+' ');
|
|
End;
|
|
LogLn('');
|
|
LogLn('GetScanLine16 end');
|
|
{$Endif logging}
|
|
end;
|
|
|
|
|
|
procedure DirectPutPixel16(X,Y : SmallInt);
|
|
{ x,y -> must be in global coordinates. No clipping. }
|
|
var
|
|
color: word;
|
|
offset: word;
|
|
dummy: byte;
|
|
begin
|
|
case CurrentWriteMode of
|
|
XORPut:
|
|
begin
|
|
{ getpixel wants local/relative coordinates }
|
|
Color := GetPixel(x - StartXViewPort, y - StartYViewPort);
|
|
Color := CurrentColor xor Color;
|
|
end;
|
|
OrPut:
|
|
begin
|
|
{ getpixel wants local/relative coordinates }
|
|
Color := GetPixel(x - StartXViewPort, y - StartYViewPort);
|
|
Color := CurrentColor or Color;
|
|
end;
|
|
AndPut:
|
|
begin
|
|
{ getpixel wants local/relative coordinates }
|
|
Color := GetPixel(x - StartXViewPort, y - StartYViewPort);
|
|
Color := CurrentColor and Color;
|
|
end;
|
|
NotPut:
|
|
Color := Not Color;
|
|
else
|
|
Color := CurrentColor;
|
|
end;
|
|
offset := Y * 80 + (X shr 3) + VideoOfs;
|
|
WritePortW($3ce, $f01);
|
|
WritePortW($3ce, Color shl 8);
|
|
WritePortW($3ce, 8 or $8000 shr (X and 7));
|
|
dummy := VidMem^[offset];
|
|
VidMem^[offset] := dummy;
|
|
end;
|
|
|
|
|
|
procedure HLine16(x, x2, y: SmallInt);
|
|
var
|
|
xtmp: SmallInt;
|
|
ScrOfs, HLength: Word;
|
|
LMask, RMask: Byte;
|
|
begin
|
|
{ must we swap the values? }
|
|
if x > x2 then
|
|
begin
|
|
xtmp := x2;
|
|
x2 := x;
|
|
x:= xtmp;
|
|
end;
|
|
{ First convert to global coordinates }
|
|
Inc(x, StartXViewPort);
|
|
Inc(x2, StartXViewPort);
|
|
Inc(y, StartYViewPort);
|
|
if ClipPixels and LineClipped(x,y,x2,y,StartXViewPort,StartYViewPort,
|
|
StartXViewPort+ViewWidth, StartYViewPort+ViewHeight) then
|
|
exit;
|
|
|
|
ScrOfs := y * ScrWidth + x div 8;
|
|
HLength := x2 div 8 - x div 8;
|
|
LMask := $ff shr (x and 7);
|
|
{$ifopt r+}
|
|
{$define rangeOn}
|
|
{$r-}
|
|
{$endif}
|
|
{$ifopt q+}
|
|
{$define overflowOn}
|
|
{$q-}
|
|
{$endif}
|
|
RMask:=$ff shl (7 - (x2 and 7));
|
|
{$ifdef rangeOn}
|
|
{$undef rangeOn}
|
|
{$r+}
|
|
{$endif}
|
|
{$ifdef overflowOn}
|
|
{$undef overflowOn}
|
|
{$q+}
|
|
{$endif}
|
|
if HLength=0 then
|
|
LMask:=LMask and RMask;
|
|
WritePortB($3ce, 0);
|
|
if CurrentWriteMode <> NotPut Then
|
|
WritePortB($3cf, CurrentColor)
|
|
else
|
|
WritePortB($3cf, not CurrentColor);
|
|
WritePortW($3ce, $0f01);
|
|
WritePortB($3ce, 3);
|
|
case CurrentWriteMode of
|
|
XORPut:
|
|
WritePortB($3cf, 3 shl 3);
|
|
ANDPut:
|
|
WritePortB($3cf, 1 shl 3);
|
|
ORPut:
|
|
WritePortB($3cf, 2 shl 3);
|
|
NormalPut, NotPut:
|
|
WritePortB($3cf, 0)
|
|
else
|
|
WritePortB($3cf, 0)
|
|
end;
|
|
|
|
WritePortB($3ce, 8);
|
|
WritePortB($3cf, LMask);
|
|
{$ifopt r+}
|
|
{$define rangeOn}
|
|
{$r-}
|
|
{$endif}
|
|
{$ifopt q+}
|
|
{$define overflowOn}
|
|
{$q-}
|
|
{$endif}
|
|
VidMem^[ScrOfs] := VidMem^[ScrOfs] + 1;
|
|
{$ifdef rangeOn}
|
|
{$undef rangeOn}
|
|
{$r+}
|
|
{$endif}
|
|
{$ifdef overflowOn}
|
|
{$undef overflowOn}
|
|
{$q+}
|
|
{$endif}
|
|
if HLength>0 then
|
|
begin
|
|
Dec(HLength);
|
|
Inc(ScrOfs);
|
|
if HLength>0 then
|
|
begin
|
|
WritePortW($3ce, $ff08);
|
|
bytemove(VidMem^[ScrOfs], VidMem^[ScrOfs], HLength);
|
|
Inc(ScrOfs, HLength);
|
|
end else
|
|
WritePortB($3ce, 8);
|
|
WritePortB($3cf, RMask);
|
|
{$ifopt r+}
|
|
{$define rangeOn}
|
|
{$r-}
|
|
{$endif}
|
|
{$ifopt q+}
|
|
{$define overflowOn}
|
|
{$q-}
|
|
{$endif}
|
|
VidMem^[ScrOfs] := VidMem^[ScrOfs] + 1;
|
|
{$ifdef rangeOn}
|
|
{$undef rangeOn}
|
|
{$r+}
|
|
{$endif}
|
|
{$ifdef overflowOn}
|
|
{$undef overflowOn}
|
|
{$q+}
|
|
{$endif}
|
|
end;
|
|
end;
|
|
|
|
|
|
|
|
procedure VLine16(x,y,y2: SmallInt);
|
|
var
|
|
ytmp: SmallInt;
|
|
ScrOfs,i: longint;
|
|
BitMask: byte;
|
|
|
|
begin
|
|
{ must we swap the values? }
|
|
if y > y2 then
|
|
begin
|
|
ytmp := y2;
|
|
y2 := y;
|
|
y:= ytmp;
|
|
end;
|
|
{ First convert to global coordinates }
|
|
Inc(x, StartXViewPort);
|
|
Inc(y, StartYViewPort);
|
|
Inc(y2, StartYViewPort);
|
|
if ClipPixels and LineClipped(x,y,x,y2,StartXViewPort,StartYViewPort,
|
|
StartXViewPort+ViewWidth, StartYViewPort+ViewHeight) then
|
|
exit;
|
|
ScrOfs:=y*ScrWidth+x div 8;
|
|
BitMask:=$80 shr (x and 7);
|
|
WritePortB($3ce, 0);
|
|
if CurrentWriteMode <> NotPut then
|
|
WritePortB($3cf, CurrentColor)
|
|
else
|
|
WritePortB($3cf, not CurrentColor);
|
|
WritePortW($3ce, $0f01);
|
|
WritePortB($3ce, 8);
|
|
WritePortB($3cf, BitMask);
|
|
WritePortB($3ce, 3);
|
|
case CurrentWriteMode of
|
|
XORPut:
|
|
WritePortB($3cf, 3 shl 3);
|
|
ANDPut:
|
|
WritePortB($3cf, 1 shl 3);
|
|
ORPut:
|
|
WritePortB($3cf, 2 shl 3);
|
|
NormalPut, NotPut:
|
|
WritePortB($3cf, 0)
|
|
else
|
|
WritePortB($3cf, 0)
|
|
end;
|
|
for i:=y to y2 do
|
|
begin
|
|
{$ifopt r+}
|
|
{$define rangeOn}
|
|
{$r-}
|
|
{$endif}
|
|
{$ifopt q+}
|
|
{$define overflowOn}
|
|
{$q-}
|
|
{$endif}
|
|
VidMem^[ScrOfs]:=VidMem^[ScrOfs]+1;
|
|
{$ifdef rangeOn}
|
|
{$undef rangeOn}
|
|
{$r+}
|
|
{$endif}
|
|
{$ifdef overflowOn}
|
|
{$undef overflowOn}
|
|
{$q+}
|
|
{$endif}
|
|
Inc(ScrOfs, ScrWidth);
|
|
end;
|
|
end;
|
|
|
|
{
|
|
$Log: graph16.inc,v $
|
|
Revision 1.4 2005/02/14 17:13:31 peter
|
|
* truncate log
|
|
|
|
}
|