+ VESA banked 32k/64k colour mode fast line drawing for msdos as well

git-svn-id: trunk@30249 -
This commit is contained in:
nickysn 2015-03-17 02:37:48 +00:00
parent 84f5184911
commit be2937bb17
2 changed files with 318 additions and 0 deletions

View File

@ -3230,6 +3230,7 @@ const CrtAddress: word = 0;
mode.GetRGBPalette := {$ifdef fpc}@{$endif}GetVESARGBPalette;
mode.SetVisualPage := {$ifdef fpc}@{$endif}SetVisualVESA;
mode.SetActivePage := {$ifdef fpc}@{$endif}SetActiveVESA;
mode.HLine := {$ifdef fpc}@{$endif}HLineVESA32kOr64k;
end;
procedure FillCommonVESA32k(var mode: TModeInfo);

View File

@ -1071,6 +1071,323 @@ end;
End;
end;
procedure HLineVESA32kOr64k(x,x2,y: smallint); {$ifndef fpc}far;{$endif fpc}
var Offs: Longint;
mask, l, bankrest: longint;
curbank, hlength: smallint;
Begin
{ must we swap the values? }
if x > x2 then
Begin
x := x xor x2;
x2 := x xor x2;
x:= x xor x2;
end;
{ First convert to global coordinates }
X := X + StartXViewPort;
X2 := X2 + StartXViewPort;
Y := Y + StartYViewPort;
if ClipPixels then
Begin
if LineClipped(x,y,x2,y,StartXViewPort,StartYViewPort,
StartXViewPort+ViewWidth, StartYViewPort+ViewHeight) then
exit;
end;
{$ifdef logging2}
LogLn('hline '+strf(x)+' - '+strf(x2)+' on '+strf(y)+' in mode '+strf(currentwritemode));
{$endif logging2}
HLength := x2 - x + 1;
{$ifdef logging2}
LogLn('length: '+strf(hlength));
{$endif logging2}
if HLength>0 then
begin
Offs:=(Longint(y)+YOffset)*bytesperline+2*x;
{$ifdef logging2}
LogLn('Offs: '+strf(offs)+' -- '+hexstr(offs,8));
{$endif logging2}
Mask := longint(word(CurrentColor))+(longint(word(CurrentColor)) shl 16);
Case CurrentWriteMode of
AndPut:
Begin
Repeat
curbank := smallint(offs shr 16);
SetWriteBank(curbank);
SetReadBank(curbank);
{$ifdef logging2}
LogLn('set bank '+strf(curbank)+' for offset '+hexstr(offs,8));
{$endif logging2}
If ((HLength >= 2) and
((offs and 3) = 0)) or
(HLength >= 3) Then
{ align target }
Begin
If (offs and 3) <> 0 then
{ this cannot go past a window boundary because the }
{ size of a window is always a multiple of 4 }
Begin
{$ifdef logging2}
LogLn('Aligning by drawing 1 pixel');
{$endif logging2}
MemW[WinWriteSeg:word(offs)] :=
MemW[WinReadSeg:word(offs)] And Word(CurrentColor);
Dec(HLength);
inc(offs, 2);
End;
{$ifdef logging2}
LogLn('Offset is now '+hexstr(offs,8)+', length left: '+strf(hlength));
{$endif logging}
{ offs is now 4-bytes aligned }
If HLength <= (($10000-(Offs and $ffff)) shr 1) Then
bankrest := HLength
else {the rest won't fit anymore in the current window }
bankrest := ($10000 - (Offs and $ffff)) shr 1;
{ it is possible that by aligningm we ended up in a new }
{ bank, so set the correct bank again to make sure }
setwritebank(offs shr 16);
setreadbank(offs shr 16);
{$ifdef logging2}
LogLn('Rest to be drawn in this window: '+strf(bankrest));
{$endif logging}
For l := 0 to (Bankrest div 2)-1 Do
MemL[WinWriteSeg:word(offs)+l*4] :=
MemL[WinReadSeg:word(offs)+l*4] And Mask;
inc(offs,l*4+4);
dec(hlength,l*2+2);
{$ifdef logging2}
LogLn('Offset is now '+hexstr(offs,8)+', length left: '+strf(hlength));
{$endif logging}
End
Else
Begin
{$ifdef logging2}
LogLn('Drawing leftover: '+strf(HLength)+' at offset '+hexstr(offs,8));
{$endif logging}
if HLength > 0 then
begin
{ this may cross a bank at any time, so adjust }
{ because this loop always runs for very little pixels, }
{ there's little gained by splitting it up }
setreadbank(offs shr 16);
setwritebank(offs shr 16);
MemW[WinWriteSeg:word(offs)] :=
MemW[WinReadSeg:word(offs)] And Word(currentColor);
HLength := 0
end;
End
Until HLength = 0;
End;
XorPut:
Begin
Repeat
curbank := smallint(offs shr 16);
SetWriteBank(curbank);
SetReadBank(curbank);
{$ifdef logging2}
LogLn('set bank '+strf(curbank)+' for offset '+hexstr(offs,8));
{$endif logging2}
If ((HLength >= 2) and
((offs and 3) = 0)) or
(HLength >= 3) Then
{ align target }
Begin
If (offs and 3) <> 0 then
{ this cannot go past a window boundary because the }
{ size of a window is always a multiple of 4 }
Begin
{$ifdef logging2}
LogLn('Aligning by drawing 1 pixel');
{$endif logging2}
MemW[WinWriteSeg:word(offs)] :=
MemW[WinReadSeg:word(offs)] Xor Word(CurrentColor);
Dec(HLength);
inc(offs, 2);
End;
{$ifdef logging2}
LogLn('Offset is now '+hexstr(offs,8)+', length left: '+strf(hlength));
{$endif logging}
{ offs is now 4-bytes aligned }
If HLength <= (($10000-(Offs and $ffff)) shr 1) Then
bankrest := HLength
else {the rest won't fit anymore in the current window }
bankrest := ($10000 - (Offs and $ffff)) shr 1;
{ it is possible that by aligningm we ended up in a new }
{ bank, so set the correct bank again to make sure }
setwritebank(offs shr 16);
setreadbank(offs shr 16);
{$ifdef logging2}
LogLn('Rest to be drawn in this window: '+strf(bankrest));
{$endif logging}
For l := 0 to (Bankrest div 2)-1 Do
MemL[WinWriteSeg:word(offs)+l*4] :=
MemL[WinReadSeg:word(offs)+l*4] Xor Mask;
inc(offs,l*4+4);
dec(hlength,l*2+2);
{$ifdef logging2}
LogLn('Offset is now '+hexstr(offs,8)+', length left: '+strf(hlength));
{$endif logging}
End
Else
Begin
{$ifdef logging2}
LogLn('Drawing leftover: '+strf(HLength)+' at offset '+hexstr(offs,8));
{$endif logging}
if HLength > 0 then
begin
{ this may cross a bank at any time, so adjust }
{ because this loop always runs for very little pixels, }
{ there's little gained by splitting it up }
setreadbank(offs shr 16);
setwritebank(offs shr 16);
MemW[WinWriteSeg:word(offs)] :=
MemW[WinReadSeg:word(offs)] Xor Word(currentColor);
HLength := 0
end;
End
Until HLength = 0;
End;
OrPut:
Begin
Repeat
curbank := smallint(offs shr 16);
SetWriteBank(curbank);
SetReadBank(curbank);
{$ifdef logging2}
LogLn('set bank '+strf(curbank)+' for offset '+hexstr(offs,8));
{$endif logging2}
If ((HLength >= 2) and
((offs and 3) = 0)) or
(HLength >= 3) Then
{ align target }
Begin
If (offs and 3) <> 0 then
{ this cannot go past a window boundary because the }
{ size of a window is always a multiple of 4 }
Begin
{$ifdef logging2}
LogLn('Aligning by drawing 1 pixel');
{$endif logging2}
MemW[WinWriteSeg:word(offs)] :=
MemW[WinReadSeg:word(offs)] Or Word(CurrentColor);
Dec(HLength);
inc(offs, 2);
End;
{$ifdef logging2}
LogLn('Offset is now '+hexstr(offs,8)+', length left: '+strf(hlength));
{$endif logging}
{ offs is now 4-bytes aligned }
If HLength <= (($10000-(Offs and $ffff)) shr 1) Then
bankrest := HLength
else {the rest won't fit anymore in the current window }
bankrest := ($10000 - (Offs and $ffff)) shr 1;
{ it is possible that by aligningm we ended up in a new }
{ bank, so set the correct bank again to make sure }
setwritebank(offs shr 16);
setreadbank(offs shr 16);
{$ifdef logging2}
LogLn('Rest to be drawn in this window: '+strf(bankrest));
{$endif logging}
For l := 0 to (Bankrest div 2)-1 Do
MemL[WinWriteSeg:word(offs)+l*4] :=
MemL[WinReadSeg:word(offs)+l*4] Or Mask;
inc(offs,l*4+4);
dec(hlength,l*2+2);
{$ifdef logging2}
LogLn('Offset is now '+hexstr(offs,8)+', length left: '+strf(hlength));
{$endif logging}
End
Else
Begin
{$ifdef logging2}
LogLn('Drawing leftover: '+strf(HLength)+' at offset '+hexstr(offs,8));
{$endif logging}
if HLength > 0 then
begin
{ this may cross a bank at any time, so adjust }
{ because this loop always runs for very little pixels, }
{ there's little gained by splitting it up }
setreadbank(offs shr 16);
setwritebank(offs shr 16);
MemW[WinWriteSeg:word(offs)] :=
MemW[WinReadSeg:word(offs)] Or Word(currentColor);
HLength := 0
end;
End
Until HLength = 0;
End
Else
Begin
If CurrentWriteMode = NotPut Then
Mask := Not(Mask);
Repeat
curbank := smallint(offs shr 16);
SetWriteBank(curbank);
SetReadBank(curbank);
{$ifdef logging2}
LogLn('set bank '+strf(curbank)+' for offset '+hexstr(offs,8));
{$endif logging2}
If ((HLength >= 2) and
((offs and 3) = 0)) or
(HLength >= 3) Then
{ align target }
Begin
If (offs and 3) <> 0 then
{ this cannot go past a window boundary because the }
{ size of a window is always a multiple of 4 }
Begin
{$ifdef logging2}
LogLn('Aligning by drawing 1 pixel');
{$endif logging2}
MemW[WinWriteSeg:word(offs)] := Word(Mask);
Dec(HLength);
inc(offs, 2);
End;
{$ifdef logging2}
LogLn('Offset is now '+hexstr(offs,8)+', length left: '+strf(hlength));
{$endif logging}
{ offs is now 4-bytes aligned }
If HLength <= (($10000-(Offs and $ffff)) shr 1) Then
bankrest := HLength
else {the rest won't fit anymore in the current window }
bankrest := ($10000 - (Offs and $ffff)) shr 1;
{ it is possible that by aligningm we ended up in a new }
{ bank, so set the correct bank again to make sure }
setwritebank(offs shr 16);
setreadbank(offs shr 16);
{$ifdef logging2}
LogLn('Rest to be drawn in this window: '+strf(bankrest));
{$endif logging}
For l := 0 to (Bankrest div 2)-1 Do
MemL[WinWriteSeg:word(offs)+l*4] := Mask;
inc(offs,l*4+4);
dec(hlength,l*2+2);
{$ifdef logging2}
LogLn('Offset is now '+hexstr(offs,8)+', length left: '+strf(hlength));
{$endif logging}
End
Else
Begin
{$ifdef logging2}
LogLn('Drawing leftover: '+strf(HLength)+' at offset '+hexstr(offs,8));
{$endif logging}
if HLength > 0 then
begin
{ this may cross a bank at any time, so adjust }
{ because this loop always runs for very little pixels, }
{ there's little gained by splitting it up }
setreadbank(offs shr 16);
setwritebank(offs shr 16);
MemW[WinWriteSeg:word(offs)] := Word(Mask);
HLength := 0
end;
End
Until HLength = 0;
End;
End;
end;
end;
{************************************************************************}
{* 4-bit pixels VESA mode routines *}