5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
28 #define VIDEOPORT_PALETTE_READ 0x03C7
29 #define VIDEOPORT_PALETTE_WRITE 0x03C8
30 #define VIDEOPORT_PALETTE_DATA 0x03C9
31 #define VIDEOPORT_VERTICAL_RETRACE 0x03DA
33 #define VIDEOVGA_MEM_ADDRESS 0xA0000
34 #define VIDEOTEXT_MEM_ADDRESS 0xB8000
35 #define VIDEOTEXT_MEM_SIZE 0x8000
37 #define VIDEOCARD_CGA_OR_OTHER 0
38 #define VIDEOCARD_EGA 1
39 #define VIDEOCARD_VGA 2
41 #define VIDEOMODE_NORMAL_TEXT 0
42 #define VIDEOMODE_EXTENDED_TEXT 1
43 #define VIDEOMODE_80X28 0x501C
44 #define VIDEOMODE_80X30 0x501E
45 #define VIDEOMODE_80X34 0x5022
46 #define VIDEOMODE_80X43 0x502B
47 #define VIDEOMODE_80X60 0x503C
48 #define VIDEOMODE_132X25 0x8419
49 #define VIDEOMODE_132X43 0x842B
50 #define VIDEOMODE_132X50 0x8432
51 #define VIDEOMODE_132X60 0x843C
53 #define VERTRES_200_SCANLINES 0x00
54 #define VERTRES_350_SCANLINES 0x01
55 #define VERTRES_400_SCANLINES 0x02
59 U16 ModeAttributes
; /* mode attributes (see #00080) */
60 U8 WindowAttributesA
; /* window attributes, window A (see #00081) */
61 U8 WindowsAttributesB
; /* window attributes, window B (see #00081) */
62 U16 WindowGranularity
; /* window granularity in KB */
63 U16 WindowSize
; /* window size in KB */
64 U16 WindowAStartSegment
; /* start segment of window A (0000h if not supported) */
65 U16 WindowBStartSegment
; /* start segment of window B (0000h if not supported) */
66 U32 WindowPositioningFunction
; /* -> FAR window positioning function (equivalent to AX=4F05h) */
67 U16 BytesPerScanLine
; /* bytes per scan line */
68 /* ---remainder is optional for VESA modes in v1.0/1.1, needed for OEM modes--- */
69 U16 WidthInPixels
; /* width in pixels (graphics) or characters (text) */
70 U16 HeightInPixels
; /* height in pixels (graphics) or characters (text) */
71 U8 CharacterWidthInPixels
; /* width of character cell in pixels */
72 U8 CharacterHeightInPixels
; /* height of character cell in pixels */
73 U8 NumberOfMemoryPlanes
; /* number of memory planes */
74 U8 BitsPerPixel
; /* number of bits per pixel */
75 U8 NumberOfBanks
; /* number of banks */
76 U8 MemoryModel
; /* memory model type (see #00082) */
77 U8 BankSize
; /* size of bank in KB */
78 U8 NumberOfImagePanes
; /* number of image pages (less one) that will fit in video RAM */
79 U8 Reserved1
; /* reserved (00h for VBE 1.0-2.0, 01h for VBE 3.0) */
80 /* ---VBE v1.2+ --- */
81 U8 RedMaskSize
; /* red mask size */
82 U8 RedMaskPosition
; /* red field position */
83 U8 GreenMaskSize
; /* green mask size */
84 U8 GreenMaskPosition
; /* green field size */
85 U8 BlueMaskSize
; /* blue mask size */
86 U8 BlueMaskPosition
; /* blue field size */
87 U8 ReservedMaskSize
; /* reserved mask size */
88 U8 ReservedMaskPosition
; /* reserved mask position */
89 U8 DirectColorModeInfo
; /* direct color mode info */
90 /* bit 0:Color ramp is programmable */
91 /* bit 1:Bytes in reserved field may be used by application */
92 /* ---VBE v2.0+ --- */
93 U32 LinearVideoBufferAddress
; /* physical address of linear video buffer */
94 U32 OffscreenMemoryPointer
; /* pointer to start of offscreen memory */
95 U16 OffscreenMemorySize
; /* KB of offscreen memory */
97 U16 LinearBytesPerScanLine
; /* bytes per scan line in linear modes */
98 U8 BankedNumberOfImages
; /* number of images (less one) for banked video modes */
99 U8 LinearNumberOfImages
; /* number of images (less one) for linear video modes */
100 U8 LinearRedMaskSize
; /* linear modes:Size of direct color red mask (in bits) */
101 U8 LinearRedMaskPosition
; /* linear modes:Bit position of red mask LSB (e.g. shift count) */
102 U8 LinearGreenMaskSize
; /* linear modes:Size of direct color green mask (in bits) */
103 U8 LinearGreenMaskPosition
; /* linear modes:Bit position of green mask LSB (e.g. shift count) */
104 U8 LinearBlueMaskSize
; /* linear modes:Size of direct color blue mask (in bits) */
105 U8 LinearBlueMaskPosition
; /* linear modes:Bit position of blue mask LSB (e.g. shift count) */
106 U8 LinearReservedMaskSize
; /* linear modes:Size of direct color reserved mask (in bits) */
107 U8 LinearReservedMaskPosition
; /* linear modes:Bit position of reserved mask LSB */
108 U32 MaximumPixelClock
; /* maximum pixel clock for graphics video mode, in Hz */
109 U8 Reserved2
[190]; /* 190 BYTEs reserved (0) */
110 } PACKED SVGA_MODE_INFORMATION
, *PSVGA_MODE_INFORMATION
;
112 static U32 BiosVideoMode
; /* Current video mode as known by BIOS */
113 static U32 ScreenWidth
= 80; /* Screen Width in characters */
114 static U32 ScreenHeight
= 25; /* Screen Height in characters */
115 static U32 BytesPerScanLine
= 160; /* Number of bytes per scanline (delta) */
116 static VIDEODISPLAYMODE DisplayMode
= VideoTextMode
; /* Current display mode */
117 static BOOL VesaVideoMode
= FALSE
; /* Are we using a VESA mode? */
118 static SVGA_MODE_INFORMATION VesaVideoModeInformation
; /* Only valid when in VESA mode */
119 static U32 CurrentMemoryBank
= 0; /* Currently selected VESA bank */
122 PcVideoDetectVideoCard(VOID
)
126 /* Int 10h AH=12h BL=10h
127 * VIDEO - ALTERNATE FUNCTION SELECT (PS,EGA,VGA,MCGA) - GET EGA INFO
133 * 00h color mode in effect (I/O port 3Dxh)
134 * 01h mono mode in effect (I/O port 3Bxh)
135 * BL = installed memory (00h = 64K, 01h = 128K, 02h = 192K, 03h = 256K)
136 * CH = feature connector bits
137 * CL = switch settings
138 * AH destroyed (at least by Tseng ET4000 BIOS v8.00n)
140 * Installation check;EGA
144 Int386(0x10, &Regs
, &Regs
);
146 /* If BL is still equal to 0x10 then there is no EGA/VGA present */
147 if (0x10 == Regs
.b
.bl
)
149 return VIDEOCARD_CGA_OR_OTHER
;
153 * VIDEO - GET DISPLAY COMBINATION CODE (PS,VGA/MCGA)
157 * AL = 1Ah if function was supported
158 * BL = active display code
159 * BH = alternate display code
161 * This function is commonly used to check for the presence of a VGA.
163 * Installation check;VGA
165 * Values for display combination code:
167 * 01h monochrome adapter w/ monochrome display
168 * 02h CGA w/ color display
170 * 04h EGA w/ color display
171 * 05h EGA w/ monochrome display
172 * 06h PGA w/ color display
173 * 07h VGA w/ monochrome analog display
174 * 08h VGA w/ color analog display
176 * 0Ah MCGA w/ digital color display
177 * 0Bh MCGA w/ monochrome analog display
178 * 0Ch MCGA w/ color analog display
179 * FFh unknown display type
183 Int386(0x10, &Regs
, &Regs
);
185 if (0x1a == Regs
.b
.al
)
187 return VIDEOCARD_VGA
;
191 return VIDEOCARD_EGA
;
195 static VOID
PcVideoSetBiosMode(U32 VideoMode
)
200 * VIDEO - SET VIDEO MODE
203 * AL = desired video mode
205 * AL = video mode flag (Phoenix, AMI BIOS)
207 * 30h modes 0-5 and 7
209 * AL = CRT controller mode byte (Phoenix 386 BIOS v1.10)
212 Regs
.b
.al
= VideoMode
;
213 Int386(0x10, &Regs
, &Regs
);
217 PcVideoSetFont8x8(VOID
)
222 * VIDEO - TEXT-MODE CHARGEN - LOAD ROM 8x8 DBL-DOT PATTERNS (PS,EGA,VGA)
231 Int386(0x10, &Regs
, &Regs
);
235 PcVideoSetFont8x14(VOID
)
240 * VIDEO - TEXT-MODE CHARGEN - LOAD ROM MONOCHROME PATTERNS (PS,EGA,VGA)
249 Int386(0x10, &Regs
, &Regs
);
252 VOID
PcVideoSelectAlternatePrintScreen(VOID
)
256 /* Int 10h AH=12h BL=20h
257 * VIDEO - ALTERNATE FUNCTION SELECT (PS,EGA,VGA,MCGA) - ALTERNATE PRTSC
260 * BL = 20h select alternate print screen routine
264 * Installs a PrtSc routine from the video card's BIOS to replace the
265 * default PrtSc handler from the ROM BIOS, which usually does not
266 * understand screen heights other than 25 lines.
268 * Some adapters disable print-screen instead of enhancing it.
272 Int386(0x10, &Regs
, &Regs
);
275 VOID
PcVideoDisableCursorEmulation(VOID
)
279 /* Int 10h AH=12h BL=34h
280 * VIDEO - ALTERNATE FUNCTION SELECT (VGA) - CURSOR EMULATION
285 * 00h enable alphanumeric cursor emulation
286 * 01h disable alphanumeric cursor emulation
288 * AL = 12h if function supported
290 * Specify whether the BIOS should automatically remap cursor start/end
291 * according to the current character height in text modes.
296 Int386(0x10, &Regs
, &Regs
);
300 PcVideoDefineCursor(U32 StartScanLine
, U32 EndScanLine
)
305 * VIDEO - SET TEXT-MODE CURSOR SHAPE
308 * CH = cursor start and options
309 * CL = bottom scan line containing cursor (bits 0-4)
313 * Specify the starting and ending scan lines to be occupied
314 * by the hardware cursor in text modes.
316 * AMI 386 BIOS and AST Premier 386 BIOS will lock up the
317 * system if AL is not equal to the current video mode.
319 * Bitfields for cursor start and options:
324 * (00=normal, 01=invisible, 10=erratic, 11=slow).
325 * (00=normal, other=invisible on EGA/VGA)
326 * 4-0 topmost scan line containing cursor
330 Regs
.b
.ch
= StartScanLine
;
331 Regs
.b
.cl
= EndScanLine
;
332 Int386(0x10, &Regs
, &Regs
);
336 PcVideoSetVerticalResolution(U32 ScanLines
)
340 /* Int 10h AH=12h BL=30h
341 * VIDEO - ALTERNATE FUNCTION SELECT (VGA) - SELECT VERTICAL RESOLUTION
345 * AL = vertical resolution
350 * AL = 12h if function supported
352 * Specifiy the number of scan lines used to display text modes.
354 * The specified resolution will take effect on the next mode set.
358 Regs
.b
.al
= ScanLines
;
359 Int386(0x10, &Regs
, &Regs
);
363 PcVideoSet480ScanLines(VOID
)
368 CRTC
= READ_PORT_UCHAR((PUCHAR
)0x03CC);
379 /* Vertical sync end (also unlocks CR0-7) */
380 WRITE_PORT_UCHAR((PUCHAR
)CRTC
, 0x11);
381 WRITE_PORT_UCHAR((PUCHAR
)CRTC
+1, 0x0C);
384 WRITE_PORT_UCHAR((PUCHAR
)CRTC
, 0x06);
385 WRITE_PORT_UCHAR((PUCHAR
)CRTC
+1, 0x0B);
387 /* (vertical) overflow */
388 WRITE_PORT_UCHAR((PUCHAR
)CRTC
, 0x07);
389 WRITE_PORT_UCHAR((PUCHAR
)CRTC
+1, 0x3E);
391 /* Vertical sync start */
392 WRITE_PORT_UCHAR((PUCHAR
)CRTC
, 0x10);
393 WRITE_PORT_UCHAR((PUCHAR
)CRTC
+1, 0xEA);
395 /* Vertical display end */
396 WRITE_PORT_UCHAR((PUCHAR
)CRTC
, 0x12);
397 WRITE_PORT_UCHAR((PUCHAR
)CRTC
+1, 0xDF);
399 /* Vertical blank start */
400 WRITE_PORT_UCHAR((PUCHAR
)CRTC
, 0x15);
401 WRITE_PORT_UCHAR((PUCHAR
)CRTC
+1, 0xE7);
403 /* Vertical blank end */
404 WRITE_PORT_UCHAR((PUCHAR
)CRTC
, 0x16);
405 WRITE_PORT_UCHAR((PUCHAR
)CRTC
+1, 0x04);
407 /* Misc output register (read) */
408 CRTC
= READ_PORT_UCHAR((PUCHAR
)0x03CC);
410 /* Preserve clock select bits and color bit */
411 CRTC
= (CRTC
& 0x0D);
412 /* Set correct sync polarity */
413 CRTC
= (CRTC
| 0xE2);
416 WRITE_PORT_UCHAR((PUCHAR
)0x03C2, CRTC
);
420 PcVideoSetDisplayEnd(VOID
)
425 CRTC
= READ_PORT_UCHAR((PUCHAR
)0x03CC);
436 /* Vertical display end */
437 WRITE_PORT_UCHAR((PUCHAR
)CRTC
, 0x12);
438 WRITE_PORT_UCHAR((PUCHAR
)CRTC
+1, 0xDF);
442 PcVideoVesaGetSVGAModeInformation(U16 Mode
, PSVGA_MODE_INFORMATION ModeInformation
)
446 RtlZeroMemory((PVOID
)BIOSCALLBUFFER
, 256);
448 /* VESA SuperVGA BIOS - GET SuperVGA MODE INFORMATION
450 * CX = SuperVGA video mode (see #04082 for bitfields)
451 * ES:DI -> 256-byte buffer for mode information (see #00079)
453 * AL = 4Fh if function supported
456 * ES:DI buffer filled
459 * Desc: Determine the attributes of the specified video mode
461 * Note: While VBE 1.1 and higher will zero out all unused bytes
462 * of the buffer, v1.0 did not, so applications that want to be
463 * backward compatible should clear the buffer before calling
467 Regs
.w
.es
= BIOSCALLBUFSEGMENT
;
468 Regs
.w
.di
= BIOSCALLBUFOFFSET
;
469 Int386(0x10, &Regs
, &Regs
);
471 if (Regs
.w
.ax
!= 0x004F)
476 RtlCopyMemory(ModeInformation
, (PVOID
)BIOSCALLBUFFER
, sizeof(SVGA_MODE_INFORMATION
));
478 DbgPrint((DPRINT_UI
, "\n"));
479 DbgPrint((DPRINT_UI
, "BiosVesaGetSVGAModeInformation() mode 0x%x\n", Mode
));
480 DbgPrint((DPRINT_UI
, "ModeAttributes = 0x%x\n", ModeInformation
->ModeAttributes
));
481 DbgPrint((DPRINT_UI
, "WindowAttributesA = 0x%x\n", ModeInformation
->WindowAttributesA
));
482 DbgPrint((DPRINT_UI
, "WindowAttributesB = 0x%x\n", ModeInformation
->WindowsAttributesB
));
483 DbgPrint((DPRINT_UI
, "WindowGranularity = %dKB\n", ModeInformation
->WindowGranularity
));
484 DbgPrint((DPRINT_UI
, "WindowSize = %dKB\n", ModeInformation
->WindowSize
));
485 DbgPrint((DPRINT_UI
, "WindowAStartSegment = 0x%x\n", ModeInformation
->WindowAStartSegment
));
486 DbgPrint((DPRINT_UI
, "WindowBStartSegment = 0x%x\n", ModeInformation
->WindowBStartSegment
));
487 DbgPrint((DPRINT_UI
, "WindowPositioningFunction = 0x%x\n", ModeInformation
->WindowPositioningFunction
));
488 DbgPrint((DPRINT_UI
, "BytesPerScanLine = %d\n", ModeInformation
->BytesPerScanLine
));
489 DbgPrint((DPRINT_UI
, "WidthInPixels = %d\n", ModeInformation
->WidthInPixels
));
490 DbgPrint((DPRINT_UI
, "HeightInPixels = %d\n", ModeInformation
->HeightInPixels
));
491 DbgPrint((DPRINT_UI
, "CharacterWidthInPixels = %d\n", ModeInformation
->CharacterWidthInPixels
));
492 DbgPrint((DPRINT_UI
, "CharacterHeightInPixels = %d\n", ModeInformation
->CharacterHeightInPixels
));
493 DbgPrint((DPRINT_UI
, "NumberOfMemoryPlanes = %d\n", ModeInformation
->NumberOfMemoryPlanes
));
494 DbgPrint((DPRINT_UI
, "BitsPerPixel = %d\n", ModeInformation
->BitsPerPixel
));
495 DbgPrint((DPRINT_UI
, "NumberOfBanks = %d\n", ModeInformation
->NumberOfBanks
));
496 DbgPrint((DPRINT_UI
, "MemoryModel = %d\n", ModeInformation
->MemoryModel
));
497 DbgPrint((DPRINT_UI
, "BankSize = %d\n", ModeInformation
->BankSize
));
498 DbgPrint((DPRINT_UI
, "NumberOfImagePlanes = %d\n", ModeInformation
->NumberOfImagePanes
));
499 DbgPrint((DPRINT_UI
, "---VBE v1.2+ ---\n"));
500 DbgPrint((DPRINT_UI
, "RedMaskSize = %d\n", ModeInformation
->RedMaskSize
));
501 DbgPrint((DPRINT_UI
, "RedMaskPosition = %d\n", ModeInformation
->RedMaskPosition
));
502 DbgPrint((DPRINT_UI
, "GreenMaskSize = %d\n", ModeInformation
->GreenMaskSize
));
503 DbgPrint((DPRINT_UI
, "GreenMaskPosition = %d\n", ModeInformation
->GreenMaskPosition
));
504 DbgPrint((DPRINT_UI
, "BlueMaskSize = %d\n", ModeInformation
->BlueMaskSize
));
505 DbgPrint((DPRINT_UI
, "BlueMaskPosition = %d\n", ModeInformation
->BlueMaskPosition
));
506 DbgPrint((DPRINT_UI
, "ReservedMaskSize = %d\n", ModeInformation
->ReservedMaskSize
));
507 DbgPrint((DPRINT_UI
, "ReservedMaskPosition = %d\n", ModeInformation
->ReservedMaskPosition
));
508 DbgPrint((DPRINT_UI
, "\n"));
514 PcVideoSetBiosVesaMode(U16 Mode
)
519 * VESA SuperVGA BIOS - SET SuperVGA VIDEO MODE
522 * BX = new video mode
523 * ES:DI -> (VBE 3.0+) CRTC information block, bit mode bit 11 set
525 * AL = 4Fh if function supported
530 * Values for VESA video mode:
531 * 00h-FFh OEM video modes (see #00010 at AH=00h)
558 * 119h 1280x1024x32K (1:5:5:5)
559 * 11Ah 1280x1024x64K (5:6:5)
565 * 81FFh special full-memory access mode
567 * Notes: The special mode 81FFh preserves the contents of the video memory and gives
568 * access to all of the memory; VESA recommends that the special mode be a packed-pixel
569 * mode. For VBE 2.0+, it is required that the VBE implement the mode, but not place it
570 * in the list of available modes (mode information for this mode can be queried
571 * directly, however).. As of VBE 2.0, VESA will no longer define video mode numbers
575 Int386(0x10, &Regs
, &Regs
);
577 if (0x004F != Regs
.w
.ax
)
586 PcVideoSetMode80x25(VOID
)
588 PcVideoSetBiosMode(0x03);
596 PcVideoSetMode80x50_80x43(VOID
)
598 if (VIDEOCARD_VGA
== PcVideoDetectVideoCard())
600 PcVideoSetBiosMode(0x03);
602 PcVideoSelectAlternatePrintScreen();
603 PcVideoDisableCursorEmulation();
604 PcVideoDefineCursor(6, 7);
608 else if (VIDEOCARD_EGA
== PcVideoDetectVideoCard())
610 PcVideoSetBiosMode(0x03);
612 PcVideoSelectAlternatePrintScreen();
613 PcVideoDisableCursorEmulation();
614 PcVideoDefineCursor(6, 7);
618 else /* VIDEOCARD_CGA_OR_OTHER */
627 PcVideoSetMode80x28(VOID
)
629 /* FIXME: Is this VGA-only? */
630 PcVideoSetMode80x25();
631 PcVideoSetFont8x14();
632 PcVideoDefineCursor(11, 12);
640 PcVideoSetMode80x30(VOID
)
642 /* FIXME: Is this VGA-only? */
643 PcVideoSetMode80x25();
644 PcVideoSet480ScanLines();
652 PcVideoSetMode80x34(VOID
)
654 /* FIXME: Is this VGA-only? */
655 PcVideoSetMode80x25();
656 PcVideoSet480ScanLines();
657 PcVideoSetFont8x14();
658 PcVideoDefineCursor(11, 12);
659 PcVideoSetDisplayEnd();
667 PcVideoSetMode80x43(VOID
)
669 /* FIXME: Is this VGA-only? */
670 PcVideoSetVerticalResolution(VERTRES_350_SCANLINES
);
671 PcVideoSetMode80x25();
673 PcVideoSelectAlternatePrintScreen();
674 PcVideoDisableCursorEmulation();
675 PcVideoDefineCursor(6, 7);
683 PcVideoSetMode80x60(VOID
)
685 /* FIXME: Is this VGA-only? */
686 PcVideoSetMode80x25();
687 PcVideoSet480ScanLines();
689 PcVideoSelectAlternatePrintScreen();
690 PcVideoDisableCursorEmulation();
691 PcVideoDefineCursor(6, 7);
692 PcVideoSetDisplayEnd();
700 PcVideoSetMode(U32 NewMode
)
702 CurrentMemoryBank
= 0;
704 /* Set the values for the default text modes
705 * If they are setting a graphics mode then
706 * these values will be changed.
708 BiosVideoMode
= NewMode
;
711 BytesPerScanLine
= 160;
712 DisplayMode
= VideoTextMode
;
713 VesaVideoMode
= FALSE
;
717 case VIDEOMODE_NORMAL_TEXT
:
718 case 0x03: /* BIOS 80x25 text mode number */
719 return PcVideoSetMode80x25();
720 case VIDEOMODE_EXTENDED_TEXT
:
721 return PcVideoSetMode80x50_80x43();
722 case VIDEOMODE_80X28
:
723 return PcVideoSetMode80x28();
724 case VIDEOMODE_80X30
:
725 return PcVideoSetMode80x30();
726 case VIDEOMODE_80X34
:
727 return PcVideoSetMode80x34();
728 case VIDEOMODE_80X43
:
729 return PcVideoSetMode80x43();
730 case VIDEOMODE_80X60
:
731 return PcVideoSetMode80x60();
737 PcVideoSetBiosMode(NewMode
);
738 WRITE_PORT_USHORT((U16
*)0x03CE, 0x0F01); /* For some reason this is necessary? */
741 BytesPerScanLine
= 80;
742 BiosVideoMode
= NewMode
;
743 DisplayMode
= VideoGraphicsMode
;
747 else if (0x13 == NewMode
)
750 PcVideoSetBiosMode(NewMode
);
753 BytesPerScanLine
= 320;
754 BiosVideoMode
= NewMode
;
755 DisplayMode
= VideoGraphicsMode
;
759 else if (0x0108 <= NewMode
&& NewMode
<= 0x010C)
762 if (! PcVideoVesaGetSVGAModeInformation(NewMode
, &VesaVideoModeInformation
))
767 if (! PcVideoSetBiosVesaMode(NewMode
))
772 ScreenWidth
= VesaVideoModeInformation
.WidthInPixels
;
773 ScreenHeight
= VesaVideoModeInformation
.HeightInPixels
;
774 BytesPerScanLine
= VesaVideoModeInformation
.BytesPerScanLine
;
775 BiosVideoMode
= NewMode
;
776 DisplayMode
= VideoTextMode
;
777 VesaVideoMode
= TRUE
;
783 /* VESA Graphics Mode */
784 if (! PcVideoVesaGetSVGAModeInformation(NewMode
, &VesaVideoModeInformation
))
789 if (! PcVideoSetBiosVesaMode(NewMode
))
794 ScreenWidth
= VesaVideoModeInformation
.WidthInPixels
;
795 ScreenHeight
= VesaVideoModeInformation
.HeightInPixels
;
796 BytesPerScanLine
= VesaVideoModeInformation
.BytesPerScanLine
;
797 BiosVideoMode
= NewMode
;
798 DisplayMode
= VideoTextMode
;
799 VesaVideoMode
= TRUE
;
808 PcVideoSetBlinkBit(BOOL Enable
)
813 * VIDEO - TOGGLE INTENSITY/BLINKING BIT (Jr, PS, TANDY 1000, EGA, VGA)
817 * 00h background intensity enabled
819 * BH = 00h to avoid problems on some adapters
823 * Note: although there is no function to get
824 * the current status, bit 5 of 0040h:0065h
825 * indicates the state.
828 Regs
.w
.bx
= Enable
? 0x0001 : 0x0000;
829 Int386(0x10, &Regs
, &Regs
);
833 PcVideoSetMemoryBank(U16 BankNumber
)
837 if (CurrentMemoryBank
!= BankNumber
)
840 * VESA SuperVGA BIOS - CPU VIDEO MEMORY CONTROL
844 * 00h select video memory window
845 * 01h get video memory window
846 * DX = window address in video memory (in granularity units)
848 * DX = window address in video memory (in gran. units)
853 * AL = 4Fh if function supported
860 Regs
.w
.dx
= BankNumber
;
861 Int386(0x10, &Regs
, &Regs
);
863 if (0x004F == Regs
.w
.ax
)
865 CurrentMemoryBank
= BankNumber
;
871 PcVideoSetDisplayMode(char *DisplayModeName
, BOOL Init
)
873 U32 VideoMode
= VIDEOMODE_NORMAL_TEXT
;
875 if (NULL
== DisplayModeName
|| '\0' == *DisplayModeName
)
877 PcVideoSetBlinkBit(! Init
);
881 if (VIDEOCARD_CGA_OR_OTHER
== PcVideoDetectVideoCard())
883 DbgPrint((DPRINT_UI
, "CGA or other display adapter detected.\n"));
884 printf("CGA or other display adapter detected.\n");
885 printf("Using 80x25 text mode.\n");
886 VideoMode
= VIDEOMODE_NORMAL_TEXT
;
888 else if (VIDEOCARD_EGA
== PcVideoDetectVideoCard())
890 DbgPrint((DPRINT_UI
, "EGA display adapter detected.\n"));
891 printf("EGA display adapter detected.\n");
892 printf("Using 80x25 text mode.\n");
893 VideoMode
= VIDEOMODE_NORMAL_TEXT
;
895 else /* if (VIDEOCARD_VGA == PcVideoDetectVideoCard()) */
897 DbgPrint((DPRINT_UI
, "VGA display adapter detected.\n"));
899 if (0 == stricmp(DisplayModeName
, "NORMAL_VGA"))
901 VideoMode
= VIDEOMODE_NORMAL_TEXT
;
903 else if (0 == stricmp(DisplayModeName
, "EXTENDED_VGA"))
905 VideoMode
= VIDEOMODE_EXTENDED_TEXT
;
909 VideoMode
= atoi(DisplayModeName
);
913 if (! PcVideoSetMode(VideoMode
))
915 printf("Error: unable to set video display mode 0x%x\n", (int) VideoMode
);
916 printf("Defaulting to 80x25 text mode.\n");
917 printf("Press any key to continue.\n");
920 PcVideoSetMode(VIDEOMODE_NORMAL_TEXT
);
923 PcVideoSetBlinkBit(! Init
);
930 PcVideoGetDisplaySize(PU32 Width
, PU32 Height
, PU32 Depth
)
932 *Width
= ScreenWidth
;
933 *Height
= ScreenHeight
;
934 if (VideoGraphicsMode
== DisplayMode
&& VesaVideoMode
)
936 if (16 == VesaVideoModeInformation
.BitsPerPixel
)
938 /* 16-bit color modes give green an extra bit (5:6:5)
939 * 15-bit color modes have just 5:5:5 for R:G:B */
940 *Depth
= (6 == VesaVideoModeInformation
.GreenMaskSize
? 16 : 15);
944 *Depth
= VesaVideoModeInformation
.BitsPerPixel
;
954 PcVideoGetBufferSize(VOID
)
956 return ScreenHeight
* BytesPerScanLine
;
960 PcVideoSetTextCursorPosition(U32 X
, U32 Y
)
965 * VIDEO - SET CURSOR POSITION
971 * 0 in graphics modes
972 * DH = row (00h is top)
973 * DL = column (00h is left)
981 Int386(0x10, &Regs
, &Regs
);
985 PcVideoHideShowTextCursor(BOOL Show
)
989 PcVideoDefineCursor(0x0D, 0x0E);
993 PcVideoDefineCursor(0x20, 0x00);
998 PcVideoCopyOffScreenBufferToVRAM(PVOID Buffer
)
1001 U32 BytesInLastBank
;
1005 /* PcVideoWaitForVerticalRetrace(); */
1007 /* Text mode (BIOS or VESA) */
1008 if (VideoTextMode
== DisplayMode
)
1010 RtlCopyMemory((PVOID
) VIDEOTEXT_MEM_ADDRESS
, Buffer
, PcVideoGetBufferSize());
1012 /* VESA graphics mode */
1013 else if (VideoGraphicsMode
== DisplayMode
&& VesaVideoMode
)
1015 BankSize
= VesaVideoModeInformation
.WindowGranularity
<< 10;
1016 BanksToCopy
= (VesaVideoModeInformation
.HeightInPixels
* VesaVideoModeInformation
.BytesPerScanLine
) / BankSize
;
1017 BytesInLastBank
= (VesaVideoModeInformation
.HeightInPixels
* VesaVideoModeInformation
.BytesPerScanLine
) % BankSize
;
1019 /* Copy all the banks but the last one because
1020 * it is probably a partial bank */
1021 for (CurrentBank
= 0; CurrentBank
< BanksToCopy
; CurrentBank
++)
1023 PcVideoSetMemoryBank(CurrentBank
);
1024 RtlCopyMemory((PVOID
) VIDEOVGA_MEM_ADDRESS
, (char *) Buffer
+ CurrentBank
* BankSize
, BankSize
);
1027 /* Copy the remaining bytes into the last bank */
1028 PcVideoSetMemoryBank(CurrentBank
);
1029 RtlCopyMemory((PVOID
)VIDEOVGA_MEM_ADDRESS
, (char *) Buffer
+ CurrentBank
* BankSize
, BytesInLastBank
);
1031 /* BIOS graphics mode */
1039 PcVideoClearScreen(U8 Attr
)
1044 AttrChar
= ((U16
) Attr
<< 8) | ' ';
1045 for (BufPtr
= (U16
*) VIDEOTEXT_MEM_ADDRESS
;
1046 BufPtr
< (U16
*) (VIDEOTEXT_MEM_ADDRESS
+ VIDEOTEXT_MEM_SIZE
);
1054 PcVideoPutChar(int Ch
, U8 Attr
, unsigned X
, unsigned Y
)
1058 BufPtr
= (U16
*) (VIDEOTEXT_MEM_ADDRESS
+ Y
* BytesPerScanLine
+ X
* 2);
1059 *BufPtr
= ((U16
) Attr
<< 8) | (Ch
& 0xff);
1063 PcVideoIsPaletteFixed(VOID
)
1069 PcVideoSetPaletteColor(U8 Color
, U8 Red
, U8 Green
, U8 Blue
)
1071 WRITE_PORT_UCHAR((U8
*) VIDEOPORT_PALETTE_WRITE
, Color
);
1072 WRITE_PORT_UCHAR((U8
*) VIDEOPORT_PALETTE_DATA
, Red
);
1073 WRITE_PORT_UCHAR((U8
*) VIDEOPORT_PALETTE_DATA
, Green
);
1074 WRITE_PORT_UCHAR((U8
*) VIDEOPORT_PALETTE_DATA
, Blue
);
1078 PcVideoGetPaletteColor(U8 Color
, U8
* Red
, U8
* Green
, U8
* Blue
)
1080 WRITE_PORT_UCHAR((U8
*) VIDEOPORT_PALETTE_READ
, Color
);
1081 *Red
= READ_PORT_UCHAR((U8
*) VIDEOPORT_PALETTE_DATA
);
1082 *Green
= READ_PORT_UCHAR((U8
*) VIDEOPORT_PALETTE_DATA
);
1083 *Blue
= READ_PORT_UCHAR((U8
*) VIDEOPORT_PALETTE_DATA
);
1089 while (1 == (READ_PORT_UCHAR((U8
*)VIDEOPORT_VERTICAL_RETRACE
) & 0x08))
1092 * Keep reading the port until bit 3 is clear
1093 * This waits for the current retrace to end and
1094 * we can catch the next one so we know we are
1095 * getting a full retrace.
1099 while (0 == (READ_PORT_UCHAR((U8
*)VIDEOPORT_VERTICAL_RETRACE
) & 0x08))
1102 * Keep reading the port until bit 3 is set
1103 * Now that we know we aren't doing a vertical
1104 * retrace we need to wait for the next one.
1110 PcVideoPrepareForReactOS(VOID
)
1112 PcVideoSetMode80x50_80x43();
1113 PcVideoHideShowTextCursor(FALSE
);