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