📄 pcvideo.c
字号:
}
/* Vertical sync end (also unlocks CR0-7) */
WRITE_PORT_UCHAR((PUCHAR)CRTC, 0x11);
WRITE_PORT_UCHAR((PUCHAR)CRTC+1, 0x0C);
/* Vertical total */
WRITE_PORT_UCHAR((PUCHAR)CRTC, 0x06);
WRITE_PORT_UCHAR((PUCHAR)CRTC+1, 0x0B);
/* (vertical) overflow */
WRITE_PORT_UCHAR((PUCHAR)CRTC, 0x07);
WRITE_PORT_UCHAR((PUCHAR)CRTC+1, 0x3E);
/* Vertical sync start */
WRITE_PORT_UCHAR((PUCHAR)CRTC, 0x10);
WRITE_PORT_UCHAR((PUCHAR)CRTC+1, 0xEA);
/* Vertical display end */
WRITE_PORT_UCHAR((PUCHAR)CRTC, 0x12);
WRITE_PORT_UCHAR((PUCHAR)CRTC+1, 0xDF);
/* Vertical blank start */
WRITE_PORT_UCHAR((PUCHAR)CRTC, 0x15);
WRITE_PORT_UCHAR((PUCHAR)CRTC+1, 0xE7);
/* Vertical blank end */
WRITE_PORT_UCHAR((PUCHAR)CRTC, 0x16);
WRITE_PORT_UCHAR((PUCHAR)CRTC+1, 0x04);
/* Misc output register (read) */
CRTC = READ_PORT_UCHAR((PUCHAR)0x03CC);
/* Preserve clock select bits and color bit */
CRTC = (CRTC & 0x0D);
/* Set correct sync polarity */
CRTC = (CRTC | 0xE2);
/* (write) */
WRITE_PORT_UCHAR((PUCHAR)0x03C2, CRTC);
}
static VOID
PcVideoSetDisplayEnd(VOID)
{
int CRTC;
/* Read CRTC port */
CRTC = READ_PORT_UCHAR((PUCHAR)0x03CC);
if (CRTC & 1)
{
CRTC = 0x3D4;
}
else
{
CRTC = 0x3B4;
}
/* Vertical display end */
WRITE_PORT_UCHAR((PUCHAR)CRTC, 0x12);
WRITE_PORT_UCHAR((PUCHAR)CRTC+1, 0xDF);
}
static BOOLEAN
PcVideoVesaGetSVGAModeInformation(USHORT Mode, PSVGA_MODE_INFORMATION ModeInformation)
{
REGS Regs;
RtlZeroMemory((PVOID)BIOSCALLBUFFER, 256);
/* VESA SuperVGA BIOS - GET SuperVGA MODE INFORMATION
* AX = 4F01h
* CX = SuperVGA video mode (see #04082 for bitfields)
* ES:DI -> 256-byte buffer for mode information (see #00079)
* Return:
* AL = 4Fh if function supported
* AH = status
* 00h successful
* ES:DI buffer filled
* 01h failed
*
* Desc: Determine the attributes of the specified video mode
*
* Note: While VBE 1.1 and higher will zero out all unused bytes
* of the buffer, v1.0 did not, so applications that want to be
* backward compatible should clear the buffer before calling
*/
Regs.w.ax = 0x4F01;
Regs.w.cx = Mode;
Regs.w.es = BIOSCALLBUFSEGMENT;
Regs.w.di = BIOSCALLBUFOFFSET;
Int386(0x10, &Regs, &Regs);
if (Regs.w.ax != 0x004F)
{
return FALSE;
}
RtlCopyMemory(ModeInformation, (PVOID)BIOSCALLBUFFER, sizeof(SVGA_MODE_INFORMATION));
DbgPrint((DPRINT_UI, "\n"));
DbgPrint((DPRINT_UI, "BiosVesaGetSVGAModeInformation() mode 0x%x\n", Mode));
DbgPrint((DPRINT_UI, "ModeAttributes = 0x%x\n", ModeInformation->ModeAttributes));
DbgPrint((DPRINT_UI, "WindowAttributesA = 0x%x\n", ModeInformation->WindowAttributesA));
DbgPrint((DPRINT_UI, "WindowAttributesB = 0x%x\n", ModeInformation->WindowsAttributesB));
DbgPrint((DPRINT_UI, "WindowGranularity = %dKB\n", ModeInformation->WindowGranularity));
DbgPrint((DPRINT_UI, "WindowSize = %dKB\n", ModeInformation->WindowSize));
DbgPrint((DPRINT_UI, "WindowAStartSegment = 0x%x\n", ModeInformation->WindowAStartSegment));
DbgPrint((DPRINT_UI, "WindowBStartSegment = 0x%x\n", ModeInformation->WindowBStartSegment));
DbgPrint((DPRINT_UI, "WindowPositioningFunction = 0x%x\n", ModeInformation->WindowPositioningFunction));
DbgPrint((DPRINT_UI, "BytesPerScanLine = %d\n", ModeInformation->BytesPerScanLine));
DbgPrint((DPRINT_UI, "WidthInPixels = %d\n", ModeInformation->WidthInPixels));
DbgPrint((DPRINT_UI, "HeightInPixels = %d\n", ModeInformation->HeightInPixels));
DbgPrint((DPRINT_UI, "CharacterWidthInPixels = %d\n", ModeInformation->CharacterWidthInPixels));
DbgPrint((DPRINT_UI, "CharacterHeightInPixels = %d\n", ModeInformation->CharacterHeightInPixels));
DbgPrint((DPRINT_UI, "NumberOfMemoryPlanes = %d\n", ModeInformation->NumberOfMemoryPlanes));
DbgPrint((DPRINT_UI, "BitsPerPixel = %d\n", ModeInformation->BitsPerPixel));
DbgPrint((DPRINT_UI, "NumberOfBanks = %d\n", ModeInformation->NumberOfBanks));
DbgPrint((DPRINT_UI, "MemoryModel = %d\n", ModeInformation->MemoryModel));
DbgPrint((DPRINT_UI, "BankSize = %d\n", ModeInformation->BankSize));
DbgPrint((DPRINT_UI, "NumberOfImagePlanes = %d\n", ModeInformation->NumberOfImagePanes));
DbgPrint((DPRINT_UI, "---VBE v1.2+ ---\n"));
DbgPrint((DPRINT_UI, "RedMaskSize = %d\n", ModeInformation->RedMaskSize));
DbgPrint((DPRINT_UI, "RedMaskPosition = %d\n", ModeInformation->RedMaskPosition));
DbgPrint((DPRINT_UI, "GreenMaskSize = %d\n", ModeInformation->GreenMaskSize));
DbgPrint((DPRINT_UI, "GreenMaskPosition = %d\n", ModeInformation->GreenMaskPosition));
DbgPrint((DPRINT_UI, "BlueMaskSize = %d\n", ModeInformation->BlueMaskSize));
DbgPrint((DPRINT_UI, "BlueMaskPosition = %d\n", ModeInformation->BlueMaskPosition));
DbgPrint((DPRINT_UI, "ReservedMaskSize = %d\n", ModeInformation->ReservedMaskSize));
DbgPrint((DPRINT_UI, "ReservedMaskPosition = %d\n", ModeInformation->ReservedMaskPosition));
DbgPrint((DPRINT_UI, "\n"));
return TRUE;
}
static BOOLEAN
PcVideoSetBiosVesaMode(USHORT Mode)
{
REGS Regs;
/* Int 10h AX=4F02h
* VESA SuperVGA BIOS - SET SuperVGA VIDEO MODE
*
* AX = 4F02h
* BX = new video mode
* ES:DI -> (VBE 3.0+) CRTC information block, bit mode bit 11 set
* Return:
* AL = 4Fh if function supported
* AH = status
* 00h successful
* 01h failed
*
* Values for VESA video mode:
* 00h-FFh OEM video modes (see #00010 at AH=00h)
* 100h 640x400x256
* 101h 640x480x256
* 102h 800x600x16
* 103h 800x600x256
* 104h 1024x768x16
* 105h 1024x768x256
* 106h 1280x1024x16
* 107h 1280x1024x256
* 108h 80x60 text
* 109h 132x25 text
* 10Ah 132x43 text
* 10Bh 132x50 text
* 10Ch 132x60 text
* ---VBE v1.2+ ---
* 10Dh 320x200x32K
* 10Eh 320x200x64K
* 10Fh 320x200x16M
* 110h 640x480x32K
* 111h 640x480x64K
* 112h 640x480x16M
* 113h 800x600x32K
* 114h 800x600x64K
* 115h 800x600x16M
* 116h 1024x768x32K
* 117h 1024x768x64K
* 118h 1024x768x16M
* 119h 1280x1024x32K (1:5:5:5)
* 11Ah 1280x1024x64K (5:6:5)
* 11Bh 1280x1024x16M
* ---VBE 2.0+ ---
* 120h 1600x1200x256
* 121h 1600x1200x32K
* 122h 1600x1200x64K
* 81FFh special full-memory access mode
*
* Notes: The special mode 81FFh preserves the contents of the video memory and gives
* access to all of the memory; VESA recommends that the special mode be a packed-pixel
* mode. For VBE 2.0+, it is required that the VBE implement the mode, but not place it
* in the list of available modes (mode information for this mode can be queried
* directly, however).. As of VBE 2.0, VESA will no longer define video mode numbers
*/
Regs.w.ax = 0x4F02;
Regs.w.bx = Mode;
Int386(0x10, &Regs, &Regs);
if (0x004F != Regs.w.ax)
{
return FALSE;
}
return TRUE;
}
static BOOLEAN
PcVideoSetMode80x25(VOID)
{
PcVideoSetBiosMode(0x03);
ScreenWidth = 80;
ScreenHeight = 25;
return TRUE;
}
static BOOLEAN
PcVideoSetMode80x50_80x43(VOID)
{
if (VIDEOCARD_VGA == PcVideoDetectVideoCard())
{
PcVideoSetBiosMode(0x12);
PcVideoSetFont8x8();
PcVideoSelectAlternatePrintScreen();
PcVideoDisableCursorEmulation();
PcVideoDefineCursor(6, 7);
ScreenWidth = 80;
ScreenHeight = 50;
}
else if (VIDEOCARD_EGA == PcVideoDetectVideoCard())
{
PcVideoSetBiosMode(0x03);
PcVideoSetFont8x8();
PcVideoSelectAlternatePrintScreen();
PcVideoDisableCursorEmulation();
PcVideoDefineCursor(6, 7);
ScreenWidth = 80;
ScreenHeight = 43;
}
else /* VIDEOCARD_CGA_OR_OTHER */
{
return FALSE;
}
return TRUE;
}
static BOOLEAN
PcVideoSetMode80x28(VOID)
{
/* FIXME: Is this VGA-only? */
PcVideoSetMode80x25();
PcVideoSetFont8x14();
PcVideoDefineCursor(11, 12);
ScreenWidth = 80;
ScreenHeight = 28;
return TRUE;
}
static BOOLEAN
PcVideoSetMode80x30(VOID)
{
/* FIXME: Is this VGA-only? */
PcVideoSetMode80x25();
PcVideoSet480ScanLines();
ScreenWidth = 80;
ScreenHeight = 30;
return TRUE;
}
static BOOLEAN
PcVideoSetMode80x34(VOID)
{
/* FIXME: Is this VGA-only? */
PcVideoSetMode80x25();
PcVideoSet480ScanLines();
PcVideoSetFont8x14();
PcVideoDefineCursor(11, 12);
PcVideoSetDisplayEnd();
ScreenWidth = 80;
ScreenHeight = 34;
return TRUE;
}
static BOOLEAN
PcVideoSetMode80x43(VOID)
{
/* FIXME: Is this VGA-only? */
PcVideoSetVerticalResolution(VERTRES_350_SCANLINES);
PcVideoSetMode80x25();
PcVideoSetFont8x8();
PcVideoSelectAlternatePrintScreen();
PcVideoDisableCursorEmulation();
PcVideoDefineCursor(6, 7);
ScreenWidth = 80;
ScreenHeight = 43;
return TRUE;
}
static BOOLEAN
PcVideoSetMode80x60(VOID)
{
/* FIXME: Is this VGA-only? */
PcVideoSetMode80x25();
PcVideoSet480ScanLines();
PcVideoSetFont8x8();
PcVideoSelectAlternatePrintScreen();
PcVideoDisableCursorEmulation();
PcVideoDefineCursor(6, 7);
PcVideoSetDisplayEnd();
ScreenWidth = 80;
ScreenHeight = 60;
return TRUE;
}
static BOOLEAN
PcVideoSetMode(ULONG NewMode)
{
CurrentMemoryBank = 0;
/* Set the values for the default text modes
* If they are setting a graphics mode then
* these values will be changed.
*/
BiosVideoMode = NewMode;
ScreenWidth = 80;
ScreenHeight = 25;
BytesPerScanLine = 160;
DisplayMode = VideoTextMode;
VesaVideoMode = FALSE;
switch (NewMode)
{
case VIDEOMODE_NORMAL_TEXT:
case 0x03: /* BIOS 80x25 text mode number */
return PcVideoSetMode80x25();
case VIDEOMODE_EXTENDED_TEXT:
return PcVideoSetMode80x50_80x43();
case VIDEOMODE_80X28:
return PcVideoSetMode80x28();
case VIDEOMODE_80X30:
return PcVideoSetMode80x30();
case VIDEOMODE_80X34:
return PcVideoSetMode80x34();
case VIDEOMODE_80X43:
return PcVideoSetMode80x43();
case VIDEOMODE_80X60:
return PcVideoSetMode80x60();
}
if (0x12 == NewMode)
{
/* 640x480x16 */
PcVideoSetBiosMode(NewMode);
WRITE_PORT_USHORT((USHORT*)0x03CE, 0x0F01); /* For some reason this is necessary? */
ScreenWidth = 640;
ScreenHeight = 480;
BytesPerScanLine = 80;
BiosVideoMode = NewMode;
DisplayMode = VideoGraphicsMode;
return TRUE;
}
else if (0x13 == NewMode)
{
/* 320x200x256 */
PcVideoSetBiosMode(NewMode);
ScreenWidth = 320;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -