📄 pcvideo.c
字号:
/* $Id: pcvideo.c 25800 2007-02-14 20:30:33Z ion $
*
* FreeLoader
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <freeldr.h>
#define NDEBUG
#include <debug.h>
#define VIDEOPORT_PALETTE_READ 0x03C7
#define VIDEOPORT_PALETTE_WRITE 0x03C8
#define VIDEOPORT_PALETTE_DATA 0x03C9
#define VIDEOPORT_VERTICAL_RETRACE 0x03DA
#define VIDEOVGA_MEM_ADDRESS 0xA0000
#define VIDEOTEXT_MEM_ADDRESS 0xB8000
#define VIDEOTEXT_MEM_SIZE 0x8000
#define VIDEOCARD_CGA_OR_OTHER 0
#define VIDEOCARD_EGA 1
#define VIDEOCARD_VGA 2
#define VIDEOMODE_NORMAL_TEXT 0
#define VIDEOMODE_EXTENDED_TEXT 1
#define VIDEOMODE_80X28 0x501C
#define VIDEOMODE_80X30 0x501E
#define VIDEOMODE_80X34 0x5022
#define VIDEOMODE_80X43 0x502B
#define VIDEOMODE_80X60 0x503C
#define VIDEOMODE_132X25 0x8419
#define VIDEOMODE_132X43 0x842B
#define VIDEOMODE_132X50 0x8432
#define VIDEOMODE_132X60 0x843C
#define VERTRES_200_SCANLINES 0x00
#define VERTRES_350_SCANLINES 0x01
#define VERTRES_400_SCANLINES 0x02
typedef struct
{
USHORT ModeAttributes; /* mode attributes (see #00080) */
UCHAR WindowAttributesA; /* window attributes, window A (see #00081) */
UCHAR WindowsAttributesB; /* window attributes, window B (see #00081) */
USHORT WindowGranularity; /* window granularity in KB */
USHORT WindowSize; /* window size in KB */
USHORT WindowAStartSegment; /* start segment of window A (0000h if not supported) */
USHORT WindowBStartSegment; /* start segment of window B (0000h if not supported) */
ULONG WindowPositioningFunction; /* -> FAR window positioning function (equivalent to AX=4F05h) */
USHORT BytesPerScanLine; /* bytes per scan line */
/* ---remainder is optional for VESA modes in v1.0/1.1, needed for OEM modes--- */
USHORT WidthInPixels; /* width in pixels (graphics) or characters (text) */
USHORT HeightInPixels; /* height in pixels (graphics) or characters (text) */
UCHAR CharacterWidthInPixels; /* width of character cell in pixels */
UCHAR CharacterHeightInPixels; /* height of character cell in pixels */
UCHAR NumberOfMemoryPlanes; /* number of memory planes */
UCHAR BitsPerPixel; /* number of bits per pixel */
UCHAR NumberOfBanks; /* number of banks */
UCHAR MemoryModel; /* memory model type (see #00082) */
UCHAR BankSize; /* size of bank in KB */
UCHAR NumberOfImagePanes; /* number of image pages (less one) that will fit in video RAM */
UCHAR Reserved1; /* reserved (00h for VBE 1.0-2.0, 01h for VBE 3.0) */
/* ---VBE v1.2+ --- */
UCHAR RedMaskSize; /* red mask size */
UCHAR RedMaskPosition; /* red field position */
UCHAR GreenMaskSize; /* green mask size */
UCHAR GreenMaskPosition; /* green field size */
UCHAR BlueMaskSize; /* blue mask size */
UCHAR BlueMaskPosition; /* blue field size */
UCHAR ReservedMaskSize; /* reserved mask size */
UCHAR ReservedMaskPosition; /* reserved mask position */
UCHAR DirectColorModeInfo; /* direct color mode info */
/* bit 0:Color ramp is programmable */
/* bit 1:Bytes in reserved field may be used by application */
/* ---VBE v2.0+ --- */
ULONG LinearVideoBufferAddress; /* physical address of linear video buffer */
ULONG OffscreenMemoryPointer; /* pointer to start of offscreen memory */
USHORT OffscreenMemorySize; /* KB of offscreen memory */
/* ---VBE v3.0 --- */
USHORT LinearBytesPerScanLine; /* bytes per scan line in linear modes */
UCHAR BankedNumberOfImages; /* number of images (less one) for banked video modes */
UCHAR LinearNumberOfImages; /* number of images (less one) for linear video modes */
UCHAR LinearRedMaskSize; /* linear modes:Size of direct color red mask (in bits) */
UCHAR LinearRedMaskPosition; /* linear modes:Bit position of red mask LSB (e.g. shift count) */
UCHAR LinearGreenMaskSize; /* linear modes:Size of direct color green mask (in bits) */
UCHAR LinearGreenMaskPosition; /* linear modes:Bit position of green mask LSB (e.g. shift count) */
UCHAR LinearBlueMaskSize; /* linear modes:Size of direct color blue mask (in bits) */
UCHAR LinearBlueMaskPosition; /* linear modes:Bit position of blue mask LSB (e.g. shift count) */
UCHAR LinearReservedMaskSize; /* linear modes:Size of direct color reserved mask (in bits) */
UCHAR LinearReservedMaskPosition; /* linear modes:Bit position of reserved mask LSB */
ULONG MaximumPixelClock; /* maximum pixel clock for graphics video mode, in Hz */
UCHAR Reserved2[190]; /* 190 BYTEs reserved (0) */
} PACKED SVGA_MODE_INFORMATION, *PSVGA_MODE_INFORMATION;
static ULONG BiosVideoMode; /* Current video mode as known by BIOS */
static ULONG ScreenWidth = 80; /* Screen Width in characters */
static ULONG ScreenHeight = 25; /* Screen Height in characters */
static ULONG BytesPerScanLine = 160; /* Number of bytes per scanline (delta) */
static VIDEODISPLAYMODE DisplayMode = VideoTextMode; /* Current display mode */
static BOOLEAN VesaVideoMode = FALSE; /* Are we using a VESA mode? */
static SVGA_MODE_INFORMATION VesaVideoModeInformation; /* Only valid when in VESA mode */
static ULONG CurrentMemoryBank = 0; /* Currently selected VESA bank */
static ULONG
PcVideoDetectVideoCard(VOID)
{
REGS Regs;
/* Int 10h AH=12h BL=10h
* VIDEO - ALTERNATE FUNCTION SELECT (PS,EGA,VGA,MCGA) - GET EGA INFO
*
* AH = 12h
* BL = 10h
* Return:
* BH = video state
* 00h color mode in effect (I/O port 3Dxh)
* 01h mono mode in effect (I/O port 3Bxh)
* BL = installed memory (00h = 64K, 01h = 128K, 02h = 192K, 03h = 256K)
* CH = feature connector bits
* CL = switch settings
* AH destroyed (at least by Tseng ET4000 BIOS v8.00n)
*
* Installation check;EGA
*/
Regs.b.ah = 0x12;
Regs.b.bl = 0x10;
Int386(0x10, &Regs, &Regs);
/* If BL is still equal to 0x10 then there is no EGA/VGA present */
if (0x10 == Regs.b.bl)
{
return VIDEOCARD_CGA_OR_OTHER;
}
/* Int 10h AX=1A00h
* VIDEO - GET DISPLAY COMBINATION CODE (PS,VGA/MCGA)
*
* AX = 1A00h
* Return:
* AL = 1Ah if function was supported
* BL = active display code
* BH = alternate display code
*
* This function is commonly used to check for the presence of a VGA.
*
* Installation check;VGA
*
* Values for display combination code:
* 00h no display
* 01h monochrome adapter w/ monochrome display
* 02h CGA w/ color display
* 03h reserved
* 04h EGA w/ color display
* 05h EGA w/ monochrome display
* 06h PGA w/ color display
* 07h VGA w/ monochrome analog display
* 08h VGA w/ color analog display
* 09h reserved
* 0Ah MCGA w/ digital color display
* 0Bh MCGA w/ monochrome analog display
* 0Ch MCGA w/ color analog display
* FFh unknown display type
*/
Regs.b.ah = 0x12;
Regs.b.bl = 0x10;
Int386(0x10, &Regs, &Regs);
if (0x1a == Regs.b.al)
{
return VIDEOCARD_VGA;
}
else
{
return VIDEOCARD_EGA;
}
}
static VOID PcVideoSetBiosMode(ULONG VideoMode)
{
REGS Regs;
/* Int 10h AH=00h
* VIDEO - SET VIDEO MODE
*
* AH = 00h
* AL = desired video mode
* Return:
* AL = video mode flag (Phoenix, AMI BIOS)
* 20h mode > 7
* 30h modes 0-5 and 7
* 3Fh mode 6
* AL = CRT controller mode byte (Phoenix 386 BIOS v1.10)
*/
Regs.b.ah = 0x00;
Regs.b.al = VideoMode;
Int386(0x10, &Regs, &Regs);
}
static VOID
PcVideoSetFont8x8(VOID)
{
REGS Regs;
/* Int 10h AX=1112h
* VIDEO - TEXT-MODE CHARGEN - LOAD ROM 8x8 DBL-DOT PATTERNS (PS,EGA,VGA)
*
* AX = 1112h
* BL = block to load
* Return:
* Nothing
*/
Regs.w.ax = 0x1112;
Regs.b.bl = 0x00;
Int386(0x10, &Regs, &Regs);
}
static VOID
PcVideoSetFont8x14(VOID)
{
REGS Regs;
/* Int 10h AX=1111h
* VIDEO - TEXT-MODE CHARGEN - LOAD ROM MONOCHROME PATTERNS (PS,EGA,VGA)
*
* AX = 1111h
* BL = block to load
* Return:
* Nothing
*/
Regs.w.ax = 0x1111;
Regs.b.bl = 0;
Int386(0x10, &Regs, &Regs);
}
static VOID
PcVideoSelectAlternatePrintScreen(VOID)
{
REGS Regs;
/* Int 10h AH=12h BL=20h
* VIDEO - ALTERNATE FUNCTION SELECT (PS,EGA,VGA,MCGA) - ALTERNATE PRTSC
*
* AH = 12h
* BL = 20h select alternate print screen routine
* Return:
* Nothing
*
* Installs a PrtSc routine from the video card's BIOS to replace the
* default PrtSc handler from the ROM BIOS, which usually does not
* understand screen heights other than 25 lines.
*
* Some adapters disable print-screen instead of enhancing it.
*/
Regs.b.ah = 0x12;
Regs.b.bl = 0x20;
Int386(0x10, &Regs, &Regs);
}
static VOID
PcVideoDisableCursorEmulation(VOID)
{
REGS Regs;
/* Int 10h AH=12h BL=34h
* VIDEO - ALTERNATE FUNCTION SELECT (VGA) - CURSOR EMULATION
*
* AH = 12h
* BL = 34h
* AL = new state
* 00h enable alphanumeric cursor emulation
* 01h disable alphanumeric cursor emulation
* Return:
* AL = 12h if function supported
*
* Specify whether the BIOS should automatically remap cursor start/end
* according to the current character height in text modes.
*/
Regs.b.ah = 0x12;
Regs.b.bl = 0x34;
Regs.b.al = 0x01;
Int386(0x10, &Regs, &Regs);
}
static VOID
PcVideoDefineCursor(ULONG StartScanLine, ULONG EndScanLine)
{
REGS Regs;
/* Int 10h AH=01h
* VIDEO - SET TEXT-MODE CURSOR SHAPE
*
* AH = 01h
* CH = cursor start and options
* CL = bottom scan line containing cursor (bits 0-4)
* Return:
* Nothing
*
* Specify the starting and ending scan lines to be occupied
* by the hardware cursor in text modes.
*
* AMI 386 BIOS and AST Premier 386 BIOS will lock up the
* system if AL is not equal to the current video mode.
*
* Bitfields for cursor start and options:
*
* Bit(s) Description
* 7 should be zero
* 6,5 cursor blink
* (00=normal, 01=invisible, 10=erratic, 11=slow).
* (00=normal, other=invisible on EGA/VGA)
* 4-0 topmost scan line containing cursor
*/
Regs.b.ah = 0x01;
Regs.b.al = 0x03;
Regs.b.ch = StartScanLine;
Regs.b.cl = EndScanLine;
Int386(0x10, &Regs, &Regs);
}
static VOID
PcVideoSetVerticalResolution(ULONG ScanLines)
{
REGS Regs;
/* Int 10h AH=12h BL=30h
* VIDEO - ALTERNATE FUNCTION SELECT (VGA) - SELECT VERTICAL RESOLUTION
*
* AH = 12h
* BL = 30h
* AL = vertical resolution
* 00h 200 scan lines
* 01h 350 scan lines
* 02h 400 scan lines
* Return:
* AL = 12h if function supported
*
* Specifiy the number of scan lines used to display text modes.
*
* The specified resolution will take effect on the next mode set.
*/
Regs.b.ah = 0x12;
Regs.b.bl = 0x30;
Regs.b.al = ScanLines;
Int386(0x10, &Regs, &Regs);
}
static VOID
PcVideoSet480ScanLines(VOID)
{
int CRTC;
/* Read CRTC port */
CRTC = READ_PORT_UCHAR((PUCHAR)0x03CC);
if (CRTC & 1)
{
CRTC = 0x3D4;
}
else
{
CRTC = 0x3B4;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -