vga.c
来自「这是一个开放源代码的与WINNT/WIN2K/WIN2003兼容的操作系统」· C语言 代码 · 共 1,275 行 · 第 1/3 页
C
1,275 行
/* Set Scroll Region */
ScrollRegion[0] = x1;
ScrollRegion[1] = y1;
ScrollRegion[2] = x2;
ScrollRegion[3] = y2;
/* Set current X and Y */
curr_x = x1;
curr_y = y1;
}
/*
* @implemented
*/
VOID
NTAPI
VidCleanUp(VOID)
{
/* Select bit mask register */
WRITE_PORT_UCHAR((PUCHAR)VgaRegisterBase + 0x3CE, 8);
/* Clear it */
WRITE_PORT_UCHAR((PUCHAR)VgaRegisterBase + 0x3CF, 255);
}
/*
* @implemented
*/
VOID
NTAPI
VidBufferToScreenBlt(IN PUCHAR Buffer,
IN ULONG Left,
IN ULONG Top,
IN ULONG Width,
IN ULONG Height,
IN ULONG Delta)
{
/* Make sure we have a width and height */
if (!(Width) || !(Height)) return;
/* Call the helper function */
BitBlt(Left, Top, Width, Height, Buffer, 4, Delta);
}
/*
* @implemented
*/
VOID
NTAPI
VidDisplayString(PUCHAR String)
{
ULONG TopDelta = 14;
/* Start looping the string */
while (*String)
{
/* Treat new-line separately */
if (*String == '\n')
{
/* Modify Y position */
curr_y += TopDelta;
if (curr_y >= ScrollRegion[3])
{
/* Scroll the view */
VgaScroll(TopDelta);
curr_y -= TopDelta;
/* Preserve row */
PreserveRow(curr_y, TopDelta, TRUE);
}
/* Update current X */
curr_x = ScrollRegion[0];
/* Preseve the current row */
PreserveRow(curr_y, TopDelta, FALSE);
}
else if (*String == '\r')
{
/* Update current X */
curr_x = ScrollRegion[0];
/* Check if we're being followed by a new line */
if (String[1] != '\n') NextLine = TRUE;
}
else
{
/* Check if we had a \n\r last time */
if (NextLine)
{
/* We did, preserve the current row */
PreserveRow(curr_y, TopDelta, TRUE);
NextLine = FALSE;
}
/* Display this character */
DisplayCharacter(*String, curr_x, curr_y, TextColor, 16);
curr_x += 8;
/* Check if we should scroll */
if (curr_x > ScrollRegion[2])
{
/* Update Y position and check if we should scroll it */
curr_y += TopDelta;
if (curr_y > ScrollRegion[3])
{
/* Do the scroll */
VgaScroll(TopDelta);
curr_y -= TopDelta;
/* Save the row */
PreserveRow(curr_y, TopDelta, TRUE);
}
/* Update X */
curr_x = ScrollRegion[0];
}
}
/* Get the next character */
String++;
}
}
/*
* @implemented
*/
VOID
NTAPI
VidBitBlt(PUCHAR Buffer,
ULONG Left,
ULONG Top)
{
PBITMAPINFOHEADER BitmapInfoHeader;
LONG Delta;
PUCHAR BitmapOffset;
/* Get the Bitmap Header */
BitmapInfoHeader = (PBITMAPINFOHEADER)Buffer;
/* Initialize the palette */
InitPaletteWithTable((PULONG)(Buffer + BitmapInfoHeader->biSize),
(BitmapInfoHeader->biClrUsed) ?
BitmapInfoHeader->biClrUsed : 16);
/* Make sure we can support this bitmap */
ASSERT((BitmapInfoHeader->biBitCount * BitmapInfoHeader->biPlanes) <= 4);
/* Calculate the delta and align it on 32-bytes, then calculate the actual */
/* start of the bitmap data. */
Delta = (BitmapInfoHeader->biBitCount * BitmapInfoHeader->biWidth) + 31;
Delta >>= 3;
Delta &= ~3;
BitmapOffset = Buffer + sizeof(BITMAPINFOHEADER) + 16 * sizeof(ULONG);
/* Check the compression of the bitmap */
if (BitmapInfoHeader->biCompression == 2)
{
/* Make sure we have a width and a height */
if ((BitmapInfoHeader->biWidth) && (BitmapInfoHeader->biHeight))
{
/* We can use RLE Bit Blt */
RleBitBlt(Left,
Top,
BitmapInfoHeader->biWidth,
BitmapInfoHeader->biHeight,
BitmapOffset);
}
}
else
{
/* Check if the height is negative */
if (BitmapInfoHeader->biHeight < 0)
{
/* Make it positive in the header */
BitmapInfoHeader->biHeight *= -1;
}
else
{
/* Update buffer offset */
BitmapOffset += ((BitmapInfoHeader->biHeight -1) * Delta);
Delta *= -1;
}
/* Make sure we have a width and a height */
if ((BitmapInfoHeader->biWidth) && (BitmapInfoHeader->biHeight))
{
/* Do the BitBlt */
BitBlt(Left,
Top,
BitmapInfoHeader->biWidth,
BitmapInfoHeader->biHeight,
BitmapOffset,
BitmapInfoHeader->biBitCount,
Delta);
}
}
}
/*
* @implemented
*/
VOID
NTAPI
VidScreenToBufferBlt(PUCHAR Buffer,
ULONG Left,
ULONG Top,
ULONG Width,
ULONG Height,
ULONG Delta)
{
ULONG Plane;
ULONG XDistance;
ULONG LeftDelta, RightDelta;
ULONG PixelOffset;
PUCHAR PixelPosition;
PUCHAR k, i;
PULONG m;
UCHAR Value, Value2;
UCHAR a;
ULONG b;
ULONG x, y;
/* Calculate total distance to copy on X */
XDistance = Left + Width - 1;
/* Start at plane 0 */
Plane = 0;
/* Calculate the 8-byte left and right deltas */
LeftDelta = Left & 7;
RightDelta = 8 - LeftDelta;
/* Clear the destination buffer */
RtlZeroMemory(Buffer, Delta * Height);
/* Calculate the pixel offset and convert the X distance into byte form */
PixelOffset = Top * 80 + (Left >> 3);
XDistance >>= 3;
/* Loop the 4 planes */
do
{
/* Set the current pixel position and reset buffer loop variable */
PixelPosition = (PUCHAR)VgaBase + PixelOffset;
i = Buffer;
/* Set Mode 0 */
ReadWriteMode(0);
/* Set the current plane */
__outpw(0x3CE, (Plane << 8) | 4);
/* Make sure we have a height */
if (Height > 0)
{
/* Start the outer Y loop */
y = Height;
do
{
/* Read the current value */
m = (PULONG)i;
Value = READ_REGISTER_UCHAR(PixelPosition);
/* Set Pixel Position loop variable */
k = PixelPosition + 1;
/* Check if we're still within bounds */
if (Left <= XDistance)
{
/* Start X Inner loop */
x = (XDistance - Left) + 1;
do
{
/* Read the current value */
Value2 = READ_REGISTER_UCHAR(k);
/* Increase pixel position */
k++;
/* Do the blt */
a = Value2 >> (UCHAR)RightDelta;
a |= Value << (UCHAR)LeftDelta;
b = lookup[a & 0xF];
a >>= 4;
b <<= 16;
b |= lookup[a];
/* Save new value to buffer */
*m |= (b << Plane);
/* Move to next destination location */
m++;
/* Write new value */
Value = Value2;
} while (--x);
}
/* Update pixel position */
PixelPosition += 80;
i += Delta;
} while (--y);
}
} while (++Plane < 4);
}
/*
* @implemented
*/
VOID
NTAPI
VidSolidColorFill(IN ULONG Left,
IN ULONG Top,
IN ULONG Right,
IN ULONG Bottom,
IN UCHAR Color)
{
ULONG rMask, lMask;
ULONG LeftOffset, RightOffset, Distance;
PUCHAR Offset;
ULONG i, j;
/* Get the left and right masks, shifts, and delta */
LeftOffset = Left >> 3;
lMask = (lMaskTable[Left & 0x7] << 8) | 8;
RightOffset = Right >> 3;
rMask = (rMaskTable[Right & 0x7] << 8) | 8;
Distance = RightOffset - LeftOffset;
/* If there is no distance, then combine the right and left masks */
if (!Distance) lMask &= rMask;
/* Switch to mode 10 */
ReadWriteMode(10);
/* Clear the 4 planes (we're already in unchained mode here) */
__outpw(0x3C4, 0xF02);
/* Select the color don't care register */
__outpw(0x3CE, 7);
/* Calculate pixel position for the read */
Offset = VgaBase + (Top * 80) + (PUCHAR)LeftOffset;
/* Select the bitmask register and write the mask */
__outpw(0x3CE, (USHORT)lMask);
/* Check if the top coord is below the bottom one */
if (Top <= Bottom)
{
/* Start looping each line */
i = (Bottom - Top) + 1;
do
{
/* Read the previous value and add our color */
WRITE_REGISTER_UCHAR(Offset, READ_REGISTER_UCHAR(Offset) & Color);
/* Move to the next line */
Offset += 80;
} while (--i);
}
/* Check if we have a delta */
if (Distance)
{
/* Calculate new pixel position */
Offset = VgaBase + (Top * 80) + (PUCHAR)RightOffset;
Distance--;
/* Select the bitmask register and write the mask */
__outpw(0x3CE, (USHORT)rMask);
/* Check if the top coord is below the bottom one */
if (Top <= Bottom)
{
/* Start looping each line */
i = (Bottom - Top) + 1;
do
{
/* Read the previous value and add our color */
WRITE_REGISTER_UCHAR(Offset,
READ_REGISTER_UCHAR(Offset) & Color);
/* Move to the next line */
Offset += 80;
} while (--i);
}
/* Check if we still have a delta */
if (Distance)
{
/* Calculate new pixel position */
Offset = VgaBase + (Top * 80) + (PUCHAR)(LeftOffset + 1);
/* Set the bitmask to 0xFF for all 4 planes */
__outpw(0x3CE, 0xFF08);
/* Check if the top coord is below the bottom one */
if (Top <= Bottom)
{
/* Start looping each line */
i = (Bottom - Top) + 1;
do
{
/* Loop the shift delta */
if (Distance > 0)
{
for (j = Distance; j; Offset++, j--)
{
/* Write the color */
WRITE_REGISTER_UCHAR(Offset, Color);
}
}
/* Update position in memory */
Offset += (80 - Distance);
} while (--i);
}
}
}
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?