📄 pcvideo.c
字号:
ScreenHeight = 200;
BytesPerScanLine = 320;
BiosVideoMode = NewMode;
DisplayMode = VideoGraphicsMode;
return TRUE;
}
else if (0x0108 <= NewMode && NewMode <= 0x010C)
{
/* VESA Text Mode */
if (! PcVideoVesaGetSVGAModeInformation(NewMode, &VesaVideoModeInformation))
{
return FALSE;
}
if (! PcVideoSetBiosVesaMode(NewMode))
{
return FALSE;
}
ScreenWidth = VesaVideoModeInformation.WidthInPixels;
ScreenHeight = VesaVideoModeInformation.HeightInPixels;
BytesPerScanLine = VesaVideoModeInformation.BytesPerScanLine;
BiosVideoMode = NewMode;
DisplayMode = VideoTextMode;
VesaVideoMode = TRUE;
return TRUE;
}
else
{
/* VESA Graphics Mode */
if (! PcVideoVesaGetSVGAModeInformation(NewMode, &VesaVideoModeInformation))
{
return FALSE;
}
if (! PcVideoSetBiosVesaMode(NewMode))
{
return FALSE;
}
ScreenWidth = VesaVideoModeInformation.WidthInPixels;
ScreenHeight = VesaVideoModeInformation.HeightInPixels;
BytesPerScanLine = VesaVideoModeInformation.BytesPerScanLine;
BiosVideoMode = NewMode;
DisplayMode = VideoTextMode;
VesaVideoMode = TRUE;
return TRUE;
}
return FALSE;
}
static VOID
PcVideoSetBlinkBit(BOOLEAN Enable)
{
REGS Regs;
/* Int 10h AX=1003h
* VIDEO - TOGGLE INTENSITY/BLINKING BIT (Jr, PS, TANDY 1000, EGA, VGA)
*
* AX = 1003h
* BL = new state
* 00h background intensity enabled
* 01h blink enabled
* BH = 00h to avoid problems on some adapters
* Return:
* Nothing
*
* Note: although there is no function to get
* the current status, bit 5 of 0040h:0065h
* indicates the state.
*/
Regs.w.ax = 0x1003;
Regs.w.bx = Enable ? 0x0001 : 0x0000;
Int386(0x10, &Regs, &Regs);
}
static VOID
PcVideoSetMemoryBank(USHORT BankNumber)
{
REGS Regs;
if (CurrentMemoryBank != BankNumber)
{
/* Int 10h AX=4F05h
* VESA SuperVGA BIOS - CPU VIDEO MEMORY CONTROL
*
* AX = 4F05h
* BH = subfunction
* 00h select video memory window
* 01h get video memory window
* DX = window address in video memory (in granularity units)
* Return:
* DX = window address in video memory (in gran. units)
* BL = window number
* 00h window A
* 01h window B.
* Return:
* AL = 4Fh if function supported
* AH = status
* 00h successful
* 01h failed
*/
Regs.w.ax = 0x4F05;
Regs.w.bx = 0x0000;
Regs.w.dx = BankNumber;
Int386(0x10, &Regs, &Regs);
if (0x004F == Regs.w.ax)
{
CurrentMemoryBank = BankNumber;
}
}
}
VIDEODISPLAYMODE
PcVideoSetDisplayMode(char *DisplayModeName, BOOLEAN Init)
{
ULONG VideoMode = VIDEOMODE_NORMAL_TEXT;
if (NULL == DisplayModeName || '\0' == *DisplayModeName)
{
PcVideoSetBlinkBit(! Init);
return DisplayMode;
}
if (VIDEOCARD_CGA_OR_OTHER == PcVideoDetectVideoCard())
{
DbgPrint((DPRINT_UI, "CGA or other display adapter detected.\n"));
printf("CGA or other display adapter detected.\n");
printf("Using 80x25 text mode.\n");
VideoMode = VIDEOMODE_NORMAL_TEXT;
}
else if (VIDEOCARD_EGA == PcVideoDetectVideoCard())
{
DbgPrint((DPRINT_UI, "EGA display adapter detected.\n"));
printf("EGA display adapter detected.\n");
printf("Using 80x25 text mode.\n");
VideoMode = VIDEOMODE_NORMAL_TEXT;
}
else /* if (VIDEOCARD_VGA == PcVideoDetectVideoCard()) */
{
DbgPrint((DPRINT_UI, "VGA display adapter detected.\n"));
if (0 == _stricmp(DisplayModeName, "NORMAL_VGA"))
{
VideoMode = VIDEOMODE_NORMAL_TEXT;
}
else if (0 == _stricmp(DisplayModeName, "EXTENDED_VGA"))
{
VideoMode = VIDEOMODE_EXTENDED_TEXT;
}
else
{
VideoMode = atoi(DisplayModeName);
}
}
if (! PcVideoSetMode(VideoMode))
{
printf("Error: unable to set video display mode 0x%x\n", (int) VideoMode);
printf("Defaulting to 80x25 text mode.\n");
printf("Press any key to continue.\n");
PcConsGetCh();
PcVideoSetMode(VIDEOMODE_NORMAL_TEXT);
}
PcVideoSetBlinkBit(! Init);
return DisplayMode;
}
VOID
PcVideoGetDisplaySize(PULONG Width, PULONG Height, PULONG Depth)
{
*Width = ScreenWidth;
*Height = ScreenHeight;
if (VideoGraphicsMode == DisplayMode && VesaVideoMode)
{
if (16 == VesaVideoModeInformation.BitsPerPixel)
{
/* 16-bit color modes give green an extra bit (5:6:5)
* 15-bit color modes have just 5:5:5 for R:G:B */
*Depth = (6 == VesaVideoModeInformation.GreenMaskSize ? 16 : 15);
}
else
{
*Depth = VesaVideoModeInformation.BitsPerPixel;
}
}
else
{
*Depth = 0;
}
}
ULONG
PcVideoGetBufferSize(VOID)
{
return ScreenHeight * BytesPerScanLine;
}
VOID
PcVideoSetTextCursorPosition(ULONG X, ULONG Y)
{
REGS Regs;
/* Int 10h AH=02h
* VIDEO - SET CURSOR POSITION
*
* AH = 02h
* BH = page number
* 0-3 in modes 2&3
* 0-7 in modes 0&1
* 0 in graphics modes
* DH = row (00h is top)
* DL = column (00h is left)
* Return:
* Nothing
*/
Regs.b.ah = 0x02;
Regs.b.bh = 0x00;
Regs.b.dh = Y;
Regs.b.dl = X;
Int386(0x10, &Regs, &Regs);
}
VOID
PcVideoHideShowTextCursor(BOOLEAN Show)
{
if (Show)
{
PcVideoDefineCursor(0x0D, 0x0E);
}
else
{
PcVideoDefineCursor(0x20, 0x00);
}
}
VOID
PcVideoCopyOffScreenBufferToVRAM(PVOID Buffer)
{
ULONG BanksToCopy;
ULONG BytesInLastBank;
ULONG CurrentBank;
ULONG BankSize;
/* PcVideoWaitForVerticalRetrace(); */
/* Text mode (BIOS or VESA) */
if (VideoTextMode == DisplayMode)
{
RtlCopyMemory((PVOID) VIDEOTEXT_MEM_ADDRESS, Buffer, PcVideoGetBufferSize());
}
/* VESA graphics mode */
else if (VideoGraphicsMode == DisplayMode && VesaVideoMode)
{
BankSize = VesaVideoModeInformation.WindowGranularity << 10;
BanksToCopy = (VesaVideoModeInformation.HeightInPixels * VesaVideoModeInformation.BytesPerScanLine) / BankSize;
BytesInLastBank = (VesaVideoModeInformation.HeightInPixels * VesaVideoModeInformation.BytesPerScanLine) % BankSize;
/* Copy all the banks but the last one because
* it is probably a partial bank */
for (CurrentBank = 0; CurrentBank < BanksToCopy; CurrentBank++)
{
PcVideoSetMemoryBank(CurrentBank);
RtlCopyMemory((PVOID) VIDEOVGA_MEM_ADDRESS, (char *) Buffer + CurrentBank * BankSize, BankSize);
}
/* Copy the remaining bytes into the last bank */
PcVideoSetMemoryBank(CurrentBank);
RtlCopyMemory((PVOID)VIDEOVGA_MEM_ADDRESS, (char *) Buffer + CurrentBank * BankSize, BytesInLastBank);
}
/* BIOS graphics mode */
else
{
UNIMPLEMENTED();
}
}
VOID
PcVideoClearScreen(UCHAR Attr)
{
USHORT AttrChar;
USHORT *BufPtr;
AttrChar = ((USHORT) Attr << 8) | ' ';
for (BufPtr = (USHORT *) VIDEOTEXT_MEM_ADDRESS;
BufPtr < (USHORT *) (VIDEOTEXT_MEM_ADDRESS + VIDEOTEXT_MEM_SIZE);
BufPtr++)
{
*BufPtr = AttrChar;
}
}
VOID
PcVideoPutChar(int Ch, UCHAR Attr, unsigned X, unsigned Y)
{
USHORT *BufPtr;
BufPtr = (USHORT *) (VIDEOTEXT_MEM_ADDRESS + Y * BytesPerScanLine + X * 2);
*BufPtr = ((USHORT) Attr << 8) | (Ch & 0xff);
}
BOOLEAN
PcVideoIsPaletteFixed(VOID)
{
return FALSE;
}
VOID
PcVideoSetPaletteColor(UCHAR Color, UCHAR Red, UCHAR Green, UCHAR Blue)
{
WRITE_PORT_UCHAR((UCHAR*) VIDEOPORT_PALETTE_WRITE, Color);
WRITE_PORT_UCHAR((UCHAR*) VIDEOPORT_PALETTE_DATA, Red);
WRITE_PORT_UCHAR((UCHAR*) VIDEOPORT_PALETTE_DATA, Green);
WRITE_PORT_UCHAR((UCHAR*) VIDEOPORT_PALETTE_DATA, Blue);
}
VOID
PcVideoGetPaletteColor(UCHAR Color, UCHAR* Red, UCHAR* Green, UCHAR* Blue)
{
WRITE_PORT_UCHAR((UCHAR*) VIDEOPORT_PALETTE_READ, Color);
*Red = READ_PORT_UCHAR((UCHAR*) VIDEOPORT_PALETTE_DATA);
*Green = READ_PORT_UCHAR((UCHAR*) VIDEOPORT_PALETTE_DATA);
*Blue = READ_PORT_UCHAR((UCHAR*) VIDEOPORT_PALETTE_DATA);
}
VOID
PcVideoSync(VOID)
{
while (1 == (READ_PORT_UCHAR((UCHAR*)VIDEOPORT_VERTICAL_RETRACE) & 0x08))
{
/*
* Keep reading the port until bit 3 is clear
* This waits for the current retrace to end and
* we can catch the next one so we know we are
* getting a full retrace.
*/
}
while (0 == (READ_PORT_UCHAR((UCHAR*)VIDEOPORT_VERTICAL_RETRACE) & 0x08))
{
/*
* Keep reading the port until bit 3 is set
* Now that we know we aren't doing a vertical
* retrace we need to wait for the next one.
*/
}
}
VOID
PcVideoPrepareForReactOS(IN BOOLEAN Setup)
{
if (Setup)
{
PcVideoSetMode80x50_80x43();
}
else
{
PcVideoSetBiosMode(0x12);
}
PcVideoHideShowTextCursor(FALSE);
}
/* EOF */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -