[NTVDM]: Break the BIOS into the BIOS and the video BIOS.
[reactos.git] / subsystems / ntvdm / bios / vidbios.c
1 /*
2 * COPYRIGHT: GPL - See COPYING in the top level directory
3 * PROJECT: ReactOS Virtual DOS Machine
4 * FILE: vidbios.c
5 * PURPOSE: VDM Video BIOS
6 * PROGRAMMERS: Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
7 */
8
9 /* INCLUDES *******************************************************************/
10
11 #define NDEBUG
12
13 #include "emulator.h"
14 // #include "vidbios.h"
15 #include "bios.h"
16
17 #include "io.h"
18 #include "hardware/vga.h"
19
20 #include "int32.h"
21 #include "registers.h"
22
23 /* MACROS *********************************************************************/
24
25 //
26 // These macros are defined for ease-of-use of some VGA I/O ports
27 // whose addresses depend whether we are in Monochrome or Colour mode.
28 //
29 #define VGA_INSTAT1_READ Bda->CrtBasePort + 6 // VGA_INSTAT1_READ_MONO or VGA_INSTAT1_READ_COLOR
30 #define VGA_CRTC_INDEX Bda->CrtBasePort // VGA_CRTC_INDEX_MONO or VGA_CRTC_INDEX_COLOR
31 #define VGA_CRTC_DATA Bda->CrtBasePort + 1 // VGA_CRTC_DATA_MONO or VGA_CRTC_DATA_COLOR
32
33 /* PRIVATE VARIABLES **********************************************************/
34
35 static HANDLE VidBiosConsoleOutput = INVALID_HANDLE_VALUE;
36
37 /*
38 * VGA Register Configurations for BIOS Video Modes
39 * The configurations come from DOSBox.
40 */
41 static VGA_REGISTERS VideoMode_40x25_text =
42 {
43 /* Miscellaneous Register */
44 0x67,
45
46 /* Sequencer Registers */
47 {0x00, 0x08, 0x03, 0x00, 0x07},
48
49 /* CRTC Registers */
50 {0x2D, 0x27, 0x28, 0x90, 0x2B, 0xA0, 0xBF, 0x1F, 0x00, 0x4F, 0x0D, 0x0E,
51 0x00, 0x00, 0x00, 0x00, 0x9C, 0x8E, 0x8F, 0x14, 0x1F, 0x96, 0xB9, 0xA3,
52 0xFF},
53
54 /* GC Registers */
55 {0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x0E, 0x0F, 0xFF},
56
57 /* AC Registers */
58 {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x14, 0x07, 0x38, 0x39, 0x3A, 0x3B,
59 0x3C, 0x3D, 0x3E, 0x3F, 0x0C, 0x00, 0x0F, 0x08, 0x00}
60 };
61
62 static VGA_REGISTERS VideoMode_80x25_text =
63 {
64 /* Miscellaneous Register */
65 0x67,
66
67 /* Sequencer Registers */
68 {0x00, 0x00, 0x03, 0x00, 0x07},
69
70 /* CRTC Registers */
71 {0x5F, 0x4F, 0x50, 0x82, 0x55, 0x81, 0xBF, 0x1F, 0x00, 0x4F, 0x0D, 0x0E,
72 0x00, 0x00, 0x00, 0x00, 0x9C, 0x8E, 0x8F, 0x28, 0x1F, 0x96, 0xB9, 0xA3,
73 0xFF},
74
75 /* GC Registers */
76 {0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x0E, 0x0F, 0xFF},
77
78 /* AC Registers */
79 {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x14, 0x07, 0x38, 0x39, 0x3A, 0x3B,
80 0x3C, 0x3D, 0x3E, 0x3F, 0x0C, 0x00, 0x0F, 0x08, 0x00}
81 };
82
83 static VGA_REGISTERS VideoMode_320x200_4color =
84 {
85 /* Miscellaneous Register */
86 0x63,
87
88 /* Sequencer Registers */
89 {0x00, 0x09, 0x03, 0x00, 0x02},
90
91 /* CRTC Registers */
92 {0x2D, 0x27, 0x28, 0x90, 0x2B, 0x80, 0xBF, 0x1F, 0x00, 0xC1, 0x00, 0x00,
93 0x00, 0x00, 0x00, 0x00, 0x9C, 0x8E, 0x8F, 0x14, 0x00, 0x96, 0xB9, 0xA2,
94 0xFF},
95
96 /* GC Registers */
97 {0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x0F, 0x0F, 0xFF},
98
99 /* AC Registers */
100 {0x00, 0x13, 0x15, 0x17, 0x02, 0x04, 0x06, 0x07, 0x10, 0x11, 0x12, 0x13,
101 0x14, 0x15, 0x16, 0x17, 0x01, 0x00, 0x0F, 0x00, 0x00}
102 };
103
104 static VGA_REGISTERS VideoMode_640x200_2color =
105 {
106 /* Miscellaneous Register */
107 0x63,
108
109 /* Sequencer Registers */
110 {0x00, 0x09, 0x0F, 0x00, 0x02},
111
112 /* CRTC Registers */
113 {0x5F, 0x4F, 0x50, 0x82, 0x54, 0x80, 0xBF, 0x1F, 0x00, 0xC1, 0x00, 0x00,
114 0x00, 0x00, 0x00, 0x00, 0x9C, 0x8E, 0x8F, 0x28, 0x00, 0x96, 0xB9, 0xC2,
115 0xFF},
116
117 /* GC Registers */
118 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x0F, 0xFF},
119
120 /* AC Registers */
121 {0x00, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17,
122 0x17, 0x17, 0x17, 0x17, 0x01, 0x00, 0x01, 0x00, 0x00}
123 };
124
125 static VGA_REGISTERS VideoMode_320x200_16color =
126 {
127 /* Miscellaneous Register */
128 0x63,
129
130 /* Sequencer Registers */
131 {0x00, 0x09, 0x0F, 0x00, 0x02},
132
133 /* CRTC Registers */
134 {0x2D, 0x27, 0x28, 0x90, 0x2B, 0x80, 0xBF, 0x1F, 0x00, 0xC0, 0x00, 0x00,
135 0x00, 0x00, 0x00, 0x00, 0x9C, 0x8E, 0x8F, 0x14, 0x00, 0x96, 0xB9, 0xE3,
136 0xFF},
137
138 /* GC Registers */
139 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x0F, 0xFF},
140
141 /* AC Registers */
142 // {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x14, 0x07, 0x38, 0x39, 0x3A, 0x3B,
143 // 0x3C, 0x3D, 0x3E, 0x3F, 0x01, 0x00, 0x0F, 0x00, 0x00}
144 {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x10, 0x11, 0x12, 0x13,
145 0x14, 0x15, 0x16, 0x17, 0x01, 0x00, 0x0F, 0x00, 0x00}
146 };
147
148 static VGA_REGISTERS VideoMode_640x200_16color =
149 {
150 /* Miscellaneous Register */
151 0x63,
152
153 /* Sequencer Registers */
154 {0x00, 0x01, 0x0F, 0x00, 0x02},
155
156 /* CRTC Registers */
157 {0x5F, 0x4F, 0x50, 0x82, 0x54, 0x80, 0xBF, 0x1F, 0x00, 0xC0, 0x00, 0x00,
158 0x00, 0x00, 0x00, 0x00, 0x9C, 0x8E, 0x8F, 0x28, 0x00, 0x96, 0xB9, 0xE3,
159 0xFF},
160
161 /* GC Registers */
162 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x0F, 0xFF},
163
164 /* AC Registers */
165 // {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x14, 0x07, 0x38, 0x39, 0x3A, 0x3B,
166 // 0x3C, 0x3D, 0x3E, 0x3F, 0x01, 0x00, 0x0F, 0x00, 0x00}
167 {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x10, 0x11, 0x12, 0x13,
168 0x14, 0x15, 0x16, 0x17, 0x01, 0x00, 0x0F, 0x00, 0x00}
169 };
170
171 static VGA_REGISTERS VideoMode_640x350_16color =
172 {
173 /* Miscellaneous Register */
174 0xA3,
175
176 /* Sequencer Registers */
177 {0x00, 0x01, 0x0F, 0x00, 0x02},
178
179 /* CRTC Registers */
180 {0x5F, 0x4F, 0x50, 0x82, 0x54, 0x80, 0xBF, 0x1F, 0x00, 0x40, 0x00, 0x00,
181 0x00, 0x00, 0x00, 0x00, 0x83, 0x85, 0x5D, 0x28, 0x0F, 0x63, 0xBA, 0xE3,
182 0xFF},
183
184 /* GC Registers */
185 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x0F, 0xFF},
186
187 /* AC Registers */
188 {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x14, 0x07, 0x38, 0x39, 0x3A, 0x3B,
189 0x3C, 0x3D, 0x3E, 0x3F, 0x01, 0x00, 0x0F, 0x00, 0x00}
190 };
191
192 static VGA_REGISTERS VideoMode_640x480_2color =
193 {
194 /* Miscellaneous Register */
195 0xE3,
196
197 /* Sequencer Registers */
198 {0x00, 0x01, 0x0F, 0x00, 0x02},
199
200 /* CRTC Registers */
201 {0x5F, 0x4F, 0x50, 0x82, 0x54, 0x80, 0x0B, 0x3E, 0x00, 0x40, 0x00, 0x00,
202 0x00, 0x00, 0x00, 0x00, 0xEA, 0x8C, 0xDF, 0x28, 0x00, 0xE7, 0x04, 0xC3,
203 0xFF},
204
205 /* GC Registers */
206 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x0F, 0xFF},
207
208 /* AC Registers */
209 {0x00, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
210 0x3F, 0x3F, 0x3F, 0x3F, 0x01, 0x00, 0x0F, 0x00, 0x00}
211 };
212
213 static VGA_REGISTERS VideoMode_640x480_16color =
214 {
215 /* Miscellaneous Register */
216 0xE3,
217
218 /* Sequencer Registers */
219 {0x00, 0x01, 0x0F, 0x00, 0x02},
220
221 /* CRTC Registers */
222 {0x5F, 0x4F, 0x50, 0x82, 0x54, 0x80, 0x0B, 0x3E, 0x00, 0x40, 0x00, 0x00,
223 0x00, 0x00, 0x00, 0x00, 0xEA, 0x8C, 0xDF, 0x28, 0x00, 0xE7, 0x04, 0xE3,
224 0xFF},
225
226 /* GC Registers */
227 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x0F, 0xFF},
228
229 /* AC Registers */
230 {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x14, 0x07, 0x38, 0x39, 0x3A, 0x3B,
231 0x3C, 0x3D, 0x3E, 0x3F, 0x01, 0x00, 0x0F, 0x00, 0x00}
232 };
233
234 static VGA_REGISTERS VideoMode_320x200_256color =
235 {
236 /* Miscellaneous Register */
237 0x63,
238
239 /* Sequencer Registers */
240 {0x00, 0x01, 0x0F, 0x00, 0x0E},
241
242 /* CRTC Registers */
243 {0x5F, 0x4F, 0x50, 0x82, 0x54, 0x80, 0xBF, 0x1F, 0x00, 0x41, 0x00, 0x00,
244 0x00, 0x00, 0x00, 0x00, 0x9C, 0x8E, 0x8F, 0x28, 0x40, 0x96, 0xB9, 0xA3,
245 0xFF},
246
247 /* GC Registers */
248 {0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F, 0xFF},
249
250 /* AC Registers */
251 {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B,
252 0x0C, 0x0D, 0x0E, 0x0F, 0x41, 0x00, 0x0F, 0x00, 0x00}
253 };
254
255 /* See http://wiki.osdev.org/Drawing_In_Protected_Mode#Locating_Video_Memory */
256 static PVGA_REGISTERS VideoModes[BIOS_MAX_VIDEO_MODE + 1] =
257 {
258 &VideoMode_40x25_text, /* Mode 00h */ // 16 color (mono)
259 &VideoMode_40x25_text, /* Mode 01h */ // 16 color
260 &VideoMode_80x25_text, /* Mode 02h */ // 16 color (mono)
261 &VideoMode_80x25_text, /* Mode 03h */ // 16 color
262 &VideoMode_320x200_4color, /* Mode 04h */ // CGA 4 color
263 &VideoMode_320x200_4color, /* Mode 05h */ // CGA same (m)
264 &VideoMode_640x200_2color, /* Mode 06h */ // CGA 640*200 2 color
265 NULL, /* Mode 07h */ // MDA monochrome text 80*25
266 NULL, /* Mode 08h */ // PCjr
267 NULL, /* Mode 09h */ // PCjr
268 NULL, /* Mode 0Ah */ // PCjr
269 NULL, /* Mode 0Bh */ // Reserved
270 NULL, /* Mode 0Ch */ // Reserved
271 &VideoMode_320x200_16color, /* Mode 0Dh */ // EGA 320*200 16 color
272 &VideoMode_640x200_16color, /* Mode 0Eh */ // EGA 640*200 16 color
273 NULL, /* Mode 0Fh */ // EGA 640*350 mono
274 &VideoMode_640x350_16color, /* Mode 10h */ // EGA 640*350 HiRes 16 color
275 &VideoMode_640x480_2color, /* Mode 11h */ // VGA 640*480 mono
276 &VideoMode_640x480_16color, /* Mode 12h */ // VGA
277 &VideoMode_320x200_256color, /* Mode 13h */ // VGA
278 };
279
280 // FIXME: Are they computable with the previous data ??
281 // Values taken from DOSBox.
282 static WORD VideoModePageSize[BIOS_MAX_VIDEO_MODE + 1] =
283 {
284 0x0800, 0x0800, 0x1000, 0x1000,
285 0x4000, 0x4000, 0x4000, 0x1000,
286 0x0000, 0x0000, 0x0000, 0x0000,
287 0x0000, 0x2000, 0x4000, 0x8000,
288 0x8000, 0xA000, 0xA000, 0x2000
289 };
290
291 /*
292 * BIOS Mode Palettes
293 *
294 * Many people have different versions of those palettes
295 * (e.g. DOSBox, http://www.brokenthorn.com/Resources/OSDevVid2.html ,
296 * etc...) A choice should be made at some point.
297 */
298
299 // This is the same as EgaPalette__HiRes
300 static CONST COLORREF TextPalette[VGA_MAX_COLORS / 4] =
301 {
302 RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0xAA), RGB(0x00, 0xAA, 0x00), RGB(0x00, 0xAA, 0xAA),
303 RGB(0xAA, 0x00, 0x00), RGB(0xAA, 0x00, 0xAA), RGB(0xAA, 0xAA, 0x00), RGB(0xAA, 0xAA, 0xAA),
304 RGB(0x00, 0x00, 0x55), RGB(0x00, 0x00, 0xFF), RGB(0x00, 0xAA, 0x55), RGB(0x00, 0xAA, 0xFF),
305 RGB(0xAA, 0x00, 0x55), RGB(0xAA, 0x00, 0xFF), RGB(0xAA, 0xAA, 0x55), RGB(0xAA, 0xAA, 0xFF),
306
307 RGB(0x00, 0x55, 0x00), RGB(0x00, 0x55, 0xAA), RGB(0x00, 0xFF, 0x00), RGB(0x00, 0xFF, 0xAA),
308 RGB(0xAA, 0x55, 0x00), RGB(0xAA, 0x55, 0xAA), RGB(0xAA, 0xFF, 0x00), RGB(0xAA, 0xFF, 0xAA),
309 RGB(0x00, 0x55, 0x55), RGB(0x00, 0x55, 0xFF), RGB(0x00, 0xFF, 0x55), RGB(0x00, 0xFF, 0xFF),
310 RGB(0xAA, 0x55, 0x55), RGB(0xAA, 0x55, 0xFF), RGB(0xAA, 0xFF, 0x55), RGB(0xAA, 0xFF, 0xFF),
311
312
313 RGB(0x55, 0x00, 0x00), RGB(0x55, 0x00, 0xAA), RGB(0x55, 0xAA, 0x00), RGB(0x55, 0xAA, 0xAA),
314 RGB(0xFF, 0x00, 0x00), RGB(0xFF, 0x00, 0xAA), RGB(0xFF, 0xAA, 0x00), RGB(0xFF, 0xAA, 0xAA),
315 RGB(0x55, 0x00, 0x55), RGB(0x55, 0x00, 0xFF), RGB(0x55, 0xAA, 0x55), RGB(0x55, 0xAA, 0xFF),
316 RGB(0xFF, 0x00, 0x55), RGB(0xFF, 0x00, 0xFF), RGB(0xFF, 0xAA, 0x55), RGB(0xFF, 0xAA, 0xFF),
317
318 RGB(0x55, 0x55, 0x00), RGB(0x55, 0x55, 0xAA), RGB(0x55, 0xFF, 0x00), RGB(0x55, 0xFF, 0xAA),
319 RGB(0xFF, 0x55, 0x00), RGB(0xFF, 0x55, 0xAA), RGB(0xFF, 0xFF, 0x00), RGB(0xFF, 0xFF, 0xAA),
320 RGB(0x55, 0x55, 0x55), RGB(0x55, 0x55, 0xFF), RGB(0x55, 0xFF, 0x55), RGB(0x55, 0xFF, 0xFF),
321 RGB(0xFF, 0x55, 0x55), RGB(0xFF, 0x55, 0xFF), RGB(0xFF, 0xFF, 0x55), RGB(0xFF, 0xFF, 0xFF)
322 };
323
324 // Unused at the moment
325 static CONST COLORREF mtext_palette[64] =
326 {
327 RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00),
328 RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00),
329 RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA),
330 RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA),
331 RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00),
332 RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00),
333 RGB(0xFF, 0xFF, 0xFF), RGB(0xFF, 0xFF, 0xFF), RGB(0xFF, 0xFF, 0xFF), RGB(0xFF, 0xFF, 0xFF),
334 RGB(0xFF, 0xFF, 0xFF), RGB(0xFF, 0xFF, 0xFF), RGB(0xFF, 0xFF, 0xFF), RGB(0xFF, 0xFF, 0xFF),
335
336 RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00),
337 RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00),
338 RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA),
339 RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA),
340 RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00),
341 RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00),
342 RGB(0xFF, 0xFF, 0xFF), RGB(0xFF, 0xFF, 0xFF), RGB(0xFF, 0xFF, 0xFF), RGB(0xFF, 0xFF, 0xFF),
343 RGB(0xFF, 0xFF, 0xFF), RGB(0xFF, 0xFF, 0xFF), RGB(0xFF, 0xFF, 0xFF), RGB(0xFF, 0xFF, 0xFF)
344 };
345
346 // Unused at the moment
347 static CONST COLORREF mtext_s3_palette[64] =
348 {
349 RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00),
350 RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00),
351 RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA),
352 RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA),
353 RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA),
354 RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA),
355 RGB(0xFF, 0xFF, 0xFF), RGB(0xFF, 0xFF, 0xFF), RGB(0xFF, 0xFF, 0xFF), RGB(0xFF, 0xFF, 0xFF),
356 RGB(0xFF, 0xFF, 0xFF), RGB(0xFF, 0xFF, 0xFF), RGB(0xFF, 0xFF, 0xFF), RGB(0xFF, 0xFF, 0xFF),
357
358 RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00),
359 RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00),
360 RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA),
361 RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA),
362 RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA),
363 RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA),
364 RGB(0xFF, 0xFF, 0xFF), RGB(0xFF, 0xFF, 0xFF), RGB(0xFF, 0xFF, 0xFF), RGB(0xFF, 0xFF, 0xFF),
365 RGB(0xFF, 0xFF, 0xFF), RGB(0xFF, 0xFF, 0xFF), RGB(0xFF, 0xFF, 0xFF), RGB(0xFF, 0xFF, 0xFF)
366 };
367
368 // Unused at the moment
369 static CONST COLORREF CgaPalette[16] =
370 {
371 RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0xAA), RGB(0x00, 0xAA, 0x00), RGB(0x00, 0xAA, 0xAA),
372 RGB(0xAA, 0x00, 0x00), RGB(0xAA, 0x00, 0xAA), RGB(0xAA, 0x55, 0x00), RGB(0xAA, 0xAA, 0xAA),
373 RGB(0x55, 0x55, 0x55), RGB(0x55, 0x55, 0xFF), RGB(0x55, 0xFF, 0x55), RGB(0x55, 0xFF, 0xFF),
374 RGB(0xFF, 0x55, 0x55), RGB(0xFF, 0x55, 0xFF), RGB(0xFF, 0xFF, 0x55), RGB(0xFF, 0xFF, 0xFF)
375 };
376
377 // Unused at the moment
378 static CONST COLORREF CgaPalette2[VGA_MAX_COLORS / 4] =
379 {
380 RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0xAA), RGB(0x00, 0xAA, 0x00), RGB(0x00, 0xAA, 0xAA),
381 RGB(0xAA, 0x00, 0x00), RGB(0xAA, 0x00, 0xAA), RGB(0xAA, 0x55, 0x00), RGB(0xAA, 0xAA, 0xAA),
382 RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0xAA), RGB(0x00, 0xAA, 0x00), RGB(0x00, 0xAA, 0xAA),
383 RGB(0xAA, 0x00, 0x00), RGB(0xAA, 0x00, 0xAA), RGB(0xAA, 0x55, 0x00), RGB(0xAA, 0xAA, 0xAA),
384 RGB(0x55, 0x55, 0x55), RGB(0x55, 0x55, 0xFF), RGB(0x55, 0xFF, 0x55), RGB(0x55, 0xFF, 0xFF),
385 RGB(0xFF, 0x55, 0x55), RGB(0xFF, 0x55, 0xFF), RGB(0xFF, 0xFF, 0x55), RGB(0xFF, 0xFF, 0xFF),
386 RGB(0x55, 0x55, 0x55), RGB(0x55, 0x55, 0xFF), RGB(0x55, 0xFF, 0x55), RGB(0x55, 0xFF, 0xFF),
387 RGB(0xFF, 0x55, 0x55), RGB(0xFF, 0x55, 0xFF), RGB(0xFF, 0xFF, 0x55), RGB(0xFF, 0xFF, 0xFF),
388 RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0xAA), RGB(0x00, 0xAA, 0x00), RGB(0x00, 0xAA, 0xAA),
389 RGB(0xAA, 0x00, 0x00), RGB(0xAA, 0x00, 0xAA), RGB(0xAA, 0x55, 0x00), RGB(0xAA, 0xAA, 0xAA),
390 RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0xAA), RGB(0x00, 0xAA, 0x00), RGB(0x00, 0xAA, 0xAA),
391 RGB(0xAA, 0x00, 0x00), RGB(0xAA, 0x00, 0xAA), RGB(0xAA, 0x55, 0x00), RGB(0xAA, 0xAA, 0xAA),
392 RGB(0x55, 0x55, 0x55), RGB(0x55, 0x55, 0xFF), RGB(0x55, 0xFF, 0x55), RGB(0x55, 0xFF, 0xFF),
393 RGB(0xFF, 0x55, 0x55), RGB(0xFF, 0x55, 0xFF), RGB(0xFF, 0xFF, 0x55), RGB(0xFF, 0xFF, 0xFF),
394 RGB(0x55, 0x55, 0x55), RGB(0x55, 0x55, 0xFF), RGB(0x55, 0xFF, 0x55), RGB(0x55, 0xFF, 0xFF),
395 RGB(0xFF, 0x55, 0x55), RGB(0xFF, 0x55, 0xFF), RGB(0xFF, 0xFF, 0x55), RGB(0xFF, 0xFF, 0xFF)
396 };
397
398 static CONST COLORREF EgaPalette___16ColorFixed_DOSBox[VGA_MAX_COLORS / 4] =
399 {
400 RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0xAA), RGB(0x00, 0xAA, 0x00), RGB(0x00, 0xAA, 0xAA),
401 RGB(0xAA, 0x00, 0x00), RGB(0xAA, 0x00, 0xAA), RGB(0xAA, 0x55, 0x00), RGB(0xAA, 0xAA, 0xAA),
402
403 RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0xAA), RGB(0x00, 0xAA, 0x00), RGB(0x00, 0xAA, 0xAA),
404 RGB(0xAA, 0x00, 0x00), RGB(0xAA, 0x00, 0xAA), RGB(0xAA, 0x55, 0x00), RGB(0xAA, 0xAA, 0xAA),
405
406
407 RGB(0x55, 0x55, 0x55), RGB(0x55, 0x55, 0xFF), RGB(0x55, 0xFF, 0x55), RGB(0x55, 0xFF, 0xFF),
408 RGB(0xFF, 0x55, 0x55), RGB(0xFF, 0x55, 0xFF), RGB(0xFF, 0xFF, 0x55), RGB(0xFF, 0xFF, 0xFF),
409
410 RGB(0x55, 0x55, 0x55), RGB(0x55, 0x55, 0xFF), RGB(0x55, 0xFF, 0x55), RGB(0x55, 0xFF, 0xFF),
411 RGB(0xFF, 0x55, 0x55), RGB(0xFF, 0x55, 0xFF), RGB(0xFF, 0xFF, 0x55), RGB(0xFF, 0xFF, 0xFF),
412
413
414
415 RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0xAA), RGB(0x00, 0xAA, 0x00), RGB(0x00, 0xAA, 0xAA),
416 RGB(0xAA, 0x00, 0x00), RGB(0xAA, 0x00, 0xAA), RGB(0xAA, 0x55, 0x00), RGB(0xAA, 0xAA, 0xAA),
417
418 RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0xAA), RGB(0x00, 0xAA, 0x00), RGB(0x00, 0xAA, 0xAA),
419 RGB(0xAA, 0x00, 0x00), RGB(0xAA, 0x00, 0xAA), RGB(0xAA, 0x55, 0x00), RGB(0xAA, 0xAA, 0xAA),
420
421
422 RGB(0x55, 0x55, 0x55), RGB(0x55, 0x55, 0xFF), RGB(0x55, 0xFF, 0x55), RGB(0x55, 0xFF, 0xFF),
423 RGB(0xFF, 0x55, 0x55), RGB(0xFF, 0x55, 0xFF), RGB(0xFF, 0xFF, 0x55), RGB(0xFF, 0xFF, 0xFF),
424
425 RGB(0x55, 0x55, 0x55), RGB(0x55, 0x55, 0xFF), RGB(0x55, 0xFF, 0x55), RGB(0x55, 0xFF, 0xFF),
426 RGB(0xFF, 0x55, 0x55), RGB(0xFF, 0x55, 0xFF), RGB(0xFF, 0xFF, 0x55), RGB(0xFF, 0xFF, 0xFF)
427 };
428
429 // This is the same as TextPalette
430 static CONST COLORREF EgaPalette__HiRes[VGA_MAX_COLORS / 4] =
431 {
432 RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0xAA), RGB(0x00, 0xAA, 0x00), RGB(0x00, 0xAA, 0xAA),
433 RGB(0xAA, 0x00, 0x00), RGB(0xAA, 0x00, 0xAA), RGB(0xAA, 0xAA, 0x00), RGB(0xAA, 0xAA, 0xAA),
434 RGB(0x00, 0x00, 0x55), RGB(0x00, 0x00, 0xFF), RGB(0x00, 0xAA, 0x55), RGB(0x00, 0xAA, 0xFF),
435 RGB(0xAA, 0x00, 0x55), RGB(0xAA, 0x00, 0xFF), RGB(0xAA, 0xAA, 0x55), RGB(0xAA, 0xAA, 0xFF),
436
437 RGB(0x00, 0x55, 0x00), RGB(0x00, 0x55, 0xAA), RGB(0x00, 0xFF, 0x00), RGB(0x00, 0xFF, 0xAA),
438 RGB(0xAA, 0x55, 0x00), RGB(0xAA, 0x55, 0xAA), RGB(0xAA, 0xFF, 0x00), RGB(0xAA, 0xFF, 0xAA),
439 RGB(0x00, 0x55, 0x55), RGB(0x00, 0x55, 0xFF), RGB(0x00, 0xFF, 0x55), RGB(0x00, 0xFF, 0xFF),
440 RGB(0xAA, 0x55, 0x55), RGB(0xAA, 0x55, 0xFF), RGB(0xAA, 0xFF, 0x55), RGB(0xAA, 0xFF, 0xFF),
441
442
443 RGB(0x55, 0x00, 0x00), RGB(0x55, 0x00, 0xAA), RGB(0x55, 0xAA, 0x00), RGB(0x55, 0xAA, 0xAA),
444 RGB(0xFF, 0x00, 0x00), RGB(0xFF, 0x00, 0xAA), RGB(0xFF, 0xAA, 0x00), RGB(0xFF, 0xAA, 0xAA),
445 RGB(0x55, 0x00, 0x55), RGB(0x55, 0x00, 0xFF), RGB(0x55, 0xAA, 0x55), RGB(0x55, 0xAA, 0xFF),
446 RGB(0xFF, 0x00, 0x55), RGB(0xFF, 0x00, 0xFF), RGB(0xFF, 0xAA, 0x55), RGB(0xFF, 0xAA, 0xFF),
447
448 RGB(0x55, 0x55, 0x00), RGB(0x55, 0x55, 0xAA), RGB(0x55, 0xFF, 0x00), RGB(0x55, 0xFF, 0xAA),
449 RGB(0xFF, 0x55, 0x00), RGB(0xFF, 0x55, 0xAA), RGB(0xFF, 0xFF, 0x00), RGB(0xFF, 0xFF, 0xAA),
450 RGB(0x55, 0x55, 0x55), RGB(0x55, 0x55, 0xFF), RGB(0x55, 0xFF, 0x55), RGB(0x55, 0xFF, 0xFF),
451 RGB(0xFF, 0x55, 0x55), RGB(0xFF, 0x55, 0xFF), RGB(0xFF, 0xFF, 0x55), RGB(0xFF, 0xFF, 0xFF)
452 };
453
454 #define USE_REACTOS_COLORS
455 // #define USE_DOSBOX_COLORS
456
457 /*
458 * Same palette as the default one 'VgaDefaultPalette' in vga.c
459 */
460 #if defined(USE_REACTOS_COLORS)
461
462 // ReactOS colors
463 static CONST COLORREF VgaPalette[VGA_MAX_COLORS] =
464 {
465 RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0xAA), RGB(0x00, 0xAA, 0x00), RGB(0x00, 0xAA, 0xAA),
466 RGB(0xAA, 0x00, 0x00), RGB(0xAA, 0x00, 0xAA), RGB(0xAA, 0x55, 0x00), RGB(0xAA, 0xAA, 0xAA),
467 RGB(0x55, 0x55, 0x55), RGB(0x55, 0x55, 0xFF), RGB(0x55, 0xFF, 0x55), RGB(0x55, 0xFF, 0xFF),
468 RGB(0xFF, 0x55, 0x55), RGB(0xFF, 0x55, 0xFF), RGB(0xFF, 0xFF, 0x55), RGB(0xFF, 0xFF, 0xFF),
469 RGB(0x00, 0x00, 0x00), RGB(0x10, 0x10, 0x10), RGB(0x20, 0x20, 0x20), RGB(0x35, 0x35, 0x35),
470 RGB(0x45, 0x45, 0x45), RGB(0x55, 0x55, 0x55), RGB(0x65, 0x65, 0x65), RGB(0x75, 0x75, 0x75),
471 RGB(0x8A, 0x8A, 0x8A), RGB(0x9A, 0x9A, 0x9A), RGB(0xAA, 0xAA, 0xAA), RGB(0xBA, 0xBA, 0xBA),
472 RGB(0xCA, 0xCA, 0xCA), RGB(0xDF, 0xDF, 0xDF), RGB(0xEF, 0xEF, 0xEF), RGB(0xFF, 0xFF, 0xFF),
473 RGB(0x00, 0x00, 0xFF), RGB(0x41, 0x00, 0xFF), RGB(0x82, 0x00, 0xFF), RGB(0xBE, 0x00, 0xFF),
474 RGB(0xFF, 0x00, 0xFF), RGB(0xFF, 0x00, 0xBE), RGB(0xFF, 0x00, 0x82), RGB(0xFF, 0x00, 0x41),
475 RGB(0xFF, 0x00, 0x00), RGB(0xFF, 0x41, 0x00), RGB(0xFF, 0x82, 0x00), RGB(0xFF, 0xBE, 0x00),
476 RGB(0xFF, 0xFF, 0x00), RGB(0xBE, 0xFF, 0x00), RGB(0x82, 0xFF, 0x00), RGB(0x41, 0xFF, 0x00),
477 RGB(0x00, 0xFF, 0x00), RGB(0x00, 0xFF, 0x41), RGB(0x00, 0xFF, 0x82), RGB(0x00, 0xFF, 0xBE),
478 RGB(0x00, 0xFF, 0xFF), RGB(0x00, 0xBE, 0xFF), RGB(0x00, 0x82, 0xFF), RGB(0x00, 0x41, 0xFF),
479 RGB(0x82, 0x82, 0xFF), RGB(0x9E, 0x82, 0xFF), RGB(0xBE, 0x82, 0xFF), RGB(0xDF, 0x82, 0xFF),
480 RGB(0xFF, 0x82, 0xFF), RGB(0xFF, 0x82, 0xDF), RGB(0xFF, 0x82, 0xBE), RGB(0xFF, 0x82, 0x9E),
481 RGB(0xFF, 0x82, 0x82), RGB(0xFF, 0x9E, 0x82), RGB(0xFF, 0xBE, 0x82), RGB(0xFF, 0xDF, 0x82),
482 RGB(0xFF, 0xFF, 0x82), RGB(0xDF, 0xFF, 0x82), RGB(0xBE, 0xFF, 0x82), RGB(0x9E, 0xFF, 0x82),
483 RGB(0x82, 0xFF, 0x82), RGB(0x82, 0xFF, 0x9E), RGB(0x82, 0xFF, 0xBE), RGB(0x82, 0xFF, 0xDF),
484 RGB(0x82, 0xFF, 0xFF), RGB(0x82, 0xDF, 0xFF), RGB(0x82, 0xBE, 0xFF), RGB(0x82, 0x9E, 0xFF),
485 RGB(0xBA, 0xBA, 0xFF), RGB(0xCA, 0xBA, 0xFF), RGB(0xDF, 0xBA, 0xFF), RGB(0xEF, 0xBA, 0xFF),
486 RGB(0xFF, 0xBA, 0xFF), RGB(0xFF, 0xBA, 0xEF), RGB(0xFF, 0xBA, 0xDF), RGB(0xFF, 0xBA, 0xCA),
487 RGB(0xFF, 0xBA, 0xBA), RGB(0xFF, 0xCA, 0xBA), RGB(0xFF, 0xDF, 0xBA), RGB(0xFF, 0xEF, 0xBA),
488 RGB(0xFF, 0xFF, 0xBA), RGB(0xEF, 0xFF, 0xBA), RGB(0xDF, 0xFF, 0xBA), RGB(0xCA, 0xFF, 0xBA),
489 RGB(0xBA, 0xFF, 0xBA), RGB(0xBA, 0xFF, 0xCA), RGB(0xBA, 0xFF, 0xDF), RGB(0xBA, 0xFF, 0xEF),
490 RGB(0xBA, 0xFF, 0xFF), RGB(0xBA, 0xEF, 0xFF), RGB(0xBA, 0xDF, 0xFF), RGB(0xBA, 0xCA, 0xFF),
491 RGB(0x00, 0x00, 0x71), RGB(0x1C, 0x00, 0x71), RGB(0x39, 0x00, 0x71), RGB(0x55, 0x00, 0x71),
492 RGB(0x71, 0x00, 0x71), RGB(0x71, 0x00, 0x55), RGB(0x71, 0x00, 0x39), RGB(0x71, 0x00, 0x1C),
493 RGB(0x71, 0x00, 0x00), RGB(0x71, 0x1C, 0x00), RGB(0x71, 0x39, 0x00), RGB(0x71, 0x55, 0x00),
494 RGB(0x71, 0x71, 0x00), RGB(0x55, 0x71, 0x00), RGB(0x39, 0x71, 0x00), RGB(0x1C, 0x71, 0x00),
495 RGB(0x00, 0x71, 0x00), RGB(0x00, 0x71, 0x1C), RGB(0x00, 0x71, 0x39), RGB(0x00, 0x71, 0x55),
496 RGB(0x00, 0x71, 0x71), RGB(0x00, 0x55, 0x71), RGB(0x00, 0x39, 0x71), RGB(0x00, 0x1C, 0x71),
497 RGB(0x39, 0x39, 0x71), RGB(0x45, 0x39, 0x71), RGB(0x55, 0x39, 0x71), RGB(0x61, 0x39, 0x71),
498 RGB(0x71, 0x39, 0x71), RGB(0x71, 0x39, 0x61), RGB(0x71, 0x39, 0x55), RGB(0x71, 0x39, 0x45),
499 RGB(0x71, 0x39, 0x39), RGB(0x71, 0x45, 0x39), RGB(0x71, 0x55, 0x39), RGB(0x71, 0x61, 0x39),
500 RGB(0x71, 0x71, 0x39), RGB(0x61, 0x71, 0x39), RGB(0x55, 0x71, 0x39), RGB(0x45, 0x71, 0x39),
501 RGB(0x39, 0x71, 0x39), RGB(0x39, 0x71, 0x45), RGB(0x39, 0x71, 0x55), RGB(0x39, 0x71, 0x61),
502 RGB(0x39, 0x71, 0x71), RGB(0x39, 0x61, 0x71), RGB(0x39, 0x55, 0x71), RGB(0x39, 0x45, 0x71),
503 RGB(0x51, 0x51, 0x71), RGB(0x59, 0x51, 0x71), RGB(0x61, 0x51, 0x71), RGB(0x69, 0x51, 0x71),
504 RGB(0x71, 0x51, 0x71), RGB(0x71, 0x51, 0x69), RGB(0x71, 0x51, 0x61), RGB(0x71, 0x51, 0x59),
505 RGB(0x71, 0x51, 0x51), RGB(0x71, 0x59, 0x51), RGB(0x71, 0x61, 0x51), RGB(0x71, 0x69, 0x51),
506 RGB(0x71, 0x71, 0x51), RGB(0x69, 0x71, 0x51), RGB(0x61, 0x71, 0x51), RGB(0x59, 0x71, 0x51),
507 RGB(0x51, 0x71, 0x51), RGB(0x51, 0x71, 0x59), RGB(0x51, 0x71, 0x61), RGB(0x51, 0x71, 0x69),
508 RGB(0x51, 0x71, 0x71), RGB(0x51, 0x69, 0x71), RGB(0x51, 0x61, 0x71), RGB(0x51, 0x59, 0x71),
509 RGB(0x00, 0x00, 0x41), RGB(0x10, 0x00, 0x41), RGB(0x20, 0x00, 0x41), RGB(0x31, 0x00, 0x41),
510 RGB(0x41, 0x00, 0x41), RGB(0x41, 0x00, 0x31), RGB(0x41, 0x00, 0x20), RGB(0x41, 0x00, 0x10),
511 RGB(0x41, 0x00, 0x00), RGB(0x41, 0x10, 0x00), RGB(0x41, 0x20, 0x00), RGB(0x41, 0x31, 0x00),
512 RGB(0x41, 0x41, 0x00), RGB(0x31, 0x41, 0x00), RGB(0x20, 0x41, 0x00), RGB(0x10, 0x41, 0x00),
513 RGB(0x00, 0x41, 0x00), RGB(0x00, 0x41, 0x10), RGB(0x00, 0x41, 0x20), RGB(0x00, 0x41, 0x31),
514 RGB(0x00, 0x41, 0x41), RGB(0x00, 0x31, 0x41), RGB(0x00, 0x20, 0x41), RGB(0x00, 0x10, 0x41),
515 RGB(0x20, 0x20, 0x41), RGB(0x28, 0x20, 0x41), RGB(0x31, 0x20, 0x41), RGB(0x39, 0x20, 0x41),
516 RGB(0x41, 0x20, 0x41), RGB(0x41, 0x20, 0x39), RGB(0x41, 0x20, 0x31), RGB(0x41, 0x20, 0x28),
517 RGB(0x41, 0x20, 0x20), RGB(0x41, 0x28, 0x20), RGB(0x41, 0x31, 0x20), RGB(0x41, 0x39, 0x20),
518 RGB(0x41, 0x41, 0x20), RGB(0x39, 0x41, 0x20), RGB(0x31, 0x41, 0x20), RGB(0x28, 0x41, 0x20),
519 RGB(0x20, 0x41, 0x20), RGB(0x20, 0x41, 0x28), RGB(0x20, 0x41, 0x31), RGB(0x20, 0x41, 0x39),
520 RGB(0x20, 0x41, 0x41), RGB(0x20, 0x39, 0x41), RGB(0x20, 0x31, 0x41), RGB(0x20, 0x28, 0x41),
521 RGB(0x2D, 0x2D, 0x41), RGB(0x31, 0x2D, 0x41), RGB(0x35, 0x2D, 0x41), RGB(0x3D, 0x2D, 0x41),
522 RGB(0x41, 0x2D, 0x41), RGB(0x41, 0x2D, 0x3D), RGB(0x41, 0x2D, 0x35), RGB(0x41, 0x2D, 0x31),
523 RGB(0x41, 0x2D, 0x2D), RGB(0x41, 0x31, 0x2D), RGB(0x41, 0x35, 0x2D), RGB(0x41, 0x3D, 0x2D),
524 RGB(0x41, 0x41, 0x2D), RGB(0x3D, 0x41, 0x2D), RGB(0x35, 0x41, 0x2D), RGB(0x31, 0x41, 0x2D),
525 RGB(0x2D, 0x41, 0x2D), RGB(0x2D, 0x41, 0x31), RGB(0x2D, 0x41, 0x35), RGB(0x2D, 0x41, 0x3D),
526 RGB(0x2D, 0x41, 0x41), RGB(0x2D, 0x3D, 0x41), RGB(0x2D, 0x35, 0x41), RGB(0x2D, 0x31, 0x41),
527 RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00),
528 RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00)
529 };
530
531 #elif defined(USE_DOSBOX_COLORS)
532
533 // DOSBox colors
534 static CONST COLORREF VgaPalette[VGA_MAX_COLORS] =
535 {
536 RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0xAA), RGB(0x00, 0xAA, 0x00), RGB(0x00, 0xAA, 0xAA),
537 RGB(0xAA, 0x00, 0x00), RGB(0xAA, 0x00, 0xAA), RGB(0xAA, 0x55, 0x00), RGB(0xAA, 0xAA, 0xAA),
538 RGB(0x55, 0x55, 0x55), RGB(0x55, 0x55, 0xFF), RGB(0x55, 0xFF, 0x55), RGB(0x55, 0xFF, 0xFF),
539 RGB(0xFF, 0x55, 0x55), RGB(0xFF, 0x55, 0xFF), RGB(0xFF, 0xFF, 0x55), RGB(0xFF, 0xFF, 0xFF),
540 RGB(0x00, 0x00, 0x00), RGB(0x14, 0x14, 0x14), RGB(0x20, 0x20, 0x20), RGB(0x2C, 0x2C, 0x2C),
541 RGB(0x38, 0x38, 0x38), RGB(0x45, 0x45, 0x45), RGB(0x51, 0x51, 0x51), RGB(0x61, 0x61, 0x61),
542 RGB(0x71, 0x71, 0x71), RGB(0x82, 0x82, 0x82), RGB(0x92, 0x92, 0x92), RGB(0xA2, 0xA2, 0xA2),
543 RGB(0xB6, 0xB6, 0xB6), RGB(0xCB, 0xCB, 0xCB), RGB(0xE3, 0xE3, 0xE3), RGB(0xFF, 0xFF, 0xFF),
544 RGB(0x00, 0x00, 0xFF), RGB(0x41, 0x00, 0xFF), RGB(0x7D, 0x00, 0xFF), RGB(0xBE, 0x00, 0xFF),
545 RGB(0xFF, 0x00, 0xFF), RGB(0xFF, 0x00, 0xBE), RGB(0xFF, 0x00, 0x7D), RGB(0xFF, 0x00, 0x41),
546 RGB(0xFF, 0x00, 0x00), RGB(0xFF, 0x41, 0x00), RGB(0xFF, 0x7D, 0x00), RGB(0xFF, 0xBE, 0x00),
547 RGB(0xFF, 0xFF, 0x00), RGB(0xBE, 0xFF, 0x00), RGB(0x7D, 0xFF, 0x00), RGB(0x41, 0xFF, 0x00),
548 RGB(0x00, 0xFF, 0x00), RGB(0x00, 0xFF, 0x41), RGB(0x00, 0xFF, 0x7D), RGB(0x00, 0xFF, 0xBE),
549 RGB(0x00, 0xFF, 0xFF), RGB(0x00, 0xBE, 0xFF), RGB(0x00, 0x7D, 0xFF), RGB(0x00, 0x41, 0xFF),
550 RGB(0x7D, 0x7D, 0xFF), RGB(0x9E, 0x7D, 0xFF), RGB(0xBE, 0x7D, 0xFF), RGB(0xDF, 0x7D, 0xFF),
551 RGB(0xFF, 0x7D, 0xFF), RGB(0xFF, 0x7D, 0xDF), RGB(0xFF, 0x7D, 0xBE), RGB(0xFF, 0x7D, 0x9E),
552
553 RGB(0xFF, 0x7D, 0x7D), RGB(0xFF, 0x9E, 0x7D), RGB(0xFF, 0xBE, 0x7D), RGB(0xFF, 0xDF, 0x7D),
554 RGB(0xFF, 0xFF, 0x7D), RGB(0xDF, 0xFF, 0x7D), RGB(0xBE, 0xFF, 0x7D), RGB(0x9E, 0xFF, 0x7D),
555 RGB(0x7D, 0xFF, 0x7D), RGB(0x7D, 0xFF, 0x9E), RGB(0x7D, 0xFF, 0xBE), RGB(0x7D, 0xFF, 0xDF),
556 RGB(0x7D, 0xFF, 0xFF), RGB(0x7D, 0xDF, 0xFF), RGB(0x7D, 0xBE, 0xFF), RGB(0x7D, 0x9E, 0xFF),
557 RGB(0xB6, 0xB6, 0xFF), RGB(0xC7, 0xB6, 0xFF), RGB(0xDB, 0xB6, 0xFF), RGB(0xEB, 0xB6, 0xFF),
558 RGB(0xFF, 0xB6, 0xFF), RGB(0xFF, 0xB6, 0xEB), RGB(0xFF, 0xB6, 0xDB), RGB(0xFF, 0xB6, 0xC7),
559 RGB(0xFF, 0xB6, 0xB6), RGB(0xFF, 0xC7, 0xB6), RGB(0xFF, 0xDB, 0xB6), RGB(0xFF, 0xEB, 0xB6),
560 RGB(0xFF, 0xFF, 0xB6), RGB(0xEB, 0xFF, 0xB6), RGB(0xDB, 0xFF, 0xB6), RGB(0xC7, 0xFF, 0xB6),
561 RGB(0xB6, 0xFF, 0xB6), RGB(0xB6, 0xFF, 0xC7), RGB(0xB6, 0xFF, 0xDB), RGB(0xB6, 0xFF, 0xEB),
562 RGB(0xB6, 0xFF, 0xFF), RGB(0xB6, 0xEB, 0xFF), RGB(0xB6, 0xDB, 0xFF), RGB(0xB6, 0xC7, 0xFF),
563 RGB(0x00, 0x00, 0x71), RGB(0x1C, 0x00, 0x71), RGB(0x38, 0x00, 0x71), RGB(0x55, 0x00, 0x71),
564 RGB(0x71, 0x00, 0x71), RGB(0x71, 0x00, 0x55), RGB(0x71, 0x00, 0x38), RGB(0x71, 0x00, 0x1C),
565 RGB(0x71, 0x00, 0x00), RGB(0x71, 0x1C, 0x00), RGB(0x71, 0x38, 0x00), RGB(0x71, 0x55, 0x00),
566 RGB(0x71, 0x71, 0x00), RGB(0x55, 0x71, 0x00), RGB(0x38, 0x71, 0x00), RGB(0x1C, 0x71, 0x00),
567 RGB(0x00, 0x71, 0x00), RGB(0x00, 0x71, 0x1C), RGB(0x00, 0x71, 0x38), RGB(0x00, 0x71, 0x55),
568 RGB(0x00, 0x71, 0x71), RGB(0x00, 0x55, 0x71), RGB(0x00, 0x38, 0x71), RGB(0x00, 0x1C, 0x71),
569
570 RGB(0x38, 0x38, 0x71), RGB(0x45, 0x38, 0x71), RGB(0x55, 0x38, 0x71), RGB(0x61, 0x38, 0x71),
571 RGB(0x71, 0x38, 0x71), RGB(0x71, 0x38, 0x61), RGB(0x71, 0x38, 0x55), RGB(0x71, 0x38, 0x45),
572 RGB(0x71, 0x38, 0x38), RGB(0x71, 0x45, 0x38), RGB(0x71, 0x55, 0x38), RGB(0x71, 0x61, 0x38),
573 RGB(0x71, 0x71, 0x38), RGB(0x61, 0x71, 0x38), RGB(0x55, 0x71, 0x38), RGB(0x45, 0x71, 0x38),
574 RGB(0x38, 0x71, 0x38), RGB(0x38, 0x71, 0x45), RGB(0x38, 0x71, 0x55), RGB(0x38, 0x71, 0x61),
575 RGB(0x38, 0x71, 0x71), RGB(0x38, 0x61, 0x71), RGB(0x38, 0x55, 0x71), RGB(0x38, 0x45, 0x71),
576 RGB(0x51, 0x51, 0x71), RGB(0x59, 0x51, 0x71), RGB(0x61, 0x51, 0x71), RGB(0x69, 0x51, 0x71),
577 RGB(0x71, 0x51, 0x71), RGB(0x71, 0x51, 0x69), RGB(0x71, 0x51, 0x61), RGB(0x71, 0x51, 0x59),
578 RGB(0x71, 0x51, 0x51), RGB(0x71, 0x59, 0x51), RGB(0x71, 0x61, 0x51), RGB(0x71, 0x69, 0x51),
579 RGB(0x71, 0x71, 0x51), RGB(0x69, 0x71, 0x51), RGB(0x61, 0x71, 0x51), RGB(0x59, 0x71, 0x51),
580 RGB(0x51, 0x71, 0x51), RGB(0x51, 0x71, 0x59), RGB(0x51, 0x71, 0x61), RGB(0x51, 0x71, 0x69),
581 RGB(0x51, 0x71, 0x71), RGB(0x51, 0x69, 0x71), RGB(0x51, 0x61, 0x71), RGB(0x51, 0x59, 0x71),
582 RGB(0x00, 0x00, 0x41), RGB(0x10, 0x00, 0x41), RGB(0x20, 0x00, 0x41), RGB(0x30, 0x00, 0x41),
583 RGB(0x41, 0x00, 0x41), RGB(0x41, 0x00, 0x30), RGB(0x41, 0x00, 0x20), RGB(0x41, 0x00, 0x10),
584 RGB(0x41, 0x00, 0x00), RGB(0x41, 0x10, 0x00), RGB(0x41, 0x20, 0x00), RGB(0x41, 0x30, 0x00),
585 RGB(0x41, 0x41, 0x00), RGB(0x30, 0x41, 0x00), RGB(0x20, 0x41, 0x00), RGB(0x10, 0x41, 0x00),
586
587 RGB(0x00, 0x41, 0x00), RGB(0x00, 0x41, 0x10), RGB(0x00, 0x41, 0x20), RGB(0x00, 0x41, 0x30),
588 RGB(0x00, 0x41, 0x41), RGB(0x00, 0x30, 0x41), RGB(0x00, 0x20, 0x41), RGB(0x00, 0x10, 0x41),
589 RGB(0x20, 0x20, 0x41), RGB(0x28, 0x20, 0x41), RGB(0x30, 0x20, 0x41), RGB(0x38, 0x20, 0x41),
590 RGB(0x41, 0x20, 0x41), RGB(0x41, 0x20, 0x38), RGB(0x41, 0x20, 0x30), RGB(0x41, 0x20, 0x28),
591 RGB(0x41, 0x20, 0x20), RGB(0x41, 0x28, 0x20), RGB(0x41, 0x30, 0x20), RGB(0x41, 0x38, 0x20),
592 RGB(0x41, 0x41, 0x20), RGB(0x38, 0x41, 0x20), RGB(0x30, 0x41, 0x20), RGB(0x28, 0x41, 0x20),
593 RGB(0x20, 0x41, 0x20), RGB(0x20, 0x41, 0x28), RGB(0x20, 0x41, 0x30), RGB(0x20, 0x41, 0x38),
594 RGB(0x20, 0x41, 0x41), RGB(0x20, 0x38, 0x41), RGB(0x20, 0x30, 0x41), RGB(0x20, 0x28, 0x41),
595 RGB(0x2C, 0x2C, 0x41), RGB(0x30, 0x2C, 0x41), RGB(0x34, 0x2C, 0x41), RGB(0x3C, 0x2C, 0x41),
596 RGB(0x41, 0x2C, 0x41), RGB(0x41, 0x2C, 0x3C), RGB(0x41, 0x2C, 0x34), RGB(0x41, 0x2C, 0x30),
597 RGB(0x41, 0x2C, 0x2C), RGB(0x41, 0x30, 0x2C), RGB(0x41, 0x34, 0x2C), RGB(0x41, 0x3C, 0x2C),
598 RGB(0x41, 0x41, 0x2C), RGB(0x3C, 0x41, 0x2C), RGB(0x34, 0x41, 0x2C), RGB(0x30, 0x41, 0x2C),
599 RGB(0x2C, 0x41, 0x2C), RGB(0x2C, 0x41, 0x30), RGB(0x2C, 0x41, 0x34), RGB(0x2C, 0x41, 0x3C),
600 RGB(0x2C, 0x41, 0x41), RGB(0x2C, 0x3C, 0x41), RGB(0x2C, 0x34, 0x41), RGB(0x2C, 0x30, 0x41),
601 RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00),
602 RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00)
603 };
604
605 #endif
606
607 /* PRIVATE FUNCTIONS **********************************************************/
608
609 static VOID VidBiosReadWindow(LPWORD Buffer, SMALL_RECT Rectangle, BYTE Page)
610 {
611 INT i, j;
612 INT Counter = 0;
613 WORD Character;
614 DWORD VideoAddress = TO_LINEAR(TEXT_VIDEO_SEG, Page * Bda->VideoPageSize);
615
616 for (i = Rectangle.Top; i <= Rectangle.Bottom; i++)
617 {
618 for (j = Rectangle.Left; j <= Rectangle.Right; j++)
619 {
620 /* Read from video memory */
621 VgaReadMemory(VideoAddress + (i * Bda->ScreenColumns + j) * sizeof(WORD),
622 (LPVOID)&Character,
623 sizeof(WORD));
624
625 /* Write the data to the buffer in row order */
626 Buffer[Counter++] = Character;
627 }
628 }
629 }
630
631 static VOID VidBiosWriteWindow(LPWORD Buffer, SMALL_RECT Rectangle, BYTE Page)
632 {
633 INT i, j;
634 INT Counter = 0;
635 WORD Character;
636 DWORD VideoAddress = TO_LINEAR(TEXT_VIDEO_SEG, Page * Bda->VideoPageSize);
637
638 for (i = Rectangle.Top; i <= Rectangle.Bottom; i++)
639 {
640 for (j = Rectangle.Left; j <= Rectangle.Right; j++)
641 {
642 Character = Buffer[Counter++];
643
644 /* Write to video memory */
645 VgaWriteMemory(VideoAddress + (i * Bda->ScreenColumns + j) * sizeof(WORD),
646 (LPVOID)&Character,
647 sizeof(WORD));
648 }
649 }
650 }
651
652 static BOOLEAN VidBiosScrollWindow(INT Direction,
653 DWORD Amount,
654 SMALL_RECT Rectangle,
655 BYTE Page,
656 BYTE FillAttribute)
657 {
658 DWORD i;
659 LPWORD WindowData;
660 WORD WindowWidth = Rectangle.Right - Rectangle.Left + 1;
661 WORD WindowHeight = Rectangle.Bottom - Rectangle.Top + 1;
662 DWORD WindowSize = WindowWidth * WindowHeight;
663
664 /* Allocate a buffer for the window */
665 WindowData = (LPWORD)HeapAlloc(GetProcessHeap(),
666 HEAP_ZERO_MEMORY,
667 WindowSize * sizeof(WORD));
668 if (WindowData == NULL) return FALSE;
669
670 /* Read the window data */
671 VidBiosReadWindow(WindowData, Rectangle, Page);
672
673 if ((Amount == 0)
674 || (((Direction == SCROLL_DIRECTION_UP)
675 || (Direction == SCROLL_DIRECTION_DOWN))
676 && (Amount >= WindowHeight))
677 || (((Direction == SCROLL_DIRECTION_LEFT)
678 || (Direction == SCROLL_DIRECTION_RIGHT))
679 && (Amount >= WindowWidth)))
680 {
681 /* Fill the window */
682 for (i = 0; i < WindowSize; i++)
683 {
684 WindowData[i] = MAKEWORD(' ', FillAttribute);
685 }
686
687 goto Done;
688 }
689
690 switch (Direction)
691 {
692 case SCROLL_DIRECTION_UP:
693 {
694 RtlMoveMemory(WindowData,
695 &WindowData[WindowWidth * Amount],
696 (WindowSize - WindowWidth * Amount) * sizeof(WORD));
697
698 for (i = 0; i < Amount * WindowWidth; i++)
699 {
700 WindowData[WindowSize - i - 1] = MAKEWORD(' ', FillAttribute);
701 }
702
703 break;
704 }
705
706 case SCROLL_DIRECTION_DOWN:
707 {
708 RtlMoveMemory(&WindowData[WindowWidth * Amount],
709 WindowData,
710 (WindowSize - WindowWidth * Amount) * sizeof(WORD));
711
712 for (i = 0; i < Amount * WindowWidth; i++)
713 {
714 WindowData[i] = MAKEWORD(' ', FillAttribute);
715 }
716
717 break;
718 }
719
720 default:
721 {
722 // TODO: NOT IMPLEMENTED!
723 UNIMPLEMENTED;
724 }
725 }
726
727 Done:
728 /* Write back the window data */
729 VidBiosWriteWindow(WindowData, Rectangle, Page);
730
731 /* Free the window buffer */
732 HeapFree(GetProcessHeap(), 0, WindowData);
733
734 return TRUE;
735 }
736
737 static VOID VidBiosCopyTextConsoleToVgaMemory(HANDLE ConsoleOutput, PCOORD ConsoleSize)
738 {
739 PCHAR_INFO CharBuffer;
740 COORD BufferSize = {Bda->ScreenColumns, Bda->ScreenRows + 1};
741 COORD Origin = { 0, 0 };
742 SMALL_RECT ConRect;
743
744 INT i, j;
745 INT Counter = 0;
746 WORD Character;
747 DWORD VideoAddress = TO_LINEAR(TEXT_VIDEO_SEG, Bda->VideoPage * Bda->VideoPageSize);
748
749 /* Allocate a temporary buffer for ReadConsoleOutput */
750 CharBuffer = HeapAlloc(GetProcessHeap(),
751 HEAP_ZERO_MEMORY,
752 BufferSize.X * BufferSize.Y
753 * sizeof(CHAR_INFO));
754 if (CharBuffer == NULL) return;
755
756 ConRect.Left = 0;
757 ConRect.Top = ConsoleSize->Y - BufferSize.Y;
758 ConRect.Right = ConRect.Left + BufferSize.X - 1;
759 ConRect.Bottom = ConRect.Top + BufferSize.Y - 1;
760
761 /* Read the data from the console into the temporary buffer... */
762 ReadConsoleOutputA(ConsoleOutput,
763 CharBuffer,
764 BufferSize,
765 Origin,
766 &ConRect);
767
768 /* ... and copy the temporary buffer into the VGA memory */
769 for (i = 0; i < BufferSize.Y; i++)
770 {
771 for (j = 0; j < BufferSize.X; j++)
772 {
773 Character = MAKEWORD(CharBuffer[Counter].Char.AsciiChar,
774 (BYTE)CharBuffer[Counter].Attributes);
775 ++Counter;
776
777 /* Write to video memory */
778 VgaWriteMemory(VideoAddress + (i * Bda->ScreenColumns + j) * sizeof(WORD),
779 (LPVOID)&Character,
780 sizeof(WORD));
781 }
782 }
783
784 /* Free the temporary buffer */
785 HeapFree(GetProcessHeap(), 0, CharBuffer);
786 }
787
788 static BOOLEAN VgaSetRegisters(PVGA_REGISTERS Registers)
789 {
790 INT i;
791
792 if (Registers == NULL) return FALSE;
793
794 /* Disable interrupts */
795 setIF(0);
796
797 /*
798 * Set the CRT base address according to the selected mode,
799 * monochrome or color. The following macros:
800 * VGA_INSTAT1_READ, VGA_CRTC_INDEX and VGA_CRTC_DATA are then
801 * used to access the correct VGA I/O ports.
802 */
803 Bda->CrtBasePort = (Registers->Misc & 0x01) ? VGA_CRTC_INDEX_COLOR
804 : VGA_CRTC_INDEX_MONO;
805
806 /* Write the misc register */
807 IOWriteB(VGA_MISC_WRITE, Registers->Misc);
808
809 /* Synchronous reset on */
810 IOWriteB(VGA_SEQ_INDEX, VGA_SEQ_RESET_REG);
811 IOWriteB(VGA_SEQ_DATA , VGA_SEQ_RESET_AR);
812
813 /* Write the sequencer registers */
814 for (i = 1; i < VGA_SEQ_MAX_REG; i++)
815 {
816 IOWriteB(VGA_SEQ_INDEX, i);
817 IOWriteB(VGA_SEQ_DATA, Registers->Sequencer[i]);
818 }
819
820 /* Synchronous reset off */
821 IOWriteB(VGA_SEQ_INDEX, VGA_SEQ_RESET_REG);
822 IOWriteB(VGA_SEQ_DATA , VGA_SEQ_RESET_SR | VGA_SEQ_RESET_AR);
823
824 /* Unlock CRTC registers 0-7 */
825 IOWriteB(VGA_CRTC_INDEX, VGA_CRTC_END_HORZ_BLANKING_REG);
826 IOWriteB(VGA_CRTC_DATA, IOReadB(VGA_CRTC_DATA) | 0x80);
827 IOWriteB(VGA_CRTC_INDEX, VGA_CRTC_VERT_RETRACE_END_REG);
828 IOWriteB(VGA_CRTC_DATA, IOReadB(VGA_CRTC_DATA) & ~0x80);
829 // Make sure they remain unlocked
830 Registers->CRT[VGA_CRTC_END_HORZ_BLANKING_REG] |= 0x80;
831 Registers->CRT[VGA_CRTC_VERT_RETRACE_END_REG] &= ~0x80;
832
833 /* Write the CRTC registers */
834 for (i = 0; i < VGA_CRTC_MAX_REG; i++)
835 {
836 IOWriteB(VGA_CRTC_INDEX, i);
837 IOWriteB(VGA_CRTC_DATA, Registers->CRT[i]);
838 }
839
840 /* Write the GC registers */
841 for (i = 0; i < VGA_GC_MAX_REG; i++)
842 {
843 IOWriteB(VGA_GC_INDEX, i);
844 IOWriteB(VGA_GC_DATA, Registers->Graphics[i]);
845 }
846
847 /* Write the AC registers */
848 // DbgPrint("\n");
849 for (i = 0; i < VGA_AC_MAX_REG; i++)
850 {
851 IOReadB(VGA_INSTAT1_READ); // Put the AC register into index state
852 IOWriteB(VGA_AC_INDEX, i);
853 IOWriteB(VGA_AC_WRITE, Registers->Attribute[i]);
854 // DbgPrint("Registers->Attribute[%d] = %d\n", i, Registers->Attribute[i]);
855 }
856 // DbgPrint("\n");
857
858 /* Set the PEL mask */
859 IOWriteB(VGA_DAC_MASK, 0xFF);
860
861 /* Enable screen and disable palette access */
862 IOReadB(VGA_INSTAT1_READ); // Put the AC register into index state
863 IOWriteB(VGA_AC_INDEX, 0x20);
864
865 /* Enable interrupts */
866 setIF(1);
867
868 return TRUE;
869 }
870
871 static VOID VgaSetPalette(const COLORREF* Palette, ULONG Size)
872 {
873 ULONG i;
874
875 // /* Disable screen and enable palette access */
876 // IOReadB(VGA_INSTAT1_READ); // Put the AC register into index state
877 // IOWriteB(VGA_AC_INDEX, 0x00);
878
879 for (i = 0; i < Size; i++)
880 {
881 IOWriteB(VGA_DAC_WRITE_INDEX, i);
882 IOWriteB(VGA_DAC_DATA, VGA_COLOR_TO_DAC(GetRValue(Palette[i])));
883 IOWriteB(VGA_DAC_DATA, VGA_COLOR_TO_DAC(GetGValue(Palette[i])));
884 IOWriteB(VGA_DAC_DATA, VGA_COLOR_TO_DAC(GetBValue(Palette[i])));
885 }
886
887 /* The following step might be optional */
888 for (i = Size; i < VGA_MAX_COLORS; i++)
889 {
890 IOWriteB(VGA_DAC_WRITE_INDEX, i);
891 IOWriteB(VGA_DAC_DATA, VGA_COLOR_TO_DAC(0x00));
892 IOWriteB(VGA_DAC_DATA, VGA_COLOR_TO_DAC(0x00));
893 IOWriteB(VGA_DAC_DATA, VGA_COLOR_TO_DAC(0x00));
894 }
895
896 /* Enable screen and disable palette access */
897 // IOReadB(VGA_INSTAT1_READ); // Put the AC register into index state
898 // IOWriteB(VGA_AC_INDEX, 0x20);
899 }
900
901 static VOID VgaChangePalette(BYTE ModeNumber)
902 {
903 const COLORREF* Palette;
904 ULONG Size;
905
906 if (ModeNumber >= 0x13)
907 {
908 /* VGA modes */
909 Palette = VgaPalette;
910 Size = sizeof(VgaPalette)/sizeof(VgaPalette[0]);
911 }
912 else if (ModeNumber == 0x10)
913 {
914 /* EGA HiRes mode */
915 Palette = EgaPalette__HiRes;
916 Size = sizeof(EgaPalette__HiRes)/sizeof(EgaPalette__HiRes[0]);
917 }
918 else // if ((ModeNumber == 0x0D) || (ModeNumber == 0x0E))
919 {
920 /* EGA modes */
921 Palette = EgaPalette___16ColorFixed_DOSBox;
922 Size = sizeof(EgaPalette___16ColorFixed_DOSBox)/sizeof(EgaPalette___16ColorFixed_DOSBox[0]);
923 }
924
925 VgaSetPalette(Palette, Size);
926 }
927
928 static VOID VidBiosGetCursorPosition(PBYTE Row, PBYTE Column, BYTE Page)
929 {
930 /* Make sure the selected video page is valid */
931 if (Page >= BIOS_MAX_PAGES) return;
932
933 /* Get the cursor location */
934 *Row = HIBYTE(Bda->CursorPosition[Page]);
935 *Column = LOBYTE(Bda->CursorPosition[Page]);
936 }
937
938 static VOID VidBiosSetCursorPosition(BYTE Row, BYTE Column, BYTE Page)
939 {
940 /* Make sure the selected video page is valid */
941 if (Page >= BIOS_MAX_PAGES) return;
942
943 /* Update the position in the BDA */
944 Bda->CursorPosition[Page] = MAKEWORD(Column, Row);
945
946 /* Check if this is the current video page */
947 if (Page == Bda->VideoPage)
948 {
949 WORD Offset = Row * Bda->ScreenColumns + Column;
950
951 /* Modify the CRTC registers */
952 IOWriteB(VGA_CRTC_INDEX, VGA_CRTC_CURSOR_LOC_LOW_REG);
953 IOWriteB(VGA_CRTC_DATA , LOBYTE(Offset));
954 IOWriteB(VGA_CRTC_INDEX, VGA_CRTC_CURSOR_LOC_HIGH_REG);
955 IOWriteB(VGA_CRTC_DATA , HIBYTE(Offset));
956 }
957 }
958
959 BYTE VidBiosGetVideoMode(VOID)
960 {
961 return Bda->VideoMode;
962 }
963
964 static BOOLEAN VidBiosSetVideoMode(BYTE ModeNumber)
965 {
966 BYTE Page;
967
968 COORD Resolution;
969 PVGA_REGISTERS VgaMode = VideoModes[ModeNumber];
970
971 DPRINT1("Switching to mode %Xh; VgaMode = 0x%p\n", ModeNumber, VgaMode);
972
973 if (!VgaSetRegisters(VgaMode)) return FALSE;
974
975 VgaChangePalette(ModeNumber);
976
977 /*
978 * IBM standard modes do not clear the screen if the
979 * high bit of AL is set (EGA or higher only).
980 * See Ralf Brown: http://www.ctyme.com/intr/rb-0069.htm
981 * for more information.
982 */
983 if ((ModeNumber & 0x08) == 0) VgaClearMemory();
984
985 // Bda->CrtModeControl;
986 // Bda->CrtColorPaletteMask;
987 // Bda->EGAFlags;
988 // Bda->VGAFlags;
989
990 /* Update the values in the BDA */
991 Bda->VideoMode = ModeNumber;
992 Bda->VideoPageSize = VideoModePageSize[ModeNumber];
993 Bda->VideoPage = 0;
994 Bda->VideoPageOffset = Bda->VideoPage * Bda->VideoPageSize;
995
996 /* Set the start address in the CRTC */
997 IOWriteB(VGA_CRTC_INDEX, VGA_CRTC_START_ADDR_LOW_REG);
998 IOWriteB(VGA_CRTC_DATA , LOBYTE(Bda->VideoPageOffset));
999 IOWriteB(VGA_CRTC_INDEX, VGA_CRTC_START_ADDR_HIGH_REG);
1000 IOWriteB(VGA_CRTC_DATA , HIBYTE(Bda->VideoPageOffset));
1001
1002 /* Get the character height */
1003 IOWriteB(VGA_CRTC_INDEX, VGA_CRTC_MAX_SCAN_LINE_REG);
1004 Bda->CharacterHeight = 1 + (IOReadB(VGA_CRTC_DATA) & 0x1F);
1005
1006 Resolution = VgaGetDisplayResolution();
1007 Bda->ScreenColumns = Resolution.X;
1008 Bda->ScreenRows = Resolution.Y - 1;
1009
1010 /* Set the cursor position for each page */
1011 for (Page = 0; Page < BIOS_MAX_PAGES; ++Page)
1012 VidBiosSetCursorPosition(0, 0, Page);
1013
1014 return TRUE;
1015 }
1016
1017 static BOOLEAN VidBiosSetVideoPage(BYTE PageNumber)
1018 {
1019 BYTE Row, Column;
1020
1021 /* Check if the page exists */
1022 if (PageNumber >= BIOS_MAX_PAGES) return FALSE;
1023
1024 /* Check if this is the same page */
1025 if (PageNumber == Bda->VideoPage) return TRUE;
1026
1027 /* Update the values in the BDA */
1028 Bda->VideoPage = PageNumber;
1029 Bda->VideoPageOffset = Bda->VideoPage * Bda->VideoPageSize;
1030
1031 /* Set the start address in the CRTC */
1032 IOWriteB(VGA_CRTC_INDEX, VGA_CRTC_START_ADDR_LOW_REG);
1033 IOWriteB(VGA_CRTC_DATA , LOBYTE(Bda->VideoPageOffset));
1034 IOWriteB(VGA_CRTC_INDEX, VGA_CRTC_START_ADDR_HIGH_REG);
1035 IOWriteB(VGA_CRTC_DATA , HIBYTE(Bda->VideoPageOffset));
1036
1037 /*
1038 * Get the cursor location (we don't update anything on the BIOS side
1039 * but we update the cursor location on the VGA side).
1040 */
1041 VidBiosGetCursorPosition(&Row, &Column, PageNumber);
1042 VidBiosSetCursorPosition(Row, Column, PageNumber);
1043
1044 return TRUE;
1045 }
1046
1047 static VOID WINAPI VidBiosVideoService(LPWORD Stack)
1048 {
1049 switch (getAH())
1050 {
1051 /* Set Video Mode */
1052 case 0x00:
1053 {
1054 VidBiosSetVideoMode(getAL());
1055 break;
1056 }
1057
1058 /* Set Text-Mode Cursor Shape */
1059 case 0x01:
1060 {
1061 /* Update the BDA */
1062 Bda->CursorStartLine = getCH();
1063 Bda->CursorEndLine = getCL();
1064
1065 /* Modify the CRTC registers */
1066 IOWriteB(VGA_CRTC_INDEX, VGA_CRTC_CURSOR_START_REG);
1067 IOWriteB(VGA_CRTC_DATA , Bda->CursorStartLine);
1068 IOWriteB(VGA_CRTC_INDEX, VGA_CRTC_CURSOR_END_REG);
1069 IOWriteB(VGA_CRTC_DATA , Bda->CursorEndLine);
1070
1071 break;
1072 }
1073
1074 /* Set Cursor Position */
1075 case 0x02:
1076 {
1077 VidBiosSetCursorPosition(getDH(), getDL(), getBH());
1078 break;
1079 }
1080
1081 /* Get Cursor Position */
1082 case 0x03:
1083 {
1084 /* Make sure the selected video page exists */
1085 if (getBH() >= BIOS_MAX_PAGES) break;
1086
1087 /* Return the result */
1088 setAX(0);
1089 setCX(MAKEWORD(Bda->CursorEndLine, Bda->CursorStartLine));
1090 setDX(Bda->CursorPosition[getBH()]);
1091 break;
1092 }
1093
1094 /* Query Light Pen */
1095 case 0x04:
1096 {
1097 /*
1098 * On modern BIOSes, this function returns 0
1099 * so that we can ignore the other registers.
1100 */
1101 setAX(0);
1102 break;
1103 }
1104
1105 /* Select Active Display Page */
1106 case 0x05:
1107 {
1108 VidBiosSetVideoPage(getAL());
1109 break;
1110 }
1111
1112 /* Scroll Window Up/Down */
1113 case 0x06:
1114 case 0x07:
1115 {
1116 SMALL_RECT Rectangle = { getCL(), getCH(), getDL(), getDH() };
1117
1118 /* Call the internal function */
1119 VidBiosScrollWindow((getAH() == 0x06) ? SCROLL_DIRECTION_UP
1120 : SCROLL_DIRECTION_DOWN,
1121 getAL(),
1122 Rectangle,
1123 Bda->VideoPage,
1124 getBH());
1125
1126 break;
1127 }
1128
1129 /* Read/Write Character From Cursor Position */
1130 case 0x08:
1131 case 0x09:
1132 case 0x0A:
1133 {
1134 WORD CharacterData = MAKEWORD(getAL(), getBL());
1135 BYTE Page = getBH();
1136 DWORD Offset;
1137
1138 /* Check if the page exists */
1139 if (Page >= BIOS_MAX_PAGES) break;
1140
1141 /* Find the offset of the character */
1142 Offset = Page * Bda->VideoPageSize +
1143 (HIBYTE(Bda->CursorPosition[Page]) * Bda->ScreenColumns +
1144 LOBYTE(Bda->CursorPosition[Page])) * 2;
1145
1146 if (getAH() == 0x08)
1147 {
1148 /* Read from the video memory */
1149 VgaReadMemory(TO_LINEAR(TEXT_VIDEO_SEG, Offset),
1150 (LPVOID)&CharacterData,
1151 sizeof(WORD));
1152
1153 /* Return the character in AX */
1154 setAX(CharacterData);
1155 }
1156 else
1157 {
1158 /* Write to video memory */
1159 VgaWriteMemory(TO_LINEAR(TEXT_VIDEO_SEG, Offset),
1160 (LPVOID)&CharacterData,
1161 (getBH() == 0x09) ? sizeof(WORD) : sizeof(BYTE));
1162 }
1163
1164 break;
1165 }
1166
1167 /* Teletype Output */
1168 case 0x0E:
1169 {
1170 VidBiosPrintCharacter(getAL(), getBL(), getBH());
1171 break;
1172 }
1173
1174 /* Get Current Video Mode */
1175 case 0x0F:
1176 {
1177 setAX(MAKEWORD(Bda->VideoMode, Bda->ScreenColumns));
1178 setBX(MAKEWORD(getBL(), Bda->VideoPage));
1179 break;
1180 }
1181
1182 /* Palette Control */
1183 case 0x10:
1184 {
1185 switch (getAL())
1186 {
1187 /* Set Single Palette Register */
1188 case 0x00:
1189 {
1190 /* Write the index */
1191 IOReadB(VGA_INSTAT1_READ); // Put the AC register into index state
1192 IOWriteB(VGA_AC_INDEX, getBL());
1193
1194 /* Write the data */
1195 IOWriteB(VGA_AC_WRITE, getBH());
1196
1197 /* Enable screen and disable palette access */
1198 IOReadB(VGA_INSTAT1_READ); // Put the AC register into index state
1199 IOWriteB(VGA_AC_INDEX, 0x20);
1200 break;
1201 }
1202
1203 /* Set Overscan Color */
1204 case 0x01:
1205 {
1206 /* Write the index */
1207 IOReadB(VGA_INSTAT1_READ); // Put the AC register into index state
1208 IOWriteB(VGA_AC_INDEX, VGA_AC_OVERSCAN_REG);
1209
1210 /* Write the data */
1211 IOWriteB(VGA_AC_WRITE, getBH());
1212
1213 /* Enable screen and disable palette access */
1214 IOReadB(VGA_INSTAT1_READ); // Put the AC register into index state
1215 IOWriteB(VGA_AC_INDEX, 0x20);
1216 break;
1217 }
1218
1219 /* Set All Palette Registers */
1220 case 0x02:
1221 {
1222 INT i;
1223 LPBYTE Buffer = SEG_OFF_TO_PTR(getES(), getDX());
1224
1225 /* Set the palette registers */
1226 for (i = 0; i <= VGA_AC_PAL_F_REG; i++)
1227 {
1228 /* Write the index */
1229 IOReadB(VGA_INSTAT1_READ); // Put the AC register into index state
1230 IOWriteB(VGA_AC_INDEX, i);
1231
1232 /* Write the data */
1233 IOWriteB(VGA_AC_WRITE, Buffer[i]);
1234 }
1235
1236 /* Set the overscan register */
1237 IOWriteB(VGA_AC_INDEX, VGA_AC_OVERSCAN_REG);
1238 IOWriteB(VGA_AC_WRITE, Buffer[VGA_AC_PAL_F_REG + 1]);
1239
1240 /* Enable screen and disable palette access */
1241 IOReadB(VGA_INSTAT1_READ); // Put the AC register into index state
1242 IOWriteB(VGA_AC_INDEX, 0x20);
1243 break;
1244 }
1245
1246 /* Get Single Palette Register */
1247 case 0x07:
1248 {
1249 /* Write the index */
1250 IOReadB(VGA_INSTAT1_READ); // Put the AC register into index state
1251 IOWriteB(VGA_AC_INDEX, getBL());
1252
1253 /* Read the data */
1254 setBH(IOReadB(VGA_AC_READ));
1255
1256 /* Enable screen and disable palette access */
1257 IOReadB(VGA_INSTAT1_READ); // Put the AC register into index state
1258 IOWriteB(VGA_AC_INDEX, 0x20);
1259 break;
1260 }
1261
1262 /* Get Overscan Color */
1263 case 0x08:
1264 {
1265 /* Write the index */
1266 IOReadB(VGA_INSTAT1_READ); // Put the AC register into index state
1267 IOWriteB(VGA_AC_INDEX, VGA_AC_OVERSCAN_REG);
1268
1269 /* Read the data */
1270 setBH(IOReadB(VGA_AC_READ));
1271
1272 /* Enable screen and disable palette access */
1273 IOReadB(VGA_INSTAT1_READ); // Put the AC register into index state
1274 IOWriteB(VGA_AC_INDEX, 0x20);
1275 break;
1276 }
1277
1278 /* Get All Palette Registers */
1279 case 0x09:
1280 {
1281 INT i;
1282 LPBYTE Buffer = SEG_OFF_TO_PTR(getES(), getDX());
1283
1284 /* Get the palette registers */
1285 for (i = 0; i <= VGA_AC_PAL_F_REG; i++)
1286 {
1287 /* Write the index */
1288 IOReadB(VGA_INSTAT1_READ); // Put the AC register into index state
1289 IOWriteB(VGA_AC_INDEX, i);
1290
1291 /* Read the data */
1292 Buffer[i] = IOReadB(VGA_AC_READ);
1293 }
1294
1295 /* Get the overscan register */
1296 IOWriteB(VGA_AC_INDEX, VGA_AC_OVERSCAN_REG);
1297 Buffer[VGA_AC_PAL_F_REG + 1] = IOReadB(VGA_AC_READ);
1298
1299 /* Enable screen and disable palette access */
1300 IOReadB(VGA_INSTAT1_READ); // Put the AC register into index state
1301 IOWriteB(VGA_AC_INDEX, 0x20);
1302 break;
1303 }
1304
1305 /* Set Individual DAC Register */
1306 case 0x10:
1307 {
1308 /* Write the index */
1309 // Certainly in BL and not in BX as said by Ralf Brown...
1310 IOWriteB(VGA_DAC_WRITE_INDEX, getBL());
1311
1312 /* Write the data in this order: Red, Green, Blue */
1313 IOWriteB(VGA_DAC_DATA, getDH());
1314 IOWriteB(VGA_DAC_DATA, getCH());
1315 IOWriteB(VGA_DAC_DATA, getCL());
1316
1317 break;
1318 }
1319
1320 /* Set Block of DAC Registers */
1321 case 0x12:
1322 {
1323 INT i;
1324 LPBYTE Buffer = SEG_OFF_TO_PTR(getES(), getDX());
1325
1326 /* Write the index */
1327 // Certainly in BL and not in BX as said by Ralf Brown...
1328 IOWriteB(VGA_DAC_WRITE_INDEX, getBL());
1329
1330 for (i = 0; i < getCX(); i++)
1331 {
1332 /* Write the data in this order: Red, Green, Blue */
1333 IOWriteB(VGA_DAC_DATA, *Buffer++);
1334 IOWriteB(VGA_DAC_DATA, *Buffer++);
1335 IOWriteB(VGA_DAC_DATA, *Buffer++);
1336 }
1337
1338 break;
1339 }
1340
1341 /* Get Individual DAC Register */
1342 case 0x15:
1343 {
1344 /* Write the index */
1345 IOWriteB(VGA_DAC_READ_INDEX, getBL());
1346
1347 /* Read the data in this order: Red, Green, Blue */
1348 setDH(IOReadB(VGA_DAC_DATA));
1349 setCH(IOReadB(VGA_DAC_DATA));
1350 setCL(IOReadB(VGA_DAC_DATA));
1351
1352 break;
1353 }
1354
1355 /* Get Block of DAC Registers */
1356 case 0x17:
1357 {
1358 INT i;
1359 LPBYTE Buffer = SEG_OFF_TO_PTR(getES(), getDX());
1360
1361 /* Write the index */
1362 // Certainly in BL and not in BX as said by Ralf Brown...
1363 IOWriteB(VGA_DAC_READ_INDEX, getBL());
1364
1365 for (i = 0; i < getCX(); i++)
1366 {
1367 /* Write the data in this order: Red, Green, Blue */
1368 *Buffer++ = IOReadB(VGA_DAC_DATA);
1369 *Buffer++ = IOReadB(VGA_DAC_DATA);
1370 *Buffer++ = IOReadB(VGA_DAC_DATA);
1371 }
1372
1373 break;
1374 }
1375
1376 default:
1377 {
1378 DPRINT1("BIOS Palette Control Sub-command AL = 0x%02X NOT IMPLEMENTED\n",
1379 getAL());
1380 break;
1381 }
1382 }
1383
1384 break;
1385 }
1386
1387 /* Scroll Window */
1388 case 0x12:
1389 {
1390 SMALL_RECT Rectangle = { getCL(), getCH(), getDL(), getDH() };
1391
1392 /* Call the internal function */
1393 VidBiosScrollWindow(getBL(),
1394 getAL(),
1395 Rectangle,
1396 Bda->VideoPage,
1397 DEFAULT_ATTRIBUTE);
1398
1399 break;
1400 }
1401
1402 /* Display combination code */
1403 case 0x1A:
1404 {
1405 switch(getAL())
1406 {
1407 case 0x00: /* Get Display combiantion code */
1408 setAX(MAKEWORD(0x1A, 0x1A));
1409 setBX(MAKEWORD(0x08, 0x00)); /* VGA w/ color analog display */
1410 break;
1411 case 0x01: /* Set Display combination code */
1412 DPRINT1("Set Display combination code - Unsupported\n");
1413 break;
1414 default:
1415 break;
1416 }
1417 break;
1418 }
1419
1420 default:
1421 {
1422 DPRINT1("BIOS Function INT 10h, AH = 0x%02X NOT IMPLEMENTED\n",
1423 getAH());
1424 }
1425 }
1426 }
1427
1428 /* PUBLIC FUNCTIONS ***********************************************************/
1429
1430 VOID VidBiosPrintCharacter(CHAR Character, BYTE Attribute, BYTE Page)
1431 {
1432 WORD CharData = MAKEWORD(Character, Attribute);
1433 BYTE Row, Column;
1434
1435 /* Make sure the page exists */
1436 if (Page >= BIOS_MAX_PAGES) return;
1437
1438 /* Get the cursor location */
1439 VidBiosGetCursorPosition(&Row, &Column, Page);
1440
1441 if (Character == '\a')
1442 {
1443 /* Bell control character */
1444 // NOTE: We may use what the terminal emulator offers to us...
1445 Beep(800, 200);
1446 return;
1447 }
1448 else if (Character == '\b')
1449 {
1450 /* Backspace control character */
1451 if (Column > 0)
1452 {
1453 Column--;
1454 }
1455 else if (Row > 0)
1456 {
1457 Column = Bda->ScreenColumns - 1;
1458 Row--;
1459 }
1460
1461 /* Erase the existing character */
1462 CharData = MAKEWORD(' ', Attribute);
1463 EmulatorWriteMemory(&EmulatorContext,
1464 TO_LINEAR(TEXT_VIDEO_SEG,
1465 Page * Bda->VideoPageSize +
1466 (Row * Bda->ScreenColumns + Column) * sizeof(WORD)),
1467 (LPVOID)&CharData,
1468 sizeof(WORD));
1469 }
1470 else if (Character == '\t')
1471 {
1472 /* Horizontal Tabulation control character */
1473 do
1474 {
1475 // Taken from DOSBox
1476 VidBiosPrintCharacter(' ', Attribute, Page);
1477 VidBiosGetCursorPosition(&Row, &Column, Page);
1478 } while (Column % 8);
1479 }
1480 else if (Character == '\n')
1481 {
1482 /* Line Feed control character */
1483 Row++;
1484 }
1485 else if (Character == '\r')
1486 {
1487 /* Carriage Return control character */
1488 Column = 0;
1489 }
1490 else
1491 {
1492 /* Default character */
1493
1494 /* Write the character */
1495 EmulatorWriteMemory(&EmulatorContext,
1496 TO_LINEAR(TEXT_VIDEO_SEG,
1497 Page * Bda->VideoPageSize +
1498 (Row * Bda->ScreenColumns + Column) * sizeof(WORD)),
1499 (LPVOID)&CharData,
1500 sizeof(WORD));
1501
1502 /* Advance the cursor */
1503 Column++;
1504 }
1505
1506 /* Check if it passed the end of the row */
1507 if (Column >= Bda->ScreenColumns)
1508 {
1509 /* Return to the first column and go to the next line */
1510 Column = 0;
1511 Row++;
1512 }
1513
1514 /* Scroll the screen up if needed */
1515 if (Row > Bda->ScreenRows)
1516 {
1517 /* The screen must be scrolled up */
1518 SMALL_RECT Rectangle = { 0, 0, Bda->ScreenColumns - 1, Bda->ScreenRows };
1519
1520 VidBiosScrollWindow(SCROLL_DIRECTION_UP,
1521 1,
1522 Rectangle,
1523 Page,
1524 DEFAULT_ATTRIBUTE);
1525
1526 Row--;
1527 }
1528
1529 /* Set the cursor position */
1530 VidBiosSetCursorPosition(Row, Column, Page);
1531 }
1532
1533 BOOLEAN VidBiosInitialize(HANDLE ConsoleOutput)
1534 {
1535 CONSOLE_SCREEN_BUFFER_INFO ConsoleInfo;
1536
1537 /* Some interrupts are in fact addresses to tables */
1538 ((PDWORD)BaseAddress)[0x1D] = (DWORD)NULL;
1539 ((PDWORD)BaseAddress)[0x1E] = (DWORD)NULL;
1540 ((PDWORD)BaseAddress)[0x1F] = (DWORD)NULL;
1541
1542 ((PDWORD)BaseAddress)[0x41] = (DWORD)NULL;
1543 ((PDWORD)BaseAddress)[0x43] = (DWORD)NULL;
1544 ((PDWORD)BaseAddress)[0x44] = (DWORD)NULL;
1545 ((PDWORD)BaseAddress)[0x46] = (DWORD)NULL;
1546 ((PDWORD)BaseAddress)[0x48] = (DWORD)NULL;
1547 ((PDWORD)BaseAddress)[0x49] = (DWORD)NULL;
1548
1549 /* Save the default BIOS console output handle for cleanup */
1550 if (ConsoleOutput == INVALID_HANDLE_VALUE) return FALSE;
1551 VidBiosConsoleOutput = ConsoleOutput;
1552
1553 /* Initialize VGA */
1554 if (!VgaInitialize(ConsoleOutput)) return FALSE;
1555
1556 /* Set the default video mode */
1557 VidBiosSetVideoMode(BIOS_DEFAULT_VIDEO_MODE);
1558
1559 GetConsoleScreenBufferInfo(ConsoleOutput, &ConsoleInfo);
1560
1561 /* Copy console data into VGA memory */
1562 VidBiosCopyTextConsoleToVgaMemory(ConsoleOutput, &ConsoleInfo.dwSize);
1563
1564 /* Update the cursor position for the current page */
1565 VidBiosSetCursorPosition(ConsoleInfo.dwCursorPosition.Y,
1566 ConsoleInfo.dwCursorPosition.X,
1567 Bda->VideoPage);
1568
1569 /* Register the BIOS 32-bit Interrupts */
1570 RegisterInt32(BIOS_VIDEO_INTERRUPT, VidBiosVideoService);
1571
1572 return TRUE;
1573 }
1574
1575 VOID VidBiosCleanup(VOID)
1576 {
1577 /* Restore the old screen buffer */
1578 SetConsoleActiveScreenBuffer(VidBiosConsoleOutput);
1579 }
1580
1581 /* EOF */