fpc/rtl/unix/graph16.inc
fpc 50778076c3 initial import
git-svn-id: trunk@1 -
2005-05-16 18:37:41 +00:00

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
}