123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434 |
- {************************************************************************}
- {* 4-bit planar VGA mode routines *}
- {************************************************************************}
- const
- VideoOfs = 0;
- var
- VidMem: PByteArray;
- ScrWidth: Integer;
- procedure bytemove(var source, dest; count: Integer);
- 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 : Integer; 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: Integer):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: integer; 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 : Integer);
- { 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: Integer);
- var
- xtmp: Integer;
- 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: integer);
- var
- ytmp: integer;
- 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$
- Revision 1.2 2002-09-07 16:01:27 peter
- * old logs removed and tabs fixed
- }
|