444e7e1a8a5b70fb305075ff42434549cf1e6a5d
[reactos.git] / reactos / 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) (uses 3rd CGA palette)
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 #if 0
373
374 // Unused at the moment
375 static CONST COLORREF CgaPalette[16] =
376 {
377 RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0xAA), RGB(0x00, 0xAA, 0x00), RGB(0x00, 0xAA, 0xAA),
378 RGB(0xAA, 0x00, 0x00), RGB(0xAA, 0x00, 0xAA), RGB(0xAA, 0x55, 0x00), RGB(0xAA, 0xAA, 0xAA),
379 RGB(0x55, 0x55, 0x55), RGB(0x55, 0x55, 0xFF), RGB(0x55, 0xFF, 0x55), RGB(0x55, 0xFF, 0xFF),
380 RGB(0xFF, 0x55, 0x55), RGB(0xFF, 0x55, 0xFF), RGB(0xFF, 0xFF, 0x55), RGB(0xFF, 0xFF, 0xFF)
381 };
382
383 /* CGA palette 1 */
384 static CONST BYTE CgaPalette1[] =
385 {
386 0x00, /* 0 - Black */
387 0x03, /* 1 - Cyan */
388 0x05, /* 2- Magenta */
389 0x07, /* 3 - White */
390 }
391
392 /* CGA palette 1 bright */
393 static CONST BYTE CgaPalette1i[] =
394 {
395 0x00, /* 0 - Black */
396 0x13, /* 1 - Light cyan */
397 0x15, /* 2 - Light magenta */
398 0x17, /* 3 - Bright White */
399 };
400
401 /* CGA palette 2 */
402 static CONST BYTE CgaPalette2[] =
403 {
404 0x00, /* 0 - Black */
405 0x02, /* 1 - Green */
406 0x04, /* 2 - Red */
407 0x06, /* 3 - Brown */
408 };
409
410 /* CGA palette 2 bright */
411 static CONST BYTE CgaPalette2i[] =
412 {
413 0x00, /* 0 - Black */
414 0x12, /* 1 - Light green */
415 0x14, /* 2 - Light red */
416 0x16, /* 3 - Yellow */
417 };
418
419 // Unused at the moment; same palette as EgaPalette__16Colors
420 static CONST COLORREF CgaPalette2[VGA_MAX_COLORS / 4] =
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 RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0xAA), RGB(0x00, 0xAA, 0x00), RGB(0x00, 0xAA, 0xAA),
425 RGB(0xAA, 0x00, 0x00), RGB(0xAA, 0x00, 0xAA), RGB(0xAA, 0x55, 0x00), RGB(0xAA, 0xAA, 0xAA),
426
427 RGB(0x55, 0x55, 0x55), RGB(0x55, 0x55, 0xFF), RGB(0x55, 0xFF, 0x55), RGB(0x55, 0xFF, 0xFF),
428 RGB(0xFF, 0x55, 0x55), RGB(0xFF, 0x55, 0xFF), RGB(0xFF, 0xFF, 0x55), RGB(0xFF, 0xFF, 0xFF),
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(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0xAA), RGB(0x00, 0xAA, 0x00), RGB(0x00, 0xAA, 0xAA),
433 RGB(0xAA, 0x00, 0x00), RGB(0xAA, 0x00, 0xAA), RGB(0xAA, 0x55, 0x00), RGB(0xAA, 0xAA, 0xAA),
434 RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0xAA), RGB(0x00, 0xAA, 0x00), RGB(0x00, 0xAA, 0xAA),
435 RGB(0xAA, 0x00, 0x00), RGB(0xAA, 0x00, 0xAA), RGB(0xAA, 0x55, 0x00), RGB(0xAA, 0xAA, 0xAA),
436
437 RGB(0x55, 0x55, 0x55), RGB(0x55, 0x55, 0xFF), RGB(0x55, 0xFF, 0x55), RGB(0x55, 0xFF, 0xFF),
438 RGB(0xFF, 0x55, 0x55), RGB(0xFF, 0x55, 0xFF), RGB(0xFF, 0xFF, 0x55), RGB(0xFF, 0xFF, 0xFF),
439 RGB(0x55, 0x55, 0x55), RGB(0x55, 0x55, 0xFF), RGB(0x55, 0xFF, 0x55), RGB(0x55, 0xFF, 0xFF),
440 RGB(0xFF, 0x55, 0x55), RGB(0xFF, 0x55, 0xFF), RGB(0xFF, 0xFF, 0x55), RGB(0xFF, 0xFF, 0xFF)
441 };
442
443 #endif
444
445 static CONST COLORREF EgaPalette__16Colors[VGA_MAX_COLORS / 4] =
446 {
447 RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0xAA), RGB(0x00, 0xAA, 0x00), RGB(0x00, 0xAA, 0xAA),
448 RGB(0xAA, 0x00, 0x00), RGB(0xAA, 0x00, 0xAA), RGB(0xAA, 0x55, 0x00), RGB(0xAA, 0xAA, 0xAA),
449
450 RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0xAA), RGB(0x00, 0xAA, 0x00), RGB(0x00, 0xAA, 0xAA),
451 RGB(0xAA, 0x00, 0x00), RGB(0xAA, 0x00, 0xAA), RGB(0xAA, 0x55, 0x00), RGB(0xAA, 0xAA, 0xAA),
452
453
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 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
462 RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0xAA), RGB(0x00, 0xAA, 0x00), RGB(0x00, 0xAA, 0xAA),
463 RGB(0xAA, 0x00, 0x00), RGB(0xAA, 0x00, 0xAA), RGB(0xAA, 0x55, 0x00), RGB(0xAA, 0xAA, 0xAA),
464
465 RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0xAA), RGB(0x00, 0xAA, 0x00), RGB(0x00, 0xAA, 0xAA),
466 RGB(0xAA, 0x00, 0x00), RGB(0xAA, 0x00, 0xAA), RGB(0xAA, 0x55, 0x00), RGB(0xAA, 0xAA, 0xAA),
467
468
469 RGB(0x55, 0x55, 0x55), RGB(0x55, 0x55, 0xFF), RGB(0x55, 0xFF, 0x55), RGB(0x55, 0xFF, 0xFF),
470 RGB(0xFF, 0x55, 0x55), RGB(0xFF, 0x55, 0xFF), RGB(0xFF, 0xFF, 0x55), RGB(0xFF, 0xFF, 0xFF),
471
472 RGB(0x55, 0x55, 0x55), RGB(0x55, 0x55, 0xFF), RGB(0x55, 0xFF, 0x55), RGB(0x55, 0xFF, 0xFF),
473 RGB(0xFF, 0x55, 0x55), RGB(0xFF, 0x55, 0xFF), RGB(0xFF, 0xFF, 0x55), RGB(0xFF, 0xFF, 0xFF)
474 };
475
476 // This is the same as TextPalette
477 static CONST COLORREF EgaPalette__HiRes[VGA_MAX_COLORS / 4] =
478 {
479 RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0xAA), RGB(0x00, 0xAA, 0x00), RGB(0x00, 0xAA, 0xAA),
480 RGB(0xAA, 0x00, 0x00), RGB(0xAA, 0x00, 0xAA), RGB(0xAA, 0xAA, 0x00), RGB(0xAA, 0xAA, 0xAA),
481 RGB(0x00, 0x00, 0x55), RGB(0x00, 0x00, 0xFF), RGB(0x00, 0xAA, 0x55), RGB(0x00, 0xAA, 0xFF),
482 RGB(0xAA, 0x00, 0x55), RGB(0xAA, 0x00, 0xFF), RGB(0xAA, 0xAA, 0x55), RGB(0xAA, 0xAA, 0xFF),
483
484 RGB(0x00, 0x55, 0x00), RGB(0x00, 0x55, 0xAA), RGB(0x00, 0xFF, 0x00), RGB(0x00, 0xFF, 0xAA),
485 RGB(0xAA, 0x55, 0x00), RGB(0xAA, 0x55, 0xAA), RGB(0xAA, 0xFF, 0x00), RGB(0xAA, 0xFF, 0xAA),
486 RGB(0x00, 0x55, 0x55), RGB(0x00, 0x55, 0xFF), RGB(0x00, 0xFF, 0x55), RGB(0x00, 0xFF, 0xFF),
487 RGB(0xAA, 0x55, 0x55), RGB(0xAA, 0x55, 0xFF), RGB(0xAA, 0xFF, 0x55), RGB(0xAA, 0xFF, 0xFF),
488
489
490 RGB(0x55, 0x00, 0x00), RGB(0x55, 0x00, 0xAA), RGB(0x55, 0xAA, 0x00), RGB(0x55, 0xAA, 0xAA),
491 RGB(0xFF, 0x00, 0x00), RGB(0xFF, 0x00, 0xAA), RGB(0xFF, 0xAA, 0x00), RGB(0xFF, 0xAA, 0xAA),
492 RGB(0x55, 0x00, 0x55), RGB(0x55, 0x00, 0xFF), RGB(0x55, 0xAA, 0x55), RGB(0x55, 0xAA, 0xFF),
493 RGB(0xFF, 0x00, 0x55), RGB(0xFF, 0x00, 0xFF), RGB(0xFF, 0xAA, 0x55), RGB(0xFF, 0xAA, 0xFF),
494
495 RGB(0x55, 0x55, 0x00), RGB(0x55, 0x55, 0xAA), RGB(0x55, 0xFF, 0x00), RGB(0x55, 0xFF, 0xAA),
496 RGB(0xFF, 0x55, 0x00), RGB(0xFF, 0x55, 0xAA), RGB(0xFF, 0xFF, 0x00), RGB(0xFF, 0xFF, 0xAA),
497 RGB(0x55, 0x55, 0x55), RGB(0x55, 0x55, 0xFF), RGB(0x55, 0xFF, 0x55), RGB(0x55, 0xFF, 0xFF),
498 RGB(0xFF, 0x55, 0x55), RGB(0xFF, 0x55, 0xFF), RGB(0xFF, 0xFF, 0x55), RGB(0xFF, 0xFF, 0xFF)
499 };
500
501 #define USE_REACTOS_COLORS
502 // #define USE_DOSBOX_COLORS
503
504 /*
505 * Same palette as the default one 'VgaDefaultPalette' in vga.c
506 */
507 #if defined(USE_REACTOS_COLORS)
508
509 // ReactOS colors
510 static CONST COLORREF VgaPalette[VGA_MAX_COLORS] =
511 {
512 RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0xAA), RGB(0x00, 0xAA, 0x00), RGB(0x00, 0xAA, 0xAA),
513 RGB(0xAA, 0x00, 0x00), RGB(0xAA, 0x00, 0xAA), RGB(0xAA, 0x55, 0x00), RGB(0xAA, 0xAA, 0xAA),
514 RGB(0x55, 0x55, 0x55), RGB(0x55, 0x55, 0xFF), RGB(0x55, 0xFF, 0x55), RGB(0x55, 0xFF, 0xFF),
515 RGB(0xFF, 0x55, 0x55), RGB(0xFF, 0x55, 0xFF), RGB(0xFF, 0xFF, 0x55), RGB(0xFF, 0xFF, 0xFF),
516 RGB(0x00, 0x00, 0x00), RGB(0x10, 0x10, 0x10), RGB(0x20, 0x20, 0x20), RGB(0x35, 0x35, 0x35),
517 RGB(0x45, 0x45, 0x45), RGB(0x55, 0x55, 0x55), RGB(0x65, 0x65, 0x65), RGB(0x75, 0x75, 0x75),
518 RGB(0x8A, 0x8A, 0x8A), RGB(0x9A, 0x9A, 0x9A), RGB(0xAA, 0xAA, 0xAA), RGB(0xBA, 0xBA, 0xBA),
519 RGB(0xCA, 0xCA, 0xCA), RGB(0xDF, 0xDF, 0xDF), RGB(0xEF, 0xEF, 0xEF), RGB(0xFF, 0xFF, 0xFF),
520 RGB(0x00, 0x00, 0xFF), RGB(0x41, 0x00, 0xFF), RGB(0x82, 0x00, 0xFF), RGB(0xBE, 0x00, 0xFF),
521 RGB(0xFF, 0x00, 0xFF), RGB(0xFF, 0x00, 0xBE), RGB(0xFF, 0x00, 0x82), RGB(0xFF, 0x00, 0x41),
522 RGB(0xFF, 0x00, 0x00), RGB(0xFF, 0x41, 0x00), RGB(0xFF, 0x82, 0x00), RGB(0xFF, 0xBE, 0x00),
523 RGB(0xFF, 0xFF, 0x00), RGB(0xBE, 0xFF, 0x00), RGB(0x82, 0xFF, 0x00), RGB(0x41, 0xFF, 0x00),
524 RGB(0x00, 0xFF, 0x00), RGB(0x00, 0xFF, 0x41), RGB(0x00, 0xFF, 0x82), RGB(0x00, 0xFF, 0xBE),
525 RGB(0x00, 0xFF, 0xFF), RGB(0x00, 0xBE, 0xFF), RGB(0x00, 0x82, 0xFF), RGB(0x00, 0x41, 0xFF),
526 RGB(0x82, 0x82, 0xFF), RGB(0x9E, 0x82, 0xFF), RGB(0xBE, 0x82, 0xFF), RGB(0xDF, 0x82, 0xFF),
527 RGB(0xFF, 0x82, 0xFF), RGB(0xFF, 0x82, 0xDF), RGB(0xFF, 0x82, 0xBE), RGB(0xFF, 0x82, 0x9E),
528 RGB(0xFF, 0x82, 0x82), RGB(0xFF, 0x9E, 0x82), RGB(0xFF, 0xBE, 0x82), RGB(0xFF, 0xDF, 0x82),
529 RGB(0xFF, 0xFF, 0x82), RGB(0xDF, 0xFF, 0x82), RGB(0xBE, 0xFF, 0x82), RGB(0x9E, 0xFF, 0x82),
530 RGB(0x82, 0xFF, 0x82), RGB(0x82, 0xFF, 0x9E), RGB(0x82, 0xFF, 0xBE), RGB(0x82, 0xFF, 0xDF),
531 RGB(0x82, 0xFF, 0xFF), RGB(0x82, 0xDF, 0xFF), RGB(0x82, 0xBE, 0xFF), RGB(0x82, 0x9E, 0xFF),
532 RGB(0xBA, 0xBA, 0xFF), RGB(0xCA, 0xBA, 0xFF), RGB(0xDF, 0xBA, 0xFF), RGB(0xEF, 0xBA, 0xFF),
533 RGB(0xFF, 0xBA, 0xFF), RGB(0xFF, 0xBA, 0xEF), RGB(0xFF, 0xBA, 0xDF), RGB(0xFF, 0xBA, 0xCA),
534 RGB(0xFF, 0xBA, 0xBA), RGB(0xFF, 0xCA, 0xBA), RGB(0xFF, 0xDF, 0xBA), RGB(0xFF, 0xEF, 0xBA),
535 RGB(0xFF, 0xFF, 0xBA), RGB(0xEF, 0xFF, 0xBA), RGB(0xDF, 0xFF, 0xBA), RGB(0xCA, 0xFF, 0xBA),
536 RGB(0xBA, 0xFF, 0xBA), RGB(0xBA, 0xFF, 0xCA), RGB(0xBA, 0xFF, 0xDF), RGB(0xBA, 0xFF, 0xEF),
537 RGB(0xBA, 0xFF, 0xFF), RGB(0xBA, 0xEF, 0xFF), RGB(0xBA, 0xDF, 0xFF), RGB(0xBA, 0xCA, 0xFF),
538 RGB(0x00, 0x00, 0x71), RGB(0x1C, 0x00, 0x71), RGB(0x39, 0x00, 0x71), RGB(0x55, 0x00, 0x71),
539 RGB(0x71, 0x00, 0x71), RGB(0x71, 0x00, 0x55), RGB(0x71, 0x00, 0x39), RGB(0x71, 0x00, 0x1C),
540 RGB(0x71, 0x00, 0x00), RGB(0x71, 0x1C, 0x00), RGB(0x71, 0x39, 0x00), RGB(0x71, 0x55, 0x00),
541 RGB(0x71, 0x71, 0x00), RGB(0x55, 0x71, 0x00), RGB(0x39, 0x71, 0x00), RGB(0x1C, 0x71, 0x00),
542 RGB(0x00, 0x71, 0x00), RGB(0x00, 0x71, 0x1C), RGB(0x00, 0x71, 0x39), RGB(0x00, 0x71, 0x55),
543 RGB(0x00, 0x71, 0x71), RGB(0x00, 0x55, 0x71), RGB(0x00, 0x39, 0x71), RGB(0x00, 0x1C, 0x71),
544 RGB(0x39, 0x39, 0x71), RGB(0x45, 0x39, 0x71), RGB(0x55, 0x39, 0x71), RGB(0x61, 0x39, 0x71),
545 RGB(0x71, 0x39, 0x71), RGB(0x71, 0x39, 0x61), RGB(0x71, 0x39, 0x55), RGB(0x71, 0x39, 0x45),
546 RGB(0x71, 0x39, 0x39), RGB(0x71, 0x45, 0x39), RGB(0x71, 0x55, 0x39), RGB(0x71, 0x61, 0x39),
547 RGB(0x71, 0x71, 0x39), RGB(0x61, 0x71, 0x39), RGB(0x55, 0x71, 0x39), RGB(0x45, 0x71, 0x39),
548 RGB(0x39, 0x71, 0x39), RGB(0x39, 0x71, 0x45), RGB(0x39, 0x71, 0x55), RGB(0x39, 0x71, 0x61),
549 RGB(0x39, 0x71, 0x71), RGB(0x39, 0x61, 0x71), RGB(0x39, 0x55, 0x71), RGB(0x39, 0x45, 0x71),
550 RGB(0x51, 0x51, 0x71), RGB(0x59, 0x51, 0x71), RGB(0x61, 0x51, 0x71), RGB(0x69, 0x51, 0x71),
551 RGB(0x71, 0x51, 0x71), RGB(0x71, 0x51, 0x69), RGB(0x71, 0x51, 0x61), RGB(0x71, 0x51, 0x59),
552 RGB(0x71, 0x51, 0x51), RGB(0x71, 0x59, 0x51), RGB(0x71, 0x61, 0x51), RGB(0x71, 0x69, 0x51),
553 RGB(0x71, 0x71, 0x51), RGB(0x69, 0x71, 0x51), RGB(0x61, 0x71, 0x51), RGB(0x59, 0x71, 0x51),
554 RGB(0x51, 0x71, 0x51), RGB(0x51, 0x71, 0x59), RGB(0x51, 0x71, 0x61), RGB(0x51, 0x71, 0x69),
555 RGB(0x51, 0x71, 0x71), RGB(0x51, 0x69, 0x71), RGB(0x51, 0x61, 0x71), RGB(0x51, 0x59, 0x71),
556 RGB(0x00, 0x00, 0x41), RGB(0x10, 0x00, 0x41), RGB(0x20, 0x00, 0x41), RGB(0x31, 0x00, 0x41),
557 RGB(0x41, 0x00, 0x41), RGB(0x41, 0x00, 0x31), RGB(0x41, 0x00, 0x20), RGB(0x41, 0x00, 0x10),
558 RGB(0x41, 0x00, 0x00), RGB(0x41, 0x10, 0x00), RGB(0x41, 0x20, 0x00), RGB(0x41, 0x31, 0x00),
559 RGB(0x41, 0x41, 0x00), RGB(0x31, 0x41, 0x00), RGB(0x20, 0x41, 0x00), RGB(0x10, 0x41, 0x00),
560 RGB(0x00, 0x41, 0x00), RGB(0x00, 0x41, 0x10), RGB(0x00, 0x41, 0x20), RGB(0x00, 0x41, 0x31),
561 RGB(0x00, 0x41, 0x41), RGB(0x00, 0x31, 0x41), RGB(0x00, 0x20, 0x41), RGB(0x00, 0x10, 0x41),
562 RGB(0x20, 0x20, 0x41), RGB(0x28, 0x20, 0x41), RGB(0x31, 0x20, 0x41), RGB(0x39, 0x20, 0x41),
563 RGB(0x41, 0x20, 0x41), RGB(0x41, 0x20, 0x39), RGB(0x41, 0x20, 0x31), RGB(0x41, 0x20, 0x28),
564 RGB(0x41, 0x20, 0x20), RGB(0x41, 0x28, 0x20), RGB(0x41, 0x31, 0x20), RGB(0x41, 0x39, 0x20),
565 RGB(0x41, 0x41, 0x20), RGB(0x39, 0x41, 0x20), RGB(0x31, 0x41, 0x20), RGB(0x28, 0x41, 0x20),
566 RGB(0x20, 0x41, 0x20), RGB(0x20, 0x41, 0x28), RGB(0x20, 0x41, 0x31), RGB(0x20, 0x41, 0x39),
567 RGB(0x20, 0x41, 0x41), RGB(0x20, 0x39, 0x41), RGB(0x20, 0x31, 0x41), RGB(0x20, 0x28, 0x41),
568 RGB(0x2D, 0x2D, 0x41), RGB(0x31, 0x2D, 0x41), RGB(0x35, 0x2D, 0x41), RGB(0x3D, 0x2D, 0x41),
569 RGB(0x41, 0x2D, 0x41), RGB(0x41, 0x2D, 0x3D), RGB(0x41, 0x2D, 0x35), RGB(0x41, 0x2D, 0x31),
570 RGB(0x41, 0x2D, 0x2D), RGB(0x41, 0x31, 0x2D), RGB(0x41, 0x35, 0x2D), RGB(0x41, 0x3D, 0x2D),
571 RGB(0x41, 0x41, 0x2D), RGB(0x3D, 0x41, 0x2D), RGB(0x35, 0x41, 0x2D), RGB(0x31, 0x41, 0x2D),
572 RGB(0x2D, 0x41, 0x2D), RGB(0x2D, 0x41, 0x31), RGB(0x2D, 0x41, 0x35), RGB(0x2D, 0x41, 0x3D),
573 RGB(0x2D, 0x41, 0x41), RGB(0x2D, 0x3D, 0x41), RGB(0x2D, 0x35, 0x41), RGB(0x2D, 0x31, 0x41),
574 RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00),
575 RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00)
576 };
577
578 #elif defined(USE_DOSBOX_COLORS)
579
580 // DOSBox colors
581 static CONST COLORREF VgaPalette[VGA_MAX_COLORS] =
582 {
583 RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0xAA), RGB(0x00, 0xAA, 0x00), RGB(0x00, 0xAA, 0xAA),
584 RGB(0xAA, 0x00, 0x00), RGB(0xAA, 0x00, 0xAA), RGB(0xAA, 0x55, 0x00), RGB(0xAA, 0xAA, 0xAA),
585 RGB(0x55, 0x55, 0x55), RGB(0x55, 0x55, 0xFF), RGB(0x55, 0xFF, 0x55), RGB(0x55, 0xFF, 0xFF),
586 RGB(0xFF, 0x55, 0x55), RGB(0xFF, 0x55, 0xFF), RGB(0xFF, 0xFF, 0x55), RGB(0xFF, 0xFF, 0xFF),
587 RGB(0x00, 0x00, 0x00), RGB(0x14, 0x14, 0x14), RGB(0x20, 0x20, 0x20), RGB(0x2C, 0x2C, 0x2C),
588 RGB(0x38, 0x38, 0x38), RGB(0x45, 0x45, 0x45), RGB(0x51, 0x51, 0x51), RGB(0x61, 0x61, 0x61),
589 RGB(0x71, 0x71, 0x71), RGB(0x82, 0x82, 0x82), RGB(0x92, 0x92, 0x92), RGB(0xA2, 0xA2, 0xA2),
590 RGB(0xB6, 0xB6, 0xB6), RGB(0xCB, 0xCB, 0xCB), RGB(0xE3, 0xE3, 0xE3), RGB(0xFF, 0xFF, 0xFF),
591 RGB(0x00, 0x00, 0xFF), RGB(0x41, 0x00, 0xFF), RGB(0x7D, 0x00, 0xFF), RGB(0xBE, 0x00, 0xFF),
592 RGB(0xFF, 0x00, 0xFF), RGB(0xFF, 0x00, 0xBE), RGB(0xFF, 0x00, 0x7D), RGB(0xFF, 0x00, 0x41),
593 RGB(0xFF, 0x00, 0x00), RGB(0xFF, 0x41, 0x00), RGB(0xFF, 0x7D, 0x00), RGB(0xFF, 0xBE, 0x00),
594 RGB(0xFF, 0xFF, 0x00), RGB(0xBE, 0xFF, 0x00), RGB(0x7D, 0xFF, 0x00), RGB(0x41, 0xFF, 0x00),
595 RGB(0x00, 0xFF, 0x00), RGB(0x00, 0xFF, 0x41), RGB(0x00, 0xFF, 0x7D), RGB(0x00, 0xFF, 0xBE),
596 RGB(0x00, 0xFF, 0xFF), RGB(0x00, 0xBE, 0xFF), RGB(0x00, 0x7D, 0xFF), RGB(0x00, 0x41, 0xFF),
597 RGB(0x7D, 0x7D, 0xFF), RGB(0x9E, 0x7D, 0xFF), RGB(0xBE, 0x7D, 0xFF), RGB(0xDF, 0x7D, 0xFF),
598 RGB(0xFF, 0x7D, 0xFF), RGB(0xFF, 0x7D, 0xDF), RGB(0xFF, 0x7D, 0xBE), RGB(0xFF, 0x7D, 0x9E),
599
600 RGB(0xFF, 0x7D, 0x7D), RGB(0xFF, 0x9E, 0x7D), RGB(0xFF, 0xBE, 0x7D), RGB(0xFF, 0xDF, 0x7D),
601 RGB(0xFF, 0xFF, 0x7D), RGB(0xDF, 0xFF, 0x7D), RGB(0xBE, 0xFF, 0x7D), RGB(0x9E, 0xFF, 0x7D),
602 RGB(0x7D, 0xFF, 0x7D), RGB(0x7D, 0xFF, 0x9E), RGB(0x7D, 0xFF, 0xBE), RGB(0x7D, 0xFF, 0xDF),
603 RGB(0x7D, 0xFF, 0xFF), RGB(0x7D, 0xDF, 0xFF), RGB(0x7D, 0xBE, 0xFF), RGB(0x7D, 0x9E, 0xFF),
604 RGB(0xB6, 0xB6, 0xFF), RGB(0xC7, 0xB6, 0xFF), RGB(0xDB, 0xB6, 0xFF), RGB(0xEB, 0xB6, 0xFF),
605 RGB(0xFF, 0xB6, 0xFF), RGB(0xFF, 0xB6, 0xEB), RGB(0xFF, 0xB6, 0xDB), RGB(0xFF, 0xB6, 0xC7),
606 RGB(0xFF, 0xB6, 0xB6), RGB(0xFF, 0xC7, 0xB6), RGB(0xFF, 0xDB, 0xB6), RGB(0xFF, 0xEB, 0xB6),
607 RGB(0xFF, 0xFF, 0xB6), RGB(0xEB, 0xFF, 0xB6), RGB(0xDB, 0xFF, 0xB6), RGB(0xC7, 0xFF, 0xB6),
608 RGB(0xB6, 0xFF, 0xB6), RGB(0xB6, 0xFF, 0xC7), RGB(0xB6, 0xFF, 0xDB), RGB(0xB6, 0xFF, 0xEB),
609 RGB(0xB6, 0xFF, 0xFF), RGB(0xB6, 0xEB, 0xFF), RGB(0xB6, 0xDB, 0xFF), RGB(0xB6, 0xC7, 0xFF),
610 RGB(0x00, 0x00, 0x71), RGB(0x1C, 0x00, 0x71), RGB(0x38, 0x00, 0x71), RGB(0x55, 0x00, 0x71),
611 RGB(0x71, 0x00, 0x71), RGB(0x71, 0x00, 0x55), RGB(0x71, 0x00, 0x38), RGB(0x71, 0x00, 0x1C),
612 RGB(0x71, 0x00, 0x00), RGB(0x71, 0x1C, 0x00), RGB(0x71, 0x38, 0x00), RGB(0x71, 0x55, 0x00),
613 RGB(0x71, 0x71, 0x00), RGB(0x55, 0x71, 0x00), RGB(0x38, 0x71, 0x00), RGB(0x1C, 0x71, 0x00),
614 RGB(0x00, 0x71, 0x00), RGB(0x00, 0x71, 0x1C), RGB(0x00, 0x71, 0x38), RGB(0x00, 0x71, 0x55),
615 RGB(0x00, 0x71, 0x71), RGB(0x00, 0x55, 0x71), RGB(0x00, 0x38, 0x71), RGB(0x00, 0x1C, 0x71),
616
617 RGB(0x38, 0x38, 0x71), RGB(0x45, 0x38, 0x71), RGB(0x55, 0x38, 0x71), RGB(0x61, 0x38, 0x71),
618 RGB(0x71, 0x38, 0x71), RGB(0x71, 0x38, 0x61), RGB(0x71, 0x38, 0x55), RGB(0x71, 0x38, 0x45),
619 RGB(0x71, 0x38, 0x38), RGB(0x71, 0x45, 0x38), RGB(0x71, 0x55, 0x38), RGB(0x71, 0x61, 0x38),
620 RGB(0x71, 0x71, 0x38), RGB(0x61, 0x71, 0x38), RGB(0x55, 0x71, 0x38), RGB(0x45, 0x71, 0x38),
621 RGB(0x38, 0x71, 0x38), RGB(0x38, 0x71, 0x45), RGB(0x38, 0x71, 0x55), RGB(0x38, 0x71, 0x61),
622 RGB(0x38, 0x71, 0x71), RGB(0x38, 0x61, 0x71), RGB(0x38, 0x55, 0x71), RGB(0x38, 0x45, 0x71),
623 RGB(0x51, 0x51, 0x71), RGB(0x59, 0x51, 0x71), RGB(0x61, 0x51, 0x71), RGB(0x69, 0x51, 0x71),
624 RGB(0x71, 0x51, 0x71), RGB(0x71, 0x51, 0x69), RGB(0x71, 0x51, 0x61), RGB(0x71, 0x51, 0x59),
625 RGB(0x71, 0x51, 0x51), RGB(0x71, 0x59, 0x51), RGB(0x71, 0x61, 0x51), RGB(0x71, 0x69, 0x51),
626 RGB(0x71, 0x71, 0x51), RGB(0x69, 0x71, 0x51), RGB(0x61, 0x71, 0x51), RGB(0x59, 0x71, 0x51),
627 RGB(0x51, 0x71, 0x51), RGB(0x51, 0x71, 0x59), RGB(0x51, 0x71, 0x61), RGB(0x51, 0x71, 0x69),
628 RGB(0x51, 0x71, 0x71), RGB(0x51, 0x69, 0x71), RGB(0x51, 0x61, 0x71), RGB(0x51, 0x59, 0x71),
629 RGB(0x00, 0x00, 0x41), RGB(0x10, 0x00, 0x41), RGB(0x20, 0x00, 0x41), RGB(0x30, 0x00, 0x41),
630 RGB(0x41, 0x00, 0x41), RGB(0x41, 0x00, 0x30), RGB(0x41, 0x00, 0x20), RGB(0x41, 0x00, 0x10),
631 RGB(0x41, 0x00, 0x00), RGB(0x41, 0x10, 0x00), RGB(0x41, 0x20, 0x00), RGB(0x41, 0x30, 0x00),
632 RGB(0x41, 0x41, 0x00), RGB(0x30, 0x41, 0x00), RGB(0x20, 0x41, 0x00), RGB(0x10, 0x41, 0x00),
633
634 RGB(0x00, 0x41, 0x00), RGB(0x00, 0x41, 0x10), RGB(0x00, 0x41, 0x20), RGB(0x00, 0x41, 0x30),
635 RGB(0x00, 0x41, 0x41), RGB(0x00, 0x30, 0x41), RGB(0x00, 0x20, 0x41), RGB(0x00, 0x10, 0x41),
636 RGB(0x20, 0x20, 0x41), RGB(0x28, 0x20, 0x41), RGB(0x30, 0x20, 0x41), RGB(0x38, 0x20, 0x41),
637 RGB(0x41, 0x20, 0x41), RGB(0x41, 0x20, 0x38), RGB(0x41, 0x20, 0x30), RGB(0x41, 0x20, 0x28),
638 RGB(0x41, 0x20, 0x20), RGB(0x41, 0x28, 0x20), RGB(0x41, 0x30, 0x20), RGB(0x41, 0x38, 0x20),
639 RGB(0x41, 0x41, 0x20), RGB(0x38, 0x41, 0x20), RGB(0x30, 0x41, 0x20), RGB(0x28, 0x41, 0x20),
640 RGB(0x20, 0x41, 0x20), RGB(0x20, 0x41, 0x28), RGB(0x20, 0x41, 0x30), RGB(0x20, 0x41, 0x38),
641 RGB(0x20, 0x41, 0x41), RGB(0x20, 0x38, 0x41), RGB(0x20, 0x30, 0x41), RGB(0x20, 0x28, 0x41),
642 RGB(0x2C, 0x2C, 0x41), RGB(0x30, 0x2C, 0x41), RGB(0x34, 0x2C, 0x41), RGB(0x3C, 0x2C, 0x41),
643 RGB(0x41, 0x2C, 0x41), RGB(0x41, 0x2C, 0x3C), RGB(0x41, 0x2C, 0x34), RGB(0x41, 0x2C, 0x30),
644 RGB(0x41, 0x2C, 0x2C), RGB(0x41, 0x30, 0x2C), RGB(0x41, 0x34, 0x2C), RGB(0x41, 0x3C, 0x2C),
645 RGB(0x41, 0x41, 0x2C), RGB(0x3C, 0x41, 0x2C), RGB(0x34, 0x41, 0x2C), RGB(0x30, 0x41, 0x2C),
646 RGB(0x2C, 0x41, 0x2C), RGB(0x2C, 0x41, 0x30), RGB(0x2C, 0x41, 0x34), RGB(0x2C, 0x41, 0x3C),
647 RGB(0x2C, 0x41, 0x41), RGB(0x2C, 0x3C, 0x41), RGB(0x2C, 0x34, 0x41), RGB(0x2C, 0x30, 0x41),
648 RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00),
649 RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00)
650 };
651
652 #endif
653
654 /* PRIVATE FUNCTIONS **********************************************************/
655
656 static VOID VidBiosReadWindow(LPWORD Buffer, SMALL_RECT Rectangle, BYTE Page)
657 {
658 INT i, j;
659 INT Counter = 0;
660 WORD Character;
661 DWORD VideoAddress = TO_LINEAR(TEXT_VIDEO_SEG, Page * Bda->VideoPageSize);
662
663 for (i = Rectangle.Top; i <= Rectangle.Bottom; i++)
664 {
665 for (j = Rectangle.Left; j <= Rectangle.Right; j++)
666 {
667 /* Read from video memory */
668 EmulatorReadMemory(&EmulatorContext,
669 VideoAddress + (i * Bda->ScreenColumns + j) * sizeof(WORD),
670 (LPVOID)&Character,
671 sizeof(WORD));
672
673 /* Write the data to the buffer in row order */
674 Buffer[Counter++] = Character;
675 }
676 }
677 }
678
679 static VOID VidBiosWriteWindow(LPWORD Buffer, SMALL_RECT Rectangle, BYTE Page)
680 {
681 INT i, j;
682 INT Counter = 0;
683 WORD Character;
684 DWORD VideoAddress = TO_LINEAR(TEXT_VIDEO_SEG, Page * Bda->VideoPageSize);
685
686 for (i = Rectangle.Top; i <= Rectangle.Bottom; i++)
687 {
688 for (j = Rectangle.Left; j <= Rectangle.Right; j++)
689 {
690 Character = Buffer[Counter++];
691
692 /* Write to video memory */
693 EmulatorWriteMemory(&EmulatorContext,
694 VideoAddress + (i * Bda->ScreenColumns + j) * sizeof(WORD),
695 (LPVOID)&Character,
696 sizeof(WORD));
697 }
698 }
699 }
700
701 static BOOLEAN VidBiosScrollWindow(INT Direction,
702 DWORD Amount,
703 SMALL_RECT Rectangle,
704 BYTE Page,
705 BYTE FillAttribute)
706 {
707 DWORD i;
708 LPWORD WindowData;
709 WORD WindowWidth = Rectangle.Right - Rectangle.Left + 1;
710 WORD WindowHeight = Rectangle.Bottom - Rectangle.Top + 1;
711 DWORD WindowSize = WindowWidth * WindowHeight;
712
713 /* Allocate a buffer for the window */
714 WindowData = (LPWORD)HeapAlloc(GetProcessHeap(),
715 HEAP_ZERO_MEMORY,
716 WindowSize * sizeof(WORD));
717 if (WindowData == NULL) return FALSE;
718
719 /* Read the window data */
720 VidBiosReadWindow(WindowData, Rectangle, Page);
721
722 if ((Amount == 0)
723 || (((Direction == SCROLL_DIRECTION_UP)
724 || (Direction == SCROLL_DIRECTION_DOWN))
725 && (Amount >= WindowHeight))
726 || (((Direction == SCROLL_DIRECTION_LEFT)
727 || (Direction == SCROLL_DIRECTION_RIGHT))
728 && (Amount >= WindowWidth)))
729 {
730 /* Fill the window */
731 for (i = 0; i < WindowSize; i++)
732 {
733 WindowData[i] = MAKEWORD(' ', FillAttribute);
734 }
735
736 goto Done;
737 }
738
739 switch (Direction)
740 {
741 case SCROLL_DIRECTION_UP:
742 {
743 RtlMoveMemory(WindowData,
744 &WindowData[WindowWidth * Amount],
745 (WindowSize - WindowWidth * Amount) * sizeof(WORD));
746
747 for (i = 0; i < Amount * WindowWidth; i++)
748 {
749 WindowData[WindowSize - i - 1] = MAKEWORD(' ', FillAttribute);
750 }
751
752 break;
753 }
754
755 case SCROLL_DIRECTION_DOWN:
756 {
757 RtlMoveMemory(&WindowData[WindowWidth * Amount],
758 WindowData,
759 (WindowSize - WindowWidth * Amount) * sizeof(WORD));
760
761 for (i = 0; i < Amount * WindowWidth; i++)
762 {
763 WindowData[i] = MAKEWORD(' ', FillAttribute);
764 }
765
766 break;
767 }
768
769 default:
770 {
771 // TODO: NOT IMPLEMENTED!
772 UNIMPLEMENTED;
773 }
774 }
775
776 Done:
777 /* Write back the window data */
778 VidBiosWriteWindow(WindowData, Rectangle, Page);
779
780 /* Free the window buffer */
781 HeapFree(GetProcessHeap(), 0, WindowData);
782
783 return TRUE;
784 }
785
786 static __inline VOID VgaSetSinglePaletteRegister(BYTE Index, BYTE Value)
787 {
788 /* Write the index */
789 IOReadB(VGA_INSTAT1_READ); // Put the AC register into index state
790 IOWriteB(VGA_AC_INDEX, Index);
791
792 /* Write the data */
793 IOWriteB(VGA_AC_WRITE, Value);
794 }
795
796 static BOOLEAN VgaSetRegisters(PVGA_REGISTERS Registers)
797 {
798 INT i;
799
800 if (Registers == NULL) return FALSE;
801
802 /* Disable interrupts */
803 setIF(0);
804
805 /*
806 * Set the CRT base address according to the selected mode,
807 * monochrome or color. The following macros:
808 * VGA_INSTAT1_READ, VGA_CRTC_INDEX and VGA_CRTC_DATA are then
809 * used to access the correct VGA I/O ports.
810 */
811 Bda->CrtBasePort = (Registers->Misc & 0x01) ? VGA_CRTC_INDEX_COLOR
812 : VGA_CRTC_INDEX_MONO;
813
814 /* Write the misc register */
815 IOWriteB(VGA_MISC_WRITE, Registers->Misc);
816
817 /* Synchronous reset on */
818 IOWriteB(VGA_SEQ_INDEX, VGA_SEQ_RESET_REG);
819 IOWriteB(VGA_SEQ_DATA , VGA_SEQ_RESET_AR);
820
821 /* Write the sequencer registers */
822 for (i = 1; i < VGA_SEQ_MAX_REG; i++)
823 {
824 IOWriteB(VGA_SEQ_INDEX, i);
825 IOWriteB(VGA_SEQ_DATA, Registers->Sequencer[i]);
826 }
827
828 /* Synchronous reset off */
829 IOWriteB(VGA_SEQ_INDEX, VGA_SEQ_RESET_REG);
830 IOWriteB(VGA_SEQ_DATA , VGA_SEQ_RESET_SR | VGA_SEQ_RESET_AR);
831
832 /* Unlock CRTC registers 0-7 */
833 IOWriteB(VGA_CRTC_INDEX, VGA_CRTC_END_HORZ_BLANKING_REG);
834 IOWriteB(VGA_CRTC_DATA, IOReadB(VGA_CRTC_DATA) | 0x80);
835 IOWriteB(VGA_CRTC_INDEX, VGA_CRTC_VERT_RETRACE_END_REG);
836 IOWriteB(VGA_CRTC_DATA, IOReadB(VGA_CRTC_DATA) & ~0x80);
837 // Make sure they remain unlocked
838 Registers->CRT[VGA_CRTC_END_HORZ_BLANKING_REG] |= 0x80;
839 Registers->CRT[VGA_CRTC_VERT_RETRACE_END_REG] &= ~0x80;
840
841 /* Write the CRTC registers */
842 for (i = 0; i < VGA_CRTC_MAX_REG; i++)
843 {
844 IOWriteB(VGA_CRTC_INDEX, i);
845 IOWriteB(VGA_CRTC_DATA, Registers->CRT[i]);
846 }
847
848 /* Write the GC registers */
849 for (i = 0; i < VGA_GC_MAX_REG; i++)
850 {
851 IOWriteB(VGA_GC_INDEX, i);
852 IOWriteB(VGA_GC_DATA, Registers->Graphics[i]);
853 }
854
855 /* Write the AC registers */
856 // DbgPrint("\n");
857 for (i = 0; i < VGA_AC_MAX_REG; i++)
858 {
859 VgaSetSinglePaletteRegister(i, Registers->Attribute[i]);
860 // DbgPrint("Registers->Attribute[%d] = %d\n", i, Registers->Attribute[i]);
861 }
862 // DbgPrint("\n");
863
864 /* Set the PEL mask */
865 IOWriteB(VGA_DAC_MASK, 0xFF);
866
867 /* Enable screen and disable palette access */
868 IOReadB(VGA_INSTAT1_READ); // Put the AC register into index state
869 IOWriteB(VGA_AC_INDEX, 0x20);
870
871 /* Enable interrupts */
872 setIF(1);
873
874 return TRUE;
875 }
876
877 static VOID VgaSetPalette(const COLORREF* Palette, ULONG Size)
878 {
879 ULONG i;
880
881 // /* Disable screen and enable palette access */
882 // IOReadB(VGA_INSTAT1_READ); // Put the AC register into index state
883 // IOWriteB(VGA_AC_INDEX, 0x00);
884
885 for (i = 0; i < Size; i++)
886 {
887 IOWriteB(VGA_DAC_WRITE_INDEX, i);
888 IOWriteB(VGA_DAC_DATA, VGA_COLOR_TO_DAC(GetRValue(Palette[i])));
889 IOWriteB(VGA_DAC_DATA, VGA_COLOR_TO_DAC(GetGValue(Palette[i])));
890 IOWriteB(VGA_DAC_DATA, VGA_COLOR_TO_DAC(GetBValue(Palette[i])));
891 }
892
893 /* The following step might be optional */
894 for (i = Size; i < VGA_MAX_COLORS; i++)
895 {
896 IOWriteB(VGA_DAC_WRITE_INDEX, i);
897 IOWriteB(VGA_DAC_DATA, VGA_COLOR_TO_DAC(0x00));
898 IOWriteB(VGA_DAC_DATA, VGA_COLOR_TO_DAC(0x00));
899 IOWriteB(VGA_DAC_DATA, VGA_COLOR_TO_DAC(0x00));
900 }
901
902 /* Enable screen and disable palette access */
903 // IOReadB(VGA_INSTAT1_READ); // Put the AC register into index state
904 // IOWriteB(VGA_AC_INDEX, 0x20);
905 }
906
907 static VOID VgaChangePalette(BYTE ModeNumber)
908 {
909 const COLORREF* Palette;
910 ULONG Size;
911
912 if (ModeNumber >= 0x13)
913 {
914 /* VGA modes */
915 Palette = VgaPalette;
916 Size = sizeof(VgaPalette)/sizeof(VgaPalette[0]);
917 }
918 else if (ModeNumber == 0x10) // || (ModeNumber == 0x0D) || (ModeNumber == 0x0E)
919 {
920 /* EGA HiRes mode */
921 Palette = EgaPalette__HiRes;
922 Size = sizeof(EgaPalette__HiRes)/sizeof(EgaPalette__HiRes[0]);
923 }
924 #if 0
925 else if ((ModeNumber == 0x04) || (ModeNumber == 0x05))
926 {
927 /*
928 * CGA modes; this palette contains both normal and
929 * bright versions of CGA palettes 0 and 1
930 */
931 Palette = CgaPalette2;
932 Size = sizeof(CgaPalette2)/sizeof(CgaPalette2[0]);
933 }
934 #endif
935 else // if ((ModeNumber == 0x0D) || (ModeNumber == 0x0E))
936 {
937 /* EGA modes */
938 Palette = EgaPalette__16Colors;
939 Size = sizeof(EgaPalette__16Colors)/sizeof(EgaPalette__16Colors[0]);
940 }
941
942 VgaSetPalette(Palette, Size);
943 }
944
945 static VOID VidBiosGetCursorPosition(PBYTE Row, PBYTE Column, BYTE Page)
946 {
947 /* Make sure the selected video page is valid */
948 if (Page >= BIOS_MAX_PAGES) return;
949
950 /* Get the cursor location */
951 *Row = HIBYTE(Bda->CursorPosition[Page]);
952 *Column = LOBYTE(Bda->CursorPosition[Page]);
953 }
954
955 static VOID VidBiosSetCursorPosition(BYTE Row, BYTE Column, BYTE Page)
956 {
957 /* Make sure the selected video page is valid */
958 if (Page >= BIOS_MAX_PAGES) return;
959
960 /* Update the position in the BDA */
961 Bda->CursorPosition[Page] = MAKEWORD(Column, Row);
962
963 /* Check if this is the current video page */
964 if (Page == Bda->VideoPage)
965 {
966 WORD Offset = Row * Bda->ScreenColumns + Column;
967
968 /* Modify the CRTC registers */
969 IOWriteB(VGA_CRTC_INDEX, VGA_CRTC_CURSOR_LOC_LOW_REG);
970 IOWriteB(VGA_CRTC_DATA , LOBYTE(Offset));
971 IOWriteB(VGA_CRTC_INDEX, VGA_CRTC_CURSOR_LOC_HIGH_REG);
972 IOWriteB(VGA_CRTC_DATA , HIBYTE(Offset));
973 }
974 }
975
976 VOID VidBiosSyncCursorPosition(VOID)
977 {
978 BYTE Row, Column;
979 BYTE Low, High;
980 SHORT ScreenColumns = VgaGetDisplayResolution().X;
981 WORD Offset;
982
983 /* Get the cursor location */
984 IOWriteB(VGA_CRTC_INDEX, VGA_CRTC_CURSOR_LOC_LOW_REG);
985 Low = IOReadB(VGA_CRTC_DATA);
986 IOWriteB(VGA_CRTC_INDEX, VGA_CRTC_CURSOR_LOC_HIGH_REG);
987 High = IOReadB(VGA_CRTC_DATA);
988
989 Offset = MAKEWORD(Low, High);
990
991 Row = (BYTE)(Offset / ScreenColumns);
992 Column = (BYTE)(Offset % ScreenColumns);
993
994 /* Synchronize our cursor position with VGA */
995 VidBiosSetCursorPosition(Row, Column, Bda->VideoPage);
996 }
997
998 BYTE VidBiosGetVideoMode(VOID)
999 {
1000 return Bda->VideoMode;
1001 }
1002
1003 static BOOLEAN VidBiosSetVideoMode(BYTE ModeNumber)
1004 {
1005 BYTE Page;
1006
1007 COORD Resolution;
1008 PVGA_REGISTERS VgaMode = VideoModes[ModeNumber];
1009
1010 DPRINT1("Switching to mode %Xh; VgaMode = 0x%p\n", ModeNumber, VgaMode);
1011
1012 if (!VgaSetRegisters(VgaMode)) return FALSE;
1013
1014 VgaChangePalette(ModeNumber);
1015
1016 /*
1017 * IBM standard modes do not clear the screen if the
1018 * high bit of AL is set (EGA or higher only).
1019 * See Ralf Brown: http://www.ctyme.com/intr/rb-0069.htm
1020 * for more information.
1021 */
1022 // if ((ModeNumber & 0x08) == 0) VgaClearMemory();
1023 VgaClearMemory();
1024
1025 // Bda->CrtModeControl;
1026 // Bda->CrtColorPaletteMask;
1027 // Bda->EGAFlags;
1028 // Bda->VGAFlags;
1029
1030 /* Update the values in the BDA */
1031 Bda->VideoMode = ModeNumber;
1032 Bda->VideoPageSize = VideoModePageSize[ModeNumber];
1033 Bda->VideoPage = 0;
1034 Bda->VideoPageOffset = Bda->VideoPage * Bda->VideoPageSize;
1035
1036 /* Set the start address in the CRTC */
1037 IOWriteB(VGA_CRTC_INDEX, VGA_CRTC_START_ADDR_LOW_REG);
1038 IOWriteB(VGA_CRTC_DATA , LOBYTE(Bda->VideoPageOffset));
1039 IOWriteB(VGA_CRTC_INDEX, VGA_CRTC_START_ADDR_HIGH_REG);
1040 IOWriteB(VGA_CRTC_DATA , HIBYTE(Bda->VideoPageOffset));
1041
1042 /* Update the character height */
1043 IOWriteB(VGA_CRTC_INDEX, VGA_CRTC_MAX_SCAN_LINE_REG);
1044 Bda->CharacterHeight = 1 + (IOReadB(VGA_CRTC_DATA) & 0x1F);
1045
1046 /* Update the screen size */
1047 Resolution = VgaGetDisplayResolution();
1048 Bda->ScreenColumns = Resolution.X;
1049 Bda->ScreenRows = Resolution.Y - 1;
1050
1051 /* Set the cursor position for each page */
1052 for (Page = 0; Page < BIOS_MAX_PAGES; ++Page)
1053 VidBiosSetCursorPosition(0, 0, Page);
1054
1055 /* Refresh display */
1056 VgaRefreshDisplay();
1057
1058 return TRUE;
1059 }
1060
1061 static BOOLEAN VidBiosSetVideoPage(BYTE PageNumber)
1062 {
1063 BYTE Row, Column;
1064
1065 /* Check if the page exists */
1066 if (PageNumber >= BIOS_MAX_PAGES) return FALSE;
1067
1068 /* Check if this is the same page */
1069 if (PageNumber == Bda->VideoPage) return TRUE;
1070
1071 /* Update the values in the BDA */
1072 Bda->VideoPage = PageNumber;
1073 Bda->VideoPageOffset = Bda->VideoPage * Bda->VideoPageSize;
1074
1075 /* Set the start address in the CRTC */
1076 IOWriteB(VGA_CRTC_INDEX, VGA_CRTC_START_ADDR_LOW_REG);
1077 IOWriteB(VGA_CRTC_DATA , LOBYTE(Bda->VideoPageOffset));
1078 IOWriteB(VGA_CRTC_INDEX, VGA_CRTC_START_ADDR_HIGH_REG);
1079 IOWriteB(VGA_CRTC_DATA , HIBYTE(Bda->VideoPageOffset));
1080
1081 /*
1082 * Get the cursor location (we don't update anything on the BIOS side
1083 * but we update the cursor location on the VGA side).
1084 */
1085 VidBiosGetCursorPosition(&Row, &Column, PageNumber);
1086 VidBiosSetCursorPosition(Row, Column, PageNumber);
1087
1088 return TRUE;
1089 }
1090
1091 static VOID VidBiosPrintCharacter(CHAR Character, BYTE Attribute, BYTE Page)
1092 {
1093 WORD CharData = MAKEWORD(Character, Attribute);
1094 BYTE Row, Column;
1095
1096 /* Make sure the page exists */
1097 if (Page >= BIOS_MAX_PAGES) return;
1098
1099 /* Get the cursor location */
1100 VidBiosGetCursorPosition(&Row, &Column, Page);
1101
1102 if (Character == '\a')
1103 {
1104 /* Bell control character */
1105 // NOTE: We may use what the terminal emulator offers to us...
1106 Beep(800, 200);
1107 return;
1108 }
1109 else if (Character == '\b')
1110 {
1111 /* Backspace control character */
1112 if (Column > 0)
1113 {
1114 Column--;
1115 }
1116 else if (Row > 0)
1117 {
1118 Column = Bda->ScreenColumns - 1;
1119 Row--;
1120 }
1121
1122 /* Erase the existing character */
1123 CharData = MAKEWORD(' ', Attribute);
1124 EmulatorWriteMemory(&EmulatorContext,
1125 TO_LINEAR(TEXT_VIDEO_SEG,
1126 Page * Bda->VideoPageSize +
1127 (Row * Bda->ScreenColumns + Column) * sizeof(WORD)),
1128 (LPVOID)&CharData,
1129 sizeof(WORD));
1130 }
1131 else if (Character == '\t')
1132 {
1133 /* Horizontal Tabulation control character */
1134 do
1135 {
1136 // Taken from DOSBox
1137 VidBiosPrintCharacter(' ', Attribute, Page);
1138 VidBiosGetCursorPosition(&Row, &Column, Page);
1139 } while (Column % 8);
1140 }
1141 else if (Character == '\n')
1142 {
1143 /* Line Feed control character */
1144 Row++;
1145 }
1146 else if (Character == '\r')
1147 {
1148 /* Carriage Return control character */
1149 Column = 0;
1150 }
1151 else
1152 {
1153 /* Default character */
1154
1155 /* Write the character */
1156 EmulatorWriteMemory(&EmulatorContext,
1157 TO_LINEAR(TEXT_VIDEO_SEG,
1158 Page * Bda->VideoPageSize +
1159 (Row * Bda->ScreenColumns + Column) * sizeof(WORD)),
1160 (LPVOID)&CharData,
1161 sizeof(WORD));
1162
1163 /* Advance the cursor */
1164 Column++;
1165 }
1166
1167 /* Check if it passed the end of the row */
1168 if (Column >= Bda->ScreenColumns)
1169 {
1170 /* Return to the first column and go to the next line */
1171 Column = 0;
1172 Row++;
1173 }
1174
1175 /* Scroll the screen up if needed */
1176 if (Row > Bda->ScreenRows)
1177 {
1178 /* The screen must be scrolled up */
1179 SMALL_RECT Rectangle = { 0, 0, Bda->ScreenColumns - 1, Bda->ScreenRows };
1180
1181 VidBiosScrollWindow(SCROLL_DIRECTION_UP,
1182 1,
1183 Rectangle,
1184 Page,
1185 DEFAULT_ATTRIBUTE);
1186
1187 Row--;
1188 }
1189
1190 /* Set the cursor position */
1191 VidBiosSetCursorPosition(Row, Column, Page);
1192 }
1193
1194 /* PUBLIC FUNCTIONS ***********************************************************/
1195
1196 VOID WINAPI VidBiosVideoService(LPWORD Stack)
1197 {
1198 switch (getAH())
1199 {
1200 /* Set Video Mode */
1201 case 0x00:
1202 {
1203 VidBiosSetVideoMode(getAL());
1204 break;
1205 }
1206
1207 /* Set Text-Mode Cursor Shape */
1208 case 0x01:
1209 {
1210 /* Update the BDA */
1211 Bda->CursorStartLine = getCH();
1212 Bda->CursorEndLine = getCL();
1213
1214 /* Modify the CRTC registers */
1215 IOWriteB(VGA_CRTC_INDEX, VGA_CRTC_CURSOR_START_REG);
1216 IOWriteB(VGA_CRTC_DATA , Bda->CursorStartLine);
1217 IOWriteB(VGA_CRTC_INDEX, VGA_CRTC_CURSOR_END_REG);
1218 IOWriteB(VGA_CRTC_DATA , Bda->CursorEndLine);
1219
1220 break;
1221 }
1222
1223 /* Set Cursor Position */
1224 case 0x02:
1225 {
1226 VidBiosSetCursorPosition(getDH(), getDL(), getBH());
1227 break;
1228 }
1229
1230 /* Get Cursor Position and Shape */
1231 case 0x03:
1232 {
1233 /* Make sure the selected video page exists */
1234 if (getBH() >= BIOS_MAX_PAGES) break;
1235
1236 /* Return the result */
1237 setAX(0);
1238 setCX(MAKEWORD(Bda->CursorEndLine, Bda->CursorStartLine));
1239 setDX(Bda->CursorPosition[getBH()]);
1240 break;
1241 }
1242
1243 /* Query Light Pen */
1244 case 0x04:
1245 {
1246 /*
1247 * On modern BIOSes, this function returns 0
1248 * so that we can ignore the other registers.
1249 */
1250 setAX(0);
1251 break;
1252 }
1253
1254 /* Select Active Display Page */
1255 case 0x05:
1256 {
1257 VidBiosSetVideoPage(getAL());
1258 break;
1259 }
1260
1261 /* Scroll Window Up/Down */
1262 case 0x06:
1263 case 0x07:
1264 {
1265 SMALL_RECT Rectangle = { getCL(), getCH(), getDL(), getDH() };
1266
1267 /* Call the internal function */
1268 VidBiosScrollWindow((getAH() == 0x06) ? SCROLL_DIRECTION_UP
1269 : SCROLL_DIRECTION_DOWN,
1270 getAL(),
1271 Rectangle,
1272 Bda->VideoPage,
1273 getBH());
1274
1275 break;
1276 }
1277
1278 /* Read Character and Attribute at Cursor Position */
1279 case 0x08:
1280 {
1281 WORD CharacterData;
1282 BYTE Page = getBH();
1283 DWORD Offset;
1284
1285 /* Check if the page exists */
1286 if (Page >= BIOS_MAX_PAGES) break;
1287
1288 /* Find the offset of the character */
1289 Offset = Page * Bda->VideoPageSize +
1290 (HIBYTE(Bda->CursorPosition[Page]) * Bda->ScreenColumns +
1291 LOBYTE(Bda->CursorPosition[Page])) * 2;
1292
1293 /* Read from the video memory */
1294 EmulatorReadMemory(&EmulatorContext,
1295 TO_LINEAR(TEXT_VIDEO_SEG, Offset),
1296 (LPVOID)&CharacterData,
1297 sizeof(WORD));
1298
1299 /* Return the character data in AX */
1300 setAX(CharacterData);
1301
1302 break;
1303 }
1304
1305 /* Write Character and Attribute at Cursor Position */
1306 case 0x09:
1307 /* Write Character only (PCjr: + Attribute) at Cursor Position */
1308 case 0x0A:
1309 {
1310 WORD CharacterData = MAKEWORD(getAL(), getBL());
1311 BYTE Page = getBH();
1312 DWORD Offset, Counter = getCX();
1313
1314 /* Check if the page exists */
1315 if (Page >= BIOS_MAX_PAGES) break;
1316
1317 /* Find the offset of the character */
1318 Offset = Page * Bda->VideoPageSize +
1319 (HIBYTE(Bda->CursorPosition[Page]) * Bda->ScreenColumns +
1320 LOBYTE(Bda->CursorPosition[Page])) * 2;
1321
1322 /* Write to video memory a certain number of times */
1323 while (Counter > 0)
1324 {
1325 EmulatorWriteMemory(&EmulatorContext,
1326 TO_LINEAR(TEXT_VIDEO_SEG, Offset),
1327 (LPVOID)&CharacterData,
1328 (getAH() == 0x09) ? sizeof(WORD) : sizeof(BYTE));
1329 Offset += 2;
1330 Counter--;
1331 }
1332
1333 break;
1334 }
1335
1336 /* Set Video Colors */
1337 case 0x0B:
1338 {
1339 if (Bda->VideoMode < 4 || Bda->VideoMode > 6)
1340 {
1341 DPRINT1("BIOS Function INT 10h, AH = 0Bh, BH = 0x%02X is unsupported for non-CGA modes\n",
1342 getAH(), getBH());
1343 break;
1344 }
1345
1346 switch (getBH())
1347 {
1348 case 0x00: /* Set Background/Border Color */
1349 {
1350 #ifdef DOSBOX
1351 BYTE Index = getBL();
1352 BYTE CrtColorPaletteMask = Bda->CrtColorPaletteMask;
1353 CrtColorPaletteMask = (CrtColorPaletteMask & 0xE0) | (Index & 0x1F);
1354 Bda->CrtColorPaletteMask = CrtColorPaletteMask;
1355
1356 Index = ((Index << 1) & 0x10) | (Index & 0x7);
1357
1358 /* Always set the overscan color */
1359 VgaSetSinglePaletteRegister(VGA_AC_OVERSCAN_REG, Index);
1360
1361 /* Don't set any extra colors when in text mode */
1362 if (Bda->VideoMode <= 3) break;
1363
1364 VgaSetSinglePaletteRegister(0x00, Index);
1365
1366 Index = (CrtColorPaletteMask & 0x10) | 0x02 | ((CrtColorPaletteMask & 0x20) >> 5);
1367
1368 VgaSetSinglePaletteRegister(0x01, Index);
1369 Index += 2;
1370 VgaSetSinglePaletteRegister(0x02, Index);
1371 Index += 2;
1372 VgaSetSinglePaletteRegister(0x03, Index);
1373 #else
1374 /* Background/Border Color is modifiable via the first index */
1375 VgaSetSinglePaletteRegister(0x00, getBL());
1376 #endif
1377
1378 /* Enable screen and disable palette access */
1379 IOReadB(VGA_INSTAT1_READ); // Put the AC register into index state
1380 IOWriteB(VGA_AC_INDEX, 0x20);
1381 break;
1382 }
1383
1384 case 0x01: /* Set Palette */
1385 {
1386 BYTE Index = getBL();
1387 BYTE CrtColorPaletteMask = Bda->CrtColorPaletteMask;
1388 CrtColorPaletteMask = (CrtColorPaletteMask & 0xDF) | ((Index & 1) ? 0x20 : 0x0);
1389 Bda->CrtColorPaletteMask = CrtColorPaletteMask;
1390
1391 /* Don't set any extra colors when in text mode */
1392 if (Bda->VideoMode <= 3) break;
1393
1394 Index = (CrtColorPaletteMask & 0x10) | 0x02 | Index;
1395
1396 VgaSetSinglePaletteRegister(0x01, Index);
1397 Index += 2;
1398 VgaSetSinglePaletteRegister(0x02, Index);
1399 Index += 2;
1400 VgaSetSinglePaletteRegister(0x03, Index);
1401
1402 /* Enable screen and disable palette access */
1403 IOReadB(VGA_INSTAT1_READ); // Put the AC register into index state
1404 IOWriteB(VGA_AC_INDEX, 0x20);
1405 break;
1406 }
1407
1408 default:
1409 DPRINT1("BIOS Function INT 10h, AH = 0Bh, BH = 0x%02X NOT IMPLEMENTED\n",
1410 getAH(), getBH());
1411 break;
1412 }
1413
1414 break;
1415 }
1416
1417 /* Teletype Output */
1418 case 0x0E:
1419 {
1420 VidBiosPrintCharacter(getAL(), getBL(), getBH());
1421 break;
1422 }
1423
1424 /* Get Current Video Mode */
1425 case 0x0F:
1426 {
1427 setAX(MAKEWORD(Bda->VideoMode, Bda->ScreenColumns));
1428 setBX(MAKEWORD(getBL(), Bda->VideoPage));
1429 break;
1430 }
1431
1432 /* Palette Control */
1433 case 0x10:
1434 {
1435 switch (getAL())
1436 {
1437 /* Set Single Palette Register */
1438 case 0x00:
1439 {
1440 VgaSetSinglePaletteRegister(getBL(), getBH());
1441
1442 /* Enable screen and disable palette access */
1443 IOReadB(VGA_INSTAT1_READ); // Put the AC register into index state
1444 IOWriteB(VGA_AC_INDEX, 0x20);
1445 break;
1446 }
1447
1448 /* Set Overscan Color */
1449 case 0x01:
1450 {
1451 VgaSetSinglePaletteRegister(VGA_AC_OVERSCAN_REG, getBH());
1452
1453 /* Enable screen and disable palette access */
1454 IOReadB(VGA_INSTAT1_READ); // Put the AC register into index state
1455 IOWriteB(VGA_AC_INDEX, 0x20);
1456 break;
1457 }
1458
1459 /* Set All Palette Registers */
1460 case 0x02:
1461 {
1462 INT i;
1463 LPBYTE Buffer = SEG_OFF_TO_PTR(getES(), getDX());
1464
1465 /* Set the palette registers */
1466 for (i = 0; i <= VGA_AC_PAL_F_REG; i++)
1467 {
1468 VgaSetSinglePaletteRegister(i, Buffer[i]);
1469 }
1470
1471 /* Set the overscan register */
1472 // VgaSetSinglePaletteRegister(VGA_AC_OVERSCAN_REG, Buffer[VGA_AC_PAL_F_REG + 1]);
1473 IOWriteB(VGA_AC_INDEX, VGA_AC_OVERSCAN_REG);
1474 IOWriteB(VGA_AC_WRITE, Buffer[VGA_AC_PAL_F_REG + 1]);
1475
1476 /* Enable screen and disable palette access */
1477 IOReadB(VGA_INSTAT1_READ); // Put the AC register into index state
1478 IOWriteB(VGA_AC_INDEX, 0x20);
1479 break;
1480 }
1481
1482 /* Get Single Palette Register */
1483 case 0x07:
1484 {
1485 /* Write the index */
1486 IOReadB(VGA_INSTAT1_READ); // Put the AC register into index state
1487 IOWriteB(VGA_AC_INDEX, getBL());
1488
1489 /* Read the data */
1490 setBH(IOReadB(VGA_AC_READ));
1491
1492 /* Enable screen and disable palette access */
1493 IOReadB(VGA_INSTAT1_READ); // Put the AC register into index state
1494 IOWriteB(VGA_AC_INDEX, 0x20);
1495 break;
1496 }
1497
1498 /* Get Overscan Color */
1499 case 0x08:
1500 {
1501 /* Write the index */
1502 IOReadB(VGA_INSTAT1_READ); // Put the AC register into index state
1503 IOWriteB(VGA_AC_INDEX, VGA_AC_OVERSCAN_REG);
1504
1505 /* Read the data */
1506 setBH(IOReadB(VGA_AC_READ));
1507
1508 /* Enable screen and disable palette access */
1509 IOReadB(VGA_INSTAT1_READ); // Put the AC register into index state
1510 IOWriteB(VGA_AC_INDEX, 0x20);
1511 break;
1512 }
1513
1514 /* Get All Palette Registers */
1515 case 0x09:
1516 {
1517 INT i;
1518 LPBYTE Buffer = SEG_OFF_TO_PTR(getES(), getDX());
1519
1520 /* Get the palette registers */
1521 for (i = 0; i <= VGA_AC_PAL_F_REG; i++)
1522 {
1523 /* Write the index */
1524 IOReadB(VGA_INSTAT1_READ); // Put the AC register into index state
1525 IOWriteB(VGA_AC_INDEX, i);
1526
1527 /* Read the data */
1528 Buffer[i] = IOReadB(VGA_AC_READ);
1529 }
1530
1531 /* Get the overscan register */
1532 IOWriteB(VGA_AC_INDEX, VGA_AC_OVERSCAN_REG);
1533 Buffer[VGA_AC_PAL_F_REG + 1] = IOReadB(VGA_AC_READ);
1534
1535 /* Enable screen and disable palette access */
1536 IOReadB(VGA_INSTAT1_READ); // Put the AC register into index state
1537 IOWriteB(VGA_AC_INDEX, 0x20);
1538 break;
1539 }
1540
1541 /* Set Individual DAC Register */
1542 case 0x10:
1543 {
1544 /* Write the index */
1545 // Certainly in BL and not in BX as said by Ralf Brown...
1546 IOWriteB(VGA_DAC_WRITE_INDEX, getBL());
1547
1548 /* Write the data in this order: Red, Green, Blue */
1549 IOWriteB(VGA_DAC_DATA, getDH());
1550 IOWriteB(VGA_DAC_DATA, getCH());
1551 IOWriteB(VGA_DAC_DATA, getCL());
1552
1553 break;
1554 }
1555
1556 /* Set Block of DAC Registers */
1557 case 0x12:
1558 {
1559 INT i;
1560 LPBYTE Buffer = SEG_OFF_TO_PTR(getES(), getDX());
1561
1562 /* Write the index */
1563 // Certainly in BL and not in BX as said by Ralf Brown...
1564 IOWriteB(VGA_DAC_WRITE_INDEX, getBL());
1565
1566 for (i = 0; i < getCX(); i++)
1567 {
1568 /* Write the data in this order: Red, Green, Blue */
1569 IOWriteB(VGA_DAC_DATA, *Buffer++);
1570 IOWriteB(VGA_DAC_DATA, *Buffer++);
1571 IOWriteB(VGA_DAC_DATA, *Buffer++);
1572 }
1573
1574 break;
1575 }
1576
1577 /* Get Individual DAC Register */
1578 case 0x15:
1579 {
1580 /* Write the index */
1581 IOWriteB(VGA_DAC_READ_INDEX, getBL());
1582
1583 /* Read the data in this order: Red, Green, Blue */
1584 setDH(IOReadB(VGA_DAC_DATA));
1585 setCH(IOReadB(VGA_DAC_DATA));
1586 setCL(IOReadB(VGA_DAC_DATA));
1587
1588 break;
1589 }
1590
1591 /* Get Block of DAC Registers */
1592 case 0x17:
1593 {
1594 INT i;
1595 LPBYTE Buffer = SEG_OFF_TO_PTR(getES(), getDX());
1596
1597 /* Write the index */
1598 // Certainly in BL and not in BX as said by Ralf Brown...
1599 IOWriteB(VGA_DAC_READ_INDEX, getBL());
1600
1601 for (i = 0; i < getCX(); i++)
1602 {
1603 /* Write the data in this order: Red, Green, Blue */
1604 *Buffer++ = IOReadB(VGA_DAC_DATA);
1605 *Buffer++ = IOReadB(VGA_DAC_DATA);
1606 *Buffer++ = IOReadB(VGA_DAC_DATA);
1607 }
1608
1609 break;
1610 }
1611
1612 default:
1613 {
1614 DPRINT1("BIOS Palette Control Sub-command AL = 0x%02X NOT IMPLEMENTED\n",
1615 getAL());
1616 break;
1617 }
1618 }
1619
1620 break;
1621 }
1622
1623 /* Alternate Function Select */
1624 case 0x12:
1625 {
1626 DPRINT1("BIOS Function INT 10h, AH = 12h (Alternate Function Select), BX = 0x%04X NOT IMPLEMENTED\n",
1627 getBX());
1628 break;
1629 }
1630
1631 /* Write String */
1632 case 0x13:
1633 {
1634 DPRINT1("BIOS Function INT 13h (Write String) is UNIMPLEMENTED\n");
1635 break;
1636 }
1637
1638 /* Display combination code */
1639 case 0x1A:
1640 {
1641 switch (getAL())
1642 {
1643 case 0x00: /* Get Display combiantion code */
1644 setAX(MAKEWORD(0x1A, 0x1A));
1645 setBX(MAKEWORD(0x08, 0x00)); /* VGA w/ color analog display */
1646 break;
1647 case 0x01: /* Set Display combination code */
1648 DPRINT1("Set Display combination code - Unsupported\n");
1649 break;
1650 default:
1651 break;
1652 }
1653 break;
1654 }
1655
1656 default:
1657 {
1658 DPRINT1("BIOS Function INT 10h, AH = 0x%02X, AL = 0x%02X, BH = 0x%02X NOT IMPLEMENTED\n",
1659 getAH(), getAL(), getBH());
1660 }
1661 }
1662 }
1663
1664
1665 /*
1666 * Those attach / detach functions are work-in-progress
1667 */
1668
1669 static BOOL Attached = TRUE;
1670
1671 VOID VidBiosAttachToConsole(VOID)
1672 {
1673 // VgaRefreshDisplay();
1674 if (!Attached)
1675 {
1676 VgaAttachToConsole();
1677 Attached = TRUE;
1678 }
1679
1680 VgaRefreshDisplay();
1681 VidBiosSyncCursorPosition();
1682 }
1683
1684 VOID VidBiosDetachFromConsole(VOID)
1685 {
1686 /* Perform another screen refresh */
1687 VgaRefreshDisplay();
1688
1689 /* Detach from the console */
1690 VgaDetachFromConsole(FALSE);
1691 Attached = FALSE;
1692 }
1693
1694
1695 BOOLEAN VidBiosInitialize(VOID)
1696 {
1697 /* Some interrupts are in fact addresses to tables */
1698 ((PULONG)BaseAddress)[0x1D] = (ULONG)NULL;
1699 ((PULONG)BaseAddress)[0x1F] = (ULONG)NULL;
1700 // ((PULONG)BaseAddress)[0x42] = (ULONG)NULL;
1701 ((PULONG)BaseAddress)[0x43] = (ULONG)NULL;
1702 ((PULONG)BaseAddress)[0x44] = (ULONG)NULL;
1703
1704 /* Initialize the VGA BDA data */
1705 Bda->VGAOptions = 0x30; /* 256 KB Video RAM */
1706 Bda->VGASwitches = 0x09; /* High-resolution */
1707
1708 //
1709 // FIXME: At the moment we always set a VGA mode. In the future,
1710 // we should set this mode **only** when:
1711 // - an app starts to use directly the video memory
1712 // (that should be done in emulator.c)
1713 // - or starts to use non-stream I/O interrupts
1714 // (that should be done here, or maybe in VGA ??)
1715 //
1716
1717 /* Set the default video mode */
1718 VidBiosSetVideoMode(BIOS_DEFAULT_VIDEO_MODE);
1719
1720 /* Synchronize our cursor position with VGA */
1721 VidBiosSyncCursorPosition();
1722
1723 /* Register the BIOS support BOPs */
1724 RegisterBop(BOP_VIDEO_INT, VidBiosVideoService);
1725
1726 return TRUE;
1727 }
1728
1729 VOID VidBiosCleanup(VOID)
1730 {
1731 }
1732
1733 /* EOF */