9c060bef453fa5405dc164267e43b5a81c5218fc
[reactos.git] / subsystems / ntvdm / bios.c
1 /*
2 * COPYRIGHT: GPL - See COPYING in the top level directory
3 * PROJECT: ReactOS Virtual DOS Machine
4 * FILE: bios.c
5 * PURPOSE: VDM 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 "bios.h"
15
16 #include "vga.h"
17 #include "pic.h"
18 #include "ps2.h"
19 #include "timer.h"
20
21 #include "int32.h"
22 #include "registers.h"
23
24 /* MACROS *********************************************************************/
25
26 //
27 // These macros are defined for ease-of-use of some VGA I/O ports
28 // whose addresses depend whether we are in Monochrome or Colour mode.
29 //
30 #define VGA_INSTAT1_READ Bda->CrtBasePort + 6 // VGA_INSTAT1_READ_MONO or VGA_INSTAT1_READ_COLOR
31 #define VGA_CRTC_INDEX Bda->CrtBasePort // VGA_CRTC_INDEX_MONO or VGA_CRTC_INDEX_COLOR
32 #define VGA_CRTC_DATA Bda->CrtBasePort + 1 // VGA_CRTC_DATA_MONO or VGA_CRTC_DATA_COLOR
33
34 /* PRIVATE VARIABLES **********************************************************/
35
36 PBIOS_DATA_AREA Bda;
37 static BYTE BiosKeyboardMap[256];
38 static HANDLE BiosConsoleInput = INVALID_HANDLE_VALUE;
39 static HANDLE BiosConsoleOutput = INVALID_HANDLE_VALUE;
40 static DWORD BiosSavedConInMode, BiosSavedConOutMode;
41 static CONSOLE_CURSOR_INFO BiosSavedCursorInfo;
42 static CONSOLE_SCREEN_BUFFER_INFO BiosSavedBufferInfo;
43
44 /*
45 * VGA Register Configurations for BIOS Video Modes
46 * The configurations come from DOSBox.
47 */
48 static VGA_REGISTERS VideoMode_40x25_text =
49 {
50 /* Miscellaneous Register */
51 0x67,
52
53 /* Sequencer Registers */
54 {0x00, 0x08, 0x03, 0x00, 0x07},
55
56 /* CRTC Registers */
57 {0x2D, 0x27, 0x28, 0x90, 0x2B, 0xA0, 0xBF, 0x1F, 0x00, 0x4F, 0x0D, 0x0E,
58 0x00, 0x00, 0x00, 0x00, 0x9C, 0x8E, 0x8F, 0x14, 0x1F, 0x96, 0xB9, 0xA3,
59 0xFF},
60
61 /* GC Registers */
62 {0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x0E, 0x0F, 0xFF},
63
64 /* AC Registers */
65 {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x14, 0x07, 0x38, 0x39, 0x3A, 0x3B,
66 0x3C, 0x3D, 0x3E, 0x3F, 0x0C, 0x00, 0x0F, 0x08, 0x00}
67 };
68
69 static VGA_REGISTERS VideoMode_80x25_text =
70 {
71 /* Miscellaneous Register */
72 0x67,
73
74 /* Sequencer Registers */
75 {0x00, 0x00, 0x03, 0x00, 0x07},
76
77 /* CRTC Registers */
78 {0x5F, 0x4F, 0x50, 0x82, 0x55, 0x81, 0xBF, 0x1F, 0x00, 0x4F, 0x0D, 0x0E,
79 0x00, 0x00, 0x00, 0x00, 0x9C, 0x8E, 0x8F, 0x28, 0x1F, 0x96, 0xB9, 0xA3,
80 0xFF},
81
82 /* GC Registers */
83 {0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x0E, 0x0F, 0xFF},
84
85 /* AC Registers */
86 {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x14, 0x07, 0x38, 0x39, 0x3A, 0x3B,
87 0x3C, 0x3D, 0x3E, 0x3F, 0x0C, 0x00, 0x0F, 0x08, 0x00}
88 };
89
90 static VGA_REGISTERS VideoMode_320x200_4color =
91 {
92 /* Miscellaneous Register */
93 0x63,
94
95 /* Sequencer Registers */
96 {0x00, 0x09, 0x03, 0x00, 0x02},
97
98 /* CRTC Registers */
99 {0x2D, 0x27, 0x28, 0x90, 0x2B, 0x80, 0xBF, 0x1F, 0x00, 0xC1, 0x00, 0x00,
100 0x00, 0x00, 0x00, 0x00, 0x9C, 0x8E, 0x8F, 0x14, 0x00, 0x96, 0xB9, 0xA2,
101 0xFF},
102
103 /* GC Registers */
104 {0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x0F, 0x0F, 0xFF},
105
106 /* AC Registers */
107 {0x00, 0x13, 0x15, 0x17, 0x02, 0x04, 0x06, 0x07, 0x10, 0x11, 0x12, 0x13,
108 0x14, 0x15, 0x16, 0x17, 0x01, 0x00, 0x0F, 0x00, 0x00}
109 };
110
111 static VGA_REGISTERS VideoMode_640x200_2color =
112 {
113 /* Miscellaneous Register */
114 0x63,
115
116 /* Sequencer Registers */
117 {0x00, 0x09, 0x0F, 0x00, 0x02},
118
119 /* CRTC Registers */
120 {0x5F, 0x4F, 0x50, 0x82, 0x54, 0x80, 0xBF, 0x1F, 0x00, 0xC1, 0x00, 0x00,
121 0x00, 0x00, 0x00, 0x00, 0x9C, 0x8E, 0x8F, 0x28, 0x00, 0x96, 0xB9, 0xC2,
122 0xFF},
123
124 /* GC Registers */
125 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x0F, 0xFF},
126
127 /* AC Registers */
128 {0x00, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17,
129 0x17, 0x17, 0x17, 0x17, 0x01, 0x00, 0x01, 0x00, 0x00}
130 };
131
132 static VGA_REGISTERS VideoMode_320x200_16color =
133 {
134 /* Miscellaneous Register */
135 0x63,
136
137 /* Sequencer Registers */
138 {0x00, 0x09, 0x0F, 0x00, 0x02},
139
140 /* CRTC Registers */
141 {0x2D, 0x27, 0x28, 0x90, 0x2B, 0x80, 0xBF, 0x1F, 0x00, 0xC0, 0x00, 0x00,
142 0x00, 0x00, 0x00, 0x00, 0x9C, 0x8E, 0x8F, 0x14, 0x00, 0x96, 0xB9, 0xE3,
143 0xFF},
144
145 /* GC Registers */
146 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x0F, 0xFF},
147
148 /* AC Registers */
149 // {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x14, 0x07, 0x38, 0x39, 0x3A, 0x3B,
150 // 0x3C, 0x3D, 0x3E, 0x3F, 0x01, 0x00, 0x0F, 0x00, 0x00}
151 {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x10, 0x11, 0x12, 0x13,
152 0x14, 0x15, 0x16, 0x17, 0x01, 0x00, 0x0F, 0x00, 0x00}
153 };
154
155 static VGA_REGISTERS VideoMode_640x200_16color =
156 {
157 /* Miscellaneous Register */
158 0x63,
159
160 /* Sequencer Registers */
161 {0x00, 0x01, 0x0F, 0x00, 0x02},
162
163 /* CRTC Registers */
164 {0x5F, 0x4F, 0x50, 0x82, 0x54, 0x80, 0xBF, 0x1F, 0x00, 0xC0, 0x00, 0x00,
165 0x00, 0x00, 0x00, 0x00, 0x9C, 0x8E, 0x8F, 0x28, 0x00, 0x96, 0xB9, 0xE3,
166 0xFF},
167
168 /* GC Registers */
169 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x0F, 0xFF},
170
171 /* AC Registers */
172 // {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x14, 0x07, 0x38, 0x39, 0x3A, 0x3B,
173 // 0x3C, 0x3D, 0x3E, 0x3F, 0x01, 0x00, 0x0F, 0x00, 0x00}
174 {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x10, 0x11, 0x12, 0x13,
175 0x14, 0x15, 0x16, 0x17, 0x01, 0x00, 0x0F, 0x00, 0x00}
176 };
177
178 static VGA_REGISTERS VideoMode_640x350_16color =
179 {
180 /* Miscellaneous Register */
181 0xA3,
182
183 /* Sequencer Registers */
184 {0x00, 0x01, 0x0F, 0x00, 0x02},
185
186 /* CRTC Registers */
187 {0x5F, 0x4F, 0x50, 0x82, 0x54, 0x80, 0xBF, 0x1F, 0x00, 0x40, 0x00, 0x00,
188 0x00, 0x00, 0x00, 0x00, 0x83, 0x85, 0x5D, 0x28, 0x0F, 0x63, 0xBA, 0xE3,
189 0xFF},
190
191 /* GC Registers */
192 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x0F, 0xFF},
193
194 /* AC Registers */
195 {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x14, 0x07, 0x38, 0x39, 0x3A, 0x3B,
196 0x3C, 0x3D, 0x3E, 0x3F, 0x01, 0x00, 0x0F, 0x00, 0x00}
197 };
198
199 static VGA_REGISTERS VideoMode_640x480_2color =
200 {
201 /* Miscellaneous Register */
202 0xE3,
203
204 /* Sequencer Registers */
205 {0x00, 0x01, 0x0F, 0x00, 0x02},
206
207 /* CRTC Registers */
208 {0x5F, 0x4F, 0x50, 0x82, 0x54, 0x80, 0x0B, 0x3E, 0x00, 0x40, 0x00, 0x00,
209 0x00, 0x00, 0x00, 0x00, 0xEA, 0x8C, 0xDF, 0x28, 0x00, 0xE7, 0x04, 0xC3,
210 0xFF},
211
212 /* GC Registers */
213 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x0F, 0xFF},
214
215 /* AC Registers */
216 {0x00, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
217 0x3F, 0x3F, 0x3F, 0x3F, 0x01, 0x00, 0x0F, 0x00, 0x00}
218 };
219
220 static VGA_REGISTERS VideoMode_640x480_16color =
221 {
222 /* Miscellaneous Register */
223 0xE3,
224
225 /* Sequencer Registers */
226 {0x00, 0x01, 0x0F, 0x00, 0x02},
227
228 /* CRTC Registers */
229 {0x5F, 0x4F, 0x50, 0x82, 0x54, 0x80, 0x0B, 0x3E, 0x00, 0x40, 0x00, 0x00,
230 0x00, 0x00, 0x00, 0x00, 0xEA, 0x8C, 0xDF, 0x28, 0x00, 0xE7, 0x04, 0xE3,
231 0xFF},
232
233 /* GC Registers */
234 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x0F, 0xFF},
235
236 /* AC Registers */
237 {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x14, 0x07, 0x38, 0x39, 0x3A, 0x3B,
238 0x3C, 0x3D, 0x3E, 0x3F, 0x01, 0x00, 0x0F, 0x00, 0x00}
239 };
240
241 static VGA_REGISTERS VideoMode_320x200_256color =
242 {
243 /* Miscellaneous Register */
244 0x63,
245
246 /* Sequencer Registers */
247 {0x00, 0x01, 0x0F, 0x00, 0x0E},
248
249 /* CRTC Registers */
250 {0x5F, 0x4F, 0x50, 0x82, 0x54, 0x80, 0xBF, 0x1F, 0x00, 0x41, 0x00, 0x00,
251 0x00, 0x00, 0x00, 0x00, 0x9C, 0x8E, 0x8F, 0x28, 0x40, 0x96, 0xB9, 0xA3,
252 0xFF},
253
254 /* GC Registers */
255 {0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F, 0xFF},
256
257 /* AC Registers */
258 {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B,
259 0x0C, 0x0D, 0x0E, 0x0F, 0x41, 0x00, 0x0F, 0x00, 0x00}
260 };
261
262 /* See http://wiki.osdev.org/Drawing_In_Protected_Mode#Locating_Video_Memory */
263 static PVGA_REGISTERS VideoModes[BIOS_MAX_VIDEO_MODE + 1] =
264 {
265 &VideoMode_40x25_text, /* Mode 00h */ // 16 color (mono)
266 &VideoMode_40x25_text, /* Mode 01h */ // 16 color
267 &VideoMode_80x25_text, /* Mode 02h */ // 16 color (mono)
268 &VideoMode_80x25_text, /* Mode 03h */ // 16 color
269 &VideoMode_320x200_4color, /* Mode 04h */ // CGA 4 color
270 &VideoMode_320x200_4color, /* Mode 05h */ // CGA same (m)
271 &VideoMode_640x200_2color, /* Mode 06h */ // CGA 640*200 2 color
272 NULL, /* Mode 07h */ // MDA monochrome text 80*25
273 NULL, /* Mode 08h */ // PCjr
274 NULL, /* Mode 09h */ // PCjr
275 NULL, /* Mode 0Ah */ // PCjr
276 NULL, /* Mode 0Bh */ // Reserved
277 NULL, /* Mode 0Ch */ // Reserved
278 &VideoMode_320x200_16color, /* Mode 0Dh */ // EGA 320*200 16 color
279 &VideoMode_640x200_16color, /* Mode 0Eh */ // EGA 640*200 16 color
280 NULL, /* Mode 0Fh */ // EGA 640*350 mono
281 &VideoMode_640x350_16color, /* Mode 10h */ // EGA 640*350 HiRes 16 color
282 &VideoMode_640x480_2color, /* Mode 11h */ // VGA 640*480 mono
283 &VideoMode_640x480_16color, /* Mode 12h */ // VGA
284 &VideoMode_320x200_256color, /* Mode 13h */ // VGA
285 };
286
287 // FIXME: Are they computable with the previous data ??
288 // Values taken from DOSBox.
289 static WORD VideoModePageSize[BIOS_MAX_VIDEO_MODE + 1] =
290 {
291 0x0800, 0x0800, 0x1000, 0x1000,
292 0x4000, 0x4000, 0x4000, 0x1000,
293 0x0000, 0x0000, 0x0000, 0x0000,
294 0x0000, 0x2000, 0x4000, 0x8000,
295 0x8000, 0xA000, 0xA000, 0x2000
296 };
297
298 /*
299 * BIOS Mode Palettes
300 *
301 * Many people have different versions of those palettes
302 * (e.g. DOSBox, http://www.brokenthorn.com/Resources/OSDevVid2.html ,
303 * etc...) A choice should be made at some point.
304 */
305
306 // This is the same as EgaPalette__HiRes
307 static CONST COLORREF TextPalette[VGA_MAX_COLORS / 4] =
308 {
309 RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0xAA), RGB(0x00, 0xAA, 0x00), RGB(0x00, 0xAA, 0xAA),
310 RGB(0xAA, 0x00, 0x00), RGB(0xAA, 0x00, 0xAA), RGB(0xAA, 0xAA, 0x00), RGB(0xAA, 0xAA, 0xAA),
311 RGB(0x00, 0x00, 0x55), RGB(0x00, 0x00, 0xFF), RGB(0x00, 0xAA, 0x55), RGB(0x00, 0xAA, 0xFF),
312 RGB(0xAA, 0x00, 0x55), RGB(0xAA, 0x00, 0xFF), RGB(0xAA, 0xAA, 0x55), RGB(0xAA, 0xAA, 0xFF),
313
314 RGB(0x00, 0x55, 0x00), RGB(0x00, 0x55, 0xAA), RGB(0x00, 0xFF, 0x00), RGB(0x00, 0xFF, 0xAA),
315 RGB(0xAA, 0x55, 0x00), RGB(0xAA, 0x55, 0xAA), RGB(0xAA, 0xFF, 0x00), RGB(0xAA, 0xFF, 0xAA),
316 RGB(0x00, 0x55, 0x55), RGB(0x00, 0x55, 0xFF), RGB(0x00, 0xFF, 0x55), RGB(0x00, 0xFF, 0xFF),
317 RGB(0xAA, 0x55, 0x55), RGB(0xAA, 0x55, 0xFF), RGB(0xAA, 0xFF, 0x55), RGB(0xAA, 0xFF, 0xFF),
318
319
320 RGB(0x55, 0x00, 0x00), RGB(0x55, 0x00, 0xAA), RGB(0x55, 0xAA, 0x00), RGB(0x55, 0xAA, 0xAA),
321 RGB(0xFF, 0x00, 0x00), RGB(0xFF, 0x00, 0xAA), RGB(0xFF, 0xAA, 0x00), RGB(0xFF, 0xAA, 0xAA),
322 RGB(0x55, 0x00, 0x55), RGB(0x55, 0x00, 0xFF), RGB(0x55, 0xAA, 0x55), RGB(0x55, 0xAA, 0xFF),
323 RGB(0xFF, 0x00, 0x55), RGB(0xFF, 0x00, 0xFF), RGB(0xFF, 0xAA, 0x55), RGB(0xFF, 0xAA, 0xFF),
324
325 RGB(0x55, 0x55, 0x00), RGB(0x55, 0x55, 0xAA), RGB(0x55, 0xFF, 0x00), RGB(0x55, 0xFF, 0xAA),
326 RGB(0xFF, 0x55, 0x00), RGB(0xFF, 0x55, 0xAA), RGB(0xFF, 0xFF, 0x00), RGB(0xFF, 0xFF, 0xAA),
327 RGB(0x55, 0x55, 0x55), RGB(0x55, 0x55, 0xFF), RGB(0x55, 0xFF, 0x55), RGB(0x55, 0xFF, 0xFF),
328 RGB(0xFF, 0x55, 0x55), RGB(0xFF, 0x55, 0xFF), RGB(0xFF, 0xFF, 0x55), RGB(0xFF, 0xFF, 0xFF)
329 };
330
331 // Unused at the moment
332 static CONST COLORREF mtext_palette[64] =
333 {
334 RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00),
335 RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00),
336 RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA),
337 RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA),
338 RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00),
339 RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00),
340 RGB(0xFF, 0xFF, 0xFF), RGB(0xFF, 0xFF, 0xFF), RGB(0xFF, 0xFF, 0xFF), RGB(0xFF, 0xFF, 0xFF),
341 RGB(0xFF, 0xFF, 0xFF), RGB(0xFF, 0xFF, 0xFF), RGB(0xFF, 0xFF, 0xFF), RGB(0xFF, 0xFF, 0xFF),
342
343 RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00),
344 RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00),
345 RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA),
346 RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA),
347 RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00),
348 RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00),
349 RGB(0xFF, 0xFF, 0xFF), RGB(0xFF, 0xFF, 0xFF), RGB(0xFF, 0xFF, 0xFF), RGB(0xFF, 0xFF, 0xFF),
350 RGB(0xFF, 0xFF, 0xFF), RGB(0xFF, 0xFF, 0xFF), RGB(0xFF, 0xFF, 0xFF), RGB(0xFF, 0xFF, 0xFF)
351 };
352
353 // Unused at the moment
354 static CONST COLORREF mtext_s3_palette[64] =
355 {
356 RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00),
357 RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00),
358 RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA),
359 RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA),
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(0xFF, 0xFF, 0xFF), RGB(0xFF, 0xFF, 0xFF), RGB(0xFF, 0xFF, 0xFF), RGB(0xFF, 0xFF, 0xFF),
363 RGB(0xFF, 0xFF, 0xFF), RGB(0xFF, 0xFF, 0xFF), RGB(0xFF, 0xFF, 0xFF), RGB(0xFF, 0xFF, 0xFF),
364
365 RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00),
366 RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00),
367 RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA),
368 RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA),
369 RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA),
370 RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA),
371 RGB(0xFF, 0xFF, 0xFF), RGB(0xFF, 0xFF, 0xFF), RGB(0xFF, 0xFF, 0xFF), RGB(0xFF, 0xFF, 0xFF),
372 RGB(0xFF, 0xFF, 0xFF), RGB(0xFF, 0xFF, 0xFF), RGB(0xFF, 0xFF, 0xFF), RGB(0xFF, 0xFF, 0xFF)
373 };
374
375 // Unused at the moment
376 static CONST COLORREF CgaPalette[16] =
377 {
378 RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0xAA), RGB(0x00, 0xAA, 0x00), RGB(0x00, 0xAA, 0xAA),
379 RGB(0xAA, 0x00, 0x00), RGB(0xAA, 0x00, 0xAA), RGB(0xAA, 0x55, 0x00), RGB(0xAA, 0xAA, 0xAA),
380 RGB(0x55, 0x55, 0x55), RGB(0x55, 0x55, 0xFF), RGB(0x55, 0xFF, 0x55), RGB(0x55, 0xFF, 0xFF),
381 RGB(0xFF, 0x55, 0x55), RGB(0xFF, 0x55, 0xFF), RGB(0xFF, 0xFF, 0x55), RGB(0xFF, 0xFF, 0xFF)
382 };
383
384 // Unused at the moment
385 static CONST COLORREF CgaPalette2[VGA_MAX_COLORS / 4] =
386 {
387 RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0xAA), RGB(0x00, 0xAA, 0x00), RGB(0x00, 0xAA, 0xAA),
388 RGB(0xAA, 0x00, 0x00), RGB(0xAA, 0x00, 0xAA), RGB(0xAA, 0x55, 0x00), RGB(0xAA, 0xAA, 0xAA),
389 RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0xAA), RGB(0x00, 0xAA, 0x00), RGB(0x00, 0xAA, 0xAA),
390 RGB(0xAA, 0x00, 0x00), RGB(0xAA, 0x00, 0xAA), RGB(0xAA, 0x55, 0x00), RGB(0xAA, 0xAA, 0xAA),
391 RGB(0x55, 0x55, 0x55), RGB(0x55, 0x55, 0xFF), RGB(0x55, 0xFF, 0x55), RGB(0x55, 0xFF, 0xFF),
392 RGB(0xFF, 0x55, 0x55), RGB(0xFF, 0x55, 0xFF), RGB(0xFF, 0xFF, 0x55), RGB(0xFF, 0xFF, 0xFF),
393 RGB(0x55, 0x55, 0x55), RGB(0x55, 0x55, 0xFF), RGB(0x55, 0xFF, 0x55), RGB(0x55, 0xFF, 0xFF),
394 RGB(0xFF, 0x55, 0x55), RGB(0xFF, 0x55, 0xFF), RGB(0xFF, 0xFF, 0x55), RGB(0xFF, 0xFF, 0xFF),
395 RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0xAA), RGB(0x00, 0xAA, 0x00), RGB(0x00, 0xAA, 0xAA),
396 RGB(0xAA, 0x00, 0x00), RGB(0xAA, 0x00, 0xAA), RGB(0xAA, 0x55, 0x00), RGB(0xAA, 0xAA, 0xAA),
397 RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0xAA), RGB(0x00, 0xAA, 0x00), RGB(0x00, 0xAA, 0xAA),
398 RGB(0xAA, 0x00, 0x00), RGB(0xAA, 0x00, 0xAA), RGB(0xAA, 0x55, 0x00), RGB(0xAA, 0xAA, 0xAA),
399 RGB(0x55, 0x55, 0x55), RGB(0x55, 0x55, 0xFF), RGB(0x55, 0xFF, 0x55), RGB(0x55, 0xFF, 0xFF),
400 RGB(0xFF, 0x55, 0x55), RGB(0xFF, 0x55, 0xFF), RGB(0xFF, 0xFF, 0x55), RGB(0xFF, 0xFF, 0xFF),
401 RGB(0x55, 0x55, 0x55), RGB(0x55, 0x55, 0xFF), RGB(0x55, 0xFF, 0x55), RGB(0x55, 0xFF, 0xFF),
402 RGB(0xFF, 0x55, 0x55), RGB(0xFF, 0x55, 0xFF), RGB(0xFF, 0xFF, 0x55), RGB(0xFF, 0xFF, 0xFF)
403 };
404
405 static CONST COLORREF EgaPalette___16ColorFixed_DOSBox[VGA_MAX_COLORS / 4] =
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 RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0xAA), RGB(0x00, 0xAA, 0x00), RGB(0x00, 0xAA, 0xAA),
411 RGB(0xAA, 0x00, 0x00), RGB(0xAA, 0x00, 0xAA), RGB(0xAA, 0x55, 0x00), RGB(0xAA, 0xAA, 0xAA),
412
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 RGB(0x55, 0x55, 0x55), RGB(0x55, 0x55, 0xFF), RGB(0x55, 0xFF, 0x55), RGB(0x55, 0xFF, 0xFF),
418 RGB(0xFF, 0x55, 0x55), RGB(0xFF, 0x55, 0xFF), RGB(0xFF, 0xFF, 0x55), RGB(0xFF, 0xFF, 0xFF),
419
420
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 RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0xAA), RGB(0x00, 0xAA, 0x00), RGB(0x00, 0xAA, 0xAA),
426 RGB(0xAA, 0x00, 0x00), RGB(0xAA, 0x00, 0xAA), RGB(0xAA, 0x55, 0x00), RGB(0xAA, 0xAA, 0xAA),
427
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 RGB(0x55, 0x55, 0x55), RGB(0x55, 0x55, 0xFF), RGB(0x55, 0xFF, 0x55), RGB(0x55, 0xFF, 0xFF),
433 RGB(0xFF, 0x55, 0x55), RGB(0xFF, 0x55, 0xFF), RGB(0xFF, 0xFF, 0x55), RGB(0xFF, 0xFF, 0xFF)
434 };
435
436 // This is the same as TextPalette
437 static CONST COLORREF EgaPalette__HiRes[VGA_MAX_COLORS / 4] =
438 {
439 RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0xAA), RGB(0x00, 0xAA, 0x00), RGB(0x00, 0xAA, 0xAA),
440 RGB(0xAA, 0x00, 0x00), RGB(0xAA, 0x00, 0xAA), RGB(0xAA, 0xAA, 0x00), RGB(0xAA, 0xAA, 0xAA),
441 RGB(0x00, 0x00, 0x55), RGB(0x00, 0x00, 0xFF), RGB(0x00, 0xAA, 0x55), RGB(0x00, 0xAA, 0xFF),
442 RGB(0xAA, 0x00, 0x55), RGB(0xAA, 0x00, 0xFF), RGB(0xAA, 0xAA, 0x55), RGB(0xAA, 0xAA, 0xFF),
443
444 RGB(0x00, 0x55, 0x00), RGB(0x00, 0x55, 0xAA), RGB(0x00, 0xFF, 0x00), RGB(0x00, 0xFF, 0xAA),
445 RGB(0xAA, 0x55, 0x00), RGB(0xAA, 0x55, 0xAA), RGB(0xAA, 0xFF, 0x00), RGB(0xAA, 0xFF, 0xAA),
446 RGB(0x00, 0x55, 0x55), RGB(0x00, 0x55, 0xFF), RGB(0x00, 0xFF, 0x55), RGB(0x00, 0xFF, 0xFF),
447 RGB(0xAA, 0x55, 0x55), RGB(0xAA, 0x55, 0xFF), RGB(0xAA, 0xFF, 0x55), RGB(0xAA, 0xFF, 0xFF),
448
449
450 RGB(0x55, 0x00, 0x00), RGB(0x55, 0x00, 0xAA), RGB(0x55, 0xAA, 0x00), RGB(0x55, 0xAA, 0xAA),
451 RGB(0xFF, 0x00, 0x00), RGB(0xFF, 0x00, 0xAA), RGB(0xFF, 0xAA, 0x00), RGB(0xFF, 0xAA, 0xAA),
452 RGB(0x55, 0x00, 0x55), RGB(0x55, 0x00, 0xFF), RGB(0x55, 0xAA, 0x55), RGB(0x55, 0xAA, 0xFF),
453 RGB(0xFF, 0x00, 0x55), RGB(0xFF, 0x00, 0xFF), RGB(0xFF, 0xAA, 0x55), RGB(0xFF, 0xAA, 0xFF),
454
455 RGB(0x55, 0x55, 0x00), RGB(0x55, 0x55, 0xAA), RGB(0x55, 0xFF, 0x00), RGB(0x55, 0xFF, 0xAA),
456 RGB(0xFF, 0x55, 0x00), RGB(0xFF, 0x55, 0xAA), RGB(0xFF, 0xFF, 0x00), RGB(0xFF, 0xFF, 0xAA),
457 RGB(0x55, 0x55, 0x55), RGB(0x55, 0x55, 0xFF), RGB(0x55, 0xFF, 0x55), RGB(0x55, 0xFF, 0xFF),
458 RGB(0xFF, 0x55, 0x55), RGB(0xFF, 0x55, 0xFF), RGB(0xFF, 0xFF, 0x55), RGB(0xFF, 0xFF, 0xFF)
459 };
460
461 #define USE_REACTOS_COLORS
462 // #define USE_DOSBOX_COLORS
463
464 /*
465 * Same palette as the default one 'VgaDefaultPalette' in vga.c
466 */
467 #if defined(USE_REACTOS_COLORS)
468
469 // ReactOS colors
470 static CONST COLORREF VgaPalette[VGA_MAX_COLORS] =
471 {
472 RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0xAA), RGB(0x00, 0xAA, 0x00), RGB(0x00, 0xAA, 0xAA),
473 RGB(0xAA, 0x00, 0x00), RGB(0xAA, 0x00, 0xAA), RGB(0xAA, 0x55, 0x00), RGB(0xAA, 0xAA, 0xAA),
474 RGB(0x55, 0x55, 0x55), RGB(0x55, 0x55, 0xFF), RGB(0x55, 0xFF, 0x55), RGB(0x55, 0xFF, 0xFF),
475 RGB(0xFF, 0x55, 0x55), RGB(0xFF, 0x55, 0xFF), RGB(0xFF, 0xFF, 0x55), RGB(0xFF, 0xFF, 0xFF),
476 RGB(0x00, 0x00, 0x00), RGB(0x10, 0x10, 0x10), RGB(0x20, 0x20, 0x20), RGB(0x35, 0x35, 0x35),
477 RGB(0x45, 0x45, 0x45), RGB(0x55, 0x55, 0x55), RGB(0x65, 0x65, 0x65), RGB(0x75, 0x75, 0x75),
478 RGB(0x8A, 0x8A, 0x8A), RGB(0x9A, 0x9A, 0x9A), RGB(0xAA, 0xAA, 0xAA), RGB(0xBA, 0xBA, 0xBA),
479 RGB(0xCA, 0xCA, 0xCA), RGB(0xDF, 0xDF, 0xDF), RGB(0xEF, 0xEF, 0xEF), RGB(0xFF, 0xFF, 0xFF),
480 RGB(0x00, 0x00, 0xFF), RGB(0x41, 0x00, 0xFF), RGB(0x82, 0x00, 0xFF), RGB(0xBE, 0x00, 0xFF),
481 RGB(0xFF, 0x00, 0xFF), RGB(0xFF, 0x00, 0xBE), RGB(0xFF, 0x00, 0x82), RGB(0xFF, 0x00, 0x41),
482 RGB(0xFF, 0x00, 0x00), RGB(0xFF, 0x41, 0x00), RGB(0xFF, 0x82, 0x00), RGB(0xFF, 0xBE, 0x00),
483 RGB(0xFF, 0xFF, 0x00), RGB(0xBE, 0xFF, 0x00), RGB(0x82, 0xFF, 0x00), RGB(0x41, 0xFF, 0x00),
484 RGB(0x00, 0xFF, 0x00), RGB(0x00, 0xFF, 0x41), RGB(0x00, 0xFF, 0x82), RGB(0x00, 0xFF, 0xBE),
485 RGB(0x00, 0xFF, 0xFF), RGB(0x00, 0xBE, 0xFF), RGB(0x00, 0x82, 0xFF), RGB(0x00, 0x41, 0xFF),
486 RGB(0x82, 0x82, 0xFF), RGB(0x9E, 0x82, 0xFF), RGB(0xBE, 0x82, 0xFF), RGB(0xDF, 0x82, 0xFF),
487 RGB(0xFF, 0x82, 0xFF), RGB(0xFF, 0x82, 0xDF), RGB(0xFF, 0x82, 0xBE), RGB(0xFF, 0x82, 0x9E),
488 RGB(0xFF, 0x82, 0x82), RGB(0xFF, 0x9E, 0x82), RGB(0xFF, 0xBE, 0x82), RGB(0xFF, 0xDF, 0x82),
489 RGB(0xFF, 0xFF, 0x82), RGB(0xDF, 0xFF, 0x82), RGB(0xBE, 0xFF, 0x82), RGB(0x9E, 0xFF, 0x82),
490 RGB(0x82, 0xFF, 0x82), RGB(0x82, 0xFF, 0x9E), RGB(0x82, 0xFF, 0xBE), RGB(0x82, 0xFF, 0xDF),
491 RGB(0x82, 0xFF, 0xFF), RGB(0x82, 0xDF, 0xFF), RGB(0x82, 0xBE, 0xFF), RGB(0x82, 0x9E, 0xFF),
492 RGB(0xBA, 0xBA, 0xFF), RGB(0xCA, 0xBA, 0xFF), RGB(0xDF, 0xBA, 0xFF), RGB(0xEF, 0xBA, 0xFF),
493 RGB(0xFF, 0xBA, 0xFF), RGB(0xFF, 0xBA, 0xEF), RGB(0xFF, 0xBA, 0xDF), RGB(0xFF, 0xBA, 0xCA),
494 RGB(0xFF, 0xBA, 0xBA), RGB(0xFF, 0xCA, 0xBA), RGB(0xFF, 0xDF, 0xBA), RGB(0xFF, 0xEF, 0xBA),
495 RGB(0xFF, 0xFF, 0xBA), RGB(0xEF, 0xFF, 0xBA), RGB(0xDF, 0xFF, 0xBA), RGB(0xCA, 0xFF, 0xBA),
496 RGB(0xBA, 0xFF, 0xBA), RGB(0xBA, 0xFF, 0xCA), RGB(0xBA, 0xFF, 0xDF), RGB(0xBA, 0xFF, 0xEF),
497 RGB(0xBA, 0xFF, 0xFF), RGB(0xBA, 0xEF, 0xFF), RGB(0xBA, 0xDF, 0xFF), RGB(0xBA, 0xCA, 0xFF),
498 RGB(0x00, 0x00, 0x71), RGB(0x1C, 0x00, 0x71), RGB(0x39, 0x00, 0x71), RGB(0x55, 0x00, 0x71),
499 RGB(0x71, 0x00, 0x71), RGB(0x71, 0x00, 0x55), RGB(0x71, 0x00, 0x39), RGB(0x71, 0x00, 0x1C),
500 RGB(0x71, 0x00, 0x00), RGB(0x71, 0x1C, 0x00), RGB(0x71, 0x39, 0x00), RGB(0x71, 0x55, 0x00),
501 RGB(0x71, 0x71, 0x00), RGB(0x55, 0x71, 0x00), RGB(0x39, 0x71, 0x00), RGB(0x1C, 0x71, 0x00),
502 RGB(0x00, 0x71, 0x00), RGB(0x00, 0x71, 0x1C), RGB(0x00, 0x71, 0x39), RGB(0x00, 0x71, 0x55),
503 RGB(0x00, 0x71, 0x71), RGB(0x00, 0x55, 0x71), RGB(0x00, 0x39, 0x71), RGB(0x00, 0x1C, 0x71),
504 RGB(0x39, 0x39, 0x71), RGB(0x45, 0x39, 0x71), RGB(0x55, 0x39, 0x71), RGB(0x61, 0x39, 0x71),
505 RGB(0x71, 0x39, 0x71), RGB(0x71, 0x39, 0x61), RGB(0x71, 0x39, 0x55), RGB(0x71, 0x39, 0x45),
506 RGB(0x71, 0x39, 0x39), RGB(0x71, 0x45, 0x39), RGB(0x71, 0x55, 0x39), RGB(0x71, 0x61, 0x39),
507 RGB(0x71, 0x71, 0x39), RGB(0x61, 0x71, 0x39), RGB(0x55, 0x71, 0x39), RGB(0x45, 0x71, 0x39),
508 RGB(0x39, 0x71, 0x39), RGB(0x39, 0x71, 0x45), RGB(0x39, 0x71, 0x55), RGB(0x39, 0x71, 0x61),
509 RGB(0x39, 0x71, 0x71), RGB(0x39, 0x61, 0x71), RGB(0x39, 0x55, 0x71), RGB(0x39, 0x45, 0x71),
510 RGB(0x51, 0x51, 0x71), RGB(0x59, 0x51, 0x71), RGB(0x61, 0x51, 0x71), RGB(0x69, 0x51, 0x71),
511 RGB(0x71, 0x51, 0x71), RGB(0x71, 0x51, 0x69), RGB(0x71, 0x51, 0x61), RGB(0x71, 0x51, 0x59),
512 RGB(0x71, 0x51, 0x51), RGB(0x71, 0x59, 0x51), RGB(0x71, 0x61, 0x51), RGB(0x71, 0x69, 0x51),
513 RGB(0x71, 0x71, 0x51), RGB(0x69, 0x71, 0x51), RGB(0x61, 0x71, 0x51), RGB(0x59, 0x71, 0x51),
514 RGB(0x51, 0x71, 0x51), RGB(0x51, 0x71, 0x59), RGB(0x51, 0x71, 0x61), RGB(0x51, 0x71, 0x69),
515 RGB(0x51, 0x71, 0x71), RGB(0x51, 0x69, 0x71), RGB(0x51, 0x61, 0x71), RGB(0x51, 0x59, 0x71),
516 RGB(0x00, 0x00, 0x41), RGB(0x10, 0x00, 0x41), RGB(0x20, 0x00, 0x41), RGB(0x31, 0x00, 0x41),
517 RGB(0x41, 0x00, 0x41), RGB(0x41, 0x00, 0x31), RGB(0x41, 0x00, 0x20), RGB(0x41, 0x00, 0x10),
518 RGB(0x41, 0x00, 0x00), RGB(0x41, 0x10, 0x00), RGB(0x41, 0x20, 0x00), RGB(0x41, 0x31, 0x00),
519 RGB(0x41, 0x41, 0x00), RGB(0x31, 0x41, 0x00), RGB(0x20, 0x41, 0x00), RGB(0x10, 0x41, 0x00),
520 RGB(0x00, 0x41, 0x00), RGB(0x00, 0x41, 0x10), RGB(0x00, 0x41, 0x20), RGB(0x00, 0x41, 0x31),
521 RGB(0x00, 0x41, 0x41), RGB(0x00, 0x31, 0x41), RGB(0x00, 0x20, 0x41), RGB(0x00, 0x10, 0x41),
522 RGB(0x20, 0x20, 0x41), RGB(0x28, 0x20, 0x41), RGB(0x31, 0x20, 0x41), RGB(0x39, 0x20, 0x41),
523 RGB(0x41, 0x20, 0x41), RGB(0x41, 0x20, 0x39), RGB(0x41, 0x20, 0x31), RGB(0x41, 0x20, 0x28),
524 RGB(0x41, 0x20, 0x20), RGB(0x41, 0x28, 0x20), RGB(0x41, 0x31, 0x20), RGB(0x41, 0x39, 0x20),
525 RGB(0x41, 0x41, 0x20), RGB(0x39, 0x41, 0x20), RGB(0x31, 0x41, 0x20), RGB(0x28, 0x41, 0x20),
526 RGB(0x20, 0x41, 0x20), RGB(0x20, 0x41, 0x28), RGB(0x20, 0x41, 0x31), RGB(0x20, 0x41, 0x39),
527 RGB(0x20, 0x41, 0x41), RGB(0x20, 0x39, 0x41), RGB(0x20, 0x31, 0x41), RGB(0x20, 0x28, 0x41),
528 RGB(0x2D, 0x2D, 0x41), RGB(0x31, 0x2D, 0x41), RGB(0x35, 0x2D, 0x41), RGB(0x3D, 0x2D, 0x41),
529 RGB(0x41, 0x2D, 0x41), RGB(0x41, 0x2D, 0x3D), RGB(0x41, 0x2D, 0x35), RGB(0x41, 0x2D, 0x31),
530 RGB(0x41, 0x2D, 0x2D), RGB(0x41, 0x31, 0x2D), RGB(0x41, 0x35, 0x2D), RGB(0x41, 0x3D, 0x2D),
531 RGB(0x41, 0x41, 0x2D), RGB(0x3D, 0x41, 0x2D), RGB(0x35, 0x41, 0x2D), RGB(0x31, 0x41, 0x2D),
532 RGB(0x2D, 0x41, 0x2D), RGB(0x2D, 0x41, 0x31), RGB(0x2D, 0x41, 0x35), RGB(0x2D, 0x41, 0x3D),
533 RGB(0x2D, 0x41, 0x41), RGB(0x2D, 0x3D, 0x41), RGB(0x2D, 0x35, 0x41), RGB(0x2D, 0x31, 0x41),
534 RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00),
535 RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00)
536 };
537
538 #elif defined(USE_DOSBOX_COLORS)
539
540 // DOSBox colors
541 static CONST COLORREF VgaPalette[VGA_MAX_COLORS] =
542 {
543 RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0xAA), RGB(0x00, 0xAA, 0x00), RGB(0x00, 0xAA, 0xAA),
544 RGB(0xAA, 0x00, 0x00), RGB(0xAA, 0x00, 0xAA), RGB(0xAA, 0x55, 0x00), RGB(0xAA, 0xAA, 0xAA),
545 RGB(0x55, 0x55, 0x55), RGB(0x55, 0x55, 0xFF), RGB(0x55, 0xFF, 0x55), RGB(0x55, 0xFF, 0xFF),
546 RGB(0xFF, 0x55, 0x55), RGB(0xFF, 0x55, 0xFF), RGB(0xFF, 0xFF, 0x55), RGB(0xFF, 0xFF, 0xFF),
547 RGB(0x00, 0x00, 0x00), RGB(0x14, 0x14, 0x14), RGB(0x20, 0x20, 0x20), RGB(0x2C, 0x2C, 0x2C),
548 RGB(0x38, 0x38, 0x38), RGB(0x45, 0x45, 0x45), RGB(0x51, 0x51, 0x51), RGB(0x61, 0x61, 0x61),
549 RGB(0x71, 0x71, 0x71), RGB(0x82, 0x82, 0x82), RGB(0x92, 0x92, 0x92), RGB(0xA2, 0xA2, 0xA2),
550 RGB(0xB6, 0xB6, 0xB6), RGB(0xCB, 0xCB, 0xCB), RGB(0xE3, 0xE3, 0xE3), RGB(0xFF, 0xFF, 0xFF),
551 RGB(0x00, 0x00, 0xFF), RGB(0x41, 0x00, 0xFF), RGB(0x7D, 0x00, 0xFF), RGB(0xBE, 0x00, 0xFF),
552 RGB(0xFF, 0x00, 0xFF), RGB(0xFF, 0x00, 0xBE), RGB(0xFF, 0x00, 0x7D), RGB(0xFF, 0x00, 0x41),
553 RGB(0xFF, 0x00, 0x00), RGB(0xFF, 0x41, 0x00), RGB(0xFF, 0x7D, 0x00), RGB(0xFF, 0xBE, 0x00),
554 RGB(0xFF, 0xFF, 0x00), RGB(0xBE, 0xFF, 0x00), RGB(0x7D, 0xFF, 0x00), RGB(0x41, 0xFF, 0x00),
555 RGB(0x00, 0xFF, 0x00), RGB(0x00, 0xFF, 0x41), RGB(0x00, 0xFF, 0x7D), RGB(0x00, 0xFF, 0xBE),
556 RGB(0x00, 0xFF, 0xFF), RGB(0x00, 0xBE, 0xFF), RGB(0x00, 0x7D, 0xFF), RGB(0x00, 0x41, 0xFF),
557 RGB(0x7D, 0x7D, 0xFF), RGB(0x9E, 0x7D, 0xFF), RGB(0xBE, 0x7D, 0xFF), RGB(0xDF, 0x7D, 0xFF),
558 RGB(0xFF, 0x7D, 0xFF), RGB(0xFF, 0x7D, 0xDF), RGB(0xFF, 0x7D, 0xBE), RGB(0xFF, 0x7D, 0x9E),
559
560 RGB(0xFF, 0x7D, 0x7D), RGB(0xFF, 0x9E, 0x7D), RGB(0xFF, 0xBE, 0x7D), RGB(0xFF, 0xDF, 0x7D),
561 RGB(0xFF, 0xFF, 0x7D), RGB(0xDF, 0xFF, 0x7D), RGB(0xBE, 0xFF, 0x7D), RGB(0x9E, 0xFF, 0x7D),
562 RGB(0x7D, 0xFF, 0x7D), RGB(0x7D, 0xFF, 0x9E), RGB(0x7D, 0xFF, 0xBE), RGB(0x7D, 0xFF, 0xDF),
563 RGB(0x7D, 0xFF, 0xFF), RGB(0x7D, 0xDF, 0xFF), RGB(0x7D, 0xBE, 0xFF), RGB(0x7D, 0x9E, 0xFF),
564 RGB(0xB6, 0xB6, 0xFF), RGB(0xC7, 0xB6, 0xFF), RGB(0xDB, 0xB6, 0xFF), RGB(0xEB, 0xB6, 0xFF),
565 RGB(0xFF, 0xB6, 0xFF), RGB(0xFF, 0xB6, 0xEB), RGB(0xFF, 0xB6, 0xDB), RGB(0xFF, 0xB6, 0xC7),
566 RGB(0xFF, 0xB6, 0xB6), RGB(0xFF, 0xC7, 0xB6), RGB(0xFF, 0xDB, 0xB6), RGB(0xFF, 0xEB, 0xB6),
567 RGB(0xFF, 0xFF, 0xB6), RGB(0xEB, 0xFF, 0xB6), RGB(0xDB, 0xFF, 0xB6), RGB(0xC7, 0xFF, 0xB6),
568 RGB(0xB6, 0xFF, 0xB6), RGB(0xB6, 0xFF, 0xC7), RGB(0xB6, 0xFF, 0xDB), RGB(0xB6, 0xFF, 0xEB),
569 RGB(0xB6, 0xFF, 0xFF), RGB(0xB6, 0xEB, 0xFF), RGB(0xB6, 0xDB, 0xFF), RGB(0xB6, 0xC7, 0xFF),
570 RGB(0x00, 0x00, 0x71), RGB(0x1C, 0x00, 0x71), RGB(0x38, 0x00, 0x71), RGB(0x55, 0x00, 0x71),
571 RGB(0x71, 0x00, 0x71), RGB(0x71, 0x00, 0x55), RGB(0x71, 0x00, 0x38), RGB(0x71, 0x00, 0x1C),
572 RGB(0x71, 0x00, 0x00), RGB(0x71, 0x1C, 0x00), RGB(0x71, 0x38, 0x00), RGB(0x71, 0x55, 0x00),
573 RGB(0x71, 0x71, 0x00), RGB(0x55, 0x71, 0x00), RGB(0x38, 0x71, 0x00), RGB(0x1C, 0x71, 0x00),
574 RGB(0x00, 0x71, 0x00), RGB(0x00, 0x71, 0x1C), RGB(0x00, 0x71, 0x38), RGB(0x00, 0x71, 0x55),
575 RGB(0x00, 0x71, 0x71), RGB(0x00, 0x55, 0x71), RGB(0x00, 0x38, 0x71), RGB(0x00, 0x1C, 0x71),
576
577 RGB(0x38, 0x38, 0x71), RGB(0x45, 0x38, 0x71), RGB(0x55, 0x38, 0x71), RGB(0x61, 0x38, 0x71),
578 RGB(0x71, 0x38, 0x71), RGB(0x71, 0x38, 0x61), RGB(0x71, 0x38, 0x55), RGB(0x71, 0x38, 0x45),
579 RGB(0x71, 0x38, 0x38), RGB(0x71, 0x45, 0x38), RGB(0x71, 0x55, 0x38), RGB(0x71, 0x61, 0x38),
580 RGB(0x71, 0x71, 0x38), RGB(0x61, 0x71, 0x38), RGB(0x55, 0x71, 0x38), RGB(0x45, 0x71, 0x38),
581 RGB(0x38, 0x71, 0x38), RGB(0x38, 0x71, 0x45), RGB(0x38, 0x71, 0x55), RGB(0x38, 0x71, 0x61),
582 RGB(0x38, 0x71, 0x71), RGB(0x38, 0x61, 0x71), RGB(0x38, 0x55, 0x71), RGB(0x38, 0x45, 0x71),
583 RGB(0x51, 0x51, 0x71), RGB(0x59, 0x51, 0x71), RGB(0x61, 0x51, 0x71), RGB(0x69, 0x51, 0x71),
584 RGB(0x71, 0x51, 0x71), RGB(0x71, 0x51, 0x69), RGB(0x71, 0x51, 0x61), RGB(0x71, 0x51, 0x59),
585 RGB(0x71, 0x51, 0x51), RGB(0x71, 0x59, 0x51), RGB(0x71, 0x61, 0x51), RGB(0x71, 0x69, 0x51),
586 RGB(0x71, 0x71, 0x51), RGB(0x69, 0x71, 0x51), RGB(0x61, 0x71, 0x51), RGB(0x59, 0x71, 0x51),
587 RGB(0x51, 0x71, 0x51), RGB(0x51, 0x71, 0x59), RGB(0x51, 0x71, 0x61), RGB(0x51, 0x71, 0x69),
588 RGB(0x51, 0x71, 0x71), RGB(0x51, 0x69, 0x71), RGB(0x51, 0x61, 0x71), RGB(0x51, 0x59, 0x71),
589 RGB(0x00, 0x00, 0x41), RGB(0x10, 0x00, 0x41), RGB(0x20, 0x00, 0x41), RGB(0x30, 0x00, 0x41),
590 RGB(0x41, 0x00, 0x41), RGB(0x41, 0x00, 0x30), RGB(0x41, 0x00, 0x20), RGB(0x41, 0x00, 0x10),
591 RGB(0x41, 0x00, 0x00), RGB(0x41, 0x10, 0x00), RGB(0x41, 0x20, 0x00), RGB(0x41, 0x30, 0x00),
592 RGB(0x41, 0x41, 0x00), RGB(0x30, 0x41, 0x00), RGB(0x20, 0x41, 0x00), RGB(0x10, 0x41, 0x00),
593
594 RGB(0x00, 0x41, 0x00), RGB(0x00, 0x41, 0x10), RGB(0x00, 0x41, 0x20), RGB(0x00, 0x41, 0x30),
595 RGB(0x00, 0x41, 0x41), RGB(0x00, 0x30, 0x41), RGB(0x00, 0x20, 0x41), RGB(0x00, 0x10, 0x41),
596 RGB(0x20, 0x20, 0x41), RGB(0x28, 0x20, 0x41), RGB(0x30, 0x20, 0x41), RGB(0x38, 0x20, 0x41),
597 RGB(0x41, 0x20, 0x41), RGB(0x41, 0x20, 0x38), RGB(0x41, 0x20, 0x30), RGB(0x41, 0x20, 0x28),
598 RGB(0x41, 0x20, 0x20), RGB(0x41, 0x28, 0x20), RGB(0x41, 0x30, 0x20), RGB(0x41, 0x38, 0x20),
599 RGB(0x41, 0x41, 0x20), RGB(0x38, 0x41, 0x20), RGB(0x30, 0x41, 0x20), RGB(0x28, 0x41, 0x20),
600 RGB(0x20, 0x41, 0x20), RGB(0x20, 0x41, 0x28), RGB(0x20, 0x41, 0x30), RGB(0x20, 0x41, 0x38),
601 RGB(0x20, 0x41, 0x41), RGB(0x20, 0x38, 0x41), RGB(0x20, 0x30, 0x41), RGB(0x20, 0x28, 0x41),
602 RGB(0x2C, 0x2C, 0x41), RGB(0x30, 0x2C, 0x41), RGB(0x34, 0x2C, 0x41), RGB(0x3C, 0x2C, 0x41),
603 RGB(0x41, 0x2C, 0x41), RGB(0x41, 0x2C, 0x3C), RGB(0x41, 0x2C, 0x34), RGB(0x41, 0x2C, 0x30),
604 RGB(0x41, 0x2C, 0x2C), RGB(0x41, 0x30, 0x2C), RGB(0x41, 0x34, 0x2C), RGB(0x41, 0x3C, 0x2C),
605 RGB(0x41, 0x41, 0x2C), RGB(0x3C, 0x41, 0x2C), RGB(0x34, 0x41, 0x2C), RGB(0x30, 0x41, 0x2C),
606 RGB(0x2C, 0x41, 0x2C), RGB(0x2C, 0x41, 0x30), RGB(0x2C, 0x41, 0x34), RGB(0x2C, 0x41, 0x3C),
607 RGB(0x2C, 0x41, 0x41), RGB(0x2C, 0x3C, 0x41), RGB(0x2C, 0x34, 0x41), RGB(0x2C, 0x30, 0x41),
608 RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00),
609 RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00)
610 };
611
612 #endif
613
614 /* PRIVATE FUNCTIONS **********************************************************/
615
616 static BOOLEAN BiosKbdBufferPush(WORD Data)
617 {
618 /* Get the location of the element after the tail */
619 WORD NextElement = Bda->KeybdBufferTail + sizeof(WORD);
620
621 /* Wrap it around if it's at or beyond the end */
622 if (NextElement >= Bda->KeybdBufferEnd) NextElement = Bda->KeybdBufferStart;
623
624 /* If it's full, fail */
625 if (NextElement == Bda->KeybdBufferHead) return FALSE;
626
627 /* Put the value in the queue */
628 *((LPWORD)((ULONG_PTR)Bda + Bda->KeybdBufferTail)) = Data;
629 Bda->KeybdBufferTail += sizeof(WORD);
630
631 /* Check if we are at, or have passed, the end of the buffer */
632 if (Bda->KeybdBufferTail >= Bda->KeybdBufferEnd)
633 {
634 /* Return it to the beginning */
635 Bda->KeybdBufferTail = Bda->KeybdBufferStart;
636 }
637
638 /* Return success */
639 return TRUE;
640 }
641
642 static BOOLEAN BiosKbdBufferTop(LPWORD Data)
643 {
644 /* If it's empty, fail */
645 if (Bda->KeybdBufferHead == Bda->KeybdBufferTail) return FALSE;
646
647 /* Otherwise, get the value and return success */
648 *Data = *((LPWORD)((ULONG_PTR)Bda + Bda->KeybdBufferHead));
649
650 return TRUE;
651 }
652
653 static BOOLEAN BiosKbdBufferPop(VOID)
654 {
655 /* If it's empty, fail */
656 if (Bda->KeybdBufferHead == Bda->KeybdBufferTail) return FALSE;
657
658 /* Remove the value from the queue */
659 Bda->KeybdBufferHead += sizeof(WORD);
660
661 /* Check if we are at, or have passed, the end of the buffer */
662 if (Bda->KeybdBufferHead >= Bda->KeybdBufferEnd)
663 {
664 /* Return it to the beginning */
665 Bda->KeybdBufferHead = Bda->KeybdBufferStart;
666 }
667
668 /* Return success */
669 return TRUE;
670 }
671
672 static VOID BiosReadWindow(LPWORD Buffer, SMALL_RECT Rectangle, BYTE Page)
673 {
674 INT i, j;
675 INT Counter = 0;
676 WORD Character;
677 DWORD VideoAddress = TO_LINEAR(TEXT_VIDEO_SEG, Page * Bda->VideoPageSize);
678
679 for (i = Rectangle.Top; i <= Rectangle.Bottom; i++)
680 {
681 for (j = Rectangle.Left; j <= Rectangle.Right; j++)
682 {
683 /* Read from video memory */
684 VgaReadMemory(VideoAddress + (i * Bda->ScreenColumns + j) * sizeof(WORD),
685 (LPVOID)&Character,
686 sizeof(WORD));
687
688 /* Write the data to the buffer in row order */
689 Buffer[Counter++] = Character;
690 }
691 }
692 }
693
694 static VOID BiosWriteWindow(LPWORD Buffer, SMALL_RECT Rectangle, BYTE Page)
695 {
696 INT i, j;
697 INT Counter = 0;
698 WORD Character;
699 DWORD VideoAddress = TO_LINEAR(TEXT_VIDEO_SEG, Page * Bda->VideoPageSize);
700
701 for (i = Rectangle.Top; i <= Rectangle.Bottom; i++)
702 {
703 for (j = Rectangle.Left; j <= Rectangle.Right; j++)
704 {
705 Character = Buffer[Counter++];
706
707 /* Write to video memory */
708 VgaWriteMemory(VideoAddress + (i * Bda->ScreenColumns + j) * sizeof(WORD),
709 (LPVOID)&Character,
710 sizeof(WORD));
711 }
712 }
713 }
714
715 static BOOLEAN BiosScrollWindow(INT Direction,
716 DWORD Amount,
717 SMALL_RECT Rectangle,
718 BYTE Page,
719 BYTE FillAttribute)
720 {
721 DWORD i;
722 LPWORD WindowData;
723 WORD WindowWidth = Rectangle.Right - Rectangle.Left + 1;
724 WORD WindowHeight = Rectangle.Bottom - Rectangle.Top + 1;
725 DWORD WindowSize = WindowWidth * WindowHeight;
726
727 /* Allocate a buffer for the window */
728 WindowData = (LPWORD)HeapAlloc(GetProcessHeap(),
729 HEAP_ZERO_MEMORY,
730 WindowSize * sizeof(WORD));
731 if (WindowData == NULL) return FALSE;
732
733 /* Read the window data */
734 BiosReadWindow(WindowData, Rectangle, Page);
735
736 if ((Amount == 0)
737 || (((Direction == SCROLL_DIRECTION_UP)
738 || (Direction == SCROLL_DIRECTION_DOWN))
739 && (Amount >= WindowHeight))
740 || (((Direction == SCROLL_DIRECTION_LEFT)
741 || (Direction == SCROLL_DIRECTION_RIGHT))
742 && (Amount >= WindowWidth)))
743 {
744 /* Fill the window */
745 for (i = 0; i < WindowSize; i++)
746 {
747 WindowData[i] = MAKEWORD(' ', FillAttribute);
748 }
749
750 goto Done;
751 }
752
753 switch (Direction)
754 {
755 case SCROLL_DIRECTION_UP:
756 {
757 RtlMoveMemory(WindowData,
758 &WindowData[WindowWidth * Amount],
759 (WindowSize - WindowWidth * Amount) * sizeof(WORD));
760
761 for (i = 0; i < Amount * WindowWidth; i++)
762 {
763 WindowData[WindowSize - i - 1] = MAKEWORD(' ', FillAttribute);
764 }
765
766 break;
767 }
768
769 case SCROLL_DIRECTION_DOWN:
770 {
771 RtlMoveMemory(&WindowData[WindowWidth * Amount],
772 WindowData,
773 (WindowSize - WindowWidth * Amount) * sizeof(WORD));
774
775 for (i = 0; i < Amount * WindowWidth; i++)
776 {
777 WindowData[i] = MAKEWORD(' ', FillAttribute);
778 }
779
780 break;
781 }
782
783 default:
784 {
785 // TODO: NOT IMPLEMENTED!
786 UNIMPLEMENTED;
787 }
788 }
789
790 Done:
791 /* Write back the window data */
792 BiosWriteWindow(WindowData, Rectangle, Page);
793
794 /* Free the window buffer */
795 HeapFree(GetProcessHeap(), 0, WindowData);
796
797 return TRUE;
798 }
799
800 static VOID BiosCopyTextConsoleToVgaMemory(PCOORD ConsoleSize)
801 {
802 PCHAR_INFO CharBuffer;
803 COORD BufferSize = {Bda->ScreenColumns, Bda->ScreenRows + 1};
804 COORD Origin = { 0, 0 };
805 SMALL_RECT ConRect;
806
807 INT i, j;
808 INT Counter = 0;
809 WORD Character;
810 DWORD VideoAddress = TO_LINEAR(TEXT_VIDEO_SEG, Bda->VideoPage * Bda->VideoPageSize);
811
812 /* Allocate a temporary buffer for ReadConsoleOutput */
813 CharBuffer = HeapAlloc(GetProcessHeap(),
814 HEAP_ZERO_MEMORY,
815 BufferSize.X * BufferSize.Y
816 * sizeof(CHAR_INFO));
817 if (CharBuffer == NULL) return;
818
819 ConRect.Left = 0;
820 ConRect.Top = ConsoleSize->Y - BufferSize.Y;
821 ConRect.Right = ConRect.Left + BufferSize.X - 1;
822 ConRect.Bottom = ConRect.Top + BufferSize.Y - 1;
823
824 /* Read the data from the console into the temporary buffer... */
825 ReadConsoleOutputA(BiosConsoleOutput,
826 CharBuffer,
827 BufferSize,
828 Origin,
829 &ConRect);
830
831 /* ... and copy the temporary buffer into the VGA memory */
832 for (i = 0; i < BufferSize.Y; i++)
833 {
834 for (j = 0; j < BufferSize.X; j++)
835 {
836 Character = MAKEWORD(CharBuffer[Counter].Char.AsciiChar,
837 (BYTE)CharBuffer[Counter].Attributes);
838 ++Counter;
839
840 /* Write to video memory */
841 VgaWriteMemory(VideoAddress + (i * Bda->ScreenColumns + j) * sizeof(WORD),
842 (LPVOID)&Character,
843 sizeof(WORD));
844 }
845 }
846
847 /* Free the temporary buffer */
848 HeapFree(GetProcessHeap(), 0, CharBuffer);
849 }
850
851 static BOOLEAN VgaSetRegisters(PVGA_REGISTERS Registers)
852 {
853 INT i;
854
855 if (Registers == NULL) return FALSE;
856
857 /* Disable interrupts */
858 setIF(0);
859
860 /*
861 * Set the CRT base address according to the selected mode,
862 * monochrome or color. The following macros:
863 * VGA_INSTAT1_READ, VGA_CRTC_INDEX and VGA_CRTC_DATA are then
864 * used to access the correct VGA I/O ports.
865 */
866 Bda->CrtBasePort = (Registers->Misc & 0x01) ? VGA_CRTC_INDEX_COLOR
867 : VGA_CRTC_INDEX_MONO;
868
869 /* Write the misc register */
870 VgaWritePort(VGA_MISC_WRITE, Registers->Misc);
871
872 /* Synchronous reset on */
873 VgaWritePort(VGA_SEQ_INDEX, VGA_SEQ_RESET_REG);
874 VgaWritePort(VGA_SEQ_DATA , VGA_SEQ_RESET_AR);
875
876 /* Write the sequencer registers */
877 for (i = 1; i < VGA_SEQ_MAX_REG; i++)
878 {
879 VgaWritePort(VGA_SEQ_INDEX, i);
880 VgaWritePort(VGA_SEQ_DATA, Registers->Sequencer[i]);
881 }
882
883 /* Synchronous reset off */
884 VgaWritePort(VGA_SEQ_INDEX, VGA_SEQ_RESET_REG);
885 VgaWritePort(VGA_SEQ_DATA , VGA_SEQ_RESET_SR | VGA_SEQ_RESET_AR);
886
887 /* Unlock CRTC registers 0-7 */
888 VgaWritePort(VGA_CRTC_INDEX, VGA_CRTC_END_HORZ_BLANKING_REG);
889 VgaWritePort(VGA_CRTC_DATA, VgaReadPort(VGA_CRTC_DATA) | 0x80);
890 VgaWritePort(VGA_CRTC_INDEX, VGA_CRTC_VERT_RETRACE_END_REG);
891 VgaWritePort(VGA_CRTC_DATA, VgaReadPort(VGA_CRTC_DATA) & ~0x80);
892 // Make sure they remain unlocked
893 Registers->CRT[VGA_CRTC_END_HORZ_BLANKING_REG] |= 0x80;
894 Registers->CRT[VGA_CRTC_VERT_RETRACE_END_REG] &= ~0x80;
895
896 /* Write the CRTC registers */
897 for (i = 0; i < VGA_CRTC_MAX_REG; i++)
898 {
899 VgaWritePort(VGA_CRTC_INDEX, i);
900 VgaWritePort(VGA_CRTC_DATA, Registers->CRT[i]);
901 }
902
903 /* Write the GC registers */
904 for (i = 0; i < VGA_GC_MAX_REG; i++)
905 {
906 VgaWritePort(VGA_GC_INDEX, i);
907 VgaWritePort(VGA_GC_DATA, Registers->Graphics[i]);
908 }
909
910 /* Write the AC registers */
911 // DbgPrint("\n");
912 for (i = 0; i < VGA_AC_MAX_REG; i++)
913 {
914 VgaReadPort(VGA_INSTAT1_READ); // Put the AC register into index state
915 VgaWritePort(VGA_AC_INDEX, i);
916 VgaWritePort(VGA_AC_WRITE, Registers->Attribute[i]);
917 // DbgPrint("Registers->Attribute[%d] = %d\n", i, Registers->Attribute[i]);
918 }
919 // DbgPrint("\n");
920
921 /* Set the PEL mask */
922 VgaWritePort(VGA_DAC_MASK, 0xFF);
923
924 /* Enable screen and disable palette access */
925 VgaReadPort(VGA_INSTAT1_READ); // Put the AC register into index state
926 VgaWritePort(VGA_AC_INDEX, 0x20);
927
928 /* Enable interrupts */
929 setIF(1);
930
931 return TRUE;
932 }
933
934 static VOID VgaSetPalette(const COLORREF* Palette, ULONG Size)
935 {
936 ULONG i;
937
938 // /* Disable screen and enable palette access */
939 // VgaReadPort(VGA_INSTAT1_READ); // Put the AC register into index state
940 // VgaWritePort(VGA_AC_INDEX, 0x00);
941
942 for (i = 0; i < Size; i++)
943 {
944 VgaWritePort(VGA_DAC_WRITE_INDEX, i);
945 VgaWritePort(VGA_DAC_DATA, VGA_COLOR_TO_DAC(GetRValue(Palette[i])));
946 VgaWritePort(VGA_DAC_DATA, VGA_COLOR_TO_DAC(GetGValue(Palette[i])));
947 VgaWritePort(VGA_DAC_DATA, VGA_COLOR_TO_DAC(GetBValue(Palette[i])));
948 }
949
950 /* The following step might be optional */
951 for (i = Size; i < VGA_MAX_COLORS; i++)
952 {
953 VgaWritePort(VGA_DAC_WRITE_INDEX, i);
954 VgaWritePort(VGA_DAC_DATA, VGA_COLOR_TO_DAC(0x00));
955 VgaWritePort(VGA_DAC_DATA, VGA_COLOR_TO_DAC(0x00));
956 VgaWritePort(VGA_DAC_DATA, VGA_COLOR_TO_DAC(0x00));
957 }
958
959 /* Enable screen and disable palette access */
960 // VgaReadPort(VGA_INSTAT1_READ); // Put the AC register into index state
961 // VgaWritePort(VGA_AC_INDEX, 0x20);
962 }
963
964 static VOID VgaChangePalette(BYTE ModeNumber)
965 {
966 const COLORREF* Palette;
967 ULONG Size;
968
969 if (ModeNumber >= 0x13)
970 {
971 /* VGA modes */
972 Palette = VgaPalette;
973 Size = sizeof(VgaPalette)/sizeof(VgaPalette[0]);
974 }
975 else if (ModeNumber == 0x10)
976 {
977 /* EGA HiRes mode */
978 Palette = EgaPalette__HiRes;
979 Size = sizeof(EgaPalette__HiRes)/sizeof(EgaPalette__HiRes[0]);
980 }
981 else // if ((ModeNumber == 0x0D) || (ModeNumber == 0x0E))
982 {
983 /* EGA modes */
984 Palette = EgaPalette___16ColorFixed_DOSBox;
985 Size = sizeof(EgaPalette___16ColorFixed_DOSBox)/sizeof(EgaPalette___16ColorFixed_DOSBox[0]);
986 }
987
988 VgaSetPalette(Palette, Size);
989 }
990
991 static VOID BiosGetCursorPosition(PBYTE Row, PBYTE Column, BYTE Page)
992 {
993 /* Make sure the selected video page is valid */
994 if (Page >= BIOS_MAX_PAGES) return;
995
996 /* Get the cursor location */
997 *Row = HIBYTE(Bda->CursorPosition[Page]);
998 *Column = LOBYTE(Bda->CursorPosition[Page]);
999 }
1000
1001 static VOID BiosSetCursorPosition(BYTE Row, BYTE Column, BYTE Page)
1002 {
1003 /* Make sure the selected video page is valid */
1004 if (Page >= BIOS_MAX_PAGES) return;
1005
1006 /* Update the position in the BDA */
1007 Bda->CursorPosition[Page] = MAKEWORD(Column, Row);
1008
1009 /* Check if this is the current video page */
1010 if (Page == Bda->VideoPage)
1011 {
1012 WORD Offset = Row * Bda->ScreenColumns + Column;
1013
1014 /* Modify the CRTC registers */
1015 VgaWritePort(VGA_CRTC_INDEX, VGA_CRTC_CURSOR_LOC_LOW_REG);
1016 VgaWritePort(VGA_CRTC_DATA , LOBYTE(Offset));
1017 VgaWritePort(VGA_CRTC_INDEX, VGA_CRTC_CURSOR_LOC_HIGH_REG);
1018 VgaWritePort(VGA_CRTC_DATA , HIBYTE(Offset));
1019 }
1020 }
1021
1022 BYTE BiosGetVideoMode(VOID)
1023 {
1024 return Bda->VideoMode;
1025 }
1026
1027 static BOOLEAN BiosSetVideoMode(BYTE ModeNumber)
1028 {
1029 BYTE Page;
1030
1031 COORD Resolution;
1032 PVGA_REGISTERS VgaMode = VideoModes[ModeNumber];
1033
1034 DPRINT1("Switching to mode %Xh; VgaMode = 0x%p\n", ModeNumber, VgaMode);
1035
1036 if (!VgaSetRegisters(VgaMode)) return FALSE;
1037
1038 VgaChangePalette(ModeNumber);
1039
1040 /*
1041 * IBM standard modes do not clear the screen if the
1042 * high bit of AL is set (EGA or higher only).
1043 * See Ralf Brown: http://www.ctyme.com/intr/rb-0069.htm
1044 * for more information.
1045 */
1046 if ((ModeNumber & 0x08) == 0) VgaClearMemory();
1047
1048 // Bda->CrtModeControl;
1049 // Bda->CrtColorPaletteMask;
1050 // Bda->EGAFlags;
1051 // Bda->VGAFlags;
1052
1053 /* Update the values in the BDA */
1054 Bda->VideoMode = ModeNumber;
1055 Bda->VideoPageSize = VideoModePageSize[ModeNumber];
1056 Bda->VideoPage = 0;
1057 Bda->VideoPageOffset = Bda->VideoPage * Bda->VideoPageSize;
1058
1059 /* Set the start address in the CRTC */
1060 VgaWritePort(VGA_CRTC_INDEX, VGA_CRTC_START_ADDR_LOW_REG);
1061 VgaWritePort(VGA_CRTC_DATA , LOBYTE(Bda->VideoPageOffset));
1062 VgaWritePort(VGA_CRTC_INDEX, VGA_CRTC_START_ADDR_HIGH_REG);
1063 VgaWritePort(VGA_CRTC_DATA , HIBYTE(Bda->VideoPageOffset));
1064
1065 /* Get the character height */
1066 VgaWritePort(VGA_CRTC_INDEX, VGA_CRTC_MAX_SCAN_LINE_REG);
1067 Bda->CharacterHeight = 1 + (VgaReadPort(VGA_CRTC_DATA) & 0x1F);
1068
1069 Resolution = VgaGetDisplayResolution();
1070 Bda->ScreenColumns = Resolution.X;
1071 Bda->ScreenRows = Resolution.Y - 1;
1072
1073 /* Set the cursor position for each page */
1074 for (Page = 0; Page < BIOS_MAX_PAGES; ++Page)
1075 BiosSetCursorPosition(0, 0, Page);
1076
1077 return TRUE;
1078 }
1079
1080 static BOOLEAN BiosSetVideoPage(BYTE PageNumber)
1081 {
1082 BYTE Row, Column;
1083
1084 /* Check if the page exists */
1085 if (PageNumber >= BIOS_MAX_PAGES) return FALSE;
1086
1087 /* Check if this is the same page */
1088 if (PageNumber == Bda->VideoPage) return TRUE;
1089
1090 /* Update the values in the BDA */
1091 Bda->VideoPage = PageNumber;
1092 Bda->VideoPageOffset = Bda->VideoPage * Bda->VideoPageSize;
1093
1094 /* Set the start address in the CRTC */
1095 VgaWritePort(VGA_CRTC_INDEX, VGA_CRTC_START_ADDR_LOW_REG);
1096 VgaWritePort(VGA_CRTC_DATA , LOBYTE(Bda->VideoPageOffset));
1097 VgaWritePort(VGA_CRTC_INDEX, VGA_CRTC_START_ADDR_HIGH_REG);
1098 VgaWritePort(VGA_CRTC_DATA , HIBYTE(Bda->VideoPageOffset));
1099
1100 /*
1101 * Get the cursor location (we don't update anything on the BIOS side
1102 * but we update the cursor location on the VGA side).
1103 */
1104 BiosGetCursorPosition(&Row, &Column, PageNumber);
1105 BiosSetCursorPosition(Row, Column, PageNumber);
1106
1107 return TRUE;
1108 }
1109
1110 static VOID WINAPI BiosVideoService(LPWORD Stack)
1111 {
1112 switch (getAH())
1113 {
1114 /* Set Video Mode */
1115 case 0x00:
1116 {
1117 BiosSetVideoMode(getAL());
1118 break;
1119 }
1120
1121 /* Set Text-Mode Cursor Shape */
1122 case 0x01:
1123 {
1124 /* Update the BDA */
1125 Bda->CursorStartLine = getCH();
1126 Bda->CursorEndLine = getCL();
1127
1128 /* Modify the CRTC registers */
1129 VgaWritePort(VGA_CRTC_INDEX, VGA_CRTC_CURSOR_START_REG);
1130 VgaWritePort(VGA_CRTC_DATA , Bda->CursorStartLine);
1131 VgaWritePort(VGA_CRTC_INDEX, VGA_CRTC_CURSOR_END_REG);
1132 VgaWritePort(VGA_CRTC_DATA , Bda->CursorEndLine);
1133
1134 break;
1135 }
1136
1137 /* Set Cursor Position */
1138 case 0x02:
1139 {
1140 BiosSetCursorPosition(getDH(), getDL(), getBH());
1141 break;
1142 }
1143
1144 /* Get Cursor Position */
1145 case 0x03:
1146 {
1147 /* Make sure the selected video page exists */
1148 if (getBH() >= BIOS_MAX_PAGES) break;
1149
1150 /* Return the result */
1151 setAX(0);
1152 setCX(MAKEWORD(Bda->CursorEndLine, Bda->CursorStartLine));
1153 setDX(Bda->CursorPosition[getBH()]);
1154 break;
1155 }
1156
1157 /* Query Light Pen */
1158 case 0x04:
1159 {
1160 /*
1161 * On modern BIOSes, this function returns 0
1162 * so that we can ignore the other registers.
1163 */
1164 setAX(0);
1165 break;
1166 }
1167
1168 /* Select Active Display Page */
1169 case 0x05:
1170 {
1171 BiosSetVideoPage(getAL());
1172 break;
1173 }
1174
1175 /* Scroll Window Up/Down */
1176 case 0x06:
1177 case 0x07:
1178 {
1179 SMALL_RECT Rectangle = { getCL(), getCH(), getDL(), getDH() };
1180
1181 /* Call the internal function */
1182 BiosScrollWindow((getAH() == 0x06) ? SCROLL_DIRECTION_UP
1183 : SCROLL_DIRECTION_DOWN,
1184 getAL(),
1185 Rectangle,
1186 Bda->VideoPage,
1187 getBH());
1188
1189 break;
1190 }
1191
1192 /* Read/Write Character From Cursor Position */
1193 case 0x08:
1194 case 0x09:
1195 case 0x0A:
1196 {
1197 WORD CharacterData = MAKEWORD(getAL(), getBL());
1198 BYTE Page = getBH();
1199 DWORD Offset;
1200
1201 /* Check if the page exists */
1202 if (Page >= BIOS_MAX_PAGES) break;
1203
1204 /* Find the offset of the character */
1205 Offset = Page * Bda->VideoPageSize +
1206 (HIBYTE(Bda->CursorPosition[Page]) * Bda->ScreenColumns +
1207 LOBYTE(Bda->CursorPosition[Page])) * 2;
1208
1209 if (getAH() == 0x08)
1210 {
1211 /* Read from the video memory */
1212 VgaReadMemory(TO_LINEAR(TEXT_VIDEO_SEG, Offset),
1213 (LPVOID)&CharacterData,
1214 sizeof(WORD));
1215
1216 /* Return the character in AX */
1217 setAX(CharacterData);
1218 }
1219 else
1220 {
1221 /* Write to video memory */
1222 VgaWriteMemory(TO_LINEAR(TEXT_VIDEO_SEG, Offset),
1223 (LPVOID)&CharacterData,
1224 (getBH() == 0x09) ? sizeof(WORD) : sizeof(BYTE));
1225 }
1226
1227 break;
1228 }
1229
1230 /* Teletype Output */
1231 case 0x0E:
1232 {
1233 BiosPrintCharacter(getAL(), getBL(), getBH());
1234 break;
1235 }
1236
1237 /* Get Current Video Mode */
1238 case 0x0F:
1239 {
1240 setAX(MAKEWORD(Bda->VideoMode, Bda->ScreenColumns));
1241 setBX(MAKEWORD(getBL(), Bda->VideoPage));
1242 break;
1243 }
1244
1245 /* Palette Control */
1246 case 0x10:
1247 {
1248 switch (getAL())
1249 {
1250 /* Set Single Palette Register */
1251 case 0x00:
1252 {
1253 /* Write the index */
1254 VgaReadPort(VGA_INSTAT1_READ); // Put the AC register into index state
1255 VgaWritePort(VGA_AC_INDEX, getBL());
1256
1257 /* Write the data */
1258 VgaWritePort(VGA_AC_WRITE, getBH());
1259
1260 /* Enable screen and disable palette access */
1261 VgaReadPort(VGA_INSTAT1_READ); // Put the AC register into index state
1262 VgaWritePort(VGA_AC_INDEX, 0x20);
1263 break;
1264 }
1265
1266 /* Set Overscan Color */
1267 case 0x01:
1268 {
1269 /* Write the index */
1270 VgaReadPort(VGA_INSTAT1_READ); // Put the AC register into index state
1271 VgaWritePort(VGA_AC_INDEX, VGA_AC_OVERSCAN_REG);
1272
1273 /* Write the data */
1274 VgaWritePort(VGA_AC_WRITE, getBH());
1275
1276 /* Enable screen and disable palette access */
1277 VgaReadPort(VGA_INSTAT1_READ); // Put the AC register into index state
1278 VgaWritePort(VGA_AC_INDEX, 0x20);
1279 break;
1280 }
1281
1282 /* Set All Palette Registers */
1283 case 0x02:
1284 {
1285 INT i;
1286 LPBYTE Buffer = SEG_OFF_TO_PTR(getES(), getDX());
1287
1288 /* Set the palette registers */
1289 for (i = 0; i <= VGA_AC_PAL_F_REG; i++)
1290 {
1291 /* Write the index */
1292 VgaReadPort(VGA_INSTAT1_READ); // Put the AC register into index state
1293 VgaWritePort(VGA_AC_INDEX, i);
1294
1295 /* Write the data */
1296 VgaWritePort(VGA_AC_WRITE, Buffer[i]);
1297 }
1298
1299 /* Set the overscan register */
1300 VgaWritePort(VGA_AC_INDEX, VGA_AC_OVERSCAN_REG);
1301 VgaWritePort(VGA_AC_WRITE, Buffer[VGA_AC_PAL_F_REG + 1]);
1302
1303 /* Enable screen and disable palette access */
1304 VgaReadPort(VGA_INSTAT1_READ); // Put the AC register into index state
1305 VgaWritePort(VGA_AC_INDEX, 0x20);
1306 break;
1307 }
1308
1309 /* Get Single Palette Register */
1310 case 0x07:
1311 {
1312 /* Write the index */
1313 VgaReadPort(VGA_INSTAT1_READ); // Put the AC register into index state
1314 VgaWritePort(VGA_AC_INDEX, getBL());
1315
1316 /* Read the data */
1317 setBH(VgaReadPort(VGA_AC_READ));
1318
1319 /* Enable screen and disable palette access */
1320 VgaReadPort(VGA_INSTAT1_READ); // Put the AC register into index state
1321 VgaWritePort(VGA_AC_INDEX, 0x20);
1322 break;
1323 }
1324
1325 /* Get Overscan Color */
1326 case 0x08:
1327 {
1328 /* Write the index */
1329 VgaReadPort(VGA_INSTAT1_READ); // Put the AC register into index state
1330 VgaWritePort(VGA_AC_INDEX, VGA_AC_OVERSCAN_REG);
1331
1332 /* Read the data */
1333 setBH(VgaReadPort(VGA_AC_READ));
1334
1335 /* Enable screen and disable palette access */
1336 VgaReadPort(VGA_INSTAT1_READ); // Put the AC register into index state
1337 VgaWritePort(VGA_AC_INDEX, 0x20);
1338 break;
1339 }
1340
1341 /* Get All Palette Registers */
1342 case 0x09:
1343 {
1344 INT i;
1345 LPBYTE Buffer = SEG_OFF_TO_PTR(getES(), getDX());
1346
1347 /* Get the palette registers */
1348 for (i = 0; i <= VGA_AC_PAL_F_REG; i++)
1349 {
1350 /* Write the index */
1351 VgaReadPort(VGA_INSTAT1_READ); // Put the AC register into index state
1352 VgaWritePort(VGA_AC_INDEX, i);
1353
1354 /* Read the data */
1355 Buffer[i] = VgaReadPort(VGA_AC_READ);
1356 }
1357
1358 /* Get the overscan register */
1359 VgaWritePort(VGA_AC_INDEX, VGA_AC_OVERSCAN_REG);
1360 Buffer[VGA_AC_PAL_F_REG + 1] = VgaReadPort(VGA_AC_READ);
1361
1362 /* Enable screen and disable palette access */
1363 VgaReadPort(VGA_INSTAT1_READ); // Put the AC register into index state
1364 VgaWritePort(VGA_AC_INDEX, 0x20);
1365 break;
1366 }
1367
1368 /* Set Individual DAC Register */
1369 case 0x10:
1370 {
1371 /* Write the index */
1372 // Certainly in BL and not in BX as said by Ralf Brown...
1373 VgaWritePort(VGA_DAC_WRITE_INDEX, getBL());
1374
1375 /* Write the data in this order: Red, Green, Blue */
1376 VgaWritePort(VGA_DAC_DATA, getDH());
1377 VgaWritePort(VGA_DAC_DATA, getCH());
1378 VgaWritePort(VGA_DAC_DATA, getCL());
1379
1380 break;
1381 }
1382
1383 /* Set Block of DAC Registers */
1384 case 0x12:
1385 {
1386 INT i;
1387 LPBYTE Buffer = SEG_OFF_TO_PTR(getES(), getDX());
1388
1389 /* Write the index */
1390 // Certainly in BL and not in BX as said by Ralf Brown...
1391 VgaWritePort(VGA_DAC_WRITE_INDEX, getBL());
1392
1393 for (i = 0; i < getCX(); i++)
1394 {
1395 /* Write the data in this order: Red, Green, Blue */
1396 VgaWritePort(VGA_DAC_DATA, *Buffer++);
1397 VgaWritePort(VGA_DAC_DATA, *Buffer++);
1398 VgaWritePort(VGA_DAC_DATA, *Buffer++);
1399 }
1400
1401 break;
1402 }
1403
1404 /* Get Individual DAC Register */
1405 case 0x15:
1406 {
1407 /* Write the index */
1408 VgaWritePort(VGA_DAC_READ_INDEX, getBL());
1409
1410 /* Read the data in this order: Red, Green, Blue */
1411 setDH(VgaReadPort(VGA_DAC_DATA));
1412 setCH(VgaReadPort(VGA_DAC_DATA));
1413 setCL(VgaReadPort(VGA_DAC_DATA));
1414
1415 break;
1416 }
1417
1418 /* Get Block of DAC Registers */
1419 case 0x17:
1420 {
1421 INT i;
1422 LPBYTE Buffer = SEG_OFF_TO_PTR(getES(), getDX());
1423
1424 /* Write the index */
1425 // Certainly in BL and not in BX as said by Ralf Brown...
1426 VgaWritePort(VGA_DAC_READ_INDEX, getBL());
1427
1428 for (i = 0; i < getCX(); i++)
1429 {
1430 /* Write the data in this order: Red, Green, Blue */
1431 *Buffer++ = VgaReadPort(VGA_DAC_DATA);
1432 *Buffer++ = VgaReadPort(VGA_DAC_DATA);
1433 *Buffer++ = VgaReadPort(VGA_DAC_DATA);
1434 }
1435
1436 break;
1437 }
1438
1439 default:
1440 {
1441 DPRINT1("BIOS Palette Control Sub-command AL = 0x%02X NOT IMPLEMENTED\n",
1442 getAL());
1443 break;
1444 }
1445 }
1446
1447 break;
1448 }
1449
1450 /* Scroll Window */
1451 case 0x12:
1452 {
1453 SMALL_RECT Rectangle = { getCL(), getCH(), getDL(), getDH() };
1454
1455 /* Call the internal function */
1456 BiosScrollWindow(getBL(),
1457 getAL(),
1458 Rectangle,
1459 Bda->VideoPage,
1460 DEFAULT_ATTRIBUTE);
1461
1462 break;
1463 }
1464
1465 /* Display combination code */
1466 case 0x1A:
1467 {
1468 switch(getAL())
1469 {
1470 case 0x00: /* Get Display combiantion code */
1471 setAX(MAKEWORD(0x1A, 0x1A));
1472 setBX(MAKEWORD(0x08, 0x00)); /* VGA w/ color analog display */
1473 break;
1474 case 0x01: /* Set Display combination code */
1475 DPRINT1("Set Display combination code - Unsupported\n");
1476 break;
1477 default:
1478 break;
1479 }
1480 break;
1481 }
1482
1483 default:
1484 {
1485 DPRINT1("BIOS Function INT 10h, AH = 0x%02X NOT IMPLEMENTED\n",
1486 getAH());
1487 }
1488 }
1489 }
1490
1491 static VOID WINAPI BiosEquipmentService(LPWORD Stack)
1492 {
1493 /* Return the equipment list */
1494 setAX(Bda->EquipmentList);
1495 }
1496
1497 static VOID WINAPI BiosGetMemorySize(LPWORD Stack)
1498 {
1499 /* Return the conventional memory size in kB, typically 640 kB */
1500 setAX(Bda->MemorySize);
1501 }
1502
1503 static VOID WINAPI BiosMiscService(LPWORD Stack)
1504 {
1505 switch (getAH())
1506 {
1507 /* Copy Extended Memory */
1508 case 0x87:
1509 {
1510 DWORD Count = (DWORD)getCX() * 2;
1511 PFAST486_GDT_ENTRY Gdt = (PFAST486_GDT_ENTRY)SEG_OFF_TO_PTR(getES(), getSI());
1512 DWORD SourceBase = Gdt[2].Base + (Gdt[2].BaseMid << 16) + (Gdt[2].BaseHigh << 24);
1513 DWORD SourceLimit = Gdt[2].Limit + (Gdt[2].LimitHigh << 16);
1514 DWORD DestBase = Gdt[3].Base + (Gdt[3].BaseMid << 16) + (Gdt[3].BaseHigh << 24);
1515 DWORD DestLimit = Gdt[3].Limit + (Gdt[3].LimitHigh << 16);
1516
1517 /* Check for flags */
1518 if (Gdt[2].Granularity) SourceLimit = (SourceLimit << 12) | 0xFFF;
1519 if (Gdt[3].Granularity) DestLimit = (DestLimit << 12) | 0xFFF;
1520
1521 if ((Count > SourceLimit) || (Count > DestLimit))
1522 {
1523 setAX(0x80);
1524 Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF;
1525
1526 break;
1527 }
1528
1529 /* Copy */
1530 RtlMoveMemory((PVOID)((ULONG_PTR)BaseAddress + DestBase),
1531 (PVOID)((ULONG_PTR)BaseAddress + SourceBase),
1532 Count);
1533
1534 setAX(ERROR_SUCCESS);
1535 Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF;
1536 break;
1537 }
1538
1539 /* Get Extended Memory Size */
1540 case 0x88:
1541 {
1542 /* Return the number of KB of RAM after 1 MB */
1543 setAX((MAX_ADDRESS - 0x100000) / 1024);
1544
1545 /* Clear CF */
1546 Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF;
1547
1548 break;
1549 }
1550
1551 default:
1552 {
1553 DPRINT1("BIOS Function INT 15h, AH = 0x%02X NOT IMPLEMENTED\n",
1554 getAH());
1555 }
1556 }
1557 }
1558
1559 static VOID WINAPI BiosKeyboardService(LPWORD Stack)
1560 {
1561 switch (getAH())
1562 {
1563 /* Wait for keystroke and read */
1564 case 0x00:
1565 /* Wait for extended keystroke and read */
1566 case 0x10: // FIXME: Temporarily do the same as INT 16h, 00h
1567 {
1568 /* Read the character (and wait if necessary) */
1569 setAX(BiosGetCharacter());
1570 break;
1571 }
1572
1573 /* Get keystroke status */
1574 case 0x01:
1575 /* Get extended keystroke status */
1576 case 0x11: // FIXME: Temporarily do the same as INT 16h, 01h
1577 {
1578 WORD Data = BiosPeekCharacter();
1579
1580 if (Data != 0xFFFF)
1581 {
1582 /* There is a character, clear ZF and return it */
1583 Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_ZF;
1584 setAX(Data);
1585 }
1586 else
1587 {
1588 /* No character, set ZF */
1589 Stack[STACK_FLAGS] |= EMULATOR_FLAG_ZF;
1590 }
1591
1592 break;
1593 }
1594
1595 /* Get shift status */
1596 case 0x02:
1597 {
1598 /* Return the lower byte of the keyboard shift status word */
1599 setAL(LOBYTE(Bda->KeybdShiftFlags));
1600 break;
1601 }
1602
1603 /* Reserved */
1604 case 0x04:
1605 {
1606 DPRINT1("BIOS Function INT 16h, AH = 0x04 is RESERVED\n");
1607 break;
1608 }
1609
1610 /* Push keystroke */
1611 case 0x05:
1612 {
1613 /* Return 0 if success, 1 if failure */
1614 setAL(BiosKbdBufferPush(getCX()) == FALSE);
1615 break;
1616 }
1617
1618 /* Get extended shift status */
1619 case 0x12:
1620 {
1621 /*
1622 * Be careful! The returned word is similar to Bda->KeybdShiftFlags
1623 * but the high byte is organized differently:
1624 * the bytes 2 and 3 of the high byte are not the same...
1625 */
1626 WORD KeybdShiftFlags = (Bda->KeybdShiftFlags & 0xF3FF);
1627
1628 /* Return the extended keyboard shift status word */
1629 setAX(KeybdShiftFlags);
1630 break;
1631 }
1632
1633 default:
1634 {
1635 DPRINT1("BIOS Function INT 16h, AH = 0x%02X NOT IMPLEMENTED\n",
1636 getAH());
1637 }
1638 }
1639 }
1640
1641 static VOID WINAPI BiosTimeService(LPWORD Stack)
1642 {
1643 switch (getAH())
1644 {
1645 case 0x00:
1646 {
1647 /* Set AL to 1 if midnight had passed, 0 otherwise */
1648 setAL(Bda->MidnightPassed ? 0x01 : 0x00);
1649
1650 /* Return the tick count in CX:DX */
1651 setCX(HIWORD(Bda->TickCounter));
1652 setDX(LOWORD(Bda->TickCounter));
1653
1654 /* Reset the midnight flag */
1655 Bda->MidnightPassed = FALSE;
1656
1657 break;
1658 }
1659
1660 case 0x01:
1661 {
1662 /* Set the tick count to CX:DX */
1663 Bda->TickCounter = MAKELONG(getDX(), getCX());
1664
1665 /* Reset the midnight flag */
1666 Bda->MidnightPassed = FALSE;
1667
1668 break;
1669 }
1670
1671 default:
1672 {
1673 DPRINT1("BIOS Function INT 1Ah, AH = 0x%02X NOT IMPLEMENTED\n",
1674 getAH());
1675 }
1676 }
1677 }
1678
1679 static VOID WINAPI BiosSystemTimerInterrupt(LPWORD Stack)
1680 {
1681 /* Increase the system tick count */
1682 Bda->TickCounter++;
1683 }
1684
1685 /* PUBLIC FUNCTIONS ***********************************************************/
1686
1687 WORD BiosPeekCharacter(VOID)
1688 {
1689 WORD CharacterData = 0;
1690
1691 /* Get the key from the queue, but don't remove it */
1692 if (BiosKbdBufferTop(&CharacterData)) return CharacterData;
1693 else return 0xFFFF;
1694 }
1695
1696 WORD BiosGetCharacter(VOID)
1697 {
1698 WORD CharacterData = 0;
1699
1700 /* Check if there is a key available */
1701 if (BiosKbdBufferTop(&CharacterData))
1702 {
1703 /* A key was available, remove it from the queue */
1704 BiosKbdBufferPop();
1705 }
1706 else
1707 {
1708 /* No key available. Set the handler CF to repeat the BOP */
1709 setCF(1);
1710 // CharacterData = 0xFFFF;
1711 }
1712
1713 return CharacterData;
1714 }
1715
1716 VOID BiosPrintCharacter(CHAR Character, BYTE Attribute, BYTE Page)
1717 {
1718 WORD CharData = MAKEWORD(Character, Attribute);
1719 BYTE Row, Column;
1720
1721 /* Make sure the page exists */
1722 if (Page >= BIOS_MAX_PAGES) return;
1723
1724 /* Get the cursor location */
1725 BiosGetCursorPosition(&Row, &Column, Page);
1726
1727 if (Character == '\a')
1728 {
1729 /* Bell control character */
1730 // NOTE: We may use what the terminal emulator offers to us...
1731 Beep(800, 200);
1732 return;
1733 }
1734 else if (Character == '\b')
1735 {
1736 /* Backspace control character */
1737 if (Column > 0)
1738 {
1739 Column--;
1740 }
1741 else if (Row > 0)
1742 {
1743 Column = Bda->ScreenColumns - 1;
1744 Row--;
1745 }
1746
1747 /* Erase the existing character */
1748 CharData = MAKEWORD(' ', Attribute);
1749 EmulatorWriteMemory(&EmulatorContext,
1750 TO_LINEAR(TEXT_VIDEO_SEG,
1751 Page * Bda->VideoPageSize +
1752 (Row * Bda->ScreenColumns + Column) * sizeof(WORD)),
1753 (LPVOID)&CharData,
1754 sizeof(WORD));
1755 }
1756 else if (Character == '\t')
1757 {
1758 /* Horizontal Tabulation control character */
1759 do
1760 {
1761 // Taken from DOSBox
1762 BiosPrintCharacter(' ', Attribute, Page);
1763 BiosGetCursorPosition(&Row, &Column, Page);
1764 } while (Column % 8);
1765 }
1766 else if (Character == '\n')
1767 {
1768 /* Line Feed control character */
1769 Row++;
1770 }
1771 else if (Character == '\r')
1772 {
1773 /* Carriage Return control character */
1774 Column = 0;
1775 }
1776 else
1777 {
1778 /* Default character */
1779
1780 /* Write the character */
1781 EmulatorWriteMemory(&EmulatorContext,
1782 TO_LINEAR(TEXT_VIDEO_SEG,
1783 Page * Bda->VideoPageSize +
1784 (Row * Bda->ScreenColumns + Column) * sizeof(WORD)),
1785 (LPVOID)&CharData,
1786 sizeof(WORD));
1787
1788 /* Advance the cursor */
1789 Column++;
1790 }
1791
1792 /* Check if it passed the end of the row */
1793 if (Column >= Bda->ScreenColumns)
1794 {
1795 /* Return to the first column and go to the next line */
1796 Column = 0;
1797 Row++;
1798 }
1799
1800 /* Scroll the screen up if needed */
1801 if (Row > Bda->ScreenRows)
1802 {
1803 /* The screen must be scrolled up */
1804 SMALL_RECT Rectangle = { 0, 0, Bda->ScreenColumns - 1, Bda->ScreenRows };
1805
1806 BiosScrollWindow(SCROLL_DIRECTION_UP,
1807 1,
1808 Rectangle,
1809 Page,
1810 DEFAULT_ATTRIBUTE);
1811
1812 Row--;
1813 }
1814
1815 /* Set the cursor position */
1816 BiosSetCursorPosition(Row, Column, Page);
1817 }
1818
1819 BOOLEAN BiosInitialize(VOID)
1820 {
1821 CONSOLE_SCREEN_BUFFER_INFO ConsoleInfo;
1822
1823 /* Initialize the BDA */
1824 Bda = (PBIOS_DATA_AREA)SEG_OFF_TO_PTR(BDA_SEGMENT, 0);
1825 Bda->EquipmentList = BIOS_EQUIPMENT_LIST;
1826 /*
1827 * Conventional memory size is 640 kB,
1828 * see: http://webpages.charter.net/danrollins/techhelp/0184.HTM
1829 * and see Ralf Brown: http://www.ctyme.com/intr/rb-0598.htm
1830 * for more information.
1831 */
1832 Bda->MemorySize = 0x0280;
1833 Bda->KeybdBufferStart = FIELD_OFFSET(BIOS_DATA_AREA, KeybdBuffer);
1834 Bda->KeybdBufferEnd = Bda->KeybdBufferStart + BIOS_KBD_BUFFER_SIZE * sizeof(WORD);
1835 Bda->KeybdBufferHead = Bda->KeybdBufferTail = 0;
1836
1837 /* Initialize the 32-bit Interrupt system */
1838 InitializeInt32(BIOS_SEGMENT);
1839
1840 /* Register the BIOS 32-bit Interrupts */
1841 RegisterInt32(BIOS_VIDEO_INTERRUPT , BiosVideoService );
1842 RegisterInt32(BIOS_EQUIPMENT_INTERRUPT, BiosEquipmentService );
1843 RegisterInt32(BIOS_MEMORY_SIZE , BiosGetMemorySize );
1844 RegisterInt32(BIOS_MISC_INTERRUPT , BiosMiscService );
1845 RegisterInt32(BIOS_KBD_INTERRUPT , BiosKeyboardService );
1846 RegisterInt32(BIOS_TIME_INTERRUPT , BiosTimeService );
1847 RegisterInt32(BIOS_SYS_TIMER_INTERRUPT, BiosSystemTimerInterrupt);
1848
1849 /* Some interrupts are in fact addresses to tables */
1850 ((PDWORD)BaseAddress)[0x1D] = (DWORD)NULL;
1851 ((PDWORD)BaseAddress)[0x1E] = (DWORD)NULL;
1852 ((PDWORD)BaseAddress)[0x1F] = (DWORD)NULL;
1853
1854 ((PDWORD)BaseAddress)[0x41] = (DWORD)NULL;
1855 ((PDWORD)BaseAddress)[0x43] = (DWORD)NULL;
1856 ((PDWORD)BaseAddress)[0x44] = (DWORD)NULL;
1857 ((PDWORD)BaseAddress)[0x46] = (DWORD)NULL;
1858 ((PDWORD)BaseAddress)[0x48] = (DWORD)NULL;
1859 ((PDWORD)BaseAddress)[0x49] = (DWORD)NULL;
1860
1861 /* Get the input handle to the real console, and check for success */
1862 BiosConsoleInput = CreateFileW(L"CONIN$",
1863 GENERIC_READ | GENERIC_WRITE,
1864 FILE_SHARE_READ | FILE_SHARE_WRITE,
1865 NULL,
1866 OPEN_EXISTING,
1867 0,
1868 NULL);
1869 if (BiosConsoleInput == INVALID_HANDLE_VALUE)
1870 {
1871 return FALSE;
1872 }
1873
1874 /* Get the output handle to the real console, and check for success */
1875 BiosConsoleOutput = CreateFileW(L"CONOUT$",
1876 GENERIC_READ | GENERIC_WRITE,
1877 FILE_SHARE_READ | FILE_SHARE_WRITE,
1878 NULL,
1879 OPEN_EXISTING,
1880 0,
1881 NULL);
1882 if (BiosConsoleOutput == INVALID_HANDLE_VALUE)
1883 {
1884 CloseHandle(BiosConsoleInput);
1885 return FALSE;
1886 }
1887
1888 /* Save the original input and output console modes */
1889 if (!GetConsoleMode(BiosConsoleInput , &BiosSavedConInMode ) ||
1890 !GetConsoleMode(BiosConsoleOutput, &BiosSavedConOutMode))
1891 {
1892 CloseHandle(BiosConsoleOutput);
1893 CloseHandle(BiosConsoleInput);
1894 return FALSE;
1895 }
1896
1897 /* Save the original cursor and console screen buffer information */
1898 if (!GetConsoleCursorInfo(BiosConsoleOutput, &BiosSavedCursorInfo) ||
1899 !GetConsoleScreenBufferInfo(BiosConsoleOutput, &BiosSavedBufferInfo))
1900 {
1901 CloseHandle(BiosConsoleOutput);
1902 CloseHandle(BiosConsoleInput);
1903 return FALSE;
1904 }
1905
1906 /* Initialize VGA */
1907 if (!VgaInitialize(BiosConsoleOutput))
1908 {
1909 CloseHandle(BiosConsoleOutput);
1910 CloseHandle(BiosConsoleInput);
1911 return FALSE;
1912 }
1913
1914 /* Set the default video mode */
1915 BiosSetVideoMode(BIOS_DEFAULT_VIDEO_MODE);
1916
1917 GetConsoleScreenBufferInfo(BiosConsoleOutput, &ConsoleInfo);
1918
1919 /* Copy console data into VGA memory */
1920 BiosCopyTextConsoleToVgaMemory(&ConsoleInfo.dwSize);
1921
1922 /* Update the cursor position for the current page */
1923 BiosSetCursorPosition(ConsoleInfo.dwCursorPosition.Y,
1924 ConsoleInfo.dwCursorPosition.X,
1925 Bda->VideoPage);
1926
1927 /* Set the console input mode */
1928 SetConsoleMode(BiosConsoleInput, ENABLE_MOUSE_INPUT | ENABLE_PROCESSED_INPUT);
1929
1930 /* Initialize PS2 */
1931 PS2Initialize(BiosConsoleInput);
1932
1933 /* Initialize the PIC */
1934 PicWriteCommand(PIC_MASTER_CMD, PIC_ICW1 | PIC_ICW1_ICW4);
1935 PicWriteCommand(PIC_SLAVE_CMD , PIC_ICW1 | PIC_ICW1_ICW4);
1936
1937 /* Set the interrupt offsets */
1938 PicWriteData(PIC_MASTER_DATA, BIOS_PIC_MASTER_INT);
1939 PicWriteData(PIC_SLAVE_DATA , BIOS_PIC_SLAVE_INT);
1940
1941 /* Tell the master PIC there is a slave at IRQ 2 */
1942 PicWriteData(PIC_MASTER_DATA, 1 << 2);
1943 PicWriteData(PIC_SLAVE_DATA , 2);
1944
1945 /* Make sure the PIC is in 8086 mode */
1946 PicWriteData(PIC_MASTER_DATA, PIC_ICW4_8086);
1947 PicWriteData(PIC_SLAVE_DATA , PIC_ICW4_8086);
1948
1949 /* Clear the masks for both PICs */
1950 PicWriteData(PIC_MASTER_DATA, 0x00);
1951 PicWriteData(PIC_SLAVE_DATA , 0x00);
1952
1953 PitWriteCommand(0x34);
1954 PitWriteData(0, 0x00);
1955 PitWriteData(0, 0x00);
1956
1957 return TRUE;
1958 }
1959
1960 VOID BiosCleanup(VOID)
1961 {
1962 SMALL_RECT ConRect;
1963 CONSOLE_SCREEN_BUFFER_INFO ConsoleInfo;
1964
1965 PS2Cleanup();
1966
1967 /* Restore the old screen buffer */
1968 SetConsoleActiveScreenBuffer(BiosConsoleOutput);
1969
1970 /* Restore the original console size */
1971 GetConsoleScreenBufferInfo(BiosConsoleOutput, &ConsoleInfo);
1972 ConRect.Left = 0; // BiosSavedBufferInfo.srWindow.Left;
1973 // ConRect.Top = ConsoleInfo.dwCursorPosition.Y / (BiosSavedBufferInfo.srWindow.Bottom - BiosSavedBufferInfo.srWindow.Top + 1);
1974 // ConRect.Top *= (BiosSavedBufferInfo.srWindow.Bottom - BiosSavedBufferInfo.srWindow.Top + 1);
1975 ConRect.Top = ConsoleInfo.dwCursorPosition.Y;
1976 ConRect.Right = ConRect.Left + BiosSavedBufferInfo.srWindow.Right - BiosSavedBufferInfo.srWindow.Left;
1977 ConRect.Bottom = ConRect.Top + BiosSavedBufferInfo.srWindow.Bottom - BiosSavedBufferInfo.srWindow.Top ;
1978 /* See the following trick explanation in vga.c:VgaEnterTextMode() */
1979 SetConsoleScreenBufferSize(BiosConsoleOutput, BiosSavedBufferInfo.dwSize);
1980 SetConsoleWindowInfo(BiosConsoleOutput, TRUE, &ConRect);
1981 // SetConsoleWindowInfo(BiosConsoleOutput, TRUE, &BiosSavedBufferInfo.srWindow);
1982 SetConsoleScreenBufferSize(BiosConsoleOutput, BiosSavedBufferInfo.dwSize);
1983
1984 /* Restore the original cursor shape */
1985 SetConsoleCursorInfo(BiosConsoleOutput, &BiosSavedCursorInfo);
1986
1987 /* Restore the original input and output console modes */
1988 SetConsoleMode(BiosConsoleOutput, BiosSavedConOutMode);
1989 SetConsoleMode(BiosConsoleInput , BiosSavedConInMode );
1990
1991 /* Close the console handles */
1992 if (BiosConsoleOutput != INVALID_HANDLE_VALUE) CloseHandle(BiosConsoleOutput);
1993 if (BiosConsoleInput != INVALID_HANDLE_VALUE) CloseHandle(BiosConsoleInput);
1994 }
1995
1996 VOID BiosHandleIrq(BYTE IrqNumber, LPWORD Stack)
1997 {
1998 switch (IrqNumber)
1999 {
2000 /* PIT IRQ */
2001 case 0:
2002 {
2003 /* Perform the system timer interrupt */
2004 EmulatorInterrupt(BIOS_SYS_TIMER_INTERRUPT);
2005 break;
2006 }
2007
2008 /* Keyboard IRQ */
2009 case 1:
2010 {
2011 BYTE ScanCode, VirtualKey;
2012 WORD Character;
2013
2014 /* Get the scan code and virtual key code */
2015 ScanCode = PS2ReadPort(PS2_DATA_PORT);
2016 VirtualKey = MapVirtualKey(ScanCode & 0x7F, MAPVK_VSC_TO_VK);
2017
2018 /* Check if this is a key press or release */
2019 if (!(ScanCode & (1 << 7)))
2020 {
2021 /* Key press */
2022 if (VirtualKey == VK_NUMLOCK ||
2023 VirtualKey == VK_CAPITAL ||
2024 VirtualKey == VK_SCROLL ||
2025 VirtualKey == VK_INSERT)
2026 {
2027 /* For toggle keys, toggle the lowest bit in the keyboard map */
2028 BiosKeyboardMap[VirtualKey] ^= ~(1 << 0);
2029 }
2030
2031 /* Set the highest bit */
2032 BiosKeyboardMap[VirtualKey] |= (1 << 7);
2033
2034 /* Find out which character this is */
2035 Character = 0;
2036 if (ToAscii(VirtualKey, ScanCode, BiosKeyboardMap, &Character, 0) == 0)
2037 {
2038 /* Not ASCII */
2039 Character = 0;
2040 }
2041
2042 /* Push it onto the BIOS keyboard queue */
2043 BiosKbdBufferPush(MAKEWORD(Character, ScanCode));
2044 }
2045 else
2046 {
2047 /* Key release, unset the highest bit */
2048 BiosKeyboardMap[VirtualKey] &= ~(1 << 7);
2049 }
2050
2051 /* Clear the keyboard flags */
2052 Bda->KeybdShiftFlags = 0;
2053
2054 /* Set the appropriate flags based on the state */
2055 if (BiosKeyboardMap[VK_RSHIFT] & (1 << 7)) Bda->KeybdShiftFlags |= BDA_KBDFLAG_RSHIFT;
2056 if (BiosKeyboardMap[VK_LSHIFT] & (1 << 7)) Bda->KeybdShiftFlags |= BDA_KBDFLAG_LSHIFT;
2057 if (BiosKeyboardMap[VK_CONTROL] & (1 << 7)) Bda->KeybdShiftFlags |= BDA_KBDFLAG_CTRL;
2058 if (BiosKeyboardMap[VK_MENU] & (1 << 7)) Bda->KeybdShiftFlags |= BDA_KBDFLAG_ALT;
2059 if (BiosKeyboardMap[VK_SCROLL] & (1 << 0)) Bda->KeybdShiftFlags |= BDA_KBDFLAG_SCROLL_ON;
2060 if (BiosKeyboardMap[VK_NUMLOCK] & (1 << 0)) Bda->KeybdShiftFlags |= BDA_KBDFLAG_NUMLOCK_ON;
2061 if (BiosKeyboardMap[VK_CAPITAL] & (1 << 0)) Bda->KeybdShiftFlags |= BDA_KBDFLAG_CAPSLOCK_ON;
2062 if (BiosKeyboardMap[VK_INSERT] & (1 << 0)) Bda->KeybdShiftFlags |= BDA_KBDFLAG_INSERT_ON;
2063 if (BiosKeyboardMap[VK_RMENU] & (1 << 7)) Bda->KeybdShiftFlags |= BDA_KBDFLAG_RALT;
2064 if (BiosKeyboardMap[VK_LMENU] & (1 << 7)) Bda->KeybdShiftFlags |= BDA_KBDFLAG_LALT;
2065 if (BiosKeyboardMap[VK_SNAPSHOT] & (1 << 7)) Bda->KeybdShiftFlags |= BDA_KBDFLAG_SYSRQ;
2066 if (BiosKeyboardMap[VK_PAUSE] & (1 << 7)) Bda->KeybdShiftFlags |= BDA_KBDFLAG_PAUSE;
2067 if (BiosKeyboardMap[VK_SCROLL] & (1 << 7)) Bda->KeybdShiftFlags |= BDA_KBDFLAG_SCROLL;
2068 if (BiosKeyboardMap[VK_NUMLOCK] & (1 << 7)) Bda->KeybdShiftFlags |= BDA_KBDFLAG_NUMLOCK;
2069 if (BiosKeyboardMap[VK_CAPITAL] & (1 << 7)) Bda->KeybdShiftFlags |= BDA_KBDFLAG_CAPSLOCK;
2070 if (BiosKeyboardMap[VK_INSERT] & (1 << 7)) Bda->KeybdShiftFlags |= BDA_KBDFLAG_INSERT;
2071
2072 break;
2073 }
2074 }
2075
2076 /* Send End-of-Interrupt to the PIC */
2077 if (IrqNumber >= 8) PicWriteCommand(PIC_SLAVE_CMD, PIC_OCW2_EOI);
2078 PicWriteCommand(PIC_MASTER_CMD, PIC_OCW2_EOI);
2079 }
2080
2081 /* EOF */