2 * COPYRIGHT: GPL - See COPYING in the top level directory
3 * PROJECT: ReactOS Virtual DOS Machine
5 * PURPOSE: VGA hardware emulation
6 * PROGRAMMERS: Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
9 /* INCLUDES *******************************************************************/
18 /* PRIVATE VARIABLES **********************************************************/
20 static CONST DWORD MemoryBase
[] = { 0xA0000, 0xA0000, 0xB0000, 0xB8000 };
21 static CONST DWORD MemoryLimit
[] = { 0xAFFFF, 0xAFFFF, 0xB7FFF, 0xBFFFF };
23 #define USE_REACTOS_COLORS
24 // #define USE_DOSBOX_COLORS
26 #if defined(USE_REACTOS_COLORS)
29 static CONST COLORREF VgaDefaultPalette
[VGA_MAX_COLORS
] =
31 RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0xAA), RGB(0x00, 0xAA, 0x00), RGB(0x00, 0xAA, 0xAA),
32 RGB(0xAA, 0x00, 0x00), RGB(0xAA, 0x00, 0xAA), RGB(0xAA, 0x55, 0x00), RGB(0xAA, 0xAA, 0xAA),
33 RGB(0x55, 0x55, 0x55), RGB(0x55, 0x55, 0xFF), RGB(0x55, 0xFF, 0x55), RGB(0x55, 0xFF, 0xFF),
34 RGB(0xFF, 0x55, 0x55), RGB(0xFF, 0x55, 0xFF), RGB(0xFF, 0xFF, 0x55), RGB(0xFF, 0xFF, 0xFF),
35 RGB(0x00, 0x00, 0x00), RGB(0x10, 0x10, 0x10), RGB(0x20, 0x20, 0x20), RGB(0x35, 0x35, 0x35),
36 RGB(0x45, 0x45, 0x45), RGB(0x55, 0x55, 0x55), RGB(0x65, 0x65, 0x65), RGB(0x75, 0x75, 0x75),
37 RGB(0x8A, 0x8A, 0x8A), RGB(0x9A, 0x9A, 0x9A), RGB(0xAA, 0xAA, 0xAA), RGB(0xBA, 0xBA, 0xBA),
38 RGB(0xCA, 0xCA, 0xCA), RGB(0xDF, 0xDF, 0xDF), RGB(0xEF, 0xEF, 0xEF), RGB(0xFF, 0xFF, 0xFF),
39 RGB(0x00, 0x00, 0xFF), RGB(0x41, 0x00, 0xFF), RGB(0x82, 0x00, 0xFF), RGB(0xBE, 0x00, 0xFF),
40 RGB(0xFF, 0x00, 0xFF), RGB(0xFF, 0x00, 0xBE), RGB(0xFF, 0x00, 0x82), RGB(0xFF, 0x00, 0x41),
41 RGB(0xFF, 0x00, 0x00), RGB(0xFF, 0x41, 0x00), RGB(0xFF, 0x82, 0x00), RGB(0xFF, 0xBE, 0x00),
42 RGB(0xFF, 0xFF, 0x00), RGB(0xBE, 0xFF, 0x00), RGB(0x82, 0xFF, 0x00), RGB(0x41, 0xFF, 0x00),
43 RGB(0x00, 0xFF, 0x00), RGB(0x00, 0xFF, 0x41), RGB(0x00, 0xFF, 0x82), RGB(0x00, 0xFF, 0xBE),
44 RGB(0x00, 0xFF, 0xFF), RGB(0x00, 0xBE, 0xFF), RGB(0x00, 0x82, 0xFF), RGB(0x00, 0x41, 0xFF),
45 RGB(0x82, 0x82, 0xFF), RGB(0x9E, 0x82, 0xFF), RGB(0xBE, 0x82, 0xFF), RGB(0xDF, 0x82, 0xFF),
46 RGB(0xFF, 0x82, 0xFF), RGB(0xFF, 0x82, 0xDF), RGB(0xFF, 0x82, 0xBE), RGB(0xFF, 0x82, 0x9E),
47 RGB(0xFF, 0x82, 0x82), RGB(0xFF, 0x9E, 0x82), RGB(0xFF, 0xBE, 0x82), RGB(0xFF, 0xDF, 0x82),
48 RGB(0xFF, 0xFF, 0x82), RGB(0xDF, 0xFF, 0x82), RGB(0xBE, 0xFF, 0x82), RGB(0x9E, 0xFF, 0x82),
49 RGB(0x82, 0xFF, 0x82), RGB(0x82, 0xFF, 0x9E), RGB(0x82, 0xFF, 0xBE), RGB(0x82, 0xFF, 0xDF),
50 RGB(0x82, 0xFF, 0xFF), RGB(0x82, 0xDF, 0xFF), RGB(0x82, 0xBE, 0xFF), RGB(0x82, 0x9E, 0xFF),
51 RGB(0xBA, 0xBA, 0xFF), RGB(0xCA, 0xBA, 0xFF), RGB(0xDF, 0xBA, 0xFF), RGB(0xEF, 0xBA, 0xFF),
52 RGB(0xFF, 0xBA, 0xFF), RGB(0xFF, 0xBA, 0xEF), RGB(0xFF, 0xBA, 0xDF), RGB(0xFF, 0xBA, 0xCA),
53 RGB(0xFF, 0xBA, 0xBA), RGB(0xFF, 0xCA, 0xBA), RGB(0xFF, 0xDF, 0xBA), RGB(0xFF, 0xEF, 0xBA),
54 RGB(0xFF, 0xFF, 0xBA), RGB(0xEF, 0xFF, 0xBA), RGB(0xDF, 0xFF, 0xBA), RGB(0xCA, 0xFF, 0xBA),
55 RGB(0xBA, 0xFF, 0xBA), RGB(0xBA, 0xFF, 0xCA), RGB(0xBA, 0xFF, 0xDF), RGB(0xBA, 0xFF, 0xEF),
56 RGB(0xBA, 0xFF, 0xFF), RGB(0xBA, 0xEF, 0xFF), RGB(0xBA, 0xDF, 0xFF), RGB(0xBA, 0xCA, 0xFF),
57 RGB(0x00, 0x00, 0x71), RGB(0x1C, 0x00, 0x71), RGB(0x39, 0x00, 0x71), RGB(0x55, 0x00, 0x71),
58 RGB(0x71, 0x00, 0x71), RGB(0x71, 0x00, 0x55), RGB(0x71, 0x00, 0x39), RGB(0x71, 0x00, 0x1C),
59 RGB(0x71, 0x00, 0x00), RGB(0x71, 0x1C, 0x00), RGB(0x71, 0x39, 0x00), RGB(0x71, 0x55, 0x00),
60 RGB(0x71, 0x71, 0x00), RGB(0x55, 0x71, 0x00), RGB(0x39, 0x71, 0x00), RGB(0x1C, 0x71, 0x00),
61 RGB(0x00, 0x71, 0x00), RGB(0x00, 0x71, 0x1C), RGB(0x00, 0x71, 0x39), RGB(0x00, 0x71, 0x55),
62 RGB(0x00, 0x71, 0x71), RGB(0x00, 0x55, 0x71), RGB(0x00, 0x39, 0x71), RGB(0x00, 0x1C, 0x71),
63 RGB(0x39, 0x39, 0x71), RGB(0x45, 0x39, 0x71), RGB(0x55, 0x39, 0x71), RGB(0x61, 0x39, 0x71),
64 RGB(0x71, 0x39, 0x71), RGB(0x71, 0x39, 0x61), RGB(0x71, 0x39, 0x55), RGB(0x71, 0x39, 0x45),
65 RGB(0x71, 0x39, 0x39), RGB(0x71, 0x45, 0x39), RGB(0x71, 0x55, 0x39), RGB(0x71, 0x61, 0x39),
66 RGB(0x71, 0x71, 0x39), RGB(0x61, 0x71, 0x39), RGB(0x55, 0x71, 0x39), RGB(0x45, 0x71, 0x39),
67 RGB(0x39, 0x71, 0x39), RGB(0x39, 0x71, 0x45), RGB(0x39, 0x71, 0x55), RGB(0x39, 0x71, 0x61),
68 RGB(0x39, 0x71, 0x71), RGB(0x39, 0x61, 0x71), RGB(0x39, 0x55, 0x71), RGB(0x39, 0x45, 0x71),
69 RGB(0x51, 0x51, 0x71), RGB(0x59, 0x51, 0x71), RGB(0x61, 0x51, 0x71), RGB(0x69, 0x51, 0x71),
70 RGB(0x71, 0x51, 0x71), RGB(0x71, 0x51, 0x69), RGB(0x71, 0x51, 0x61), RGB(0x71, 0x51, 0x59),
71 RGB(0x71, 0x51, 0x51), RGB(0x71, 0x59, 0x51), RGB(0x71, 0x61, 0x51), RGB(0x71, 0x69, 0x51),
72 RGB(0x71, 0x71, 0x51), RGB(0x69, 0x71, 0x51), RGB(0x61, 0x71, 0x51), RGB(0x59, 0x71, 0x51),
73 RGB(0x51, 0x71, 0x51), RGB(0x51, 0x71, 0x59), RGB(0x51, 0x71, 0x61), RGB(0x51, 0x71, 0x69),
74 RGB(0x51, 0x71, 0x71), RGB(0x51, 0x69, 0x71), RGB(0x51, 0x61, 0x71), RGB(0x51, 0x59, 0x71),
75 RGB(0x00, 0x00, 0x41), RGB(0x10, 0x00, 0x41), RGB(0x20, 0x00, 0x41), RGB(0x31, 0x00, 0x41),
76 RGB(0x41, 0x00, 0x41), RGB(0x41, 0x00, 0x31), RGB(0x41, 0x00, 0x20), RGB(0x41, 0x00, 0x10),
77 RGB(0x41, 0x00, 0x00), RGB(0x41, 0x10, 0x00), RGB(0x41, 0x20, 0x00), RGB(0x41, 0x31, 0x00),
78 RGB(0x41, 0x41, 0x00), RGB(0x31, 0x41, 0x00), RGB(0x20, 0x41, 0x00), RGB(0x10, 0x41, 0x00),
79 RGB(0x00, 0x41, 0x00), RGB(0x00, 0x41, 0x10), RGB(0x00, 0x41, 0x20), RGB(0x00, 0x41, 0x31),
80 RGB(0x00, 0x41, 0x41), RGB(0x00, 0x31, 0x41), RGB(0x00, 0x20, 0x41), RGB(0x00, 0x10, 0x41),
81 RGB(0x20, 0x20, 0x41), RGB(0x28, 0x20, 0x41), RGB(0x31, 0x20, 0x41), RGB(0x39, 0x20, 0x41),
82 RGB(0x41, 0x20, 0x41), RGB(0x41, 0x20, 0x39), RGB(0x41, 0x20, 0x31), RGB(0x41, 0x20, 0x28),
83 RGB(0x41, 0x20, 0x20), RGB(0x41, 0x28, 0x20), RGB(0x41, 0x31, 0x20), RGB(0x41, 0x39, 0x20),
84 RGB(0x41, 0x41, 0x20), RGB(0x39, 0x41, 0x20), RGB(0x31, 0x41, 0x20), RGB(0x28, 0x41, 0x20),
85 RGB(0x20, 0x41, 0x20), RGB(0x20, 0x41, 0x28), RGB(0x20, 0x41, 0x31), RGB(0x20, 0x41, 0x39),
86 RGB(0x20, 0x41, 0x41), RGB(0x20, 0x39, 0x41), RGB(0x20, 0x31, 0x41), RGB(0x20, 0x28, 0x41),
87 RGB(0x2D, 0x2D, 0x41), RGB(0x31, 0x2D, 0x41), RGB(0x35, 0x2D, 0x41), RGB(0x3D, 0x2D, 0x41),
88 RGB(0x41, 0x2D, 0x41), RGB(0x41, 0x2D, 0x3D), RGB(0x41, 0x2D, 0x35), RGB(0x41, 0x2D, 0x31),
89 RGB(0x41, 0x2D, 0x2D), RGB(0x41, 0x31, 0x2D), RGB(0x41, 0x35, 0x2D), RGB(0x41, 0x3D, 0x2D),
90 RGB(0x41, 0x41, 0x2D), RGB(0x3D, 0x41, 0x2D), RGB(0x35, 0x41, 0x2D), RGB(0x31, 0x41, 0x2D),
91 RGB(0x2D, 0x41, 0x2D), RGB(0x2D, 0x41, 0x31), RGB(0x2D, 0x41, 0x35), RGB(0x2D, 0x41, 0x3D),
92 RGB(0x2D, 0x41, 0x41), RGB(0x2D, 0x3D, 0x41), RGB(0x2D, 0x35, 0x41), RGB(0x2D, 0x31, 0x41),
93 RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00),
94 RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00)
97 #elif defined(USE_DOSBOX_COLORS)
100 static CONST COLORREF VgaDefaultPalette
[VGA_MAX_COLORS
] =
102 RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0xAA), RGB(0x00, 0xAA, 0x00), RGB(0x00, 0xAA, 0xAA),
103 RGB(0xAA, 0x00, 0x00), RGB(0xAA, 0x00, 0xAA), RGB(0xAA, 0x55, 0x00), RGB(0xAA, 0xAA, 0xAA),
104 RGB(0x55, 0x55, 0x55), RGB(0x55, 0x55, 0xFF), RGB(0x55, 0xFF, 0x55), RGB(0x55, 0xFF, 0xFF),
105 RGB(0xFF, 0x55, 0x55), RGB(0xFF, 0x55, 0xFF), RGB(0xFF, 0xFF, 0x55), RGB(0xFF, 0xFF, 0xFF),
106 RGB(0x00, 0x00, 0x00), RGB(0x14, 0x14, 0x14), RGB(0x20, 0x20, 0x20), RGB(0x2C, 0x2C, 0x2C),
107 RGB(0x38, 0x38, 0x38), RGB(0x45, 0x45, 0x45), RGB(0x51, 0x51, 0x51), RGB(0x61, 0x61, 0x61),
108 RGB(0x71, 0x71, 0x71), RGB(0x82, 0x82, 0x82), RGB(0x92, 0x92, 0x92), RGB(0xA2, 0xA2, 0xA2),
109 RGB(0xB6, 0xB6, 0xB6), RGB(0xCB, 0xCB, 0xCB), RGB(0xE3, 0xE3, 0xE3), RGB(0xFF, 0xFF, 0xFF),
110 RGB(0x00, 0x00, 0xFF), RGB(0x41, 0x00, 0xFF), RGB(0x7D, 0x00, 0xFF), RGB(0xBE, 0x00, 0xFF),
111 RGB(0xFF, 0x00, 0xFF), RGB(0xFF, 0x00, 0xBE), RGB(0xFF, 0x00, 0x7D), RGB(0xFF, 0x00, 0x41),
112 RGB(0xFF, 0x00, 0x00), RGB(0xFF, 0x41, 0x00), RGB(0xFF, 0x7D, 0x00), RGB(0xFF, 0xBE, 0x00),
113 RGB(0xFF, 0xFF, 0x00), RGB(0xBE, 0xFF, 0x00), RGB(0x7D, 0xFF, 0x00), RGB(0x41, 0xFF, 0x00),
114 RGB(0x00, 0xFF, 0x00), RGB(0x00, 0xFF, 0x41), RGB(0x00, 0xFF, 0x7D), RGB(0x00, 0xFF, 0xBE),
115 RGB(0x00, 0xFF, 0xFF), RGB(0x00, 0xBE, 0xFF), RGB(0x00, 0x7D, 0xFF), RGB(0x00, 0x41, 0xFF),
116 RGB(0x7D, 0x7D, 0xFF), RGB(0x9E, 0x7D, 0xFF), RGB(0xBE, 0x7D, 0xFF), RGB(0xDF, 0x7D, 0xFF),
117 RGB(0xFF, 0x7D, 0xFF), RGB(0xFF, 0x7D, 0xDF), RGB(0xFF, 0x7D, 0xBE), RGB(0xFF, 0x7D, 0x9E),
119 RGB(0xFF, 0x7D, 0x7D), RGB(0xFF, 0x9E, 0x7D), RGB(0xFF, 0xBE, 0x7D), RGB(0xFF, 0xDF, 0x7D),
120 RGB(0xFF, 0xFF, 0x7D), RGB(0xDF, 0xFF, 0x7D), RGB(0xBE, 0xFF, 0x7D), RGB(0x9E, 0xFF, 0x7D),
121 RGB(0x7D, 0xFF, 0x7D), RGB(0x7D, 0xFF, 0x9E), RGB(0x7D, 0xFF, 0xBE), RGB(0x7D, 0xFF, 0xDF),
122 RGB(0x7D, 0xFF, 0xFF), RGB(0x7D, 0xDF, 0xFF), RGB(0x7D, 0xBE, 0xFF), RGB(0x7D, 0x9E, 0xFF),
123 RGB(0xB6, 0xB6, 0xFF), RGB(0xC7, 0xB6, 0xFF), RGB(0xDB, 0xB6, 0xFF), RGB(0xEB, 0xB6, 0xFF),
124 RGB(0xFF, 0xB6, 0xFF), RGB(0xFF, 0xB6, 0xEB), RGB(0xFF, 0xB6, 0xDB), RGB(0xFF, 0xB6, 0xC7),
125 RGB(0xFF, 0xB6, 0xB6), RGB(0xFF, 0xC7, 0xB6), RGB(0xFF, 0xDB, 0xB6), RGB(0xFF, 0xEB, 0xB6),
126 RGB(0xFF, 0xFF, 0xB6), RGB(0xEB, 0xFF, 0xB6), RGB(0xDB, 0xFF, 0xB6), RGB(0xC7, 0xFF, 0xB6),
127 RGB(0xB6, 0xFF, 0xB6), RGB(0xB6, 0xFF, 0xC7), RGB(0xB6, 0xFF, 0xDB), RGB(0xB6, 0xFF, 0xEB),
128 RGB(0xB6, 0xFF, 0xFF), RGB(0xB6, 0xEB, 0xFF), RGB(0xB6, 0xDB, 0xFF), RGB(0xB6, 0xC7, 0xFF),
129 RGB(0x00, 0x00, 0x71), RGB(0x1C, 0x00, 0x71), RGB(0x38, 0x00, 0x71), RGB(0x55, 0x00, 0x71),
130 RGB(0x71, 0x00, 0x71), RGB(0x71, 0x00, 0x55), RGB(0x71, 0x00, 0x38), RGB(0x71, 0x00, 0x1C),
131 RGB(0x71, 0x00, 0x00), RGB(0x71, 0x1C, 0x00), RGB(0x71, 0x38, 0x00), RGB(0x71, 0x55, 0x00),
132 RGB(0x71, 0x71, 0x00), RGB(0x55, 0x71, 0x00), RGB(0x38, 0x71, 0x00), RGB(0x1C, 0x71, 0x00),
133 RGB(0x00, 0x71, 0x00), RGB(0x00, 0x71, 0x1C), RGB(0x00, 0x71, 0x38), RGB(0x00, 0x71, 0x55),
134 RGB(0x00, 0x71, 0x71), RGB(0x00, 0x55, 0x71), RGB(0x00, 0x38, 0x71), RGB(0x00, 0x1C, 0x71),
136 RGB(0x38, 0x38, 0x71), RGB(0x45, 0x38, 0x71), RGB(0x55, 0x38, 0x71), RGB(0x61, 0x38, 0x71),
137 RGB(0x71, 0x38, 0x71), RGB(0x71, 0x38, 0x61), RGB(0x71, 0x38, 0x55), RGB(0x71, 0x38, 0x45),
138 RGB(0x71, 0x38, 0x38), RGB(0x71, 0x45, 0x38), RGB(0x71, 0x55, 0x38), RGB(0x71, 0x61, 0x38),
139 RGB(0x71, 0x71, 0x38), RGB(0x61, 0x71, 0x38), RGB(0x55, 0x71, 0x38), RGB(0x45, 0x71, 0x38),
140 RGB(0x38, 0x71, 0x38), RGB(0x38, 0x71, 0x45), RGB(0x38, 0x71, 0x55), RGB(0x38, 0x71, 0x61),
141 RGB(0x38, 0x71, 0x71), RGB(0x38, 0x61, 0x71), RGB(0x38, 0x55, 0x71), RGB(0x38, 0x45, 0x71),
142 RGB(0x51, 0x51, 0x71), RGB(0x59, 0x51, 0x71), RGB(0x61, 0x51, 0x71), RGB(0x69, 0x51, 0x71),
143 RGB(0x71, 0x51, 0x71), RGB(0x71, 0x51, 0x69), RGB(0x71, 0x51, 0x61), RGB(0x71, 0x51, 0x59),
144 RGB(0x71, 0x51, 0x51), RGB(0x71, 0x59, 0x51), RGB(0x71, 0x61, 0x51), RGB(0x71, 0x69, 0x51),
145 RGB(0x71, 0x71, 0x51), RGB(0x69, 0x71, 0x51), RGB(0x61, 0x71, 0x51), RGB(0x59, 0x71, 0x51),
146 RGB(0x51, 0x71, 0x51), RGB(0x51, 0x71, 0x59), RGB(0x51, 0x71, 0x61), RGB(0x51, 0x71, 0x69),
147 RGB(0x51, 0x71, 0x71), RGB(0x51, 0x69, 0x71), RGB(0x51, 0x61, 0x71), RGB(0x51, 0x59, 0x71),
148 RGB(0x00, 0x00, 0x41), RGB(0x10, 0x00, 0x41), RGB(0x20, 0x00, 0x41), RGB(0x30, 0x00, 0x41),
149 RGB(0x41, 0x00, 0x41), RGB(0x41, 0x00, 0x30), RGB(0x41, 0x00, 0x20), RGB(0x41, 0x00, 0x10),
150 RGB(0x41, 0x00, 0x00), RGB(0x41, 0x10, 0x00), RGB(0x41, 0x20, 0x00), RGB(0x41, 0x30, 0x00),
151 RGB(0x41, 0x41, 0x00), RGB(0x30, 0x41, 0x00), RGB(0x20, 0x41, 0x00), RGB(0x10, 0x41, 0x00),
153 RGB(0x00, 0x41, 0x00), RGB(0x00, 0x41, 0x10), RGB(0x00, 0x41, 0x20), RGB(0x00, 0x41, 0x30),
154 RGB(0x00, 0x41, 0x41), RGB(0x00, 0x30, 0x41), RGB(0x00, 0x20, 0x41), RGB(0x00, 0x10, 0x41),
155 RGB(0x20, 0x20, 0x41), RGB(0x28, 0x20, 0x41), RGB(0x30, 0x20, 0x41), RGB(0x38, 0x20, 0x41),
156 RGB(0x41, 0x20, 0x41), RGB(0x41, 0x20, 0x38), RGB(0x41, 0x20, 0x30), RGB(0x41, 0x20, 0x28),
157 RGB(0x41, 0x20, 0x20), RGB(0x41, 0x28, 0x20), RGB(0x41, 0x30, 0x20), RGB(0x41, 0x38, 0x20),
158 RGB(0x41, 0x41, 0x20), RGB(0x38, 0x41, 0x20), RGB(0x30, 0x41, 0x20), RGB(0x28, 0x41, 0x20),
159 RGB(0x20, 0x41, 0x20), RGB(0x20, 0x41, 0x28), RGB(0x20, 0x41, 0x30), RGB(0x20, 0x41, 0x38),
160 RGB(0x20, 0x41, 0x41), RGB(0x20, 0x38, 0x41), RGB(0x20, 0x30, 0x41), RGB(0x20, 0x28, 0x41),
161 RGB(0x2C, 0x2C, 0x41), RGB(0x30, 0x2C, 0x41), RGB(0x34, 0x2C, 0x41), RGB(0x3C, 0x2C, 0x41),
162 RGB(0x41, 0x2C, 0x41), RGB(0x41, 0x2C, 0x3C), RGB(0x41, 0x2C, 0x34), RGB(0x41, 0x2C, 0x30),
163 RGB(0x41, 0x2C, 0x2C), RGB(0x41, 0x30, 0x2C), RGB(0x41, 0x34, 0x2C), RGB(0x41, 0x3C, 0x2C),
164 RGB(0x41, 0x41, 0x2C), RGB(0x3C, 0x41, 0x2C), RGB(0x34, 0x41, 0x2C), RGB(0x30, 0x41, 0x2C),
165 RGB(0x2C, 0x41, 0x2C), RGB(0x2C, 0x41, 0x30), RGB(0x2C, 0x41, 0x34), RGB(0x2C, 0x41, 0x3C),
166 RGB(0x2C, 0x41, 0x41), RGB(0x2C, 0x3C, 0x41), RGB(0x2C, 0x34, 0x41), RGB(0x2C, 0x30, 0x41),
167 RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00),
168 RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00)
174 * Console interface -- VGA-mode-agnostic
176 typedef struct _CHAR_CELL
180 } CHAR_CELL
, *PCHAR_CELL
;
181 C_ASSERT(sizeof(CHAR_CELL
) == 2);
183 static LPVOID ConsoleFramebuffer
= NULL
; // Active framebuffer, points to
184 // either TextFramebuffer or a valid
185 // graphics framebuffer.
186 static HPALETTE PaletteHandle
= NULL
;
188 static HANDLE StartEvent
= NULL
;
189 static HANDLE EndEvent
= NULL
;
190 static HANDLE AnotherEvent
= NULL
;
193 * Text mode -- we always keep a valid text mode framebuffer
194 * even if we are in graphics mode. This is needed in order to
195 * keep a consistent VGA state.
197 static CONSOLE_SCREEN_BUFFER_INFO ConsoleInfo
;
198 static COORD TextResolution
= {0};
199 static PCHAR_CELL TextFramebuffer
= NULL
;
200 static HANDLE TextConsoleBuffer
= NULL
;
203 static HANDLE GraphicsConsoleBuffer
= NULL
;
204 static HANDLE ConsoleMutex
= NULL
;
205 static BOOLEAN DoubleVision
= FALSE
;
210 static BYTE VgaMemory
[VGA_NUM_BANKS
* VGA_BANK_SIZE
];
212 static BYTE VgaLatchRegisters
[VGA_NUM_BANKS
] = {0, 0, 0, 0};
214 static BYTE VgaMiscRegister
;
215 static BYTE VgaFeatureRegister
;
217 static BYTE VgaSeqIndex
= VGA_SEQ_RESET_REG
;
218 static BYTE VgaSeqRegisters
[VGA_SEQ_MAX_REG
];
220 static BYTE VgaCrtcIndex
= VGA_CRTC_HORZ_TOTAL_REG
;
221 static BYTE VgaCrtcRegisters
[VGA_CRTC_MAX_REG
];
223 static BYTE VgaGcIndex
= VGA_GC_RESET_REG
;
224 static BYTE VgaGcRegisters
[VGA_GC_MAX_REG
];
226 static BOOLEAN VgaAcLatch
= FALSE
;
227 static BOOLEAN VgaAcPalDisable
= TRUE
;
228 static BYTE VgaAcIndex
= VGA_AC_PAL_0_REG
;
229 static BYTE VgaAcRegisters
[VGA_AC_MAX_REG
];
231 // static VGA_REGISTERS VgaRegisters;
233 static BYTE VgaDacMask
= 0xFF;
234 static WORD VgaDacIndex
= 0;
235 static BOOLEAN VgaDacReadWrite
= FALSE
;
236 static BYTE VgaDacRegisters
[VGA_PALETTE_SIZE
];
238 static BOOLEAN InVerticalRetrace
= FALSE
;
239 static BOOLEAN InHorizontalRetrace
= FALSE
;
241 static BOOLEAN NeedsUpdate
= FALSE
;
242 static BOOLEAN ModeChanged
= FALSE
;
243 static BOOLEAN CursorMoved
= FALSE
;
244 static BOOLEAN PaletteChanged
= FALSE
;
251 } ScreenMode
= TEXT_MODE
;
253 static SMALL_RECT UpdateRectangle
= { 0, 0, 0, 0 };
255 /* RegisterConsoleVDM EMULATION ***********************************************/
257 #include <ntddvdeo.h>
261 (WINAPI
*pRegisterConsoleVDM
)
264 HANDLE EventHandle_1
,
265 HANDLE EventHandle_2
,
266 HANDLE EventHandle_3
,
268 PVOID returned_val_1
,
269 PVOID
*returned_val_2
,
270 PVOID lpUnknownBuffer
,
271 DWORD theUnknownBufferLength
,
272 COORD theVDMBufferSize
,
282 HANDLE EventHandle_1
,
283 HANDLE EventHandle_2
,
284 HANDLE EventHandle_3
,
286 PVOID returned_val_1
,
287 PVOID
*returned_val_2
,
288 PVOID lpUnknownBuffer
,
289 DWORD theUnknownBufferLength
,
290 COORD theVDMBufferSize
,
294 HMODULE hKernel32
= NULL
;
295 pRegisterConsoleVDM RegisterConsoleVDM
= NULL
;
299 * This private buffer, per-console, is used by
300 * RegisterConsoleVDM and InvalidateConsoleDIBits.
302 static COORD VDMBufferSize
= {0};
303 static PCHAR_CELL VDMBuffer
= NULL
;
305 static PCHAR_INFO CharBuff
= NULL
; // This is a hack, which is unneeded
306 // for the real RegisterConsoleVDM and
307 // InvalidateConsoleDIBits
311 __RegisterConsoleVDM(BOOL IsDosVDM_flag
,
312 HANDLE EventHandle_1
,
313 HANDLE EventHandle_2
,
314 HANDLE EventHandle_3
,
316 PVOID returned_val_1
,
317 PVOID
*returned_val_2
,
318 PVOID lpUnknownBuffer
,
319 DWORD theUnknownBufferLength
,
320 COORD theVDMBufferSize
,
323 UNREFERENCED_PARAMETER(EventHandle_3
);
324 UNREFERENCED_PARAMETER(Unused1
);
325 UNREFERENCED_PARAMETER(returned_val_1
);
326 UNREFERENCED_PARAMETER(returned_val_2
);
327 UNREFERENCED_PARAMETER(lpUnknownBuffer
);
328 UNREFERENCED_PARAMETER(theUnknownBufferLength
);
331 DPRINT1("__RegisterConsoleVDM(%d)\n", IsDosVDM_flag
);
333 if (lpVDMBuffer
== NULL
) return FALSE
;
337 // if (EventHandle_1 == NULL || EventHandle_2 == NULL) return FALSE;
338 if (VDMBuffer
!= NULL
) return FALSE
;
340 VDMBufferSize
= theVDMBufferSize
;
342 /* HACK: Cache -- to be removed in the real implementation */
343 CharBuff
= HeapAlloc(GetProcessHeap(),
345 theVDMBufferSize
.X
* theVDMBufferSize
.Y
346 * sizeof(CHAR_INFO
));
349 VDMBuffer
= HeapAlloc(GetProcessHeap(),
351 theVDMBufferSize
.X
* theVDMBufferSize
.Y
352 * sizeof(CHAR_CELL
));
353 *lpVDMBuffer
= (PCHAR
)VDMBuffer
;
354 return (VDMBuffer
!= NULL
);
358 /* HACK: Cache -- to be removed in the real implementation */
359 if (CharBuff
) HeapFree(GetProcessHeap(), 0, CharBuff
);
362 if (VDMBuffer
) HeapFree(GetProcessHeap(), 0, VDMBuffer
);
365 VDMBufferSize
.X
= VDMBufferSize
.Y
= 0;
372 __InvalidateConsoleDIBits(IN HANDLE hConsoleOutput
,
373 IN PSMALL_RECT lpRect
)
375 if ((hConsoleOutput
== TextConsoleBuffer
) && (VDMBuffer
!= NULL
))
377 /* HACK: Write the cached data to the console */
379 COORD Origin
= { lpRect
->Left
, lpRect
->Top
};
384 for (i
= 0; i
< VDMBufferSize
.Y
; i
++)
386 for (j
= 0; j
< VDMBufferSize
.X
; j
++)
388 CharBuff
[i
* VDMBufferSize
.X
+ j
].Char
.AsciiChar
= VDMBuffer
[i
* VDMBufferSize
.X
+ j
].Char
;
389 CharBuff
[i
* VDMBufferSize
.X
+ j
].Attributes
= VDMBuffer
[i
* VDMBufferSize
.X
+ j
].Attributes
;
393 WriteConsoleOutputA(hConsoleOutput
,
400 return InvalidateConsoleDIBits(hConsoleOutput
, lpRect
);
403 /* PRIVATE FUNCTIONS **********************************************************/
405 static BOOL
VgaAttachToConsole(PCOORD Resolution
)
407 BOOL Success
= FALSE
;
409 PVIDEO_HARDWARE_STATE_HEADER State
;
411 ASSERT(TextFramebuffer
== NULL
);
413 // ResetEvent(AnotherEvent);
415 TextResolution
= *Resolution
;
418 * Windows 2k3 winsrv.dll calls NtVdmControl(VdmQueryVdmProcess == 14, &ConsoleHandle);
419 * in the two following APIs:
420 * SrvRegisterConsoleVDM (corresponding win32 API: RegisterConsoleVDM)
421 * SrvVDMConsoleOperation (corresponding Win32 API: )
422 * to check whether the current process is a VDM process, and fails otherwise with the
423 * error 0xC0000022 ().
425 * It is worth it to notice that also basesrv.dll does the same only for the
426 * BaseSrvIsFirstVDM API...
430 __RegisterConsoleVDM(1,
433 AnotherEvent
, // NULL,
435 &Length
, // NULL, <-- putting this (and null in the next var) makes the API returning error 12 "ERROR_INVALID_ACCESS"
436 (PVOID
*)&State
, // NULL,
440 (PCHAR
*)&TextFramebuffer
);
443 DisplayMessage(L
"RegisterConsoleVDM failed with error %d\n", GetLastError());
450 static VOID
VgaDetachFromConsole(VOID
)
454 COORD dummySize
= {0};
456 __RegisterConsoleVDM(0,
468 TextFramebuffer
= NULL
;
471 static BOOL
IsConsoleHandle(HANDLE hHandle
)
475 /* Check whether the handle may be that of a console... */
476 if ((GetFileType(hHandle
) & ~FILE_TYPE_REMOTE
) != FILE_TYPE_CHAR
)
480 * It may be. Perform another test... The idea comes from the
481 * MSDN description of the WriteConsole API:
483 * "WriteConsole fails if it is used with a standard handle
484 * that is redirected to a file. If an application processes
485 * multilingual output that can be redirected, determine whether
486 * the output handle is a console handle (one method is to call
487 * the GetConsoleMode function and check whether it succeeds).
488 * If the handle is a console handle, call WriteConsole. If the
489 * handle is not a console handle, the output is redirected and
490 * you should call WriteFile to perform the I/O."
492 return GetConsoleMode(hHandle
, &dwMode
);
495 static inline DWORD
VgaGetAddressSize(VOID
)
497 if (VgaCrtcRegisters
[VGA_CRTC_UNDERLINE_REG
] & VGA_CRTC_UNDERLINE_DWORD
)
499 /* Double-word addressing */
500 return 4; // sizeof(DWORD)
502 else if (VgaCrtcRegisters
[VGA_CRTC_MODE_CONTROL_REG
] & VGA_CRTC_MODE_CONTROL_BYTE
)
504 /* Byte addressing */
505 return 1; // sizeof(BYTE)
509 /* Word addressing */
510 return 2; // sizeof(WORD)
514 static inline DWORD
VgaTranslateReadAddress(DWORD Address
)
516 DWORD Offset
= Address
- VgaGetVideoBaseAddress();
519 /* Check for chain-4 and odd-even mode */
520 if (VgaSeqRegisters
[VGA_SEQ_MEM_REG
] & VGA_SEQ_MEM_C4
)
522 /* The lowest two bits are the plane number */
526 else if (VgaGcRegisters
[VGA_GC_MODE_REG
] & VGA_GC_MODE_OE
)
528 /* The LSB is the plane number */
534 /* Use the read mode */
535 Plane
= VgaGcRegisters
[VGA_GC_READ_MAP_SEL_REG
] & 0x03;
538 /* Multiply the offset by the address size */
539 Offset
*= VgaGetAddressSize();
541 return Offset
+ Plane
* VGA_BANK_SIZE
;
544 static inline DWORD
VgaTranslateWriteAddress(DWORD Address
)
546 DWORD Offset
= Address
- VgaGetVideoBaseAddress();
548 /* Check for chain-4 and odd-even mode */
549 if (VgaSeqRegisters
[VGA_SEQ_MEM_REG
] & VGA_SEQ_MEM_C4
)
551 /* Shift the offset to the right by 2 */
554 else if (VgaGcRegisters
[VGA_GC_MODE_REG
] & VGA_GC_MODE_OE
)
556 /* Shift the offset to the right by 1 */
560 /* Multiply the offset by the address size */
561 Offset
*= VgaGetAddressSize();
563 /* Return the offset on plane 0 */
567 static inline BYTE
VgaTranslateByteForWriting(BYTE Data
, BYTE Plane
)
569 BYTE WriteMode
= VgaGcRegisters
[VGA_GC_MODE_REG
] & 3;
570 BYTE BitMask
= VgaGcRegisters
[VGA_GC_BITMASK_REG
];
574 /* In write mode 1 just return the latch register */
575 return VgaLatchRegisters
[Plane
];
580 /* Write modes 0 and 3 rotate the data to the right first */
581 BYTE RotateCount
= VgaGcRegisters
[VGA_GC_ROTATE_REG
] & 7;
582 Data
= LOBYTE(((DWORD
)Data
>> RotateCount
) | ((DWORD
)Data
<< (8 - RotateCount
)));
586 /* Write mode 2 expands the appropriate bit to all 8 bits */
587 Data
= (Data
& (1 << Plane
)) ? 0xFF : 0x00;
593 * In write mode 0, the enable set/reset register decides if the
594 * set/reset bit should be expanded to all 8 bits.
596 if (VgaGcRegisters
[VGA_GC_ENABLE_RESET_REG
] & (1 << Plane
))
598 /* Copy the bit from the set/reset register to all 8 bits */
599 Data
= (VgaGcRegisters
[VGA_GC_RESET_REG
] & (1 << Plane
)) ? 0xFF : 0x00;
605 /* Write modes 0 and 2 then perform a logical operation on the data and latch */
606 BYTE LogicalOperation
= (VgaGcRegisters
[VGA_GC_ROTATE_REG
] >> 3) & 3;
608 if (LogicalOperation
== 1) Data
&= VgaLatchRegisters
[Plane
];
609 else if (LogicalOperation
== 2) Data
|= VgaLatchRegisters
[Plane
];
610 else if (LogicalOperation
== 3) Data
^= VgaLatchRegisters
[Plane
];
614 /* For write mode 3, we AND the bitmask with the data, which is used as the new bitmask */
617 /* Then we expand the bit in the set/reset field */
618 Data
= (VgaGcRegisters
[VGA_GC_RESET_REG
] & (1 << Plane
)) ? 0xFF : 0x00;
621 /* Bits cleared in the bitmask are replaced with latch register bits */
622 Data
= (Data
& BitMask
) | (VgaLatchRegisters
[Plane
] & (~BitMask
));
624 /* Return the byte */
628 static inline VOID
VgaMarkForUpdate(SHORT Row
, SHORT Column
)
630 /* Check if this is the first time the rectangle is updated */
633 UpdateRectangle
.Left
= UpdateRectangle
.Top
= MAXSHORT
;
634 UpdateRectangle
.Right
= UpdateRectangle
.Bottom
= MINSHORT
;
637 /* Expand the rectangle to include the point */
638 UpdateRectangle
.Left
= min(UpdateRectangle
.Left
, Column
);
639 UpdateRectangle
.Right
= max(UpdateRectangle
.Right
, Column
);
640 UpdateRectangle
.Top
= min(UpdateRectangle
.Top
, Row
);
641 UpdateRectangle
.Bottom
= max(UpdateRectangle
.Bottom
, Row
);
643 /* Set the update request flag */
647 static VOID
VgaWriteSequencer(BYTE Data
)
649 ASSERT(VgaSeqIndex
< VGA_SEQ_MAX_REG
);
652 VgaSeqRegisters
[VgaSeqIndex
] = Data
;
655 static VOID
VgaWriteGc(BYTE Data
)
657 ASSERT(VgaGcIndex
< VGA_GC_MAX_REG
);
660 VgaGcRegisters
[VgaGcIndex
] = Data
;
662 /* Check the index */
665 case VGA_GC_MISC_REG
:
667 /* The GC misc register decides if it's text or graphics mode */
674 static VOID
VgaWriteCrtc(BYTE Data
)
676 ASSERT(VgaGcIndex
< VGA_CRTC_MAX_REG
);
679 VgaCrtcRegisters
[VgaCrtcIndex
] = Data
;
681 /* Check the index */
682 switch (VgaCrtcIndex
)
684 case VGA_CRTC_END_HORZ_DISP_REG
:
685 case VGA_CRTC_VERT_DISP_END_REG
:
686 case VGA_CRTC_OVERFLOW_REG
:
688 /* The video mode has changed */
693 case VGA_CRTC_CURSOR_LOC_LOW_REG
:
694 case VGA_CRTC_CURSOR_LOC_HIGH_REG
:
695 case VGA_CRTC_CURSOR_START_REG
:
696 case VGA_CRTC_CURSOR_END_REG
:
698 /* Set the cursor moved flag */
705 static VOID
VgaWriteDac(BYTE Data
)
711 VgaDacRegisters
[VgaDacIndex
] = Data
;
713 /* Find the palette index */
714 PaletteIndex
= VgaDacIndex
/ 3;
716 /* Fill the entry structure */
717 Entry
.peRed
= VGA_DAC_TO_COLOR(VgaDacRegisters
[PaletteIndex
* 3]);
718 Entry
.peGreen
= VGA_DAC_TO_COLOR(VgaDacRegisters
[PaletteIndex
* 3 + 1]);
719 Entry
.peBlue
= VGA_DAC_TO_COLOR(VgaDacRegisters
[PaletteIndex
* 3 + 2]);
722 /* Update the palette entry and set the palette change flag */
723 SetPaletteEntries(PaletteHandle
, PaletteIndex
, 1, &Entry
);
724 PaletteChanged
= TRUE
;
726 /* Update the index */
728 VgaDacIndex
%= VGA_PALETTE_SIZE
;
731 static VOID
VgaWriteAc(BYTE Data
)
733 ASSERT(VgaAcIndex
< VGA_AC_MAX_REG
);
736 if (VgaAcIndex
<= VGA_AC_PAL_F_REG
)
738 if (VgaAcPalDisable
) return;
740 // DbgPrint(" AC Palette Writing %d to index %d\n", Data, VgaAcIndex);
741 if (VgaAcRegisters
[VgaAcIndex
] != Data
)
743 /* Update the AC register and set the palette change flag */
744 VgaAcRegisters
[VgaAcIndex
] = Data
;
745 PaletteChanged
= TRUE
;
750 VgaAcRegisters
[VgaAcIndex
] = Data
;
754 static VOID
VgaRestoreDefaultPalette(PPALETTEENTRY Entries
, USHORT NumOfEntries
)
758 /* Copy the colors of the default palette to the DAC and console palette */
759 for (i
= 0; i
< NumOfEntries
; i
++)
761 /* Set the palette entries */
762 Entries
[i
].peRed
= GetRValue(VgaDefaultPalette
[i
]);
763 Entries
[i
].peGreen
= GetGValue(VgaDefaultPalette
[i
]);
764 Entries
[i
].peBlue
= GetBValue(VgaDefaultPalette
[i
]);
765 Entries
[i
].peFlags
= 0;
767 /* Set the DAC registers */
768 VgaDacRegisters
[i
* 3] = VGA_COLOR_TO_DAC(GetRValue(VgaDefaultPalette
[i
]));
769 VgaDacRegisters
[i
* 3 + 1] = VGA_COLOR_TO_DAC(GetGValue(VgaDefaultPalette
[i
]));
770 VgaDacRegisters
[i
* 3 + 2] = VGA_COLOR_TO_DAC(GetBValue(VgaDefaultPalette
[i
]));
774 static BOOLEAN
VgaInitializePalette(VOID
)
776 LPLOGPALETTE Palette
;
778 /* Allocate storage space for the palette */
779 Palette
= (LPLOGPALETTE
)HeapAlloc(GetProcessHeap(),
782 VGA_MAX_COLORS
* sizeof(PALETTEENTRY
));
783 if (Palette
== NULL
) return FALSE
;
785 /* Initialize the palette */
786 Palette
->palVersion
= 0x0300;
787 Palette
->palNumEntries
= VGA_MAX_COLORS
;
789 /* Restore the default palette */
790 VgaRestoreDefaultPalette(Palette
->palPalEntry
, Palette
->palNumEntries
);
792 /* Create the palette */
793 PaletteHandle
= CreatePalette(Palette
);
795 /* Free the palette */
796 HeapFree(GetProcessHeap(), 0, Palette
);
798 /* Fail if the palette wasn't successfully created... */
799 if (PaletteHandle
== NULL
) return FALSE
;
801 /* ... otherwise return success */
805 static BOOL
VgaEnterGraphicsMode(PCOORD Resolution
)
808 CONSOLE_GRAPHICS_BUFFER_INFO GraphicsBufferInfo
;
809 BYTE BitmapInfoBuffer
[VGA_BITMAP_INFO_SIZE
];
810 LPBITMAPINFO BitmapInfo
= (LPBITMAPINFO
)BitmapInfoBuffer
;
811 LPWORD PaletteIndex
= (LPWORD
)(BitmapInfo
->bmiColors
);
813 LONG Width
= Resolution
->X
;
814 LONG Height
= Resolution
->Y
;
816 /* Use DoubleVision mode if the resolution is too small */
817 if (Width
< VGA_MINIMUM_WIDTH
&& Height
< VGA_MINIMUM_HEIGHT
)
825 DoubleVision
= FALSE
;
828 /* Fill the bitmap info header */
829 ZeroMemory(&BitmapInfo
->bmiHeader
, sizeof(BITMAPINFOHEADER
));
830 BitmapInfo
->bmiHeader
.biSize
= sizeof(BITMAPINFOHEADER
);
831 BitmapInfo
->bmiHeader
.biWidth
= Width
;
832 BitmapInfo
->bmiHeader
.biHeight
= Height
;
833 BitmapInfo
->bmiHeader
.biBitCount
= 8;
834 BitmapInfo
->bmiHeader
.biPlanes
= 1;
835 BitmapInfo
->bmiHeader
.biCompression
= BI_RGB
;
836 BitmapInfo
->bmiHeader
.biSizeImage
= Width
* Height
/* * 1 == biBitCount / 8 */;
838 /* Fill the palette data */
839 for (i
= 0; i
< (VGA_PALETTE_SIZE
/ 3); i
++) PaletteIndex
[i
] = (WORD
)i
;
841 /* Fill the console graphics buffer info */
842 GraphicsBufferInfo
.dwBitMapInfoLength
= VGA_BITMAP_INFO_SIZE
;
843 GraphicsBufferInfo
.lpBitMapInfo
= BitmapInfo
;
844 GraphicsBufferInfo
.dwUsage
= DIB_PAL_COLORS
;
846 /* Create the buffer */
847 GraphicsConsoleBuffer
= CreateConsoleScreenBuffer(GENERIC_READ
| GENERIC_WRITE
,
848 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
850 CONSOLE_GRAPHICS_BUFFER
,
851 &GraphicsBufferInfo
);
852 if (GraphicsConsoleBuffer
== INVALID_HANDLE_VALUE
) return FALSE
;
854 /* Save the framebuffer address and mutex */
855 ConsoleFramebuffer
= GraphicsBufferInfo
.lpBitMap
;
856 ConsoleMutex
= GraphicsBufferInfo
.hMutex
;
858 /* Clear the framebuffer */
859 ZeroMemory(ConsoleFramebuffer
, BitmapInfo
->bmiHeader
.biSizeImage
);
861 /* Set the active buffer */
862 SetConsoleActiveScreenBuffer(GraphicsConsoleBuffer
);
864 /* Set the graphics mode palette */
865 SetConsolePalette(GraphicsConsoleBuffer
,
869 /* Set the screen mode flag */
870 ScreenMode
= GRAPHICS_MODE
;
875 static VOID
VgaLeaveGraphicsMode(VOID
)
877 /* Release the console framebuffer mutex */
878 ReleaseMutex(ConsoleMutex
);
880 /* Switch back to the default console text buffer */
881 // SetConsoleActiveScreenBuffer(TextConsoleBuffer);
883 /* Cleanup the video data */
884 CloseHandle(ConsoleMutex
);
886 ConsoleFramebuffer
= NULL
;
887 CloseHandle(GraphicsConsoleBuffer
);
888 GraphicsConsoleBuffer
= NULL
;
889 DoubleVision
= FALSE
;
892 static BOOL
VgaEnterTextMode(PCOORD Resolution
)
896 /* Switch to the text buffer */
897 SetConsoleActiveScreenBuffer(TextConsoleBuffer
);
899 /* Resize the console */
900 ConRect
.Left
= 0; // ConsoleInfo.srWindow.Left;
901 ConRect
.Top
= ConsoleInfo
.srWindow
.Top
;
902 ConRect
.Right
= ConRect
.Left
+ Resolution
->X
- 1;
903 ConRect
.Bottom
= ConRect
.Top
+ Resolution
->Y
- 1;
905 * Use this trick to effectively resize the console buffer and window,
907 * - SetConsoleScreenBufferSize fails if the new console screen buffer size
908 * is smaller than the current console window size, and:
909 * - SetConsoleWindowInfo fails if the new console window size is larger
910 * than the current console screen buffer size.
912 SetConsoleScreenBufferSize(TextConsoleBuffer
, *Resolution
);
913 SetConsoleWindowInfo(TextConsoleBuffer
, TRUE
, &ConRect
);
914 SetConsoleScreenBufferSize(TextConsoleBuffer
, *Resolution
);
915 /* Update the saved console information */
916 GetConsoleScreenBufferInfo(TextConsoleBuffer
, &ConsoleInfo
);
918 /* Adjust the text framebuffer if we changed resolution */
919 if (TextResolution
.X
!= Resolution
->X
||
920 TextResolution
.Y
!= Resolution
->Y
)
922 VgaDetachFromConsole();
924 /* VgaAttachToConsole sets TextResolution to the new resolution */
925 if (!VgaAttachToConsole(Resolution
))
927 DisplayMessage(L
"An unexpected error occurred!\n");
933 /* The active framebuffer is now the text framebuffer */
934 ConsoleFramebuffer
= TextFramebuffer
;
937 * Set the text mode palette.
939 * WARNING: This call should fail on Windows (and therefore
940 * we get the default palette and our external behaviour is
941 * just like Windows' one), but it should success on ReactOS
942 * (so that we get console palette changes even for text-mode
943 * screen-buffers, which is a new feature on ReactOS).
945 SetConsolePalette(TextConsoleBuffer
,
949 /* Set the screen mode flag */
950 ScreenMode
= TEXT_MODE
;
955 static VOID
VgaLeaveTextMode(VOID
)
957 /* Reset the active framebuffer */
958 ConsoleFramebuffer
= NULL
;
961 static VOID
VgaChangeMode(VOID
)
963 COORD Resolution
= VgaGetDisplayResolution();
965 if (ScreenMode
== GRAPHICS_MODE
)
967 /* Leave the current graphics mode */
968 VgaLeaveGraphicsMode();
972 /* Leave the current text mode */
976 /* Check if the new mode is alphanumeric */
977 if (!(VgaGcRegisters
[VGA_GC_MISC_REG
] & VGA_GC_MISC_NOALPHA
))
979 /* Enter new text mode */
980 if (!VgaEnterTextMode(&Resolution
))
982 DisplayMessage(L
"An unexpected VGA error occurred while switching into text mode.");
989 /* Enter graphics mode */
990 if (!VgaEnterGraphicsMode(&Resolution
))
992 DisplayMessage(L
"An unexpected VGA error occurred while switching into graphics mode.");
998 /* Trigger a full update of the screen */
1000 UpdateRectangle
.Left
= 0;
1001 UpdateRectangle
.Top
= 0;
1002 UpdateRectangle
.Right
= Resolution
.X
;
1003 UpdateRectangle
.Bottom
= Resolution
.Y
;
1005 /* Reset the mode change flag */
1006 ModeChanged
= FALSE
;
1009 static VOID
VgaUpdateFramebuffer(VOID
)
1012 COORD Resolution
= VgaGetDisplayResolution();
1013 DWORD AddressSize
= VgaGetAddressSize();
1014 DWORD Address
= MAKEWORD(VgaCrtcRegisters
[VGA_CRTC_START_ADDR_LOW_REG
],
1015 VgaCrtcRegisters
[VGA_CRTC_START_ADDR_HIGH_REG
]);
1016 DWORD ScanlineSize
= (DWORD
)VgaCrtcRegisters
[VGA_CRTC_OFFSET_REG
] * 2;
1019 * If console framebuffer is NULL, that means something went wrong
1020 * earlier and this is the final display refresh.
1022 if (ConsoleFramebuffer
== NULL
) return;
1024 /* Check if this is text mode or graphics mode */
1025 if (VgaGcRegisters
[VGA_GC_MISC_REG
] & VGA_GC_MISC_NOALPHA
)
1028 PBYTE GraphicsBuffer
= (PBYTE
)ConsoleFramebuffer
;
1031 * Synchronize access to the graphics framebuffer
1032 * with the console framebuffer mutex.
1034 WaitForSingleObject(ConsoleMutex
, INFINITE
);
1036 /* Loop through the scanlines */
1037 for (i
= 0; i
< Resolution
.Y
; i
++)
1039 /* Loop through the pixels */
1040 for (j
= 0; j
< Resolution
.X
; j
++)
1044 /* Check the shifting mode */
1045 if (VgaGcRegisters
[VGA_GC_MODE_REG
] & VGA_GC_MODE_SHIFT256
)
1047 /* 4 bits shifted from each plane */
1049 /* Check if this is 16 or 256 color mode */
1050 if (VgaAcRegisters
[VGA_AC_CONTROL_REG
] & VGA_AC_CONTROL_8BIT
)
1052 /* One byte per pixel */
1053 PixelData
= VgaMemory
[(j
% VGA_NUM_BANKS
) * VGA_BANK_SIZE
1054 + (Address
+ (j
/ VGA_NUM_BANKS
))
1059 /* 4-bits per pixel */
1061 PixelData
= VgaMemory
[(j
% VGA_NUM_BANKS
) * VGA_BANK_SIZE
1062 + (Address
+ (j
/ (VGA_NUM_BANKS
* 2)))
1065 /* Check if we should use the highest 4 bits or lowest 4 */
1066 if (((j
/ VGA_NUM_BANKS
) % 2) == 0)
1078 else if (VgaGcRegisters
[VGA_GC_MODE_REG
] & VGA_GC_MODE_SHIFTREG
)
1080 /* Check if this is 16 or 256 color mode */
1081 if (VgaAcRegisters
[VGA_AC_CONTROL_REG
] & VGA_AC_CONTROL_8BIT
)
1083 // TODO: NOT IMPLEMENTED
1084 DPRINT1("8-bit interleaved mode is not implemented!\n");
1089 * 2 bits shifted from plane 0 and 2 for the first 4 pixels,
1090 * then 2 bits shifted from plane 1 and 3 for the next 4
1092 BYTE LowPlaneData
= VgaMemory
[((j
/ 4) % 2) * VGA_BANK_SIZE
1093 + (Address
+ (j
/ 8)) * AddressSize
];
1094 BYTE HighPlaneData
= VgaMemory
[(((j
/ 4) % 2) + 2) * VGA_BANK_SIZE
1095 + (Address
+ (j
/ 8)) * AddressSize
];
1097 /* Extract the two bits from each plane */
1098 LowPlaneData
= (LowPlaneData
>> (6 - ((j
% 4) * 2))) & 3;
1099 HighPlaneData
= (HighPlaneData
>> (6 - ((j
% 4) * 2))) & 3;
1101 /* Combine them into the pixel */
1102 PixelData
= LowPlaneData
| (HighPlaneData
<< 2);
1107 /* 1 bit shifted from each plane */
1109 /* Check if this is 16 or 256 color mode */
1110 if (VgaAcRegisters
[VGA_AC_CONTROL_REG
] & VGA_AC_CONTROL_8BIT
)
1112 /* 8 bits per pixel, 2 on each plane */
1114 for (k
= 0; k
< VGA_NUM_BANKS
; k
++)
1116 /* The data is on plane k, 4 pixels per byte */
1117 BYTE PlaneData
= VgaMemory
[k
* VGA_BANK_SIZE
1118 + (Address
+ (j
/ VGA_NUM_BANKS
))
1121 /* The mask of the first bit in the pair */
1122 BYTE BitMask
= 1 << (((3 - (j
% VGA_NUM_BANKS
)) * 2) + 1);
1124 /* Bits 0, 1, 2 and 3 come from the first bit of the pair */
1125 if (PlaneData
& BitMask
) PixelData
|= 1 << k
;
1127 /* Bits 4, 5, 6 and 7 come from the second bit of the pair */
1128 if (PlaneData
& (BitMask
>> 1)) PixelData
|= 1 << (k
+ 4);
1133 /* 4 bits per pixel, 1 on each plane */
1135 for (k
= 0; k
< VGA_NUM_BANKS
; k
++)
1137 BYTE PlaneData
= VgaMemory
[k
* VGA_BANK_SIZE
1138 + (Address
+ (j
/ (VGA_NUM_BANKS
* 2)))
1141 /* If the bit on that plane is set, set it */
1142 if (PlaneData
& (1 << (7 - (j
% 8)))) PixelData
|= 1 << k
;
1147 if (!(VgaAcRegisters
[VGA_AC_CONTROL_REG
] & VGA_AC_CONTROL_8BIT
))
1150 * In 16 color mode, the value is an index to the AC registers
1151 * if external palette access is disabled, otherwise (in case
1152 * of palette loading) it is a blank pixel.
1154 PixelData
= (VgaAcPalDisable
? VgaAcRegisters
[PixelData
& 0x0F]
1158 /* Take into account DoubleVision mode when checking for pixel updates */
1161 /* Now check if the resulting pixel data has changed */
1162 if (GraphicsBuffer
[(i
* Resolution
.X
* 4) + (j
* 2)] != PixelData
)
1164 /* Yes, write the new value */
1165 GraphicsBuffer
[(i
* Resolution
.X
* 4) + (j
* 2)] = PixelData
;
1166 GraphicsBuffer
[(i
* Resolution
.X
* 4) + (j
* 2 + 1)] = PixelData
;
1167 GraphicsBuffer
[((i
* 2 + 1) * Resolution
.X
* 2) + (j
* 2)] = PixelData
;
1168 GraphicsBuffer
[((i
* 2 + 1) * Resolution
.X
* 2) + (j
* 2 + 1)] = PixelData
;
1170 /* Mark the specified pixel as changed */
1171 VgaMarkForUpdate(i
, j
);
1176 /* Now check if the resulting pixel data has changed */
1177 if (GraphicsBuffer
[i
* Resolution
.X
+ j
] != PixelData
)
1179 /* Yes, write the new value */
1180 GraphicsBuffer
[i
* Resolution
.X
+ j
] = PixelData
;
1182 /* Mark the specified pixel as changed */
1183 VgaMarkForUpdate(i
, j
);
1188 /* Move to the next scanline */
1189 Address
+= ScanlineSize
;
1193 * Release the console framebuffer mutex
1194 * so that we allow for repainting.
1196 ReleaseMutex(ConsoleMutex
);
1202 PCHAR_CELL CharBuffer
= (PCHAR_CELL
)ConsoleFramebuffer
;
1205 /* Loop through the scanlines */
1206 for (i
= 0; i
< Resolution
.Y
; i
++)
1208 /* Loop through the characters */
1209 for (j
= 0; j
< Resolution
.X
; j
++)
1211 CurrentAddr
= LOWORD((Address
+ j
) * AddressSize
);
1213 /* Plane 0 holds the character itself */
1214 CharInfo
.Char
= VgaMemory
[CurrentAddr
];
1216 /* Plane 1 holds the attribute */
1217 CharInfo
.Attributes
= VgaMemory
[CurrentAddr
+ VGA_BANK_SIZE
];
1219 /* Now check if the resulting character data has changed */
1220 if ((CharBuffer
[i
* Resolution
.X
+ j
].Char
!= CharInfo
.Char
)
1221 || (CharBuffer
[i
* Resolution
.X
+ j
].Attributes
!= CharInfo
.Attributes
))
1223 /* Yes, write the new value */
1224 CharBuffer
[i
* Resolution
.X
+ j
] = CharInfo
;
1226 /* Mark the specified cell as changed */
1227 VgaMarkForUpdate(i
, j
);
1231 /* Move to the next scanline */
1232 Address
+= ScanlineSize
;
1237 static VOID
VgaUpdateTextCursor(VOID
)
1240 CONSOLE_CURSOR_INFO CursorInfo
;
1241 BYTE CursorStart
= VgaCrtcRegisters
[VGA_CRTC_CURSOR_START_REG
] & 0x3F;
1242 BYTE CursorEnd
= VgaCrtcRegisters
[VGA_CRTC_CURSOR_END_REG
] & 0x1F;
1243 DWORD ScanlineSize
= (DWORD
)VgaCrtcRegisters
[VGA_CRTC_OFFSET_REG
] * 2;
1244 BYTE TextSize
= 1 + (VgaCrtcRegisters
[VGA_CRTC_MAX_SCAN_LINE_REG
] & 0x1F);
1245 WORD Location
= MAKEWORD(VgaCrtcRegisters
[VGA_CRTC_CURSOR_LOC_LOW_REG
],
1246 VgaCrtcRegisters
[VGA_CRTC_CURSOR_LOC_HIGH_REG
]);
1248 /* Just return if we are not in text mode */
1249 if (VgaGcRegisters
[VGA_GC_MISC_REG
] & VGA_GC_MISC_NOALPHA
) return;
1251 if (CursorStart
< CursorEnd
)
1253 /* Visible cursor */
1254 CursorInfo
.bVisible
= TRUE
;
1255 CursorInfo
.dwSize
= (100 * (CursorEnd
- CursorStart
)) / TextSize
;
1260 CursorInfo
.bVisible
= FALSE
;
1261 CursorInfo
.dwSize
= 0;
1264 /* Add the cursor skew to the location */
1265 Location
+= (VgaCrtcRegisters
[VGA_CRTC_CURSOR_END_REG
] >> 5) & 3;
1267 /* Find the coordinates of the new position */
1268 Position
.X
= (WORD
)(Location
% ScanlineSize
);
1269 Position
.Y
= (WORD
)(Location
/ ScanlineSize
);
1271 /* Update the physical cursor */
1272 SetConsoleCursorInfo(TextConsoleBuffer
, &CursorInfo
);
1273 SetConsoleCursorPosition(TextConsoleBuffer
, Position
);
1275 /* Reset the cursor move flag */
1276 CursorMoved
= FALSE
;
1279 static BYTE WINAPI
VgaReadPort(ULONG Port
)
1281 DPRINT("VgaReadPort: Port 0x%X\n", Port
);
1286 return VgaMiscRegister
;
1288 case VGA_INSTAT0_READ
:
1289 return 0; // Not implemented
1291 case VGA_INSTAT1_READ_MONO
:
1292 case VGA_INSTAT1_READ_COLOR
:
1296 /* Reset the AC latch */
1299 /* Set a flag if there is a vertical or horizontal retrace */
1300 if (InVerticalRetrace
|| InHorizontalRetrace
) Result
|= VGA_STAT_DD
;
1302 /* Set an additional flag if there was a vertical retrace */
1303 if (InVerticalRetrace
) Result
|= VGA_STAT_VRETRACE
;
1305 /* Clear the flags */
1306 InHorizontalRetrace
= InVerticalRetrace
= FALSE
;
1311 case VGA_FEATURE_READ
:
1312 return VgaFeatureRegister
;
1318 return VgaAcRegisters
[VgaAcIndex
];
1324 return VgaSeqRegisters
[VgaSeqIndex
];
1329 case VGA_DAC_READ_INDEX
:
1330 /* This returns the read/write state */
1331 return (VgaDacReadWrite
? 0 : 3);
1333 case VGA_DAC_WRITE_INDEX
:
1334 return (VgaDacIndex
/ 3);
1338 /* Ignore reads in write mode */
1339 if (!VgaDacReadWrite
)
1341 BYTE Data
= VgaDacRegisters
[VgaDacIndex
++];
1342 VgaDacIndex
%= VGA_PALETTE_SIZE
;
1349 case VGA_CRTC_INDEX_MONO
:
1350 case VGA_CRTC_INDEX_COLOR
:
1351 return VgaCrtcIndex
;
1353 case VGA_CRTC_DATA_MONO
:
1354 case VGA_CRTC_DATA_COLOR
:
1355 return VgaCrtcRegisters
[VgaCrtcIndex
];
1361 return VgaGcRegisters
[VgaGcIndex
];
1364 DPRINT1("VgaReadPort: Unknown port 0x%X\n", Port
);
1371 static VOID WINAPI
VgaWritePort(ULONG Port
, BYTE Data
)
1373 DPRINT("VgaWritePort: Port 0x%X, Data 0x%02X\n", Port
, Data
);
1377 case VGA_MISC_WRITE
:
1379 VgaMiscRegister
= Data
;
1381 if (VgaMiscRegister
& 0x01)
1383 /* Color emulation */
1384 DPRINT1("Color emulation\n");
1386 /* Register the new I/O Ports */
1387 RegisterIoPort(0x3D4, VgaReadPort
, VgaWritePort
); // VGA_CRTC_INDEX_COLOR
1388 RegisterIoPort(0x3D5, VgaReadPort
, VgaWritePort
); // VGA_CRTC_DATA_COLOR
1389 RegisterIoPort(0x3DA, VgaReadPort
, VgaWritePort
); // VGA_INSTAT1_READ_COLOR, VGA_FEATURE_WRITE_COLOR
1391 /* Unregister the old ones */
1392 UnregisterIoPort(0x3B4); // VGA_CRTC_INDEX_MONO
1393 UnregisterIoPort(0x3B5); // VGA_CRTC_DATA_MONO
1394 UnregisterIoPort(0x3BA); // VGA_INSTAT1_READ_MONO, VGA_FEATURE_WRITE_MONO
1398 /* Monochrome emulation */
1399 DPRINT1("Monochrome emulation\n");
1401 /* Register the new I/O Ports */
1402 RegisterIoPort(0x3B4, VgaReadPort
, VgaWritePort
); // VGA_CRTC_INDEX_MONO
1403 RegisterIoPort(0x3B5, VgaReadPort
, VgaWritePort
); // VGA_CRTC_DATA_MONO
1404 RegisterIoPort(0x3BA, VgaReadPort
, VgaWritePort
); // VGA_INSTAT1_READ_MONO, VGA_FEATURE_WRITE_MONO
1406 /* Unregister the old ones */
1407 UnregisterIoPort(0x3D4); // VGA_CRTC_INDEX_COLOR
1408 UnregisterIoPort(0x3D5); // VGA_CRTC_DATA_COLOR
1409 UnregisterIoPort(0x3DA); // VGA_INSTAT1_READ_COLOR, VGA_FEATURE_WRITE_COLOR
1412 // if (VgaMiscRegister & 0x02) { /* Enable RAM access */ } else { /* Disable RAM access */ }
1416 case VGA_FEATURE_WRITE_MONO
:
1417 case VGA_FEATURE_WRITE_COLOR
:
1419 VgaFeatureRegister
= Data
;
1424 // case VGA_AC_WRITE:
1428 /* Change the index */
1429 BYTE Index
= Data
& 0x1F;
1430 if (Index
< VGA_AC_MAX_REG
) VgaAcIndex
= Index
;
1433 * Change palette protection by checking for
1434 * the Palette Address Source bit.
1436 VgaAcPalDisable
= (Data
& 0x20) ? TRUE
: FALSE
;
1440 /* Write the data */
1444 /* Toggle the latch */
1445 VgaAcLatch
= !VgaAcLatch
;
1451 /* Set the sequencer index register */
1452 if (Data
< VGA_SEQ_MAX_REG
) VgaSeqIndex
= Data
;
1458 /* Call the sequencer function */
1459 VgaWriteSequencer(Data
);
1469 case VGA_DAC_READ_INDEX
:
1471 VgaDacReadWrite
= FALSE
;
1472 VgaDacIndex
= Data
* 3;
1476 case VGA_DAC_WRITE_INDEX
:
1478 VgaDacReadWrite
= TRUE
;
1479 VgaDacIndex
= Data
* 3;
1485 /* Ignore writes in read mode */
1486 if (VgaDacReadWrite
) VgaWriteDac(Data
& 0x3F);
1490 case VGA_CRTC_INDEX_MONO
:
1491 case VGA_CRTC_INDEX_COLOR
:
1493 /* Set the CRTC index register */
1494 if (Data
< VGA_CRTC_MAX_REG
) VgaCrtcIndex
= Data
;
1498 case VGA_CRTC_DATA_MONO
:
1499 case VGA_CRTC_DATA_COLOR
:
1501 /* Call the CRTC function */
1508 /* Set the GC index register */
1509 if (Data
< VGA_GC_MAX_REG
) VgaGcIndex
= Data
;
1515 /* Call the GC function */
1521 DPRINT1("VgaWritePort: Unknown port 0x%X\n", Port
);
1526 /* PUBLIC FUNCTIONS ***********************************************************/
1528 DWORD
VgaGetVideoBaseAddress(VOID
)
1530 return MemoryBase
[(VgaGcRegisters
[VGA_GC_MISC_REG
] >> 2) & 0x03];
1533 DWORD
VgaGetVideoLimitAddress(VOID
)
1535 return MemoryLimit
[(VgaGcRegisters
[VGA_GC_MISC_REG
] >> 2) & 0x03];
1538 COORD
VgaGetDisplayResolution(VOID
)
1541 BYTE MaximumScanLine
= 1 + (VgaCrtcRegisters
[VGA_CRTC_MAX_SCAN_LINE_REG
] & 0x1F);
1543 /* The low 8 bits are in the display registers */
1544 Resolution
.X
= VgaCrtcRegisters
[VGA_CRTC_END_HORZ_DISP_REG
];
1545 Resolution
.Y
= VgaCrtcRegisters
[VGA_CRTC_VERT_DISP_END_REG
];
1547 /* Set the top bits from the overflow register */
1548 if (VgaCrtcRegisters
[VGA_CRTC_OVERFLOW_REG
] & VGA_CRTC_OVERFLOW_VDE8
)
1550 Resolution
.Y
|= 1 << 8;
1552 if (VgaCrtcRegisters
[VGA_CRTC_OVERFLOW_REG
] & VGA_CRTC_OVERFLOW_VDE9
)
1554 Resolution
.Y
|= 1 << 9;
1557 /* Increase the values by 1 */
1561 if (VgaGcRegisters
[VGA_GC_MISC_REG
] & VGA_GC_MISC_NOALPHA
)
1563 /* Multiply the horizontal resolution by the 9/8 dot mode */
1564 Resolution
.X
*= (VgaSeqRegisters
[VGA_SEQ_CLOCK_REG
] & VGA_SEQ_CLOCK_98DM
)
1567 /* The horizontal resolution is halved in 8-bit mode */
1568 if (VgaAcRegisters
[VGA_AC_CONTROL_REG
] & VGA_AC_CONTROL_8BIT
) Resolution
.X
/= 2;
1571 if (VgaCrtcRegisters
[VGA_CRTC_MAX_SCAN_LINE_REG
] & VGA_CRTC_MAXSCANLINE_DOUBLE
)
1573 /* Halve the vertical resolution */
1578 /* Divide the vertical resolution by the maximum scan line (== font size in text mode) */
1579 Resolution
.Y
/= MaximumScanLine
;
1582 /* Return the resolution */
1586 VOID
VgaRefreshDisplay(VOID
)
1588 HANDLE ConsoleBufferHandle
= NULL
;
1591 /* Set the vertical retrace flag */
1592 InVerticalRetrace
= TRUE
;
1594 /* If nothing has changed, just return */
1595 // if (!ModeChanged && !CursorMoved && !PaletteChanged && !NeedsUpdate)
1598 /* Change the display mode */
1599 if (ModeChanged
) VgaChangeMode();
1601 /* Change the text cursor location */
1602 if (CursorMoved
) VgaUpdateTextCursor();
1604 /* Retrieve the current resolution */
1605 Resolution
= VgaGetDisplayResolution();
1609 /* Trigger a full update of the screen */
1611 UpdateRectangle
.Left
= 0;
1612 UpdateRectangle
.Top
= 0;
1613 UpdateRectangle
.Right
= Resolution
.X
;
1614 UpdateRectangle
.Bottom
= Resolution
.Y
;
1616 PaletteChanged
= FALSE
;
1619 /* Update the contents of the framebuffer */
1620 VgaUpdateFramebuffer();
1622 /* Ignore if there's nothing to update */
1623 if (!NeedsUpdate
) return;
1625 DPRINT("Updating screen rectangle (%d, %d, %d, %d)\n",
1626 UpdateRectangle
.Left
,
1627 UpdateRectangle
.Top
,
1628 UpdateRectangle
.Right
,
1629 UpdateRectangle
.Bottom
);
1631 /* Check if this is text mode or graphics mode */
1632 if (VgaGcRegisters
[VGA_GC_MISC_REG
] & VGA_GC_MISC_NOALPHA
)
1635 ConsoleBufferHandle
= GraphicsConsoleBuffer
;
1637 /* In DoubleVision mode, scale the update rectangle */
1640 UpdateRectangle
.Left
*= 2;
1641 UpdateRectangle
.Top
*= 2;
1642 UpdateRectangle
.Right
= UpdateRectangle
.Right
* 2 + 1;
1643 UpdateRectangle
.Bottom
= UpdateRectangle
.Bottom
* 2 + 1;
1649 ConsoleBufferHandle
= TextConsoleBuffer
;
1652 /* Redraw the screen */
1653 __InvalidateConsoleDIBits(ConsoleBufferHandle
, &UpdateRectangle
);
1655 /* Clear the update flag */
1656 NeedsUpdate
= FALSE
;
1659 VOID
VgaHorizontalRetrace(VOID
)
1662 InHorizontalRetrace
= TRUE
;
1665 VOID
VgaReadMemory(DWORD Address
, LPBYTE Buffer
, DWORD Size
)
1670 DPRINT("VgaReadMemory: Address 0x%08X, Size %lu\n", Address
, Size
);
1672 /* Ignore if video RAM access is disabled */
1673 if ((VgaMiscRegister
& VGA_MISC_RAM_ENABLED
) == 0) return;
1675 /* Loop through each byte */
1676 for (i
= 0; i
< Size
; i
++)
1678 VideoAddress
= VgaTranslateReadAddress(Address
+ i
);
1680 /* Load the latch registers */
1681 VgaLatchRegisters
[0] = VgaMemory
[LOWORD(VideoAddress
)];
1682 VgaLatchRegisters
[1] = VgaMemory
[VGA_BANK_SIZE
+ LOWORD(VideoAddress
)];
1683 VgaLatchRegisters
[2] = VgaMemory
[(2 * VGA_BANK_SIZE
) + LOWORD(VideoAddress
)];
1684 VgaLatchRegisters
[3] = VgaMemory
[(3 * VGA_BANK_SIZE
) + LOWORD(VideoAddress
)];
1686 /* Copy the value to the buffer */
1687 Buffer
[i
] = VgaMemory
[VideoAddress
];
1691 VOID
VgaWriteMemory(DWORD Address
, LPBYTE Buffer
, DWORD Size
)
1696 DPRINT("VgaWriteMemory: Address 0x%08X, Size %lu\n", Address
, Size
);
1698 /* Ignore if video RAM access is disabled */
1699 if ((VgaMiscRegister
& VGA_MISC_RAM_ENABLED
) == 0) return;
1701 /* Also ignore if write access to all planes is disabled */
1702 if ((VgaSeqRegisters
[VGA_SEQ_MASK_REG
] & 0x0F) == 0x00) return;
1704 /* Loop through each byte */
1705 for (i
= 0; i
< Size
; i
++)
1707 VideoAddress
= VgaTranslateWriteAddress(Address
+ i
);
1709 for (j
= 0; j
< VGA_NUM_BANKS
; j
++)
1711 /* Make sure the page is writeable */
1712 if (!(VgaSeqRegisters
[VGA_SEQ_MASK_REG
] & (1 << j
))) continue;
1714 /* Check if this is chain-4 mode */
1715 if (VgaSeqRegisters
[VGA_SEQ_MEM_REG
] & VGA_SEQ_MEM_C4
)
1717 if (((Address
+ i
) & 3) != j
)
1719 /* This plane will not be accessed */
1724 /* Check if this is odd-even mode */
1725 if (VgaGcRegisters
[VGA_GC_MODE_REG
] & VGA_GC_MODE_OE
)
1727 if (((Address
+ i
) & 1) != (j
& 1))
1729 /* This plane will not be accessed */
1734 /* Copy the value to the VGA memory */
1735 VgaMemory
[VideoAddress
+ j
* VGA_BANK_SIZE
] = VgaTranslateByteForWriting(Buffer
[i
], j
);
1740 VOID
VgaClearMemory(VOID
)
1742 ZeroMemory(VgaMemory
, sizeof(VgaMemory
));
1745 VOID
VgaResetPalette(VOID
)
1747 PALETTEENTRY Entries
[VGA_MAX_COLORS
];
1749 /* Restore the default palette */
1750 VgaRestoreDefaultPalette(Entries
, VGA_MAX_COLORS
);
1751 SetPaletteEntries(PaletteHandle
, 0, VGA_MAX_COLORS
, Entries
);
1752 PaletteChanged
= TRUE
;
1755 BOOLEAN
VgaInitialize(HANDLE TextHandle
)
1757 /* Save the default text-mode console output handle */
1758 if (!IsConsoleHandle(TextHandle
)) return FALSE
;
1759 TextConsoleBuffer
= TextHandle
;
1761 /* Save the console information */
1762 if (!GetConsoleScreenBufferInfo(TextConsoleBuffer
, &ConsoleInfo
))
1767 /* Initialize the VGA palette and fail if it isn't successfully created */
1768 if (!VgaInitializePalette()) return FALSE
;
1769 /***/ VgaResetPalette(); /***/
1771 /* Switch to the text buffer */
1772 SetConsoleActiveScreenBuffer(TextConsoleBuffer
);
1774 /* Clear the VGA memory */
1777 /* Register the I/O Ports */
1778 RegisterIoPort(0x3CC, VgaReadPort
, NULL
); // VGA_MISC_READ
1779 RegisterIoPort(0x3C2, VgaReadPort
, VgaWritePort
); // VGA_MISC_WRITE, VGA_INSTAT0_READ
1780 RegisterIoPort(0x3CA, VgaReadPort
, NULL
); // VGA_FEATURE_READ
1781 RegisterIoPort(0x3C0, VgaReadPort
, VgaWritePort
); // VGA_AC_INDEX, VGA_AC_WRITE
1782 RegisterIoPort(0x3C1, VgaReadPort
, NULL
); // VGA_AC_READ
1783 RegisterIoPort(0x3C4, VgaReadPort
, VgaWritePort
); // VGA_SEQ_INDEX
1784 RegisterIoPort(0x3C5, VgaReadPort
, VgaWritePort
); // VGA_SEQ_DATA
1785 RegisterIoPort(0x3C6, VgaReadPort
, VgaWritePort
); // VGA_DAC_MASK
1786 RegisterIoPort(0x3C7, VgaReadPort
, VgaWritePort
); // VGA_DAC_READ_INDEX
1787 RegisterIoPort(0x3C8, VgaReadPort
, VgaWritePort
); // VGA_DAC_WRITE_INDEX
1788 RegisterIoPort(0x3C9, VgaReadPort
, VgaWritePort
); // VGA_DAC_DATA
1789 RegisterIoPort(0x3CE, VgaReadPort
, VgaWritePort
); // VGA_GC_INDEX
1790 RegisterIoPort(0x3CF, VgaReadPort
, VgaWritePort
); // VGA_GC_DATA
1792 /* Return success */
1796 VOID
VgaCleanup(VOID
)
1798 if (ScreenMode
== GRAPHICS_MODE
)
1800 /* Leave the current graphics mode */
1801 VgaLeaveGraphicsMode();
1805 /* Leave the current text mode */
1809 VgaDetachFromConsole();
1811 CloseHandle(AnotherEvent
);
1812 CloseHandle(EndEvent
);
1813 CloseHandle(StartEvent
);
1816 RegisterConsoleVDM
= NULL
;
1817 FreeLibrary(hKernel32
);