vga.c
来自「这是一个开放源代码的与WINNT/WIN2K/WIN2003兼容的操作系统」· C语言 代码 · 共 1,275 行 · 第 1/3 页
C
1,275 行
"Buffer: %p. Delta: %lx\n",
Width,
Height,
Left,
Top,
BitsPerPixel,
Buffer,
Delta);
return;
}
/* Get the masks and other values */
LeftAnd = Left & 0x7;
lMask = lMaskTable[LeftAnd];
Distance = Width + Left;
rMask = rMaskTable[(Distance - 1) & 0x7];
Left >>= 3;
/* Set some values */
SomeYesNoFlag = FALSE;
SomeYesNoFlag2 = FALSE;
Distance = (Distance - 1) >> 3;
DistanceMinusLeftBpp = Distance - Left;
/* Check if the distance is equal to the left position and add the masks */
if (Left == Distance) lMask += rMask;
/* Check if there's no distance offset */
if (DistanceMinusLeftBpp)
{
/* Set the first flag on */
SomeYesNoFlag = TRUE;
/* Decrease offset and check if we still have one */
if (--DistanceMinusLeftBpp)
{
/* Still have a distance offset */
SomeYesNoFlag2 = TRUE;
}
}
/* Calculate initial pixel position */
PixelPosition = (PUCHAR)VgaBase + (Top * 80) + Left;
/* Set loop buffer variable */
i = Buffer;
/* Switch to mode 0 */
ReadWriteMode(0);
/* Leave now if the height is 0 */
if (Height <= 0) return;
/* Set more weird values */
CurrentLeft = &LeftArray[Left];
NotlMask = ~(UCHAR)lMask;
LeftPlusOne = Left + 1;
LeftShifted = (lMask << 8) | 8;
j = Height;
/* Start the height loop */
do
{
/* Start the plane loop */
Plane = 0;
do
{
/* Clear the current value */
*CurrentLeft = 0;
LoopCount = 0;
/* Set the buffer loop variable for this loop */
k = i;
/* Calculate plane shift and pixel mask */
PlaneShift = 1 << Plane;
pMask = PixelMask[LeftAnd];
/* Check if we have a width */
if (Width > 0)
{
/* Loop it */
l = CurrentLeft;
x = Width;
do
{
/* Check if we're odd and increase the loop count */
Odd = LoopCount & 1 ? TRUE : FALSE;
LoopCount++;
if (Odd)
{
/* Check for the plane shift */
if (*k & PlaneShift)
{
/* Write the pixel mask */
*l |= pMask;
}
/* Increase buffer position */
k++;
}
else
{
/* Check for plane shift */
if ((*k >> 4) & PlaneShift)
{
/* Write the pixel mask */
*l |= pMask;
}
}
/* Shift the pixel mask */
pMask >>= 1;
if (!pMask)
{
/* Move to the next current left position and clear it */
l++;
*l = 0;
/* Set the pixel mask to 0x80 */
pMask = 0x80;
}
} while (--x);
}
/* Set the plane value */
__outpw(0x3C4, (1 << (Plane + 8) | 2));
/* Select the bitmask register and write the mask */
__outpw(0x3CE, (USHORT)LeftShifted);
/* Read the current Pixel value */
Value = READ_REGISTER_UCHAR(PixelPosition);
/* Add our mask */
Value = (Value & NotlMask) | *CurrentLeft;
/* Set current left for the loop, and write new pixel value */
LeftPos = LeftPlusOne;
WRITE_REGISTER_UCHAR(PixelPosition, Value);
/* Set loop pixel position and check if we should loop */
m = PixelPosition + 1;
if (SomeYesNoFlag2)
{
/* Set the bitmask to 0xFF for all 4 planes */
__outpw(0x3CE, 0xFF08);
/* Check if we have any distance left */
if (DistanceMinusLeftBpp > 0)
{
/* Start looping it */
x = DistanceMinusLeftBpp;
do
{
/* Write the value */
WRITE_REGISTER_UCHAR(m, LeftArray[LeftPos]);
/* Go to the next position */
m++;
LeftPos++;
} while (--x);
}
}
/* Check if the first flag is on */
if (SomeYesNoFlag)
{
/* Set the mask value */
__outpw(0x3CE, (rMask << 8) | 8);
/* Read the current Pixel value */
Value = READ_REGISTER_UCHAR(m);
/* Add our mask */
Value = (Value & ~(UCHAR)rMask) | LeftArray[LeftPos];
/* Set current left for the loop, and write new pixel value */
WRITE_REGISTER_UCHAR(m, Value);
}
} while (++Plane < 4);
/* Update pixel position, buffer and height */
PixelPosition += 80;
i += Delta;
} while (--j);
}
VOID
NTAPI
RleBitBlt(IN ULONG Left,
IN ULONG Top,
IN ULONG Width,
IN ULONG Height,
IN PUCHAR Buffer)
{
ULONG YDelta;
ULONG x;
ULONG RleValue, NewRleValue;
ULONG Color, Color2;
ULONG i, j;
ULONG Code;
/* Set Y height and current X value and start loop */
YDelta = Top + Height - 1;
x = Left;
for (;;)
{
/* Get the current value and advance in the buffer */
RleValue = *Buffer;
Buffer++;
if (RleValue)
{
/* Check if we've gone past the edge */
if ((x + RleValue) > (Width + Left))
{
/* Fixeup the pixel value */
RleValue = Left - x + Width;
}
/* Get the new value */
NewRleValue = *Buffer;
/* Get the two colors */
Color = NewRleValue >> 4;
Color2 = NewRleValue & 0xF;
/* Increase buffer positition */
Buffer++;
/* Check if we need to do a fill */
if (Color == Color2)
{
/* Do a fill and continue the loop */
RleValue += x;
VidSolidColorFill(x, YDelta, RleValue - 1, YDelta, (UCHAR)Color);
x = RleValue;
continue;
}
/* Check if the pixel value is 1 or below */
if (RleValue > 1)
{
/* Set loop variables */
i = (RleValue - 2) / 2 + 1;
do
{
/* Set the pixels */
SetPixel(x, YDelta, (UCHAR)Color);
x++;
SetPixel(x, YDelta, (UCHAR)Color2);
x++;
/* Decrease pixel value */
RleValue -= 2;
} while (--i);
}
/* Check if there is any value at all */
if (RleValue)
{
/* Set the pixel and increase posititon */
SetPixel(x, YDelta, (UCHAR)Color);
x++;
}
/* Start over */
continue;
}
/* Get the current pixel value */
RleValue = *Buffer;
Code = RleValue;
switch (Code)
{
/* Case 0 */
case 0:
/* Set new x value, decrease distance and restart */
x = Left;
YDelta--;
Buffer++;
continue;
/* Case 1 */
case 1:
/* Done */
return;
/* Case 2 */
case 2:
/* Set new x value, decrease distance and restart */
Buffer++;
x += *Buffer;
Buffer++;
YDelta -= *Buffer;
Buffer++;
continue;
/* Other values */
default:
Buffer++;
break;
}
/* Check if we've gone past the edge */
if ((x + RleValue) > (Width + Left))
{
/* Set fixed up loop count */
i = RleValue - Left - Width + x;
/* Fixup pixel value */
RleValue -= i;
}
else
{
/* Clear loop count */
i = 0;
}
/* Check the value now */
if (RleValue > 1)
{
/* Set loop variables */
j = (RleValue - 2) / 2 + 1;
do
{
/* Get the new value */
NewRleValue = *Buffer;
/* Get the two colors */
Color = NewRleValue >> 4;
Color2 = NewRleValue & 0xF;
/* Increase buffer position */
Buffer++;
/* Set the pixels */
SetPixel(x, YDelta, (UCHAR)Color);
x++;
SetPixel(x, YDelta, (UCHAR)Color2);
x++;
/* Decrease pixel value */
RleValue -= 2;
} while (--j);
}
/* Check if there is any value at all */
if (RleValue)
{
/* Set the pixel and increase position */
Color = *Buffer >> 4;
Buffer++;
SetPixel(x, YDelta, (UCHAR)Color);
x++;
i--;
}
/* Check loop count now */
if ((LONG)i > 0)
{
/* Decrease it */
i--;
/* Set new position */
Buffer = Buffer + (i / 2) + 1;
}
/* Check if we need to increase the buffer */
if ((ULONG_PTR)Buffer & 1) Buffer++;
}
}
/* PUBLIC FUNCTIONS **********************************************************/
/*
* @implemented
*/
ULONG
NTAPI
VidSetTextColor(ULONG Color)
{
ULONG OldColor;
/* Save the old color and set the new one */
OldColor = TextColor;
TextColor = Color;
return OldColor;
}
/*
* @implemented
*/
VOID
NTAPI
VidDisplayStringXY(PUCHAR String,
ULONG Left,
ULONG Top,
BOOLEAN Transparent)
{
ULONG BackColor;
/* If the caller wanted transparent, then send the special value (16), else */
/* use our default and call the helper routine. */
BackColor = (Transparent) ? 16 : 14;
DisplayStringXY(String, Left, Top, 12, BackColor);
}
/*
* @implemented
*/
VOID
NTAPI
VidSetScrollRegion(ULONG x1,
ULONG y1,
ULONG x2,
ULONG y2)
{
/* Assert alignment */
ASSERT((x1 & 0x7) == 0);
ASSERT((x2 & 0x7) == 7);
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?