Version:
~
[ 2.4 ] ~
[ 2.4.5 ] ~
** Warning: Cannot open xref database.
1 /////////////////////////////////////////////////////////////////////////
2 // $Id: vga.cc,v 1.165 2009/04/21 20:32:20 sshwarts Exp $
3 /////////////////////////////////////////////////////////////////////////
4 //
5 // Copyright (C) 2002 MandrakeSoft S.A.
6 //
7 // MandrakeSoft S.A.
8 // 43, rue d'Aboukir
9 // 75002 Paris - France
10 // http://www.linux-mandrake.com/
11 // http://www.mandrakesoft.com/
12 //
13 // This library is free software; you can redistribute it and/or
14 // modify it under the terms of the GNU Lesser General Public
15 // License as published by the Free Software Foundation; either
16 // version 2 of the License, or (at your option) any later version.
17 //
18 // This library is distributed in the hope that it will be useful,
19 // but WITHOUT ANY WARRANTY; without even the implied warranty of
20 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 // Lesser General Public License for more details.
22 //
23 // You should have received a copy of the GNU Lesser General Public
24 // License along with this library; if not, write to the Free Software
25 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
26 /////////////////////////////////////////////////////////////////////////
27
28 // Define BX_PLUGGABLE in files that can be compiled into plugins. For
29 // platforms that require a special tag on exported symbols, BX_PLUGGABLE
30 // is used to know when we are exporting symbols and when we are importing.
31 #define BX_PLUGGABLE
32
33 #include "iodev.h"
34 #include "vga.h"
35
36 #define LOG_THIS theVga->
37
38 #define VGA_TRACE_FEATURE
39
40 // Only reference the array if the tile numbers are within the bounds
41 // of the array. If out of bounds, do nothing.
42 #define SET_TILE_UPDATED(xtile, ytile, value) \
43 do { \
44 if (((xtile) < BX_NUM_X_TILES) && ((ytile) < BX_NUM_Y_TILES)) \
45 BX_VGA_THIS s.vga_tile_updated[(xtile)][(ytile)] = value; \
46 } while (0)
47
48 // Only reference the array if the tile numbers are within the bounds
49 // of the array. If out of bounds, return 0.
50 #define GET_TILE_UPDATED(xtile,ytile) \
51 ((((xtile) < BX_NUM_X_TILES) && ((ytile) < BX_NUM_Y_TILES))? \
52 BX_VGA_THIS s.vga_tile_updated[(xtile)][(ytile)] \
53 : 0)
54
55 static const Bit16u charmap_offset[8] = {
56 0x0000, 0x4000, 0x8000, 0xc000,
57 0x2000, 0x6000, 0xa000, 0xe000
58 };
59
60 static const Bit8u ccdat[16][4] = {
61 { 0x00, 0x00, 0x00, 0x00 },
62 { 0xff, 0x00, 0x00, 0x00 },
63 { 0x00, 0xff, 0x00, 0x00 },
64 { 0xff, 0xff, 0x00, 0x00 },
65 { 0x00, 0x00, 0xff, 0x00 },
66 { 0xff, 0x00, 0xff, 0x00 },
67 { 0x00, 0xff, 0xff, 0x00 },
68 { 0xff, 0xff, 0xff, 0x00 },
69 { 0x00, 0x00, 0x00, 0xff },
70 { 0xff, 0x00, 0x00, 0xff },
71 { 0x00, 0xff, 0x00, 0xff },
72 { 0xff, 0xff, 0x00, 0xff },
73 { 0x00, 0x00, 0xff, 0xff },
74 { 0xff, 0x00, 0xff, 0xff },
75 { 0x00, 0xff, 0xff, 0xff },
76 { 0xff, 0xff, 0xff, 0xff },
77 };
78
79 bx_vga_c *theVga = NULL;
80
81 unsigned old_iHeight = 0, old_iWidth = 0, old_MSL = 0;
82
83 #if BX_SUPPORT_CLGD54XX
84 void bx_vga_set_smf_pointer(bx_vga_c *theVga_ptr)
85 {
86 theVga = theVga_ptr;
87 }
88 #else // BX_SUPPORT_CLGD54XX
89 int libvga_LTX_plugin_init(plugin_t *plugin, plugintype_t type, int argc, char *argv[])
90 {
91 theVga = new bx_vga_c();
92 bx_devices.pluginVgaDevice = theVga;
93 BX_REGISTER_DEVICE_DEVMODEL(plugin, type, theVga, BX_PLUGIN_VGA);
94 return(0); // Success
95 }
96
97 void libvga_LTX_plugin_fini(void)
98 {
99 delete theVga;
100 }
101 #endif // BX_SUPPORT_CLGD54XX
102
103 bx_vga_c::bx_vga_c()
104 {
105 put("VGA");
106 s.vga_mem_updated = 0;
107 s.x_tilesize = X_TILESIZE;
108 s.y_tilesize = Y_TILESIZE;
109 timer_id = BX_NULL_TIMER_HANDLE;
110 s.memory = NULL;
111 }
112
113 bx_vga_c::~bx_vga_c()
114 {
115 if (s.memory != NULL) {
116 delete [] s.memory;
117 s.memory = NULL;
118 }
119 SIM->get_param_num(BXPN_VGA_UPDATE_INTERVAL)->set_handler(NULL);
120 BX_DEBUG(("Exit"));
121 }
122
123 void bx_vga_c::init(void)
124 {
125 unsigned i,string_i;
126 unsigned x,y;
127 #if BX_SUPPORT_VBE
128 unsigned addr;
129 Bit16u max_xres, max_yres, max_bpp;
130 #endif
131 int argc;
132 char *argv[16];
133 char *ptr;
134 char string[512];
135 char *extname;
136 size_t len;
137
138 // initialize VGA controllers and other internal stuff
139 BX_VGA_THIS s.vga_enabled = 1;
140 BX_VGA_THIS s.misc_output.color_emulation = 1;
141 BX_VGA_THIS s.misc_output.enable_ram = 1;
142 BX_VGA_THIS s.misc_output.clock_select = 0;
143 BX_VGA_THIS s.misc_output.select_high_bank = 0;
144 BX_VGA_THIS s.misc_output.horiz_sync_pol = 1;
145 BX_VGA_THIS s.misc_output.vert_sync_pol = 1;
146
147 BX_VGA_THIS s.attribute_ctrl.mode_ctrl.graphics_alpha = 0;
148 BX_VGA_THIS s.attribute_ctrl.mode_ctrl.display_type = 0;
149 BX_VGA_THIS s.attribute_ctrl.mode_ctrl.enable_line_graphics = 1;
150 BX_VGA_THIS s.attribute_ctrl.mode_ctrl.blink_intensity = 0;
151 BX_VGA_THIS s.attribute_ctrl.mode_ctrl.pixel_panning_compat = 0;
152 BX_VGA_THIS s.attribute_ctrl.mode_ctrl.pixel_clock_select = 0;
153 BX_VGA_THIS s.attribute_ctrl.mode_ctrl.internal_palette_size = 0;
154
155 BX_VGA_THIS s.line_offset=80;
156 BX_VGA_THIS s.line_compare=1023;
157 BX_VGA_THIS s.vertical_display_end=399;
158
159 for (i=0; i<=0x18; i++)
160 BX_VGA_THIS s.CRTC.reg[i] = 0;
161 BX_VGA_THIS s.CRTC.address = 0;
162 BX_VGA_THIS s.CRTC.write_protect = 0;
163
164 BX_VGA_THIS s.attribute_ctrl.flip_flop = 0;
165 BX_VGA_THIS s.attribute_ctrl.address = 0;
166 BX_VGA_THIS s.attribute_ctrl.video_enabled = 1;
167 for (i=0; i<16; i++)
168 BX_VGA_THIS s.attribute_ctrl.palette_reg[i] = 0;
169 BX_VGA_THIS s.attribute_ctrl.overscan_color = 0;
170 BX_VGA_THIS s.attribute_ctrl.color_plane_enable = 0x0f;
171 BX_VGA_THIS s.attribute_ctrl.horiz_pel_panning = 0;
172 BX_VGA_THIS s.attribute_ctrl.color_select = 0;
173
174 for (i=0; i<256; i++) {
175 BX_VGA_THIS s.pel.data[i].red = 0;
176 BX_VGA_THIS s.pel.data[i].green = 0;
177 BX_VGA_THIS s.pel.data[i].blue = 0;
178 }
179 BX_VGA_THIS s.pel.write_data_register = 0;
180 BX_VGA_THIS s.pel.write_data_cycle = 0;
181 BX_VGA_THIS s.pel.read_data_register = 0;
182 BX_VGA_THIS s.pel.read_data_cycle = 0;
183 BX_VGA_THIS s.pel.dac_state = 0x01;
184 BX_VGA_THIS s.pel.mask = 0xff;
185
186 BX_VGA_THIS s.graphics_ctrl.index = 0;
187 BX_VGA_THIS s.graphics_ctrl.set_reset = 0;
188 BX_VGA_THIS s.graphics_ctrl.enable_set_reset = 0;
189 BX_VGA_THIS s.graphics_ctrl.color_compare = 0;
190 BX_VGA_THIS s.graphics_ctrl.data_rotate = 0;
191 BX_VGA_THIS s.graphics_ctrl.raster_op = 0;
192 BX_VGA_THIS s.graphics_ctrl.read_map_select = 0;
193 BX_VGA_THIS s.graphics_ctrl.write_mode = 0;
194 BX_VGA_THIS s.graphics_ctrl.read_mode = 0;
195 BX_VGA_THIS s.graphics_ctrl.odd_even = 0;
196 BX_VGA_THIS s.graphics_ctrl.chain_odd_even = 0;
197 BX_VGA_THIS s.graphics_ctrl.shift_reg = 0;
198 BX_VGA_THIS s.graphics_ctrl.graphics_alpha = 0;
199 BX_VGA_THIS s.graphics_ctrl.memory_mapping = 2; // monochrome text mode
200 BX_VGA_THIS s.graphics_ctrl.color_dont_care = 0;
201 BX_VGA_THIS s.graphics_ctrl.bitmask = 0;
202 for (i=0; i<4; i++) {
203 BX_VGA_THIS s.graphics_ctrl.latch[i] = 0;
204 }
205
206 BX_VGA_THIS s.sequencer.index = 0;
207 BX_VGA_THIS s.sequencer.map_mask = 0;
208 BX_VGA_THIS s.sequencer.reset1 = 1;
209 BX_VGA_THIS s.sequencer.reset2 = 1;
210 BX_VGA_THIS s.sequencer.reg1 = 0;
211 BX_VGA_THIS s.sequencer.char_map_select = 0;
212 BX_VGA_THIS s.sequencer.extended_mem = 1; // display mem greater than 64K
213 BX_VGA_THIS s.sequencer.odd_even = 1; // use sequential addressing mode
214 BX_VGA_THIS s.sequencer.chain_four = 0; // use map mask & read map select
215
216 BX_VGA_THIS s.charmap_address = 0;
217 BX_VGA_THIS s.x_dotclockdiv2 = 0;
218 BX_VGA_THIS s.y_doublescan = 0;
219 BX_VGA_THIS s.last_bpp = 8;
220
221 BX_VGA_THIS s.vga_mem_updated = 0;
222 for (y=0; y<480/Y_TILESIZE; y++)
223 for (x=0; x<640/X_TILESIZE; x++)
224 SET_TILE_UPDATED (x, y, 0);
225
226 BX_VGA_THIS extension_init = 0;
227 BX_VGA_THIS extension_checked = 0;
228
229 // initialize memory, handlers and timer (depending on extension)
230 extname = SIM->get_param_string(BXPN_VGA_EXTENSION)->getptr();
231 if ((strlen(extname) == 0) || (!strcmp(extname, "none"))) {
232 BX_VGA_THIS s.memsize = 0x40000;
233 if (BX_VGA_THIS s.memory == NULL)
234 BX_VGA_THIS s.memory = new Bit8u[BX_VGA_THIS s.memsize];
235 memset(BX_VGA_THIS s.memory, 0, BX_VGA_THIS s.memsize);
236 }
237 #if !BX_SUPPORT_CLGD54XX
238 BX_VGA_THIS init_iohandlers(read_handler,write_handler);
239 BX_VGA_THIS init_systemtimer(timer_handler, vga_param_handler);
240 #endif
241 DEV_register_memory_handlers(theVga, mem_read_handler, mem_write_handler,
242 0xa0000, 0xbffff);
243
244 // video card with BIOS ROM
245 DEV_cmos_set_reg(0x14, (DEV_cmos_get_reg(0x14) & 0xcf) | 0x00);
246
247 // set up display library options and start gui
248 memset(argv, 0, sizeof(argv));
249 argc = 1;
250 argv[0] = (char *)"bochs";
251 len = strlen(SIM->get_param_string(BXPN_DISPLAYLIB_OPTIONS)->getptr());
252 if (len > 0) {
253 char *options = new char[len + 1];
254 strcpy(options, SIM->get_param_string(BXPN_DISPLAYLIB_OPTIONS)->getptr());
255 ptr = strtok(options, ",");
256 while (ptr) {
257 string_i = 0;
258 for (i=0; i<strlen(ptr); i++) {
259 if (!isspace(ptr[i])) string[string_i++] = ptr[i];
260 }
261 string[string_i] = '\0';
262 if (argv[argc] != NULL) {
263 free(argv[argc]);
264 argv[argc] = NULL;
265 }
266 if (argc < 16) {
267 argv[argc++] = strdup(string);
268 } else {
269 BX_PANIC (("too many parameters, max is 16\n"));
270 }
271 ptr = strtok(NULL, ",");
272 }
273 delete [] options;
274 }
275 bx_gui->init(argc, argv, BX_VGA_THIS s.x_tilesize, BX_VGA_THIS s.y_tilesize);
276 for (i = 1; i < (unsigned)argc; i++)
277 {
278 if (argv[i] != NULL)
279 {
280 free(argv[i]);
281 argv[i] = NULL;
282 }
283 }
284
285 #if BX_SUPPORT_VBE
286 // The following is for the vbe display extension
287 BX_VGA_THIS vbe.enabled=0;
288 BX_VGA_THIS vbe.dac_8bit=0;
289 if (!strcmp(extname, "vbe")) {
290 for (addr=VBE_DISPI_IOPORT_INDEX; addr<=VBE_DISPI_IOPORT_DATA; addr++) {
291 DEV_register_ioread_handler(this, vbe_read_handler, addr, "vga video", 7);
292 DEV_register_iowrite_handler(this, vbe_write_handler, addr, "vga video", 7);
293 }
294 #if BX_SUPPORT_PCI
295 if ((SIM->get_param_bool(BXPN_I440FX_SUPPORT)->get()) &&
296 (DEV_is_pci_device(BX_PLUGIN_PCIVGA))) {
297 BX_VGA_THIS vbe.base_address = 0x0000;
298 }
299 else
300 #endif
301 {
302 BX_VGA_THIS vbe.base_address = VBE_DISPI_LFB_PHYSICAL_ADDRESS;
303 DEV_register_memory_handlers(theVga, mem_read_handler, mem_write_handler,
304 BX_VGA_THIS vbe.base_address,
305 BX_VGA_THIS vbe.base_address + VBE_DISPI_TOTAL_VIDEO_MEMORY_BYTES - 1);
306
307 }
308 if (BX_VGA_THIS s.memory == NULL)
309 BX_VGA_THIS s.memory = new Bit8u[VBE_DISPI_TOTAL_VIDEO_MEMORY_BYTES];
310 memset(BX_VGA_THIS s.memory, 0, VBE_DISPI_TOTAL_VIDEO_MEMORY_BYTES);
311 BX_VGA_THIS s.memsize = VBE_DISPI_TOTAL_VIDEO_MEMORY_BYTES;
312 BX_VGA_THIS vbe.cur_dispi=VBE_DISPI_ID0;
313 BX_VGA_THIS vbe.xres=640;
314 BX_VGA_THIS vbe.yres=480;
315 BX_VGA_THIS vbe.bpp=8;
316 BX_VGA_THIS vbe.bank=0;
317 BX_VGA_THIS vbe.curindex=0;
318 BX_VGA_THIS vbe.offset_x=0;
319 BX_VGA_THIS vbe.offset_y=0;
320 BX_VGA_THIS vbe.virtual_xres=640;
321 BX_VGA_THIS vbe.virtual_yres=480;
322 BX_VGA_THIS vbe.bpp_multiplier=1;
323 BX_VGA_THIS vbe.virtual_start=0;
324 BX_VGA_THIS vbe.lfb_enabled=0;
325 BX_VGA_THIS vbe.get_capabilities=0;
326 bx_gui->get_capabilities(&max_xres, &max_yres, &max_bpp);
327 if (max_xres > VBE_DISPI_MAX_XRES) {
328 BX_VGA_THIS vbe.max_xres=VBE_DISPI_MAX_XRES;
329 } else {
330 BX_VGA_THIS vbe.max_xres=max_xres;
331 }
332 if (max_yres > VBE_DISPI_MAX_YRES) {
333 BX_VGA_THIS vbe.max_yres=VBE_DISPI_MAX_YRES;
334 } else {
335 BX_VGA_THIS vbe.max_yres=max_yres;
336 }
337 if (max_bpp > VBE_DISPI_MAX_BPP) {
338 BX_VGA_THIS vbe.max_bpp=VBE_DISPI_MAX_BPP;
339 } else {
340 BX_VGA_THIS vbe.max_bpp=max_bpp;
341 }
342 BX_VGA_THIS extension_init = 1;
343
344 BX_INFO(("VBE Bochs Display Extension Enabled"));
345 }
346 #endif
347 }
348
349 void bx_vga_c::init_iohandlers(bx_read_handler_t f_read, bx_write_handler_t f_write)
350 {
351 unsigned addr, i;
352 Bit8u io_mask[16] = {3, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1};
353 for (addr=0x03B4; addr<=0x03B5; addr++) {
354 DEV_register_ioread_handler(this, f_read, addr, "vga video", 1);
355 DEV_register_iowrite_handler(this, f_write, addr, "vga video", 3);
356 }
357
358 for (addr=0x03BA; addr<=0x03BA; addr++) {
359 DEV_register_ioread_handler(this, f_read, addr, "vga video", 1);
360 DEV_register_iowrite_handler(this, f_write, addr, "vga video", 3);
361 }
362
363 i = 0;
364 for (addr=0x03C0; addr<=0x03CF; addr++) {
365 DEV_register_ioread_handler(this, f_read, addr, "vga video", io_mask[i++]);
366 DEV_register_iowrite_handler(this, f_write, addr, "vga video", 3);
367 }
368
369 for (addr=0x03D4; addr<=0x03D5; addr++) {
370 DEV_register_ioread_handler(this, f_read, addr, "vga video", 3);
371 DEV_register_iowrite_handler(this, f_write, addr, "vga video", 3);
372 }
373
374 for (addr=0x03DA; addr<=0x03DA; addr++) {
375 DEV_register_ioread_handler(this, f_read, addr, "vga video", 1);
376 DEV_register_iowrite_handler(this, f_write, addr, "vga video", 3);
377 }
378 }
379
380 void bx_vga_c::init_systemtimer(bx_timer_handler_t f_timer, param_event_handler f_param)
381 {
382 bx_param_num_c *vga_update_interval = SIM->get_param_num(BXPN_VGA_UPDATE_INTERVAL);
383 Bit64u interval = vga_update_interval->get();
384 BX_INFO(("interval=" FMT_LL "u", interval));
385 if (BX_VGA_THIS timer_id == BX_NULL_TIMER_HANDLE) {
386 BX_VGA_THIS timer_id = bx_pc_system.register_timer(this, f_timer,
387 (Bit32u)interval, 1, 1, "vga");
388 vga_update_interval->set_handler(f_param);
389 vga_update_interval->set_runtime_param(1);
390 }
391 if (interval < 300000) {
392 BX_VGA_THIS s.blink_counter = 300000 / (unsigned)interval;
393 } else {
394 BX_VGA_THIS s.blink_counter = 1;
395 }
396 }
397
398 void bx_vga_c::reset(unsigned type)
399 {
400 if (!BX_VGA_THIS extension_checked) {
401 char *strptr = SIM->get_param_string(BXPN_VGA_EXTENSION)->getptr();
402 if (!BX_VGA_THIS extension_init &&
403 (strlen(strptr) > 0) &&
404 strcmp(strptr, "none")) {
405 BX_PANIC(("unknown display extension: %s", strptr));
406 }
407 BX_VGA_THIS extension_checked = 1;
408 }
409 }
410
411 void bx_vga_c::register_state(void)
412 {
413 unsigned i;
414 char name[6];
415 bx_list_c *parent, *reg;
416
417 parent = SIM->get_bochs_root();
418 #if BX_SUPPORT_CLGD54XX
419 if (!strcmp(SIM->get_param_string(BXPN_VGA_EXTENSION)->getptr(), "cirrus")) {
420 parent = (bx_list_c*)SIM->get_param("svga_cirrus", parent);;
421 }
422 #endif
423 bx_list_c *list = new bx_list_c(parent, "vga", "VGA Adapter State", 17);
424 bx_list_c *misc = new bx_list_c(list, "misc_output", 6);
425 new bx_shadow_bool_c(misc, "color_emulation", &BX_VGA_THIS s.misc_output.color_emulation);
426 new bx_shadow_bool_c(misc, "enable_ram", &BX_VGA_THIS s.misc_output.enable_ram);
427 new bx_shadow_num_c(misc, "clock_select", &BX_VGA_THIS s.misc_output.clock_select);
428 new bx_shadow_bool_c(misc, "select_high_bank", &BX_VGA_THIS s.misc_output.select_high_bank);
429 new bx_shadow_bool_c(misc, "horiz_sync_pol", &BX_VGA_THIS s.misc_output.horiz_sync_pol);
430 new bx_shadow_bool_c(misc, "vert_sync_pol", &BX_VGA_THIS s.misc_output.vert_sync_pol);
431 bx_list_c *crtc = new bx_list_c(list, "CRTC", 3);
432 new bx_shadow_num_c(crtc, "address", &BX_VGA_THIS s.CRTC.address, BASE_HEX);
433 reg = new bx_list_c(crtc, "reg", 0x19);
434 for (i=0; i<=0x18; i++) {
435 sprintf(name, "0x%02x", i);
436 new bx_shadow_num_c(reg, name, &BX_VGA_THIS s.CRTC.reg[i], BASE_HEX);
437 }
438 new bx_shadow_bool_c(crtc, "write_protect", &BX_VGA_THIS s.CRTC.write_protect);
439 bx_list_c *actl = new bx_list_c(list, "attribute_ctrl", 9);
440 new bx_shadow_bool_c(actl, "flip_flop", &BX_VGA_THIS s.attribute_ctrl.flip_flop);
441 new bx_shadow_num_c(actl, "address", &BX_VGA_THIS s.attribute_ctrl.address, BASE_HEX);
442 new bx_shadow_bool_c(actl, "video_enabled", &BX_VGA_THIS s.attribute_ctrl.video_enabled);
443 reg = new bx_list_c(actl, "palette_reg", 16);
444 for (i=0; i<16; i++) {
445 sprintf(name, "0x%02x", i);
446 new bx_shadow_num_c(reg, name, &BX_VGA_THIS s.attribute_ctrl.palette_reg[i], BASE_HEX);
447 }
448 new bx_shadow_num_c(actl, "overscan_color", &BX_VGA_THIS s.attribute_ctrl.overscan_color, BASE_HEX);
449 new bx_shadow_num_c(actl, "color_plane_enable", &BX_VGA_THIS s.attribute_ctrl.color_plane_enable, BASE_HEX);
450 new bx_shadow_num_c(actl, "horiz_pel_panning", &BX_VGA_THIS s.attribute_ctrl.horiz_pel_panning, BASE_HEX);
451 new bx_shadow_num_c(actl, "color_select", &BX_VGA_THIS s.attribute_ctrl.color_select, BASE_HEX);
452 bx_list_c *mode = new bx_list_c(actl, "mode_ctrl", 7);
453 new bx_shadow_bool_c(mode, "graphics_alpha", &BX_VGA_THIS s.attribute_ctrl.mode_ctrl.graphics_alpha);
454 new bx_shadow_bool_c(mode, "display_type", &BX_VGA_THIS s.attribute_ctrl.mode_ctrl.display_type);
455 new bx_shadow_bool_c(mode, "enable_line_graphics", &BX_VGA_THIS s.attribute_ctrl.mode_ctrl.enable_line_graphics);
456 new bx_shadow_bool_c(mode, "blink_intensity", &BX_VGA_THIS s.attribute_ctrl.mode_ctrl.blink_intensity);
457 new bx_shadow_bool_c(mode, "pixel_panning_compat", &BX_VGA_THIS s.attribute_ctrl.mode_ctrl.pixel_panning_compat);
458 new bx_shadow_bool_c(mode, "pixel_clock_select", &BX_VGA_THIS s.attribute_ctrl.mode_ctrl.pixel_clock_select);
459 new bx_shadow_bool_c(mode, "internal_palette_size", &BX_VGA_THIS s.attribute_ctrl.mode_ctrl.internal_palette_size);
460 bx_list_c *pel = new bx_list_c(list, "pel", 6);
461 new bx_shadow_num_c(pel, "write_data_register", &BX_VGA_THIS s.pel.write_data_register, BASE_HEX);
462 new bx_shadow_num_c(pel, "write_data_cycle", &BX_VGA_THIS s.pel.write_data_cycle);
463 new bx_shadow_num_c(pel, "read_data_register", &BX_VGA_THIS s.pel.read_data_register, BASE_HEX);
464 new bx_shadow_num_c(pel, "read_data_cycle", &BX_VGA_THIS s.pel.read_data_cycle);
465 new bx_shadow_num_c(pel, "dac_state", &BX_VGA_THIS s.pel.dac_state);
466 new bx_shadow_num_c(pel, "mask", &BX_VGA_THIS s.pel.mask, BASE_HEX);
467 new bx_shadow_data_c(list, "pel_data", &BX_VGA_THIS s.pel.data[0].red, sizeof(BX_VGA_THIS s.pel.data));
468 bx_list_c *gfxc = new bx_list_c(list, "graphics_ctrl", 20);
469 new bx_shadow_num_c(gfxc, "index", &BX_VGA_THIS s.graphics_ctrl.index);
470 new bx_shadow_num_c(gfxc, "set_reset", &BX_VGA_THIS s.graphics_ctrl.set_reset);
471 new bx_shadow_num_c(gfxc, "enable_set_reset", &BX_VGA_THIS s.graphics_ctrl.enable_set_reset);
472 new bx_shadow_num_c(gfxc, "color_compare", &BX_VGA_THIS s.graphics_ctrl.color_compare);
473 new bx_shadow_num_c(gfxc, "data_rotate", &BX_VGA_THIS s.graphics_ctrl.data_rotate);
474 new bx_shadow_num_c(gfxc, "raster_op", &BX_VGA_THIS s.graphics_ctrl.raster_op);
475 new bx_shadow_num_c(gfxc, "read_map_select", &BX_VGA_THIS s.graphics_ctrl.read_map_select);
476 new bx_shadow_num_c(gfxc, "write_mode", &BX_VGA_THIS s.graphics_ctrl.write_mode);
477 new bx_shadow_num_c(gfxc, "read_mode", &BX_VGA_THIS s.graphics_ctrl.read_mode);
478 new bx_shadow_bool_c(gfxc, "odd_even", &BX_VGA_THIS s.graphics_ctrl.odd_even);
479 new bx_shadow_bool_c(gfxc, "chain_odd_even", &BX_VGA_THIS s.graphics_ctrl.chain_odd_even);
480 new bx_shadow_num_c(gfxc, "shift_reg", &BX_VGA_THIS s.graphics_ctrl.shift_reg);
481 new bx_shadow_bool_c(gfxc, "graphics_alpha", &BX_VGA_THIS s.graphics_ctrl.graphics_alpha);
482 new bx_shadow_num_c(gfxc, "memory_mapping", &BX_VGA_THIS s.graphics_ctrl.memory_mapping);
483 new bx_shadow_num_c(gfxc, "color_dont_care", &BX_VGA_THIS s.graphics_ctrl.color_dont_care, BASE_HEX);
484 new bx_shadow_num_c(gfxc, "bitmask", &BX_VGA_THIS s.graphics_ctrl.bitmask, BASE_HEX);
485 new bx_shadow_num_c(gfxc, "latch0", &BX_VGA_THIS s.graphics_ctrl.latch[0], BASE_HEX);
486 new bx_shadow_num_c(gfxc, "latch1", &BX_VGA_THIS s.graphics_ctrl.latch[1], BASE_HEX);
487 new bx_shadow_num_c(gfxc, "latch2", &BX_VGA_THIS s.graphics_ctrl.latch[2], BASE_HEX);
488 new bx_shadow_num_c(gfxc, "latch3", &BX_VGA_THIS s.graphics_ctrl.latch[3], BASE_HEX);
489 bx_list_c *sequ = new bx_list_c(list, "sequencer", 13);
490 new bx_shadow_num_c(sequ, "index", &BX_VGA_THIS s.sequencer.index);
491 new bx_shadow_num_c(sequ, "map_mask", &BX_VGA_THIS s.sequencer.map_mask);
492 new bx_shadow_bool_c(sequ, "reset1", &BX_VGA_THIS s.sequencer.reset1);
493 new bx_shadow_bool_c(sequ, "reset2", &BX_VGA_THIS s.sequencer.reset2);
494 new bx_shadow_num_c(sequ, "reg1", &BX_VGA_THIS s.sequencer.reg1, BASE_HEX);
495 new bx_shadow_num_c(sequ, "char_map_select", &BX_VGA_THIS s.sequencer.char_map_select);
496 new bx_shadow_bool_c(sequ, "extended_mem", &BX_VGA_THIS s.sequencer.extended_mem);
497 new bx_shadow_bool_c(sequ, "odd_even", &BX_VGA_THIS s.sequencer.odd_even);
498 new bx_shadow_bool_c(sequ, "chain_four", &BX_VGA_THIS s.sequencer.chain_four);
499 new bx_shadow_bool_c(list, "enabled", &BX_VGA_THIS s.vga_enabled);
500 new bx_shadow_num_c(list, "line_offset", &BX_VGA_THIS s.line_offset);
501 new bx_shadow_num_c(list, "line_compare", &BX_VGA_THIS s.line_compare);
502 new bx_shadow_num_c(list, "vertical_display_end", &BX_VGA_THIS s.vertical_display_end);
503 new bx_shadow_num_c(list, "charmap_address", &BX_VGA_THIS s.charmap_address);
504 new bx_shadow_bool_c(list, "x_dotclockdiv2", &BX_VGA_THIS s.x_dotclockdiv2);
505 new bx_shadow_bool_c(list, "y_doublescan", &BX_VGA_THIS s.y_doublescan);
506 new bx_shadow_num_c(list, "last_bpp", &BX_VGA_THIS s.last_bpp);
507 new bx_shadow_data_c(list, "memory", BX_VGA_THIS s.memory, BX_VGA_THIS s.memsize);
508 #if BX_SUPPORT_VBE
509 if (!strcmp(SIM->get_param_string(BXPN_VGA_EXTENSION)->getptr(), "vbe")) {
510 bx_list_c *vbe = new bx_list_c(list, "vbe", 18);
511 new bx_shadow_num_c(vbe, "cur_dispi", &BX_VGA_THIS vbe.cur_dispi, BASE_HEX);
512 new bx_shadow_num_c(vbe, "xres", &BX_VGA_THIS vbe.xres);
513 new bx_shadow_num_c(vbe, "yres", &BX_VGA_THIS vbe.yres);
514 new bx_shadow_num_c(vbe, "bpp", &BX_VGA_THIS vbe.bpp);
515 new bx_shadow_num_c(vbe, "bank", &BX_VGA_THIS vbe.bank);
516 new bx_shadow_bool_c(vbe, "enabled", &BX_VGA_THIS vbe.enabled);
517 new bx_shadow_num_c(vbe, "curindex", &BX_VGA_THIS vbe.curindex);
518 new bx_shadow_num_c(vbe, "visible_screen_size", &BX_VGA_THIS vbe.visible_screen_size);
519 new bx_shadow_num_c(vbe, "offset_x", &BX_VGA_THIS vbe.offset_x);
520 new bx_shadow_num_c(vbe, "offset_y", &BX_VGA_THIS vbe.offset_y);
521 new bx_shadow_num_c(vbe, "virtual_xres", &BX_VGA_THIS vbe.virtual_xres);
522 new bx_shadow_num_c(vbe, "virtual_yres", &BX_VGA_THIS vbe.virtual_yres);
523 new bx_shadow_num_c(vbe, "virtual_start", &BX_VGA_THIS vbe.virtual_start);
524 new bx_shadow_num_c(vbe, "bpp_multiplier", &BX_VGA_THIS vbe.bpp_multiplier);
525 new bx_shadow_bool_c(vbe, "lfb_enabled", &BX_VGA_THIS vbe.lfb_enabled);
526 new bx_shadow_bool_c(vbe, "get_capabilities", &BX_VGA_THIS vbe.get_capabilities);
527 new bx_shadow_bool_c(vbe, "dac_8bit", &BX_VGA_THIS vbe.dac_8bit);
528 }
529 #endif
530 }
531
532 void bx_vga_c::after_restore_state(void)
533 {
534 for (unsigned i=0; i<256; i++) {
535 #if BX_SUPPORT_VBE
536 if (BX_VGA_THIS vbe.dac_8bit) {
537 bx_gui->palette_change(i, BX_VGA_THIS s.pel.data[i].red,
538 BX_VGA_THIS s.pel.data[i].green,
539 BX_VGA_THIS s.pel.data[i].blue);
540 }
541 else
542 #endif
543 {
544 bx_gui->palette_change(i, BX_VGA_THIS s.pel.data[i].red<<2,
545 BX_VGA_THIS s.pel.data[i].green<<2,
546 BX_VGA_THIS s.pel.data[i].blue<<2);
547 }
548 }
549 bx_gui->set_text_charmap(&BX_VGA_THIS s.memory[0x20000 + BX_VGA_THIS s.charmap_address]);
550 old_iWidth = BX_MAX_XRES;
551 old_iHeight = BX_MAX_YRES;
552 BX_VGA_THIS redraw_area(0, 0, BX_MAX_XRES, BX_MAX_YRES);
553 #if BX_SUPPORT_VBE
554 if (BX_VGA_THIS vbe.enabled) {
555 bx_gui->dimension_update(BX_VGA_THIS vbe.xres, BX_VGA_THIS vbe.yres, 0, 0,
556 BX_VGA_THIS vbe.bpp);
557 }
558 #endif
559 BX_VGA_THIS update();
560 bx_gui->flush();
561 }
562
563 void bx_vga_c::determine_screen_dimensions(unsigned *piHeight, unsigned *piWidth)
564 {
565 int ai[0x20];
566 int i,h,v;
567 for (i = 0 ; i < 0x20 ; i++)
568 ai[i] = BX_VGA_THIS s.CRTC.reg[i];
569
570 h = (ai[1] + 1) * 8;
571 v = (ai[18] | ((ai[7] & 0x02) << 7) | ((ai[7] & 0x40) << 3)) + 1;
572
573 if (BX_VGA_THIS s.graphics_ctrl.shift_reg == 0)
574 {
575 *piWidth = 640;
576 *piHeight = 480;
577
578 if (BX_VGA_THIS s.CRTC.reg[6] == 0xBF)
579 {
580 if (BX_VGA_THIS s.CRTC.reg[23] == 0xA3 &&
581 BX_VGA_THIS s.CRTC.reg[20] == 0x40 &&
582 BX_VGA_THIS s.CRTC.reg[9] == 0x41)
583 {
584 *piWidth = 320;
585 *piHeight = 240;
586 }
587 else {
588 if (BX_VGA_THIS s.x_dotclockdiv2) h <<= 1;
589 *piWidth = h;
590 *piHeight = v;
591 }
592 }
593 else if ((h >= 640) && (v >= 480)) {
594 *piWidth = h;
595 *piHeight = v;
596 }
597 }
598 else if (BX_VGA_THIS s.graphics_ctrl.shift_reg == 2)
599 {
600
601 if (BX_VGA_THIS s.sequencer.chain_four)
602 {
603 *piWidth = h;
604 *piHeight = v;
605 }
606 else
607 {
608 *piWidth = h;
609 *piHeight = v;
610 }
611 }
612 else
613 {
614 if (BX_VGA_THIS s.x_dotclockdiv2) h <<= 1;
615 *piWidth = h;
616 *piHeight = v;
617 }
618 }
619
620 // static IO port read callback handler
621 // redirects to non-static class handler to avoid virtual functions
622
623 Bit32u bx_vga_c::read_handler(void *this_ptr, Bit32u address, unsigned io_len)
624 {
625 #if BX_USE_VGA_SMF == 0
626 bx_vga_c *class_ptr = (bx_vga_c *) this_ptr;
627 return class_ptr->read(address, io_len);
628 }
629
630 Bit32u bx_vga_c::read(Bit32u address, unsigned io_len)
631 {
632 #else
633 UNUSED(this_ptr);
634 #endif // BX_USE_VGA_SMF == 0
635 bx_bool horiz_retrace = 0, vert_retrace = 0;
636 Bit64u usec;
637 Bit16u ret16, vertres;
638 Bit8u retval;
639
640 #if defined(VGA_TRACE_FEATURE)
641 Bit32u ret = 0;
642 #define RETURN(x) do { ret = (x); goto read_return; } while (0)
643 #else
644 #define RETURN return
645 #endif
646
647 if (io_len == 2) {
648 #if BX_USE_VGA_SMF
649 ret16 = bx_vga_c::read_handler(0, address, 1);
650 ret16 |= (bx_vga_c::read_handler(0, address+1, 1)) << 8;
651 #else
652 ret16 = bx_vga_c::read(address, 1);
653 ret16 |= (bx_vga_c::read(address+1, 1) << 8;
654 #endif
655 RETURN(ret16);
656 }
657
658 #ifdef __OS2__
659 if (bx_options.videomode == BX_VIDEO_DIRECT)
660 {
661 return _inp(address);
662 }
663 #endif
664
665 #if !defined(VGA_TRACE_FEATURE)
666 BX_DEBUG(("io read from 0x%04x", (unsigned) address));
667 #endif
668
669 if ((address >= 0x03b0) && (address <= 0x03bf) &&
670 (BX_VGA_THIS s.misc_output.color_emulation)) {
671 RETURN(0xff);
672 }
673 if ((address >= 0x03d0) && (address <= 0x03df) &&
674 (BX_VGA_THIS s.misc_output.color_emulation==0)) {
675 RETURN(0xff);
676 }
677
678 switch (address) {
679 case 0x03ba: /* Input Status 1 (monochrome emulation modes) */
680 case 0x03ca: /* Feature Control ??? */
681 case 0x03da: /* Input Status 1 (color emulation modes) */
682 // bit3: Vertical Retrace
683 // 0 = display is in the display mode
684 // 1 = display is in the vertical retrace mode
685 // bit0: Display Enable
686 // 0 = display is in the display mode
687 // 1 = display is not in the display mode; either the
688 // horizontal or vertical retrace period is active
689
690 // using 72 Hz vertical frequency
691 usec = bx_pc_system.time_usec();
692 switch ((BX_VGA_THIS s.misc_output.vert_sync_pol << 1) | BX_VGA_THIS s.misc_output.horiz_sync_pol)
693 {
694 case 0: vertres = 200; break;
695 case 1: vertres = 400; break;
696 case 2: vertres = 350; break;
697 default: vertres = 480; break;
698 }
699 if ((usec % 13888) < 70) {
700 vert_retrace = 1;
701 }
702 if ((usec % (13888 / vertres)) == 0) {
703 horiz_retrace = 1;
704 }
705
706 retval = 0;
707 if (horiz_retrace || vert_retrace)
708 retval = 0x01;
709 if (vert_retrace)
710 retval |= 0x08;
711
712 /* reading this port resets the flip-flop to address mode */
713 BX_VGA_THIS s.attribute_ctrl.flip_flop = 0;
714 RETURN(retval);
715 break;
716
717
718 case 0x03c0: /* */
719 if (BX_VGA_THIS s.attribute_ctrl.flip_flop == 0) {
720 //BX_INFO(("io read: 0x3c0: flip_flop = 0"));
721 retval =
722 (BX_VGA_THIS s.attribute_ctrl.video_enabled << 5) |
723 BX_VGA_THIS s.attribute_ctrl.address;
724 RETURN(retval);
725 }
726 else {
727 BX_ERROR(("io read: 0x3c0: flip_flop != 0"));
728 return(0);
729 }
730 break;
731
732 case 0x03c1: /* */
733 switch (BX_VGA_THIS s.attribute_ctrl.address) {
734 case 0x00: case 0x01: case 0x02: case 0x03:
735 case 0x04: case 0x05: case 0x06: case 0x07:
736 case 0x08: case 0x09: case 0x0a: case 0x0b:
737 case 0x0c: case 0x0d: case 0x0e: case 0x0f:
738 retval = BX_VGA_THIS s.attribute_ctrl.palette_reg[BX_VGA_THIS s.attribute_ctrl.address];
739 RETURN(retval);
740 break;
741 case 0x10: /* mode control register */
742 retval =
743 (BX_VGA_THIS s.attribute_ctrl.mode_ctrl.graphics_alpha << 0) |
744 (BX_VGA_THIS s.attribute_ctrl.mode_ctrl.display_type << 1) |
745 (BX_VGA_THIS s.attribute_ctrl.mode_ctrl.enable_line_graphics << 2) |
746 (BX_VGA_THIS s.attribute_ctrl.mode_ctrl.blink_intensity << 3) |
747 (BX_VGA_THIS s.attribute_ctrl.mode_ctrl.pixel_panning_compat << 5) |
748 (BX_VGA_THIS s.attribute_ctrl.mode_ctrl.pixel_clock_select << 6) |
749 (BX_VGA_THIS s.attribute_ctrl.mode_ctrl.internal_palette_size << 7);
750 RETURN(retval);
751 break;
752 case 0x11: /* overscan color register */
753 RETURN(BX_VGA_THIS s.attribute_ctrl.overscan_color);
754 break;
755 case 0x12: /* color plane enable */
756 RETURN(BX_VGA_THIS s.attribute_ctrl.color_plane_enable);
757 break;
758 case 0x13: /* horizontal PEL panning register */
759 RETURN(BX_VGA_THIS s.attribute_ctrl.horiz_pel_panning);
760 break;
761 case 0x14: /* color select register */
762 RETURN(BX_VGA_THIS s.attribute_ctrl.color_select);
763 break;
764 default:
765 BX_INFO(("io read: 0x3c1: unknown register 0x%02x",
766 (unsigned) BX_VGA_THIS s.attribute_ctrl.address));
767 RETURN(0);
768 }
769 break;
770
771 case 0x03c2: /* Input Status 0 */
772 BX_DEBUG(("io read 0x3c2: input status #0: ignoring"));
773 RETURN(0);
774 break;
775
776 case 0x03c3: /* VGA Enable Register */
777 RETURN(BX_VGA_THIS s.vga_enabled);
778 break;
779
780 case 0x03c4: /* Sequencer Index Register */
781 RETURN(BX_VGA_THIS s.sequencer.index);
782 break;
783
784 case 0x03c5: /* Sequencer Registers 00..04 */
785 switch (BX_VGA_THIS s.sequencer.index) {
786 case 0: /* sequencer: reset */
787 BX_DEBUG(("io read 0x3c5: sequencer reset"));
788 RETURN(BX_VGA_THIS s.sequencer.reset1 | (BX_VGA_THIS s.sequencer.reset2<<1));
789 break;
790 case 1: /* sequencer: clocking mode */
791 BX_DEBUG(("io read 0x3c5: sequencer clocking mode"));
792 RETURN(BX_VGA_THIS s.sequencer.reg1);
793 break;
794 case 2: /* sequencer: map mask register */
795 RETURN(BX_VGA_THIS s.sequencer.map_mask);
796 break;
797 case 3: /* sequencer: character map select register */
798 RETURN(BX_VGA_THIS s.sequencer.char_map_select);
799 break;
800 case 4: /* sequencer: memory mode register */
801 retval =
802 (BX_VGA_THIS s.sequencer.extended_mem << 1) |
803 (BX_VGA_THIS s.sequencer.odd_even << 2) |
804 (BX_VGA_THIS s.sequencer.chain_four << 3);
805 RETURN(retval);
806 break;
807
808 default:
809 BX_DEBUG(("io read 0x3c5: index %u unhandled",
810 (unsigned) BX_VGA_THIS s.sequencer.index));
811 RETURN(0);
812 }
813 break;
814
815 case 0x03c6: /* PEL mask ??? */
816 RETURN(BX_VGA_THIS s.pel.mask);
817 break;
818
819 case 0x03c7: /* DAC state, read = 11b, write = 00b */
820 RETURN(BX_VGA_THIS s.pel.dac_state);
821 break;
822
823 case 0x03c8: /* PEL address write mode */
824 RETURN(BX_VGA_THIS s.pel.write_data_register);
825 break;
826
827 case 0x03c9: /* PEL Data Register, colors 00..FF */
828 if (BX_VGA_THIS s.pel.dac_state == 0x03) {
829 switch (BX_VGA_THIS s.pel.read_data_cycle) {
830 case 0:
831 retval = BX_VGA_THIS s.pel.data[BX_VGA_THIS s.pel.read_data_register].red;
832 break;
833 case 1:
834 retval = BX_VGA_THIS s.pel.data[BX_VGA_THIS s.pel.read_data_register].green;
835 break;
836 case 2:
837 retval = BX_VGA_THIS s.pel.data[BX_VGA_THIS s.pel.read_data_register].blue;
838 break;
839 default:
840 retval = 0; // keep compiler happy
841 }
842 BX_VGA_THIS s.pel.read_data_cycle++;
843 if (BX_VGA_THIS s.pel.read_data_cycle >= 3) {
844 BX_VGA_THIS s.pel.read_data_cycle = 0;
845 BX_VGA_THIS s.pel.read_data_register++;
846 }
847 }
848 else {
849 retval = 0x3f;
850 }
851 RETURN(retval);
852 break;
853
854 case 0x03cc: /* Miscellaneous Output / Graphics 1 Position ??? */
855 retval =
856 ((BX_VGA_THIS s.misc_output.color_emulation & 0x01) << 0) |
857 ((BX_VGA_THIS s.misc_output.enable_ram & 0x01) << 1) |
858 ((BX_VGA_THIS s.misc_output.clock_select & 0x03) << 2) |
859 ((BX_VGA_THIS s.misc_output.select_high_bank & 0x01) << 5) |
860 ((BX_VGA_THIS s.misc_output.horiz_sync_pol & 0x01) << 6) |
861 ((BX_VGA_THIS s.misc_output.vert_sync_pol & 0x01) << 7);
862 RETURN(retval);
863 break;
864
865 case 0x03ce: /* Graphics Controller Index Register */
866 RETURN(BX_VGA_THIS s.graphics_ctrl.index);
867 break;
868
869 case 0x03cd: /* ??? */
870 BX_DEBUG(("io read from 03cd"));
871 RETURN(0x00);
872 break;
873
874 case 0x03cf: /* Graphics Controller Registers 00..08 */
875 switch (BX_VGA_THIS s.graphics_ctrl.index) {
876 case 0: /* Set/Reset */
877 RETURN(BX_VGA_THIS s.graphics_ctrl.set_reset);
878 break;
879 case 1: /* Enable Set/Reset */
880 RETURN(BX_VGA_THIS s.graphics_ctrl.enable_set_reset);
881 break;
882 case 2: /* Color Compare */
883 RETURN(BX_VGA_THIS s.graphics_ctrl.color_compare);
884 break;
885 case 3: /* Data Rotate */
886 retval =
887 ((BX_VGA_THIS s.graphics_ctrl.raster_op & 0x03) << 3) |
888 ((BX_VGA_THIS s.graphics_ctrl.data_rotate & 0x07) << 0);
889 RETURN(retval);
890 break;
891 case 4: /* Read Map Select */
892 RETURN(BX_VGA_THIS s.graphics_ctrl.read_map_select);
893 break;
894 case 5: /* Mode */
895 retval =
896 ((BX_VGA_THIS s.graphics_ctrl.shift_reg & 0x03) << 5) |
897 ((BX_VGA_THIS s.graphics_ctrl.odd_even & 0x01) << 4) |
898 ((BX_VGA_THIS s.graphics_ctrl.read_mode & 0x01) << 3) |
899 ((BX_VGA_THIS s.graphics_ctrl.write_mode & 0x03) << 0);
900
901 if (BX_VGA_THIS s.graphics_ctrl.odd_even ||
902 BX_VGA_THIS s.graphics_ctrl.shift_reg)
903 BX_DEBUG(("io read 0x3cf: reg 05 = 0x%02x", (unsigned) retval));
904 RETURN(retval);
905 break;
906 case 6: /* Miscellaneous */
907 retval =
908 ((BX_VGA_THIS s.graphics_ctrl.memory_mapping & 0x03) << 2) |
909 ((BX_VGA_THIS s.graphics_ctrl.odd_even & 0x01) << 1) |
910 ((BX_VGA_THIS s.graphics_ctrl.graphics_alpha & 0x01) << 0);
911 RETURN(retval);
912 break;
913 case 7: /* Color Don't Care */
914 RETURN(BX_VGA_THIS s.graphics_ctrl.color_dont_care);
915 break;
916 case 8: /* Bit Mask */
917 RETURN(BX_VGA_THIS s.graphics_ctrl.bitmask);
918 break;
919 default:
920 /* ??? */
921 BX_DEBUG(("io read: 0x3cf: index %u unhandled",
922 (unsigned) BX_VGA_THIS s.graphics_ctrl.index));
923 RETURN(0);
924 }
925 break;
926
927 case 0x03d4: /* CRTC Index Register (color emulation modes) */
928 RETURN(BX_VGA_THIS s.CRTC.address);
929 break;
930
931 case 0x03b5: /* CRTC Registers (monochrome emulation modes) */
932 case 0x03d5: /* CRTC Registers (color emulation modes) */
933 if (BX_VGA_THIS s.CRTC.address > 0x18) {
934 BX_DEBUG(("io read: invalid CRTC register 0x%02x",
935 (unsigned) BX_VGA_THIS s.CRTC.address));
936 RETURN(0);
937 }
938 RETURN(BX_VGA_THIS s.CRTC.reg[BX_VGA_THIS s.CRTC.address]);
939 break;
940
941 case 0x03b4: /* CRTC Index Register (monochrome emulation modes) */
942 case 0x03cb: /* not sure but OpenBSD reads it a lot */
943 default:
944 BX_INFO(("io read from vga port 0x%04x", (unsigned) address));
945 RETURN(0); /* keep compiler happy */
946 }
947
948 #if defined(VGA_TRACE_FEATURE)
949 read_return:
950 if (io_len == 1) {
951 BX_DEBUG(("8-bit read from 0x%04x = 0x%02x", (unsigned) address, ret));
952 } else {
953 BX_DEBUG(("16-bit read from 0x%04x = 0x%04x", (unsigned) address, ret));
954 }
955 return ret;
956 #endif
957 }
958 #if defined(VGA_TRACE_FEATURE)
959 #undef RETURN
960 #endif
961
962 // static IO port write callback handler
963 // redirects to non-static class handler to avoid virtual functions
964
965 void bx_vga_c::write_handler(void *this_ptr, Bit32u address, Bit32u value, unsigned io_len)
966 {
967 #if BX_USE_VGA_SMF == 0
968 bx_vga_c *class_ptr = (bx_vga_c *) this_ptr;
969 class_ptr->write(address, value, io_len, 0);
970 #else
971 UNUSED(this_ptr);
972 theVga->write(address, value, io_len, 0);
973 #endif
974 }
975
976 #if BX_USE_VGA_SMF
977 void bx_vga_c::write_handler_no_log(void *this_ptr, Bit32u address, Bit32u value, unsigned io_len)
978 {
979 UNUSED(this_ptr);
980 theVga->write(address, value, io_len, 1);
981 }
982 #endif
983
984 void bx_vga_c::write(Bit32u address, Bit32u value, unsigned io_len, bx_bool no_log)
985 {
986 Bit8u charmap1, charmap2, prev_memory_mapping;
987 bx_bool prev_video_enabled, prev_line_graphics, prev_int_pal_size;
988 bx_bool prev_graphics_alpha, prev_chain_odd_even;
989 bx_bool needs_update = 0, charmap_update = 0;
990
991 #if defined(VGA_TRACE_FEATURE)
992 if (!no_log)
993 switch (io_len) {
994 case 1:
995 BX_DEBUG(("8-bit write to %04x = %02x", (unsigned)address, (unsigned)value));
996 break;
997 case 2:
998 BX_DEBUG(("16-bit write to %04x = %04x", (unsigned)address, (unsigned)value));
999 break;
1000 default:
1001 BX_PANIC(("Weird VGA write size"));
1002 }
1003 #else
1004 if (io_len == 1) {
1005 BX_DEBUG(("io write to 0x%04x = 0x%02x", (unsigned) address,
1006 (unsigned) value));
1007 }
1008 #endif
1009
1010 if (io_len == 2) {
1011 #if BX_USE_VGA_SMF
1012 bx_vga_c::write_handler_no_log(0, address, value & 0xff, 1);
1013 bx_vga_c::write_handler_no_log(0, address+1, (value >> 8) & 0xff, 1);
1014 #else
1015 bx_vga_c::write(address, value & 0xff, 1, 1);
1016 bx_vga_c::write(address+1, (value >> 8) & 0xff, 1, 1);
1017 #endif
1018 return;
1019 }
1020
1021 #ifdef __OS2__
1022 if (bx_options.videomode == BX_VIDEO_DIRECT)
1023 {
1024 _outp(address, value);
1025 return;
1026 }
1027 #endif
1028
1029 if ((address >= 0x03b0) && (address <= 0x03bf) &&
1030 (BX_VGA_THIS s.misc_output.color_emulation))
1031 return;
1032 if ((address >= 0x03d0) && (address <= 0x03df) &&
1033 (BX_VGA_THIS s.misc_output.color_emulation==0))
1034 return;
1035
1036 switch (address) {
1037 case 0x03ba: /* Feature Control (monochrome emulation modes) */
1038 #if !defined(VGA_TRACE_FEATURE)
1039 BX_DEBUG(("io write 3ba: feature control: ignoring"));
1040 #endif
1041 break;
1042
1043 case 0x03c0: /* Attribute Controller */
1044 if (BX_VGA_THIS s.attribute_ctrl.flip_flop == 0) { /* address mode */
1045 prev_video_enabled = BX_VGA_THIS s.attribute_ctrl.video_enabled;
1046 BX_VGA_THIS s.attribute_ctrl.video_enabled = (value >> 5) & 0x01;
1047 #if !defined(VGA_TRACE_FEATURE)
1048 BX_DEBUG(("io write 3c0: video_enabled = %u",
1049 (unsigned) BX_VGA_THIS s.attribute_ctrl.video_enabled));
1050 #endif
1051 if (BX_VGA_THIS s.attribute_ctrl.video_enabled == 0)
1052 bx_gui->clear_screen();
1053 else if (!prev_video_enabled) {
1054 #if !defined(VGA_TRACE_FEATURE)
1055 BX_DEBUG(("found enable transition"));
1056 #endif
1057 needs_update = 1;
1058 }
1059 value &= 0x1f; /* address = bits 0..4 */
1060 BX_VGA_THIS s.attribute_ctrl.address = value;
1061 switch (value) {
1062 case 0x00: case 0x01: case 0x02: case 0x03:
1063 case 0x04: case 0x05: case 0x06: case 0x07:
1064 case 0x08: case 0x09: case 0x0a: case 0x0b:
1065 case 0x0c: case 0x0d: case 0x0e: case 0x0f:
1066 break;
1067
1068 default:
1069 BX_DEBUG(("io write 0x3c0: address mode reg=0x%02x",
1070 (unsigned) value));
1071 }
1072 }
1073 else { /* data-write mode */
1074 switch (BX_VGA_THIS s.attribute_ctrl.address) {
1075 case 0x00: case 0x01: case 0x02: case 0x03:
1076 case 0x04: case 0x05: case 0x06: case 0x07:
1077 case 0x08: case 0x09: case 0x0a: case 0x0b:
1078 case 0x0c: case 0x0d: case 0x0e: case 0x0f:
1079 if (value != BX_VGA_THIS s.attribute_ctrl.palette_reg[BX_VGA_THIS s.attribute_ctrl.address]) {
1080 BX_VGA_THIS s.attribute_ctrl.palette_reg[BX_VGA_THIS s.attribute_ctrl.address] =
1081 value;
1082 needs_update = 1;
1083 }
1084 break;
1085 case 0x10: // mode control register
1086 prev_line_graphics = BX_VGA_THIS s.attribute_ctrl.mode_ctrl.enable_line_graphics;
1087 prev_int_pal_size = BX_VGA_THIS s.attribute_ctrl.mode_ctrl.internal_palette_size;
1088 BX_VGA_THIS s.attribute_ctrl.mode_ctrl.graphics_alpha =
1089 (value >> 0) & 0x01;
1090 BX_VGA_THIS s.attribute_ctrl.mode_ctrl.display_type =
1091 (value >> 1) & 0x01;
1092 BX_VGA_THIS s.attribute_ctrl.mode_ctrl.enable_line_graphics =
1093 (value >> 2) & 0x01;
1094 BX_VGA_THIS s.attribute_ctrl.mode_ctrl.blink_intensity =
1095 (value >> 3) & 0x01;
1096 BX_VGA_THIS s.attribute_ctrl.mode_ctrl.pixel_panning_compat =
1097 (value >> 5) & 0x01;
1098 BX_VGA_THIS s.attribute_ctrl.mode_ctrl.pixel_clock_select =
1099 (value >> 6) & 0x01;
1100 BX_VGA_THIS s.attribute_ctrl.mode_ctrl.internal_palette_size =
1101 (value >> 7) & 0x01;
1102 if (((value >> 2) & 0x01) != prev_line_graphics) {
1103 charmap_update = 1;
1104 }
1105 if (((value >> 7) & 0x01) != prev_int_pal_size) {
1106 needs_update = 1;
1107 }
1108 #if !defined(VGA_TRACE_FEATURE)
1109 BX_DEBUG(("io write 0x3c0: mode control: 0x%02x",
1110 (unsigned) value));
1111 #endif
1112 break;
1113 case 0x11: // Overscan Color Register
1114 BX_VGA_THIS s.attribute_ctrl.overscan_color = (value & 0x3f);
1115 #if !defined(VGA_TRACE_FEATURE)
1116 BX_DEBUG(("io write 0x3c0: overscan color = 0x%02x",
1117 (unsigned) value));
1118 #endif
1119 break;
1120 case 0x12: // Color Plane Enable Register
1121 BX_VGA_THIS s.attribute_ctrl.color_plane_enable = (value & 0x0f);
1122 needs_update = 1;
1123 #if !defined(VGA_TRACE_FEATURE)
1124 BX_DEBUG(("io write 0x3c0: color plane enable = 0x%02x",
1125 (unsigned) value));
1126 #endif
1127 break;
1128 case 0x13: // Horizontal Pixel Panning Register
1129 BX_VGA_THIS s.attribute_ctrl.horiz_pel_panning = (value & 0x0f);
1130 needs_update = 1;
1131 #if !defined(VGA_TRACE_FEATURE)
1132 BX_DEBUG(("io write 0x3c0: horiz pel panning = 0x%02x",
1133 (unsigned) value));
1134 #endif
1135 break;
1136 case 0x14: // Color Select Register
1137 BX_VGA_THIS s.attribute_ctrl.color_select = (value & 0x0f);
1138 needs_update = 1;
1139 #if !defined(VGA_TRACE_FEATURE)
1140 BX_DEBUG(("io write 0x3c0: color select = 0x%02x",
1141 (unsigned) BX_VGA_THIS s.attribute_ctrl.color_select));
1142 #endif
1143 break;
1144 default:
1145 BX_DEBUG(("io write 0x3c0: data-write mode 0x%02x",
1146 (unsigned) BX_VGA_THIS s.attribute_ctrl.address));
1147 }
1148 }
1149 BX_VGA_THIS s.attribute_ctrl.flip_flop = !BX_VGA_THIS s.attribute_ctrl.flip_flop;
1150 break;
1151
1152 case 0x03c2: // Miscellaneous Output Register
1153 BX_VGA_THIS s.misc_output.color_emulation = (value >> 0) & 0x01;
1154 BX_VGA_THIS s.misc_output.enable_ram = (value >> 1) & 0x01;
1155 BX_VGA_THIS s.misc_output.clock_select = (value >> 2) & 0x03;
1156 BX_VGA_THIS s.misc_output.select_high_bank = (value >> 5) & 0x01;
1157 BX_VGA_THIS s.misc_output.horiz_sync_pol = (value >> 6) & 0x01;
1158 BX_VGA_THIS s.misc_output.vert_sync_pol = (value >> 7) & 0x01;
1159 #if !defined(VGA_TRACE_FEATURE)
1160 BX_DEBUG(("io write 3c2:"));
1161 BX_DEBUG((" color_emulation (attempted) = %u",
1162 (value >> 0) & 0x01));
1163 BX_DEBUG((" enable_ram = %u",
1164 (unsigned) BX_VGA_THIS s.misc_output.enable_ram));
1165 BX_DEBUG((" clock_select = %u",
1166 (unsigned) BX_VGA_THIS s.misc_output.clock_select));
1167 BX_DEBUG((" select_high_bank = %u",
1168 (unsigned) BX_VGA_THIS s.misc_output.select_high_bank));
1169 BX_DEBUG((" horiz_sync_pol = %u",
1170 (unsigned) BX_VGA_THIS s.misc_output.horiz_sync_pol));
1171 BX_DEBUG((" vert_sync_pol = %u",
1172 (unsigned) BX_VGA_THIS s.misc_output.vert_sync_pol));
1173 #endif
1174 break;
1175
1176 case 0x03c3: // VGA enable
1177 // bit0: enables VGA display if set
1178 BX_VGA_THIS s.vga_enabled = value & 0x01;
1179 #if !defined(VGA_TRACE_FEATURE)
1180 BX_DEBUG(("io write 0x03c3: VGA enable = %u", BX_VGA_THIS s.vga_enabled));
1181 #endif
1182 break;
1183
1184 case 0x03c4: /* Sequencer Index Register */
1185 if (value > 4) {
1186 BX_DEBUG(("io write 3c4: value > 4"));
1187 }
1188 BX_VGA_THIS s.sequencer.index = value;
1189 break;
1190
1191 case 0x03c5: /* Sequencer Registers 00..04 */
1192 switch (BX_VGA_THIS s.sequencer.index) {
1193 case 0: /* sequencer: reset */
1194 #if !defined(VGA_TRACE_FEATURE)
1195 BX_DEBUG(("write 0x3c5: sequencer reset: value=0x%02x",
1196 (unsigned) value));
1197 #endif
1198 if (BX_VGA_THIS s.sequencer.reset1 && ((value & 0x01) == 0)) {
1199 BX_VGA_THIS s.sequencer.char_map_select = 0;
1200 BX_VGA_THIS s.charmap_address = 0;
1201 charmap_update = 1;
1202 }
1203 BX_VGA_THIS s.sequencer.reset1 = (value >> 0) & 0x01;
1204 BX_VGA_THIS s.sequencer.reset2 = (value >> 1) & 0x01;
1205 break;
1206 case 1: /* sequencer: clocking mode */
1207 #if !defined(VGA_TRACE_FEATURE)
1208 BX_DEBUG(("io write 0x3c5=0x%02x: clocking mode reg: ignoring",
1209 (unsigned) value));
1210 #endif
1211 if ((value & 0x20) > 0) {
1212 bx_gui->clear_screen();
1213 } else if ((BX_VGA_THIS s.sequencer.reg1 & 0x20) > 0) {
1214 needs_update = 1;
1215 }
1216 BX_VGA_THIS s.sequencer.reg1 = value & 0x3d;
1217 BX_VGA_THIS s.x_dotclockdiv2 = ((value & 0x08) > 0);
1218 break;
1219 case 2: /* sequencer: map mask register */
1220 BX_VGA_THIS s.sequencer.map_mask = (value & 0x0f);
1221 break;
1222 case 3: /* sequencer: character map select register */
1223 BX_VGA_THIS s.sequencer.char_map_select = value & 0x3f;
1224 charmap1 = value & 0x13;
1225 if (charmap1 > 3) charmap1 = (charmap1 & 3) + 4;
1226 charmap2 = (value & 0x2C) >> 2;
1227 if (charmap2 > 3) charmap2 = (charmap2 & 3) + 4;
1228 if (BX_VGA_THIS s.CRTC.reg[0x09] > 0) {
1229 BX_VGA_THIS s.charmap_address = charmap_offset[charmap1];
1230 charmap_update = 1;
1231 }
1232 if (charmap2 != charmap1)
1233 BX_INFO(("char map select: map #2 in block #%d unused", charmap2));
1234 break;
1235 case 4: /* sequencer: memory mode register */
1236 BX_VGA_THIS s.sequencer.extended_mem = (value >> 1) & 0x01;
1237 BX_VGA_THIS s.sequencer.odd_even = (value >> 2) & 0x01;
1238 BX_VGA_THIS s.sequencer.chain_four = (value >> 3) & 0x01;
1239
1240 #if !defined(VGA_TRACE_FEATURE)
1241 BX_DEBUG(("io write 0x3c5: memory mode:"));
1242 BX_DEBUG((" extended_mem = %u",
1243 (unsigned) BX_VGA_THIS s.sequencer.extended_mem));
1244 BX_DEBUG((" odd_even = %u",
1245 (unsigned) BX_VGA_THIS s.sequencer.odd_even));
1246 BX_DEBUG((" chain_four = %u",
1247 (unsigned) BX_VGA_THIS s.sequencer.chain_four));
1248 #endif
1249 break;
1250 default:
1251 BX_DEBUG(("io write 0x3c5: index 0x%02x unhandled",
1252 (unsigned) BX_VGA_THIS s.sequencer.index));
1253 }
1254 break;
1255
1256 case 0x03c6: /* PEL mask */
1257 BX_VGA_THIS s.pel.mask = value;
1258 if (BX_VGA_THIS s.pel.mask != 0xff)
1259 BX_DEBUG(("io write 0x3c6: PEL mask=0x%02x != 0xFF", value));
1260 // BX_VGA_THIS s.pel.mask should be and'd with final value before
1261 // indexing into color register BX_VGA_THIS s.pel.data[]
1262 break;
1263
1264 case 0x03c7: // PEL address, read mode
1265 BX_VGA_THIS s.pel.read_data_register = value;
1266 BX_VGA_THIS s.pel.read_data_cycle = 0;
1267 BX_VGA_THIS s.pel.dac_state = 0x03;
1268 break;
1269
1270 case 0x03c8: /* PEL address write mode */
1271 BX_VGA_THIS s.pel.write_data_register = value;
1272 BX_VGA_THIS s.pel.write_data_cycle = 0;
1273 BX_VGA_THIS s.pel.dac_state = 0x00;
1274 break;
1275
1276 case 0x03c9: /* PEL Data Register, colors 00..FF */
1277 switch (BX_VGA_THIS s.pel.write_data_cycle) {
1278 case 0:
1279 BX_VGA_THIS s.pel.data[BX_VGA_THIS s.pel.write_data_register].red = value;
1280 break;
1281 case 1:
1282 BX_VGA_THIS s.pel.data[BX_VGA_THIS s.pel.write_data_register].green = value;
1283 break;
1284 case 2:
1285 BX_VGA_THIS s.pel.data[BX_VGA_THIS s.pel.write_data_register].blue = value;
1286
1287 #if BX_SUPPORT_VBE
1288 if (BX_VGA_THIS vbe.dac_8bit) {
1289 needs_update |= bx_gui->palette_change(BX_VGA_THIS s.pel.write_data_register,
1290 BX_VGA_THIS s.pel.data[BX_VGA_THIS s.pel.write_data_register].red,
1291 BX_VGA_THIS s.pel.data[BX_VGA_THIS s.pel.write_data_register].green,
1292 BX_VGA_THIS s.pel.data[BX_VGA_THIS s.pel.write_data_register].blue);
1293 } else {
1294 #endif
1295 needs_update |= bx_gui->palette_change(BX_VGA_THIS s.pel.write_data_register,
1296 BX_VGA_THIS s.pel.data[BX_VGA_THIS s.pel.write_data_register].red<<2,
1297 BX_VGA_THIS s.pel.data[BX_VGA_THIS s.pel.write_data_register].green<<2,
1298 BX_VGA_THIS s.pel.data[BX_VGA_THIS s.pel.write_data_register].blue<<2);
1299 #if BX_SUPPORT_VBE
1300 }
1301 #endif
1302 break;
1303 }
1304
1305 BX_VGA_THIS s.pel.write_data_cycle++;
1306 if (BX_VGA_THIS s.pel.write_data_cycle >= 3) {
1307 //BX_INFO(("BX_VGA_THIS s.pel.data[%u] {r=%u, g=%u, b=%u}",
1308 // (unsigned) BX_VGA_THIS s.pel.write_data_register,
1309 // (unsigned) BX_VGA_THIS s.pel.data[BX_VGA_THIS s.pel.write_data_register].red,
1310 // (unsigned) BX_VGA_THIS s.pel.data[BX_VGA_THIS s.pel.write_data_register].green,
1311 // (unsigned) BX_VGA_THIS s.pel.data[BX_VGA_THIS s.pel.write_data_register].blue);
1312 BX_VGA_THIS s.pel.write_data_cycle = 0;
1313 BX_VGA_THIS s.pel.write_data_register++;
1314 }
1315 break;
1316
1317 case 0x03ca: /* Graphics 2 Position (EGA) */
1318 // ignore, EGA only???
1319 break;
1320
1321 case 0x03cc: /* Graphics 1 Position (EGA) */
1322 // ignore, EGA only???
1323 break;
1324
1325 case 0x03cd: /* ??? */
1326 BX_DEBUG(("io write to 0x3cd = 0x%02x", (unsigned) value));
1327 break;
1328
1329 case 0x03ce: /* Graphics Controller Index Register */
1330 if (value > 0x08) /* ??? */
1331 BX_DEBUG(("io write: 0x3ce: value > 8"));
1332 BX_VGA_THIS s.graphics_ctrl.index = value;
1333 break;
1334
1335 case 0x03cf: /* Graphics Controller Registers 00..08 */
1336 switch (BX_VGA_THIS s.graphics_ctrl.index) {
1337 case 0: /* Set/Reset */
1338 BX_VGA_THIS s.graphics_ctrl.set_reset = value & 0x0f;
1339 break;
1340 case 1: /* Enable Set/Reset */
1341 BX_VGA_THIS s.graphics_ctrl.enable_set_reset = value & 0x0f;
1342 break;
1343 case 2: /* Color Compare */
1344 BX_VGA_THIS s.graphics_ctrl.color_compare = value & 0x0f;
1345 break;
1346 case 3: /* Data Rotate */
1347 BX_VGA_THIS s.graphics_ctrl.data_rotate = value & 0x07;
1348 BX_VGA_THIS s.graphics_ctrl.raster_op = (value >> 3) & 0x03;
1349 break;
1350 case 4: /* Read Map Select */
1351 BX_VGA_THIS s.graphics_ctrl.read_map_select = value & 0x03;
1352 #if !defined(VGA_TRACE_FEATURE)
1353 BX_DEBUG(("io write to 0x3cf = 0x%02x (RMS)", (unsigned) value));
1354 #endif
1355 break;
1356 case 5: /* Mode */
1357 BX_VGA_THIS s.graphics_ctrl.write_mode = value & 0x03;
1358 BX_VGA_THIS s.graphics_ctrl.read_mode = (value >> 3) & 0x01;
1359 BX_VGA_THIS s.graphics_ctrl.odd_even = (value >> 4) & 0x01;
1360 BX_VGA_THIS s.graphics_ctrl.shift_reg = (value >> 5) & 0x03;
1361
1362 if (BX_VGA_THIS s.graphics_ctrl.odd_even)
1363 BX_DEBUG(("io write: 0x3cf: mode reg: value = 0x%02x",
1364 (unsigned) value));
1365 if (BX_VGA_THIS s.graphics_ctrl.shift_reg)
1366 BX_DEBUG(("io write: 0x3cf: mode reg: value = 0x%02x",
1367 (unsigned) value));
1368 break;
1369 case 6: /* Miscellaneous */
1370 prev_graphics_alpha = BX_VGA_THIS s.graphics_ctrl.graphics_alpha;
1371 prev_chain_odd_even = BX_VGA_THIS s.graphics_ctrl.chain_odd_even;
1372 prev_memory_mapping = BX_VGA_THIS s.graphics_ctrl.memory_mapping;
1373
1374 BX_VGA_THIS s.graphics_ctrl.graphics_alpha = value & 0x01;
1375 BX_VGA_THIS s.graphics_ctrl.chain_odd_even = (value >> 1) & 0x01;
1376 BX_VGA_THIS s.graphics_ctrl.memory_mapping = (value >> 2) & 0x03;
1377 #if !defined(VGA_TRACE_FEATURE)
1378 BX_DEBUG(("memory_mapping set to %u",
1379 (unsigned) BX_VGA_THIS s.graphics_ctrl.memory_mapping));
1380 BX_DEBUG(("graphics mode set to %u",
1381 (unsigned) BX_VGA_THIS s.graphics_ctrl.graphics_alpha));
1382 BX_DEBUG(("odd_even mode set to %u",
1383 (unsigned) BX_VGA_THIS s.graphics_ctrl.odd_even));
1384 BX_DEBUG(("io write: 0x3cf: misc reg: value = 0x%02x",
1385 (unsigned) value));
1386 #endif
1387 if (prev_memory_mapping != BX_VGA_THIS s.graphics_ctrl.memory_mapping)
1388 needs_update = 1;
1389 if (prev_graphics_alpha != BX_VGA_THIS s.graphics_ctrl.graphics_alpha) {
1390 needs_update = 1;
1391 old_iHeight = 0;
1392 }
1393 break;
1394 case 7: /* Color Don't Care */
1395 BX_VGA_THIS s.graphics_ctrl.color_dont_care = value & 0x0f;
1396 break;
1397 case 8: /* Bit Mask */
1398 BX_VGA_THIS s.graphics_ctrl.bitmask = value;
1399 break;
1400 default:
1401 /* ??? */
1402 BX_DEBUG(("io write: 0x3cf: index %u unhandled",
1403 (unsigned) BX_VGA_THIS s.graphics_ctrl.index));
1404 }
1405 break;
1406
1407 case 0x03b4: /* CRTC Index Register (monochrome emulation modes) */
1408 case 0x03d4: /* CRTC Index Register (color emulation modes) */
1409 BX_VGA_THIS s.CRTC.address = value & 0x7f;
1410 if (BX_VGA_THIS s.CRTC.address > 0x18)
1411 BX_DEBUG(("write: invalid CRTC register 0x%02x selected",
1412 (unsigned) BX_VGA_THIS s.CRTC.address));
1413 break;
1414
1415 case 0x03b5: /* CRTC Registers (monochrome emulation modes) */
1416 case 0x03d5: /* CRTC Registers (color emulation modes) */
1417 if (BX_VGA_THIS s.CRTC.address > 0x18) {
1418 BX_DEBUG(("write: invalid CRTC register 0x%02x ignored",
1419 (unsigned) BX_VGA_THIS s.CRTC.address));
1420 return;
1421 }
1422 if (BX_VGA_THIS s.CRTC.write_protect && (BX_VGA_THIS s.CRTC.address < 0x08)) {
1423 if (BX_VGA_THIS s.CRTC.address == 0x07) {
1424 BX_VGA_THIS s.CRTC.reg[BX_VGA_THIS s.CRTC.address] &= ~0x10;
1425 BX_VGA_THIS s.CRTC.reg[BX_VGA_THIS s.CRTC.address] |= (value & 0x10);
1426 BX_VGA_THIS s.line_compare &= 0x2ff;
1427 if (BX_VGA_THIS s.CRTC.reg[0x07] & 0x10) BX_VGA_THIS s.line_compare |= 0x100;
1428 needs_update = 1;
1429 break;
1430 } else {
1431 return;
1432 }
1433 }
1434 if (value != BX_VGA_THIS s.CRTC.reg[BX_VGA_THIS s.CRTC.address]) {
1435 BX_VGA_THIS s.CRTC.reg[BX_VGA_THIS s.CRTC.address] = value;
1436 switch (BX_VGA_THIS s.CRTC.address) {
1437 case 0x07:
1438 BX_VGA_THIS s.vertical_display_end &= 0xff;
1439 if (BX_VGA_THIS s.CRTC.reg[0x07] & 0x02) BX_VGA_THIS s.vertical_display_end |= 0x100;
1440 if (BX_VGA_THIS s.CRTC.reg[0x07] & 0x40) BX_VGA_THIS s.vertical_display_end |= 0x200;
1441 BX_VGA_THIS s.line_compare &= 0x2ff;
1442 if (BX_VGA_THIS s.CRTC.reg[0x07] & 0x10) BX_VGA_THIS s.line_compare |= 0x100;
1443 needs_update = 1;
1444 break;
1445 case 0x08:
1446 // Vertical pel panning change
1447 needs_update = 1;
1448 break;
1449 case 0x09:
1450 BX_VGA_THIS s.y_doublescan = ((value & 0x9f) > 0);
1451 BX_VGA_THIS s.line_compare &= 0x1ff;
1452 if (BX_VGA_THIS s.CRTC.reg[0x09] & 0x40) BX_VGA_THIS s.line_compare |= 0x200;
1453 charmap_update = 1;
1454 needs_update = 1;
1455 break;
1456 case 0x0A:
1457 case 0x0B:
1458 case 0x0E:
1459 case 0x0F:
1460 // Cursor size / location change
1461 BX_VGA_THIS s.vga_mem_updated = 1;
1462 break;
1463 case 0x0C:
1464 case 0x0D:
1465 // Start address change
1466 if (BX_VGA_THIS s.graphics_ctrl.graphics_alpha) {
1467 needs_update = 1;
1468 } else {
1469 BX_VGA_THIS s.vga_mem_updated = 1;
1470 }
1471 break;
1472 case 0x11:
1473 BX_VGA_THIS s.CRTC.write_protect = ((BX_VGA_THIS s.CRTC.reg[0x11] & 0x80) > 0);
1474 break;
1475 case 0x12:
1476 BX_VGA_THIS s.vertical_display_end &= 0x300;
1477 BX_VGA_THIS s.vertical_display_end |= BX_VGA_THIS s.CRTC.reg[0x12];
1478 break;
1479 case 0x13:
1480 case 0x14:
1481 case 0x17:
1482 #if BX_SUPPORT_VBE
1483 if (!BX_VGA_THIS vbe.enabled || (BX_VGA_THIS vbe.bpp == VBE_DISPI_BPP_4))
1484 #endif
1485 {
1486 // Line offset change
1487 BX_VGA_THIS s.line_offset = BX_VGA_THIS s.CRTC.reg[0x13] << 1;
1488 if (BX_VGA_THIS s.CRTC.reg[0x14] & 0x40) BX_VGA_THIS s.line_offset <<= 2;
1489 else if ((BX_VGA_THIS s.CRTC.reg[0x17] & 0x40) == 0) BX_VGA_THIS s.line_offset <<= 1;
1490 needs_update = 1;
1491 }
1492 break;
1493 case 0x18:
1494 BX_VGA_THIS s.line_compare &= 0x300;
1495 BX_VGA_THIS s.line_compare |= BX_VGA_THIS s.CRTC.reg[0x18];
1496 needs_update = 1;
1497 break;
1498 }
1499
1500 }
1501 break;
1502
1503 case 0x03da: /* Feature Control (color emulation modes) */
1504 BX_DEBUG(("io write: 3da: ignoring: feature ctrl & vert sync"));
1505 break;
1506
1507 case 0x03c1: /* */
1508 default:
1509 BX_ERROR(("unsupported io write to port 0x%04x, val=0x%02x",
1510 (unsigned) address, (unsigned) value));
1511 }
1512
1513 if (charmap_update) {
1514 bx_gui->set_text_charmap(
1515 & BX_VGA_THIS s.memory[0x20000 + BX_VGA_THIS s.charmap_address]);
1516 BX_VGA_THIS s.vga_mem_updated = 1;
1517 }
1518 if (needs_update) {
1519 // Mark all video as updated so the changes will go through
1520 BX_VGA_THIS redraw_area(0, 0, old_iWidth, old_iHeight);
1521 }
1522 }
1523
1524 Bit64s bx_vga_c::vga_param_handler(bx_param_c *param, int set, Bit64s val)
1525 {
1526 // handler for runtime parameter 'vga_update_interval'
1527 if (set) {
1528 BX_INFO (("Changing timer interval to %d", (Bit32u)val));
1529 BX_VGA_THIS timer_handler (theVga);
1530 bx_pc_system.activate_timer (BX_VGA_THIS timer_id, (Bit32u)val, 1);
1531 }
1532 return val;
1533 }
1534
1535 void bx_vga_c::trigger_timer(void *this_ptr)
1536 {
1537 timer_handler(this_ptr);
1538 }
1539
1540 void bx_vga_c::timer_handler(void *this_ptr)
1541 {
1542 #if BX_USE_VGA_SMF == 0
1543 bx_vga_c *class_ptr = (bx_vga_c *) this_ptr;
1544 class_ptr->timer();
1545 }
1546
1547 void bx_vga_c::timer(void)
1548 {
1549 #else
1550 UNUSED(this_ptr);
1551 #endif
1552
1553 update();
1554 bx_gui->flush();
1555 }
1556
1557 void bx_vga_c::update(void)
1558 {
1559 unsigned iHeight, iWidth;
1560
1561 /* no screen update necessary */
1562 if ((BX_VGA_THIS s.vga_mem_updated==0) && BX_VGA_THIS s.graphics_ctrl.graphics_alpha)
1563 return;
1564
1565 /* skip screen update when vga/video is disabled or the sequencer is in reset mode */
1566 if (!BX_VGA_THIS s.vga_enabled || !BX_VGA_THIS s.attribute_ctrl.video_enabled
1567 || !BX_VGA_THIS s.sequencer.reset2 || !BX_VGA_THIS s.sequencer.reset1
1568 || (BX_VGA_THIS s.sequencer.reg1 & 0x20))
1569 return;
1570
1571 /* skip screen update if the vertical retrace is in progress
1572 (using 72 Hz vertical frequency) */
1573 if ((bx_pc_system.time_usec() % 13888) < 70)
1574 return;
1575
1576 #if BX_SUPPORT_VBE
1577 if ((BX_VGA_THIS vbe.enabled) && (BX_VGA_THIS vbe.bpp != VBE_DISPI_BPP_4))
1578 {
1579 // specific VBE code display update code
1580 unsigned pitch;
1581 unsigned xc, yc, xti, yti;
1582 unsigned r, c, w, h;
1583 int i;
1584 unsigned long red, green, blue, colour;
1585 Bit8u * vid_ptr, * vid_ptr2;
1586 Bit8u * tile_ptr, * tile_ptr2;
1587 bx_svga_tileinfo_t info;
1588 Bit8u dac_size = BX_VGA_THIS vbe.dac_8bit ? 8 : 6;
1589
1590 iWidth=BX_VGA_THIS vbe.xres;
1591 iHeight=BX_VGA_THIS vbe.yres;
1592 pitch = BX_VGA_THIS s.line_offset;
1593 Bit8u *disp_ptr = &BX_VGA_THIS s.memory[BX_VGA_THIS vbe.virtual_start];
1594
1595 if (bx_gui->graphics_tile_info(&info)) {
1596 if (info.is_indexed) {
1597 switch (BX_VGA_THIS vbe.bpp) {
1598 case 4:
1599 case 15:
1600 case 16:
1601 case 24:
1602 case 32:
1603 BX_ERROR(("current guest pixel format is unsupported on indexed colour host displays"));
1604 break;
1605 case 8:
1606 for (yc=0, yti = 0; yc<iHeight; yc+=Y_TILESIZE, yti++) {
1607 for (xc=0, xti = 0; xc<iWidth; xc+=X_TILESIZE, xti++) {
1608 if (GET_TILE_UPDATED (xti, yti)) {
1609 vid_ptr = disp_ptr + (yc * pitch + xc);
1610 tile_ptr = bx_gui->graphics_tile_get(xc, yc, &w, &h);
1611 for (r=0; r<h; r++) {
1612 vid_ptr2 = vid_ptr;
1613 tile_ptr2 = tile_ptr;
1614 for (c=0; c<w; c++) {
1615 colour = 0;
1616 for (i=0; i<(int)BX_VGA_THIS vbe.bpp; i+=8) {
1617 colour |= *(vid_ptr2++) << i;
1618 }
1619 if (info.is_little_endian) {
1620 for (i=0; i<info.bpp; i+=8) {
1621 *(tile_ptr2++) = (Bit8u)(colour >> i);
1622 }
1623 }
1624 else {
1625 for (i=info.bpp-8; i>-8; i-=8) {
1626 *(tile_ptr2++) = (Bit8u)(colour >> i);
1627 }
1628 }
1629 }
1630 vid_ptr += pitch;
1631 tile_ptr += info.pitch;
1632 }
1633 bx_gui->graphics_tile_update_in_place(xc, yc, w, h);
1634 SET_TILE_UPDATED (xti, yti, 0);
1635 }
1636 }
1637 }
1638 break;
1639 }
1640 }
1641 else {
1642 switch (BX_VGA_THIS vbe.bpp) {
1643 case 4:
1644 BX_ERROR(("cannot draw 4bpp SVGA"));
1645 break;
1646 case 8:
1647 for (yc=0, yti = 0; yc<iHeight; yc+=Y_TILESIZE, yti++) {
1648 for (xc=0, xti = 0; xc<iWidth; xc+=X_TILESIZE, xti++) {
1649 if (GET_TILE_UPDATED (xti, yti)) {
1650 vid_ptr = disp_ptr + (yc * pitch + xc);
1651 tile_ptr = bx_gui->graphics_tile_get(xc, yc, &w, &h);
1652 for (r=0; r<h; r++) {
1653 vid_ptr2 = vid_ptr;
1654 tile_ptr2 = tile_ptr;
1655 for (c=0; c<w; c++) {
1656 colour = *(vid_ptr2++);
1657 colour = MAKE_COLOUR(
1658 BX_VGA_THIS s.pel.data[colour].red, dac_size, info.red_shift, info.red_mask,
1659 BX_VGA_THIS s.pel.data[colour].green, dac_size, info.green_shift, info.green_mask,
1660 BX_VGA_THIS s.pel.data[colour].blue, dac_size, info.blue_shift, info.blue_mask);
1661 if (info.is_little_endian) {
1662 for (i=0; i<info.bpp; i+=8) {
1663 *(tile_ptr2++) = (Bit8u)(colour >> i);
1664 }
1665 }
1666 else {
1667 for (i=info.bpp-8; i>-8; i-=8) {
1668 *(tile_ptr2++) = (Bit8u)(colour >> i);
1669 }
1670 }
1671 }
1672 vid_ptr += pitch;
1673 tile_ptr += info.pitch;
1674 }
1675 bx_gui->graphics_tile_update_in_place(xc, yc, w, h);
1676 SET_TILE_UPDATED (xti, yti, 0);
1677 }
1678 }
1679 }
1680 break;
1681 case 15:
1682 for (yc=0, yti = 0; yc<iHeight; yc+=Y_TILESIZE, yti++) {
1683 for (xc=0, xti = 0; xc<iWidth; xc+=X_TILESIZE, xti++) {
1684 if (GET_TILE_UPDATED (xti, yti)) {
1685 vid_ptr = disp_ptr + (yc * pitch + (xc<<1));
1686 tile_ptr = bx_gui->graphics_tile_get(xc, yc, &w, &h);
1687 for (r=0; r<h; r++) {
1688 vid_ptr2 = vid_ptr;
1689 tile_ptr2 = tile_ptr;
1690 for (c=0; c<w; c++) {
1691 colour = *(vid_ptr2++);
1692 colour |= *(vid_ptr2++) << 8;
1693 colour = MAKE_COLOUR(
1694 colour & 0x001f, 5, info.blue_shift, info.blue_mask,
1695 colour & 0x03e0, 10, info.green_shift, info.green_mask,
1696 colour & 0x7c00, 15, info.red_shift, info.red_mask);
1697 if (info.is_little_endian) {
1698 for (i=0; i<info.bpp; i+=8) {
1699 *(tile_ptr2++) = (Bit8u)(colour >> i);
1700 }
1701 }
1702 else {
1703 for (i=info.bpp-8; i>-8; i-=8) {
1704 *(tile_ptr2++) = (Bit8u)(colour >> i);
1705 }
1706 }
1707 }
1708 vid_ptr += pitch;
1709 tile_ptr += info.pitch;
1710 }
1711 bx_gui->graphics_tile_update_in_place(xc, yc, w, h);
1712 SET_TILE_UPDATED (xti, yti, 0);
1713 }
1714 }
1715 }
1716 break;
1717 case 16:
1718 for (yc=0, yti = 0; yc<iHeight; yc+=Y_TILESIZE, yti++) {
1719 for (xc=0, xti = 0; xc<iWidth; xc+=X_TILESIZE, xti++) {
1720 if (GET_TILE_UPDATED (xti, yti)) {
1721 vid_ptr = disp_ptr + (yc * pitch + (xc<<1));
1722 tile_ptr = bx_gui->graphics_tile_get(xc, yc, &w, &h);
1723 for (r=0; r<h; r++) {
1724 vid_ptr2 = vid_ptr;
1725 tile_ptr2 = tile_ptr;
1726 for (c=0; c<w; c++) {
1727 colour = *(vid_ptr2++);
1728 colour |= *(vid_ptr2++) << 8;
1729 colour = MAKE_COLOUR(
1730 colour & 0x001f, 5, info.blue_shift, info.blue_mask,
1731 colour & 0x07e0, 11, info.green_shift, info.green_mask,
1732 colour & 0xf800, 16, info.red_shift, info.red_mask);
1733 if (info.is_little_endian) {
1734 for (i=0; i<info.bpp; i+=8) {
1735 *(tile_ptr2++) = (Bit8u)(colour >> i);
1736 }
1737 }
1738 else {
1739 for (i=info.bpp-8; i>-8; i-=8) {
1740 *(tile_ptr2++) = (Bit8u)(colour >> i);
1741 }
1742 }
1743 }
1744 vid_ptr += pitch;
1745 tile_ptr += info.pitch;
1746 }
1747 bx_gui->graphics_tile_update_in_place(xc, yc, w, h);
1748 SET_TILE_UPDATED (xti, yti, 0);
1749 }
1750 }
1751 }
1752 break;
1753 case 24:
1754 for (yc=0, yti = 0; yc<iHeight; yc+=Y_TILESIZE, yti++) {
1755 for (xc=0, xti = 0; xc<iWidth; xc+=X_TILESIZE, xti++) {
1756 if (GET_TILE_UPDATED (xti, yti)) {
1757 vid_ptr = disp_ptr + (yc * pitch + 3*xc);
1758 tile_ptr = bx_gui->graphics_tile_get(xc, yc, &w, &h);
1759 for (r=0; r<h; r++) {
1760 vid_ptr2 = vid_ptr;
1761 tile_ptr2 = tile_ptr;
1762 for (c=0; c<w; c++) {
1763 blue = *(vid_ptr2++);
1764 green = *(vid_ptr2++);
1765 red = *(vid_ptr2++);
1766 colour = MAKE_COLOUR(
1767 red, 8, info.red_shift, info.red_mask,
1768 green, 8, info.green_shift, info.green_mask,
1769 blue, 8, info.blue_shift, info.blue_mask);
1770 if (info.is_little_endian) {
1771 for (i=0; i<info.bpp; i+=8) {
1772 *(tile_ptr2++) = (Bit8u)(colour >> i);
1773 }
1774 }
1775 else {
1776 for (i=info.bpp-8; i>-8; i-=8) {
1777 *(tile_ptr2++) = (Bit8u)(colour >> i);
1778 }
1779 }
1780 }
1781 vid_ptr += pitch;
1782 tile_ptr += info.pitch;
1783 }
1784 bx_gui->graphics_tile_update_in_place(xc, yc, w, h);
1785 SET_TILE_UPDATED (xti, yti, 0);
1786 }
1787 }
1788 }
1789 break;
1790 case 32:
1791 for (yc=0, yti = 0; yc<iHeight; yc+=Y_TILESIZE, yti++) {
1792 for (xc=0, xti = 0; xc<iWidth; xc+=X_TILESIZE, xti++) {
1793 if (GET_TILE_UPDATED (xti, yti)) {
1794 vid_ptr = disp_ptr + (yc * pitch + (xc<<2));
1795 tile_ptr = bx_gui->graphics_tile_get(xc, yc, &w, &h);
1796 for (r=0; r<h; r++) {
1797 vid_ptr2 = vid_ptr;
1798 tile_ptr2 = tile_ptr;
1799 for (c=0; c<w; c++) {
1800 blue = *(vid_ptr2++);
1801 green = *(vid_ptr2++);
1802 red = *(vid_ptr2++);
1803 vid_ptr2++;
1804 colour = MAKE_COLOUR(
1805 red, 8, info.red_shift, info.red_mask,
1806 green, 8, info.green_shift, info.green_mask,
1807 blue, 8, info.blue_shift, info.blue_mask);
1808 if (info.is_little_endian) {
1809 for (i=0; i<info.bpp; i+=8) {
1810 *(tile_ptr2++) = (Bit8u)(colour >> i);
1811 }
1812 }
1813 else {
1814 for (i=info.bpp-8; i>-8; i-=8) {
1815 *(tile_ptr2++) = (Bit8u)(colour >> i);
1816 }
1817 }
1818 }
1819 vid_ptr += pitch;
1820 tile_ptr += info.pitch;
1821 }
1822 bx_gui->graphics_tile_update_in_place(xc, yc, w, h);
1823 SET_TILE_UPDATED (xti, yti, 0);
1824 }
1825 }
1826 }
1827 break;
1828 }
1829 }
1830 old_iWidth = iWidth;
1831 old_iHeight = iHeight;
1832 BX_VGA_THIS s.vga_mem_updated = 0;
1833 }
1834 else {
1835 BX_PANIC(("cannot get svga tile info"));
1836 }
1837
1838 // after a vbe display update, don't try to do any 'normal vga' updates anymore
1839 return;
1840 }
1841 #endif
1842 // fields that effect the way video memory is serialized into screen output:
1843 // GRAPHICS CONTROLLER:
1844 // BX_VGA_THIS s.graphics_ctrl.shift_reg:
1845 // 0: output data in standard VGA format or CGA-compatible 640x200 2 color
1846 // graphics mode (mode 6)
1847 // 1: output data in CGA-compatible 320x200 4 color graphics mode
1848 // (modes 4 & 5)
1849 // 2: output data 8 bits at a time from the 4 bit planes
1850 // (mode 13 and variants like modeX)
1851
1852 // if (BX_VGA_THIS s.vga_mem_updated==0 || BX_VGA_THIS s.attribute_ctrl.video_enabled == 0)
1853
1854 if (BX_VGA_THIS s.graphics_ctrl.graphics_alpha) {
1855 Bit8u color;
1856 unsigned bit_no, r, c, x, y;
1857 unsigned long byte_offset, start_addr;
1858 unsigned xc, yc, xti, yti;
1859
1860 start_addr = (BX_VGA_THIS s.CRTC.reg[0x0c] << 8) | BX_VGA_THIS s.CRTC.reg[0x0d];
1861
1862 //BX_DEBUG(("update: shiftreg=%u, chain4=%u, mapping=%u",
1863 // (unsigned) BX_VGA_THIS s.graphics_ctrl.shift_reg,
1864 // (unsigned) BX_VGA_THIS s.sequencer.chain_four,
1865 // (unsigned) BX_VGA_THIS s.graphics_ctrl.memory_mapping);
1866
1867 determine_screen_dimensions(&iHeight, &iWidth);
1868 if((iWidth != old_iWidth) || (iHeight != old_iHeight) ||
1869 (BX_VGA_THIS s.last_bpp > 8))
1870 {
1871 bx_gui->dimension_update(iWidth, iHeight);
1872 old_iWidth = iWidth;
1873 old_iHeight = iHeight;
1874 BX_VGA_THIS s.last_bpp = 8;
1875 }
1876
1877 switch (BX_VGA_THIS s.graphics_ctrl.shift_reg) {
1878 case 0:
1879 Bit8u attribute, palette_reg_val, DAC_regno;
1880 unsigned long line_compare;
1881 Bit8u *plane0, *plane1, *plane2, *plane3;
1882
1883 if (BX_VGA_THIS s.graphics_ctrl.memory_mapping == 3) { // CGA 640x200x2
1884
1885 for (yc=0, yti=0; yc<iHeight; yc+=Y_TILESIZE, yti++) {
1886 for (xc=0, xti=0; xc<iWidth; xc+=X_TILESIZE, xti++) {
1887 if (GET_TILE_UPDATED (xti, yti)) {
1888 for (r=0; r<Y_TILESIZE; r++) {
1889 y = yc + r;
1890 if (BX_VGA_THIS s.y_doublescan) y >>= 1;
1891 for (c=0; c<X_TILESIZE; c++) {
1892
1893 x = xc + c;
1894 /* 0 or 0x2000 */
1895 byte_offset = start_addr + ((y & 1) << 13);
1896 /* to the start of the line */
1897 byte_offset += (320 / 4) * (y / 2);
1898 /* to the byte start */
1899 byte_offset += (x / 8);
1900
1901 bit_no = 7 - (x % 8);
1902 palette_reg_val = (((BX_VGA_THIS s.memory[byte_offset]) >> bit_no) & 1);
1903 DAC_regno = BX_VGA_THIS s.attribute_ctrl.palette_reg[palette_reg_val];
1904 BX_VGA_THIS s.tile[r*X_TILESIZE + c] = DAC_regno;
1905 }
1906 }
1907 SET_TILE_UPDATED (xti, yti, 0);
1908 bx_gui->graphics_tile_update(BX_VGA_THIS s.tile, xc, yc);
1909 }
1910 }
1911 }
1912 } else { // output data in serial fashion with each display plane
1913 // output on its associated serial output. Standard EGA/VGA format
1914
1915 #if BX_SUPPORT_VBE
1916 if (BX_VGA_THIS vbe.enabled)
1917 {
1918 plane0 = &BX_VGA_THIS s.memory[0<<VBE_DISPI_4BPP_PLANE_SHIFT];
1919 plane1 = &BX_VGA_THIS s.memory[1<<VBE_DISPI_4BPP_PLANE_SHIFT];
1920 plane2 = &BX_VGA_THIS s.memory[2<<VBE_DISPI_4BPP_PLANE_SHIFT];
1921 plane3 = &BX_VGA_THIS s.memory[3<<VBE_DISPI_4BPP_PLANE_SHIFT];
1922 start_addr = BX_VGA_THIS vbe.virtual_start;
1923 line_compare = 0xffff;
1924 }
1925 else
1926 #endif
1927 {
1928 plane0 = &BX_VGA_THIS s.memory[0<<16];
1929 plane1 = &BX_VGA_THIS s.memory[1<<16];
1930 plane2 = &BX_VGA_THIS s.memory[2<<16];
1931 plane3 = &BX_VGA_THIS s.memory[3<<16];
1932 line_compare = BX_VGA_THIS s.line_compare;
1933 if (BX_VGA_THIS s.y_doublescan) line_compare >>= 1;
1934 }
1935
1936 for (yc=0, yti=0; yc<iHeight; yc+=Y_TILESIZE, yti++) {
1937 for (xc=0, xti=0; xc<iWidth; xc+=X_TILESIZE, xti++) {
1938 if (GET_TILE_UPDATED (xti, yti)) {
1939 for (r=0; r<Y_TILESIZE; r++) {
1940 y = yc + r;
1941 if (BX_VGA_THIS s.y_doublescan) y >>= 1;
1942 for (c=0; c<X_TILESIZE; c++) {
1943 x = xc + c;
1944 if (BX_VGA_THIS s.x_dotclockdiv2) x >>= 1;
1945 bit_no = 7 - (x % 8);
1946 if (y > line_compare) {
1947 byte_offset = x / 8 +
1948 ((y - line_compare - 1) * BX_VGA_THIS s.line_offset);
1949 } else {
1950 byte_offset = start_addr + x / 8 +
1951 (y * BX_VGA_THIS s.line_offset);
1952 }
1953 attribute =
1954 (((plane0[byte_offset] >> bit_no) & 0x01) << 0) |
1955 (((plane1[byte_offset] >> bit_no) & 0x01) << 1) |
1956 (((plane2[byte_offset] >> bit_no) & 0x01) << 2) |
1957 (((plane3[byte_offset] >> bit_no) & 0x01) << 3);
1958
1959 attribute &= BX_VGA_THIS s.attribute_ctrl.color_plane_enable;
1960 // undocumented feature ???: colors 0..7 high intensity, colors 8..15 blinking
1961 // using low/high intensity. Blinking is not implemented yet.
1962 if (BX_VGA_THIS s.attribute_ctrl.mode_ctrl.blink_intensity) attribute ^= 0x08;
1963 palette_reg_val = BX_VGA_THIS s.attribute_ctrl.palette_reg[attribute];
1964 if (BX_VGA_THIS s.attribute_ctrl.mode_ctrl.internal_palette_size) {
1965 // use 4 lower bits from palette register
1966 // use 4 higher bits from color select register
1967 // 16 banks of 16-color registers
1968 DAC_regno = (palette_reg_val & 0x0f) |
1969 (BX_VGA_THIS s.attribute_ctrl.color_select << 4);
1970 }
1971 else {
1972 // use 6 lower bits from palette register
1973 // use 2 higher bits from color select register
1974 // 4 banks of 64-color registers
1975 DAC_regno = (palette_reg_val & 0x3f) |
1976 ((BX_VGA_THIS s.attribute_ctrl.color_select & 0x0c) << 4);
1977 }
1978 // DAC_regno &= video DAC mask register ???
1979
1980 BX_VGA_THIS s.tile[r*X_TILESIZE + c] = DAC_regno;
1981 }
1982 }
1983 SET_TILE_UPDATED (xti, yti, 0);
1984 bx_gui->graphics_tile_update(BX_VGA_THIS s.tile, xc, yc);
1985 }
1986 }
1987 }
1988 }
1989 break; // case 0
1990
1991 case 1: // output the data in a CGA-compatible 320x200 4 color graphics
1992 // mode. (modes 4 & 5)
1993
1994 /* CGA 320x200x4 start */
1995
1996 for (yc=0, yti=0; yc<iHeight; yc+=Y_TILESIZE, yti++) {
1997 for (xc=0, xti=0; xc<iWidth; xc+=X_TILESIZE, xti++) {
1998 if (GET_TILE_UPDATED (xti, yti)) {
1999 for (r=0; r<Y_TILESIZE; r++) {
2000 y = yc + r;
2001 if (BX_VGA_THIS s.y_doublescan) y >>= 1;
2002 for (c=0; c<X_TILESIZE; c++) {
2003
2004 x = xc + c;
2005 if (BX_VGA_THIS s.x_dotclockdiv2) x >>= 1;
2006 /* 0 or 0x2000 */
2007 byte_offset = start_addr + ((y & 1) << 13);
2008 /* to the start of the line */
2009 byte_offset += (320 / 4) * (y / 2);
2010 /* to the byte start */
2011 byte_offset += (x / 4);
2012
2013 attribute = 6 - 2*(x % 4);
2014 palette_reg_val = (BX_VGA_THIS s.memory[byte_offset]) >> attribute;
2015 palette_reg_val &= 3;
2016 DAC_regno = BX_VGA_THIS s.attribute_ctrl.palette_reg[palette_reg_val];
2017 BX_VGA_THIS s.tile[r*X_TILESIZE + c] = DAC_regno;
2018 }
2019 }
2020 SET_TILE_UPDATED (xti, yti, 0);
2021 bx_gui->graphics_tile_update(BX_VGA_THIS s.tile, xc, yc);
2022 }
2023 }
2024 }
2025 /* CGA 320x200x4 end */
2026
2027 break; // case 1
2028
2029 case 2: // output the data eight bits at a time from the 4 bit plane
2030 // (format for VGA mode 13 hex)
2031 case 3: // FIXME: is this really the same ???
2032
2033 if (BX_VGA_THIS s.sequencer.chain_four) {
2034 unsigned long pixely, pixelx, plane;
2035
2036 if (BX_VGA_THIS s.misc_output.select_high_bank != 1)
2037 BX_PANIC(("update: select_high_bank != 1"));
2038
2039 for (yc=0, yti=0; yc<iHeight; yc+=Y_TILESIZE, yti++) {
2040 for (xc=0, xti=0; xc<iWidth; xc+=X_TILESIZE, xti++) {
2041 if (GET_TILE_UPDATED (xti, yti)) {
2042 for (r=0; r<Y_TILESIZE; r++) {
2043 pixely = yc + r;
2044 if (BX_VGA_THIS s.y_doublescan) pixely >>= 1;
2045 for (c=0; c<X_TILESIZE; c++) {
2046 pixelx = (xc + c) >> 1;
2047 plane = (pixelx % 4);
2048 byte_offset = start_addr + (plane * 65536) +
2049 (pixely * BX_VGA_THIS s.line_offset) + (pixelx & ~0x03);
2050 color = BX_VGA_THIS s.memory[byte_offset];
2051 BX_VGA_THIS s.tile[r*X_TILESIZE + c] = color;
2052 }
2053 }
2054 SET_TILE_UPDATED (xti, yti, 0);
2055 bx_gui->graphics_tile_update(BX_VGA_THIS s.tile, xc, yc);
2056 }
2057 }
2058 }
2059 }
2060
2061 else { // chain_four == 0, modeX
2062 unsigned long pixely, pixelx, plane;
2063
2064 for (yc=0, yti=0; yc<iHeight; yc+=Y_TILESIZE, yti++) {
2065 for (xc=0, xti=0; xc<iWidth; xc+=X_TILESIZE, xti++) {
2066 if (GET_TILE_UPDATED (xti, yti)) {
2067 for (r=0; r<Y_TILESIZE; r++) {
2068 pixely = yc + r;
2069 if (BX_VGA_THIS s.y_doublescan) pixely >>= 1;
2070 for (c=0; c<X_TILESIZE; c++) {
2071 pixelx = (xc + c) >> 1;
2072 plane = (pixelx % 4);
2073 byte_offset = (plane * 65536) +
2074 (pixely * BX_VGA_THIS s.line_offset)
2075 + (pixelx >> 2);
2076 color = BX_VGA_THIS s.memory[start_addr + byte_offset];
2077 BX_VGA_THIS s.tile[r*X_TILESIZE + c] = color;
2078 }
2079 }
2080 SET_TILE_UPDATED (xti, yti, 0);
2081 bx_gui->graphics_tile_update(BX_VGA_THIS s.tile, xc, yc);
2082 }
2083 }
2084 }
2085 }
2086 break; // case 2
2087
2088 default:
2089 BX_PANIC(("update: shift_reg == %u", (unsigned)
2090 BX_VGA_THIS s.graphics_ctrl.shift_reg));
2091 }
2092
2093 BX_VGA_THIS s.vga_mem_updated = 0;
2094 return;
2095 }
2096
2097 else { // text mode
2098 unsigned long start_address;
2099 unsigned long cursor_address, cursor_x, cursor_y;
2100 bx_vga_tminfo_t tm_info;
2101 unsigned VDE, MSL, cols, rows, cWidth;
2102 static unsigned cs_counter = 1;
2103 static bx_bool cs_visible = 0;
2104 bx_bool cs_toggle = 0;
2105
2106 cs_counter--;
2107 if ((BX_VGA_THIS s.vga_mem_updated==0) && (cs_counter > 0))
2108 return;
2109
2110 tm_info.start_address = 2*((BX_VGA_THIS s.CRTC.reg[12] << 8) +
2111 BX_VGA_THIS s.CRTC.reg[13]);
2112 tm_info.cs_start = BX_VGA_THIS s.CRTC.reg[0x0a] & 0x3f;
2113 if (cs_counter == 0) {
2114 cs_toggle = 1;
2115 cs_visible = !cs_visible;
2116 cs_counter = BX_VGA_THIS s.blink_counter;
2117 }
2118 if (!cs_visible) {
2119 tm_info.cs_start |= 0x20;
2120 }
2121 tm_info.cs_end = BX_VGA_THIS s.CRTC.reg[0x0b] & 0x1f;
2122 tm_info.line_offset = BX_VGA_THIS s.CRTC.reg[0x13] << 2;
2123 tm_info.line_compare = BX_VGA_THIS s.line_compare;
2124 tm_info.h_panning = BX_VGA_THIS s.attribute_ctrl.horiz_pel_panning & 0x0f;
2125 tm_info.v_panning = BX_VGA_THIS s.CRTC.reg[0x08] & 0x1f;
2126 tm_info.line_graphics = BX_VGA_THIS s.attribute_ctrl.mode_ctrl.enable_line_graphics;
2127 tm_info.split_hpanning = BX_VGA_THIS s.attribute_ctrl.mode_ctrl.pixel_panning_compat;
2128 tm_info.blink_flags = 0;
2129 if (BX_VGA_THIS s.attribute_ctrl.mode_ctrl.blink_intensity) {
2130 tm_info.blink_flags |= BX_TEXT_BLINK_MODE;
2131 if (cs_toggle)
2132 tm_info.blink_flags |= BX_TEXT_BLINK_TOGGLE;
2133 if (cs_visible)
2134 tm_info.blink_flags |= BX_TEXT_BLINK_STATE;
2135 }
2136 if ((BX_VGA_THIS s.sequencer.reg1 & 0x01) == 0) {
2137 if (tm_info.h_panning >= 8)
2138 tm_info.h_panning = 0;
2139 else
2140 tm_info.h_panning++;
2141 } else {
2142 tm_info.h_panning &= 0x07;
2143 }
2144
2145 // Verticle Display End: find out how many lines are displayed
2146 VDE = BX_VGA_THIS s.vertical_display_end;
2147 // Maximum Scan Line: height of character cell
2148 MSL = BX_VGA_THIS s.CRTC.reg[0x09] & 0x1f;
2149 cols = BX_VGA_THIS s.CRTC.reg[1] + 1;
2150 // workaround for update() calls before VGABIOS init
2151 if (cols == 1) {
2152 cols = 80;
2153 MSL = 15;
2154 }
2155 if ((MSL == 1) && (VDE == 399)) {
2156 // emulated CGA graphics mode 160x100x16 colors
2157 MSL = 3;
2158 }
2159 rows = (VDE+1)/(MSL+1);
2160 if ((rows * tm_info.line_offset) > (1 << 17)) {
2161 BX_PANIC(("update(): text mode: out of memory"));
2162 return;
2163 }
2164 cWidth = ((BX_VGA_THIS s.sequencer.reg1 & 0x01) == 1) ? 8 : 9;
2165 iWidth = cWidth * cols;
2166 iHeight = VDE+1;
2167 if ((iWidth != old_iWidth) || (iHeight != old_iHeight) || (MSL != old_MSL) ||
2168 (BX_VGA_THIS s.last_bpp > 8))
2169 {
2170 bx_gui->dimension_update(iWidth, iHeight, MSL+1, cWidth);
2171 old_iWidth = iWidth;
2172 old_iHeight = iHeight;
2173 old_MSL = MSL;
2174 BX_VGA_THIS s.last_bpp = 8;
2175 }
2176 // pass old text snapshot & new VGA memory contents
2177 start_address = tm_info.start_address;
2178 cursor_address = 2*((BX_VGA_THIS s.CRTC.reg[0x0e] << 8) +
2179 BX_VGA_THIS s.CRTC.reg[0x0f]);
2180 if (cursor_address < start_address) {
2181 cursor_x = 0xffff;
2182 cursor_y = 0xffff;
2183 } else {
2184 cursor_x = ((cursor_address - start_address)/2) % (iWidth/cWidth);
2185 cursor_y = ((cursor_address - start_address)/2) / (iWidth/cWidth);
2186 }
2187 bx_gui->text_update(BX_VGA_THIS s.text_snapshot,
2188 &BX_VGA_THIS s.memory[start_address],
2189 cursor_x, cursor_y, tm_info);
2190 if (BX_VGA_THIS s.vga_mem_updated) {
2191 // screen updated, copy new VGA memory contents into text snapshot
2192 memcpy(BX_VGA_THIS s.text_snapshot,
2193 &BX_VGA_THIS s.memory[start_address],
2194 tm_info.line_offset*rows);
2195 BX_VGA_THIS s.vga_mem_updated = 0;
2196 }
2197 }
2198 }
2199
2200 bx_bool bx_vga_c::mem_read_handler(bx_phy_address addr, unsigned len, void *data, void *param)
2201 {
2202 Bit8u *data_ptr;
2203 #ifdef BX_LITTLE_ENDIAN
2204 data_ptr = (Bit8u *) data;
2205 #else // BX_BIG_ENDIAN
2206 data_ptr = (Bit8u *) data + (len - 1);
2207 #endif
2208 for (unsigned i = 0; i < len; i++) {
2209 *data_ptr = theVga->mem_read(addr);
2210 addr++;
2211 #ifdef BX_LITTLE_ENDIAN
2212 data_ptr++;
2213 #else // BX_BIG_ENDIAN
2214 data_ptr--;
2215 #endif
2216 }
2217 return 1;
2218 }
2219
2220 Bit8u bx_vga_c::mem_read(bx_phy_address addr)
2221 {
2222 Bit32u offset;
2223 Bit8u *plane0, *plane1, *plane2, *plane3;
2224
2225 #if BX_SUPPORT_VBE
2226 // if in a vbe enabled mode, read from the vbe_memory
2227 if ((BX_VGA_THIS vbe.enabled) && (BX_VGA_THIS vbe.bpp != VBE_DISPI_BPP_4))
2228 {
2229 return vbe_mem_read(addr);
2230 }
2231 else if ((BX_VGA_THIS vbe.base_address != 0) && (addr >= BX_VGA_THIS vbe.base_address))
2232 {
2233 return 0xff;
2234 }
2235 #endif
2236
2237 #if defined(VGA_TRACE_FEATURE)
2238 // BX_DEBUG(("8-bit memory read from 0x%08x", addr));
2239 #endif
2240
2241 #ifdef __OS2__
2242
2243 #if BX_PLUGINS
2244 #error Fix the code for plugins
2245 #endif
2246
2247 if (bx_options.videomode == BX_VIDEO_DIRECT)
2248 {
2249 char value;
2250 value = devices->mem->video[addr-0xA0000];
2251 return value;
2252 }
2253 #endif
2254
2255 switch (BX_VGA_THIS s.graphics_ctrl.memory_mapping) {
2256 case 1: // 0xA0000 .. 0xAFFFF
2257 if (addr > 0xAFFFF) return 0xff;
2258 offset = addr & 0xFFFF;
2259 break;
2260 case 2: // 0xB0000 .. 0xB7FFF
2261 if ((addr < 0xB0000) || (addr > 0xB7FFF)) return 0xff;
2262 offset = addr & 0x7FFF;
2263 break;
2264 case 3: // 0xB8000 .. 0xBFFFF
2265 if (addr < 0xB8000) return 0xff;
2266 offset = addr & 0x7FFF;
2267 break;
2268 default: // 0xA0000 .. 0xBFFFF
2269 offset = addr & 0x1FFFF;
2270 }
2271
2272 if (BX_VGA_THIS s.sequencer.chain_four) {
2273 // Mode 13h: 320 x 200 256 color mode: chained pixel representation
2274 return BX_VGA_THIS s.memory[(offset & ~0x03) + (offset % 4)*65536];
2275 }
2276
2277 #if BX_SUPPORT_VBE
2278 if (BX_VGA_THIS vbe.enabled)
2279 {
2280 plane0 = &BX_VGA_THIS s.memory[(0<<VBE_DISPI_4BPP_PLANE_SHIFT) + (BX_VGA_THIS vbe.bank<<16)];
2281 plane1 = &BX_VGA_THIS s.memory[(1<<VBE_DISPI_4BPP_PLANE_SHIFT) + (BX_VGA_THIS vbe.bank<<16)];
2282 plane2 = &BX_VGA_THIS s.memory[(2<<VBE_DISPI_4BPP_PLANE_SHIFT) + (BX_VGA_THIS vbe.bank<<16)];
2283 plane3 = &BX_VGA_THIS s.memory[(3<<VBE_DISPI_4BPP_PLANE_SHIFT) + (BX_VGA_THIS vbe.bank<<16)];
2284 }
2285 else
2286 #endif
2287 {
2288 plane0 = &BX_VGA_THIS s.memory[0<<16];
2289 plane1 = &BX_VGA_THIS s.memory[1<<16];
2290 plane2 = &BX_VGA_THIS s.memory[2<<16];
2291 plane3 = &BX_VGA_THIS s.memory[3<<16];
2292 }
2293
2294 /* addr between 0xA0000 and 0xAFFFF */
2295 switch (BX_VGA_THIS s.graphics_ctrl.read_mode) {
2296 case 0: /* read mode 0 */
2297 BX_VGA_THIS s.graphics_ctrl.latch[0] = plane0[offset];
2298 BX_VGA_THIS s.graphics_ctrl.latch[1] = plane1[offset];
2299 BX_VGA_THIS s.graphics_ctrl.latch[2] = plane2[offset];
2300 BX_VGA_THIS s.graphics_ctrl.latch[3] = plane3[offset];
2301 return(BX_VGA_THIS s.graphics_ctrl.latch[BX_VGA_THIS s.graphics_ctrl.read_map_select]);
2302 break;
2303
2304 case 1: /* read mode 1 */
2305 {
2306 Bit8u color_compare, color_dont_care;
2307 Bit8u latch0, latch1, latch2, latch3, retval;
2308
2309 color_compare = BX_VGA_THIS s.graphics_ctrl.color_compare & 0x0f;
2310 color_dont_care = BX_VGA_THIS s.graphics_ctrl.color_dont_care & 0x0f;
2311 latch0 = BX_VGA_THIS s.graphics_ctrl.latch[0] = plane0[offset];
2312 latch1 = BX_VGA_THIS s.graphics_ctrl.latch[1] = plane1[offset];
2313 latch2 = BX_VGA_THIS s.graphics_ctrl.latch[2] = plane2[offset];
2314 latch3 = BX_VGA_THIS s.graphics_ctrl.latch[3] = plane3[offset];
2315
2316 latch0 ^= ccdat[color_compare][0];
2317 latch1 ^= ccdat[color_compare][1];
2318 latch2 ^= ccdat[color_compare][2];
2319 latch3 ^= ccdat[color_compare][3];
2320
2321 latch0 &= ccdat[color_dont_care][0];
2322 latch1 &= ccdat[color_dont_care][1];
2323 latch2 &= ccdat[color_dont_care][2];
2324 latch3 &= ccdat[color_dont_care][3];
2325
2326 retval = ~(latch0 | latch1 | latch2 | latch3);
2327
2328 return retval;
2329 }
2330 break;
2331 default:
2332 return 0;
2333 }
2334 }
2335
2336 bx_bool bx_vga_c::mem_write_handler(bx_phy_address addr, unsigned len, void *data, void *param)
2337 {
2338 Bit8u *data_ptr;
2339 #ifdef BX_LITTLE_ENDIAN
2340 data_ptr = (Bit8u *) data;
2341 #else // BX_BIG_ENDIAN
2342 data_ptr = (Bit8u *) data + (len - 1);
2343 #endif
2344 for (unsigned i = 0; i < len; i++) {
2345 theVga->mem_write(addr, *data_ptr);
2346 addr++;
2347 #ifdef BX_LITTLE_ENDIAN
2348 data_ptr++;
2349 #else // BX_BIG_ENDIAN
2350 data_ptr--;
2351 #endif
2352 }
2353 return 1;
2354 }
2355
2356 void bx_vga_c::mem_write(bx_phy_address addr, Bit8u value)
2357 {
2358 Bit32u offset;
2359 Bit8u new_val[4];
2360 unsigned start_addr;
2361 Bit8u *plane0, *plane1, *plane2, *plane3;
2362
2363 #if BX_SUPPORT_VBE
2364 // if in a vbe enabled mode, write to the vbe_memory
2365 if ((BX_VGA_THIS vbe.enabled) && (BX_VGA_THIS vbe.bpp != VBE_DISPI_BPP_4))
2366 {
2367 vbe_mem_write(addr, value);
2368 return;
2369 }
2370 else if ((BX_VGA_THIS vbe.base_address != 0) && (addr >= BX_VGA_THIS vbe.base_address))
2371 {
2372 return;
2373 }
2374 #endif
2375
2376 #if defined(VGA_TRACE_FEATURE)
2377 //BX_DEBUG(("8-bit memory write to %08x = %02x", addr, value));
2378 #endif
2379
2380 #ifdef __OS2__
2381
2382 #if BX_PLUGINS
2383 #error Fix the code for plugins
2384 #endif
2385
2386 if (bx_options.videomode == BX_VIDEO_DIRECT)
2387 {
2388 devices->mem->video[addr-0xA0000] = value;
2389 return;
2390 }
2391 #endif
2392
2393 switch (BX_VGA_THIS s.graphics_ctrl.memory_mapping) {
2394 case 1: // 0xA0000 .. 0xAFFFF
2395 if (addr > 0xAFFFF) return;
2396 offset = addr - 0xA0000;
2397 break;
2398 case 2: // 0xB0000 .. 0xB7FFF
2399 if ((addr < 0xB0000) || (addr > 0xB7FFF)) return;
2400 offset = addr - 0xB0000;
2401 break;
2402 case 3: // 0xB8000 .. 0xBFFFF
2403 if (addr < 0xB8000) return;
2404 offset = addr - 0xB8000;
2405 break;
2406 default: // 0xA0000 .. 0xBFFFF
2407 offset = addr - 0xA0000;
2408 }
2409
2410 start_addr = (BX_VGA_THIS s.CRTC.reg[0x0c] << 8) | BX_VGA_THIS s.CRTC.reg[0x0d];
2411
2412 if (BX_VGA_THIS s.graphics_ctrl.graphics_alpha) {
2413 if (BX_VGA_THIS s.graphics_ctrl.memory_mapping == 3) { // 0xB8000 .. 0xBFFFF
2414 unsigned x_tileno, x_tileno2, y_tileno;
2415
2416 /* CGA 320x200x4 / 640x200x2 start */
2417 BX_VGA_THIS s.memory[offset] = value;
2418 offset -= start_addr;
2419 if (offset>=0x2000) {
2420 y_tileno = offset - 0x2000;
2421 y_tileno /= (320/4);
2422 y_tileno <<= 1; //2 * y_tileno;
2423 y_tileno++;
2424 x_tileno = (offset - 0x2000) % (320/4);
2425 x_tileno <<= 2; //*= 4;
2426 } else {
2427 y_tileno = offset / (320/4);
2428 y_tileno <<= 1; //2 * y_tileno;
2429 x_tileno = offset % (320/4);
2430 x_tileno <<= 2; //*=4;
2431 }
2432 x_tileno2=x_tileno;
2433 if (BX_VGA_THIS s.graphics_ctrl.shift_reg==0) {
2434 x_tileno*=2;
2435 x_tileno2+=7;
2436 } else {
2437 x_tileno2+=3;
2438 }
2439 if (BX_VGA_THIS s.x_dotclockdiv2) {
2440 x_tileno/=(X_TILESIZE/2);
2441 x_tileno2/=(X_TILESIZE/2);
2442 } else {
2443 x_tileno/=X_TILESIZE;
2444 x_tileno2/=X_TILESIZE;
2445 }
2446 if (BX_VGA_THIS s.y_doublescan) {
2447 y_tileno/=(Y_TILESIZE/2);
2448 } else {
2449 y_tileno/=Y_TILESIZE;
2450 }
2451 BX_VGA_THIS s.vga_mem_updated = 1;
2452 SET_TILE_UPDATED (x_tileno, y_tileno, 1);
2453 if (x_tileno2!=x_tileno) {
2454 SET_TILE_UPDATED (x_tileno2, y_tileno, 1);
2455 }
2456 return;
2457 /* CGA 320x200x4 / 640x200x2 end */
2458 }
2459 else if (BX_VGA_THIS s.graphics_ctrl.memory_mapping != 1) {
2460 BX_PANIC(("mem_write: graphics: mapping = %u",
2461 (unsigned) BX_VGA_THIS s.graphics_ctrl.memory_mapping));
2462 return;
2463 }
2464
2465 if (BX_VGA_THIS s.sequencer.chain_four) {
2466 unsigned x_tileno, y_tileno;
2467
2468 // 320 x 200 256 color mode: chained pixel representation
2469 BX_VGA_THIS s.memory[(offset & ~0x03) + (offset % 4)*65536] = value;
2470 if (BX_VGA_THIS s.line_offset > 0) {
2471 offset -= start_addr;
2472 x_tileno = (offset % BX_VGA_THIS s.line_offset) / (X_TILESIZE/2);
2473 if (BX_VGA_THIS s.y_doublescan) {
2474 y_tileno = (offset / BX_VGA_THIS s.line_offset) / (Y_TILESIZE/2);
2475 } else {
2476 y_tileno = (offset / BX_VGA_THIS s.line_offset) / Y_TILESIZE;
2477 }
2478 BX_VGA_THIS s.vga_mem_updated = 1;
2479 SET_TILE_UPDATED (x_tileno, y_tileno, 1);
2480 }
2481 return;
2482 }
2483 }
2484
2485 /* addr between 0xA0000 and 0xAFFFF */
2486
2487 #if BX_SUPPORT_VBE
2488 if (BX_VGA_THIS vbe.enabled)
2489 {
2490 plane0 = &BX_VGA_THIS s.memory[(0<<VBE_DISPI_4BPP_PLANE_SHIFT) + (BX_VGA_THIS vbe.bank<<16)];
2491 plane1 = &BX_VGA_THIS s.memory[(1<<VBE_DISPI_4BPP_PLANE_SHIFT) + (BX_VGA_THIS vbe.bank<<16)];
2492 plane2 = &BX_VGA_THIS s.memory[(2<<VBE_DISPI_4BPP_PLANE_SHIFT) + (BX_VGA_THIS vbe.bank<<16)];
2493 plane3 = &BX_VGA_THIS s.memory[(3<<VBE_DISPI_4BPP_PLANE_SHIFT) + (BX_VGA_THIS vbe.bank<<16)];
2494 }
2495 else
2496 #endif
2497 {
2498 plane0 = &BX_VGA_THIS s.memory[0<<16];
2499 plane1 = &BX_VGA_THIS s.memory[1<<16];
2500 plane2 = &BX_VGA_THIS s.memory[2<<16];
2501 plane3 = &BX_VGA_THIS s.memory[3<<16];
2502 }
2503
2504 switch (BX_VGA_THIS s.graphics_ctrl.write_mode) {
2505 unsigned i;
2506
2507 case 0: /* write mode 0 */
2508 {
2509 const Bit8u bitmask = BX_VGA_THIS s.graphics_ctrl.bitmask;
2510 const Bit8u set_reset = BX_VGA_THIS s.graphics_ctrl.set_reset;
2511 const Bit8u enable_set_reset = BX_VGA_THIS s.graphics_ctrl.enable_set_reset;
2512 /* perform rotate on CPU data in case its needed */
2513 if (BX_VGA_THIS s.graphics_ctrl.data_rotate) {
2514 value = (value >> BX_VGA_THIS s.graphics_ctrl.data_rotate) |
2515 (value << (8 - BX_VGA_THIS s.graphics_ctrl.data_rotate));
2516 }
2517 new_val[0] = BX_VGA_THIS s.graphics_ctrl.latch[0] & ~bitmask;
2518 new_val[1] = BX_VGA_THIS s.graphics_ctrl.latch[1] & ~bitmask;
2519 new_val[2] = BX_VGA_THIS s.graphics_ctrl.latch[2] & ~bitmask;
2520 new_val[3] = BX_VGA_THIS s.graphics_ctrl.latch[3] & ~bitmask;
2521 switch (BX_VGA_THIS s.graphics_ctrl.raster_op) {
2522 case 0: // replace
2523 new_val[0] |= ((enable_set_reset & 1)
2524 ? ((set_reset & 1) ? bitmask : 0)
2525 : (value & bitmask));
2526 new_val[1] |= ((enable_set_reset & 2)
2527 ? ((set_reset & 2) ? bitmask : 0)
2528 : (value & bitmask));
2529 new_val[2] |= ((enable_set_reset & 4)
2530 ? ((set_reset & 4) ? bitmask : 0)
2531 : (value & bitmask));
2532 new_val[3] |= ((enable_set_reset & 8)
2533 ? ((set_reset & 8) ? bitmask : 0)
2534 : (value & bitmask));
2535 break;
2536 case 1: // AND
2537 new_val[0] |= ((enable_set_reset & 1)
2538 ? ((set_reset & 1)
2539 ? (BX_VGA_THIS s.graphics_ctrl.latch[0] & bitmask)
2540 : 0)
2541 : (value & BX_VGA_THIS s.graphics_ctrl.latch[0]) & bitmask);
2542 new_val[1] |= ((enable_set_reset & 2)
2543 ? ((set_reset & 2)
2544 ? (BX_VGA_THIS s.graphics_ctrl.latch[1] & bitmask)
2545 : 0)
2546 : (value & BX_VGA_THIS s.graphics_ctrl.latch[1]) & bitmask);
2547 new_val[2] |= ((enable_set_reset & 4)
2548 ? ((set_reset & 4)
2549 ? (BX_VGA_THIS s.graphics_ctrl.latch[2] & bitmask)
2550 : 0)
2551 : (value & BX_VGA_THIS s.graphics_ctrl.latch[2]) & bitmask);
2552 new_val[3] |= ((enable_set_reset & 8)
2553 ? ((set_reset & 8)
2554 ? (BX_VGA_THIS s.graphics_ctrl.latch[3] & bitmask)
2555 : 0)
2556 : (value & BX_VGA_THIS s.graphics_ctrl.latch[3]) & bitmask);
2557 break;
2558 case 2: // OR
2559 new_val[0]
2560 |= ((enable_set_reset & 1)
2561 ? ((set_reset & 1)
2562 ? bitmask
2563 : (BX_VGA_THIS s.graphics_ctrl.latch[0] & bitmask))
2564 : ((value | BX_VGA_THIS s.graphics_ctrl.latch[0]) & bitmask));
2565 new_val[1]
2566 |= ((enable_set_reset & 2)
2567 ? ((set_reset & 2)
2568 ? bitmask
2569 : (BX_VGA_THIS s.graphics_ctrl.latch[1] & bitmask))
2570 : ((value | BX_VGA_THIS s.graphics_ctrl.latch[1]) & bitmask));
2571 new_val[2]
2572 |= ((enable_set_reset & 4)
2573 ? ((set_reset & 4)
2574 ? bitmask
2575 : (BX_VGA_THIS s.graphics_ctrl.latch[2] & bitmask))
2576 : ((value | BX_VGA_THIS s.graphics_ctrl.latch[2]) & bitmask));
2577 new_val[3]
2578 |= ((enable_set_reset & 8)
2579 ? ((set_reset & 8)
2580 ? bitmask
2581 : (BX_VGA_THIS s.graphics_ctrl.latch[3] & bitmask))
2582 : ((value | BX_VGA_THIS s.graphics_ctrl.latch[3]) & bitmask));
2583 break;
2584 case 3: // XOR
2585 new_val[0]
2586 |= ((enable_set_reset & 1)
2587 ? ((set_reset & 1)
2588 ? (~BX_VGA_THIS s.graphics_ctrl.latch[0] & bitmask)
2589 : (BX_VGA_THIS s.graphics_ctrl.latch[0] & bitmask))
2590 : (value ^ BX_VGA_THIS s.graphics_ctrl.latch[0]) & bitmask);
2591 new_val[1]
2592 |= ((enable_set_reset & 2)
2593 ? ((set_reset & 2)
2594 ? (~BX_VGA_THIS s.graphics_ctrl.latch[1] & bitmask)
2595 : (BX_VGA_THIS s.graphics_ctrl.latch[1] & bitmask))
2596 : (value ^ BX_VGA_THIS s.graphics_ctrl.latch[1]) & bitmask);
2597 new_val[2]
2598 |= ((enable_set_reset & 4)
2599 ? ((set_reset & 4)
2600 ? (~BX_VGA_THIS s.graphics_ctrl.latch[2] & bitmask)
2601 : (BX_VGA_THIS s.graphics_ctrl.latch[2] & bitmask))
2602 : (value ^ BX_VGA_THIS s.graphics_ctrl.latch[2]) & bitmask);
2603 new_val[3]
2604 |= ((enable_set_reset & 8)
2605 ? ((set_reset & 8)
2606 ? (~BX_VGA_THIS s.graphics_ctrl.latch[3] & bitmask)
2607 : (BX_VGA_THIS s.graphics_ctrl.latch[3] & bitmask))
2608 : (value ^ BX_VGA_THIS s.graphics_ctrl.latch[3]) & bitmask);
2609 break;
2610 default:
2611 BX_PANIC(("vga_mem_write: write mode 0: op = %u",
2612 (unsigned) BX_VGA_THIS s.graphics_ctrl.raster_op));
2613 }
2614 }
2615 break;
2616
2617 case 1: /* write mode 1 */
2618 for (i=0; i<4; i++) {
2619 new_val[i] = BX_VGA_THIS s.graphics_ctrl.latch[i];
2620 }
2621 break;
2622
2623 case 2: /* write mode 2 */
2624 {
2625 const Bit8u bitmask = BX_VGA_THIS s.graphics_ctrl.bitmask;
2626
2627 new_val[0] = BX_VGA_THIS s.graphics_ctrl.latch[0] & ~bitmask;
2628 new_val[1] = BX_VGA_THIS s.graphics_ctrl.latch[1] & ~bitmask;
2629 new_val[2] = BX_VGA_THIS s.graphics_ctrl.latch[2] & ~bitmask;
2630 new_val[3] = BX_VGA_THIS s.graphics_ctrl.latch[3] & ~bitmask;
2631 switch (BX_VGA_THIS s.graphics_ctrl.raster_op) {
2632 case 0: // write
2633 new_val[0] |= (value & 1) ? bitmask : 0;
2634 new_val[1] |= (value & 2) ? bitmask : 0;
2635 new_val[2] |= (value & 4) ? bitmask : 0;
2636 new_val[3] |= (value & 8) ? bitmask : 0;
2637 break;
2638 case 1: // AND
2639 new_val[0] |= (value & 1)
2640 ? (BX_VGA_THIS s.graphics_ctrl.latch[0] & bitmask)
2641 : 0;
2642 new_val[1] |= (value & 2)
2643 ? (BX_VGA_THIS s.graphics_ctrl.latch[1] & bitmask)
2644 : 0;
2645 new_val[2] |= (value & 4)
2646 ? (BX_VGA_THIS s.graphics_ctrl.latch[2] & bitmask)
2647 : 0;
2648 new_val[3] |= (value & 8)
2649 ? (BX_VGA_THIS s.graphics_ctrl.latch[3] & bitmask)
2650 : 0;
2651 break;
2652 case 2: // OR
2653 new_val[0] |= (value & 1)
2654 ? bitmask
2655 : (BX_VGA_THIS s.graphics_ctrl.latch[0] & bitmask);
2656 new_val[1] |= (value & 2)
2657 ? bitmask
2658 : (BX_VGA_THIS s.graphics_ctrl.latch[1] & bitmask);
2659 new_val[2] |= (value & 4)
2660 ? bitmask
2661 : (BX_VGA_THIS s.graphics_ctrl.latch[2] & bitmask);
2662 new_val[3] |= (value & 8)
2663 ? bitmask
2664 : (BX_VGA_THIS s.graphics_ctrl.latch[3] & bitmask);
2665 break;
2666 case 3: // XOR
2667 new_val[0] |= (value & 1)
2668 ? (~BX_VGA_THIS s.graphics_ctrl.latch[0] & bitmask)
2669 : (BX_VGA_THIS s.graphics_ctrl.latch[0] & bitmask);
2670 new_val[1] |= (value & 2)
2671 ? (~BX_VGA_THIS s.graphics_ctrl.latch[1] & bitmask)
2672 : (BX_VGA_THIS s.graphics_ctrl.latch[1] & bitmask);
2673 new_val[2] |= (value & 4)
2674 ? (~BX_VGA_THIS s.graphics_ctrl.latch[2] & bitmask)
2675 : (BX_VGA_THIS s.graphics_ctrl.latch[2] & bitmask);
2676 new_val[3] |= (value & 8)
2677 ? (~BX_VGA_THIS s.graphics_ctrl.latch[3] & bitmask)
2678 : (BX_VGA_THIS s.graphics_ctrl.latch[3] & bitmask);
2679 break;
2680 }
2681 }
2682 break;
2683
2684 case 3: /* write mode 3 */
2685 {
2686 const Bit8u bitmask = BX_VGA_THIS s.graphics_ctrl.bitmask & value;
2687 const Bit8u set_reset = BX_VGA_THIS s.graphics_ctrl.set_reset;
2688
2689 /* perform rotate on CPU data */
2690 if (BX_VGA_THIS s.graphics_ctrl.data_rotate) {
2691 value = (value >> BX_VGA_THIS s.graphics_ctrl.data_rotate) |
2692 (value << (8 - BX_VGA_THIS s.graphics_ctrl.data_rotate));
2693 }
2694 new_val[0] = BX_VGA_THIS s.graphics_ctrl.latch[0] & ~bitmask;
2695 new_val[1] = BX_VGA_THIS s.graphics_ctrl.latch[1] & ~bitmask;
2696 new_val[2] = BX_VGA_THIS s.graphics_ctrl.latch[2] & ~bitmask;
2697 new_val[3] = BX_VGA_THIS s.graphics_ctrl.latch[3] & ~bitmask;
2698
2699 value &= bitmask;
2700
2701 switch (BX_VGA_THIS s.graphics_ctrl.raster_op) {
2702 case 0: // write
2703 new_val[0] |= (set_reset & 1) ? value : 0;
2704 new_val[1] |= (set_reset & 2) ? value : 0;
2705 new_val[2] |= (set_reset & 4) ? value : 0;
2706 new_val[3] |= (set_reset & 8) ? value : 0;
2707 break;
2708 case 1: // AND
2709 new_val[0] |= ((set_reset & 1) ? value : 0)
2710 & BX_VGA_THIS s.graphics_ctrl.latch[0];
2711 new_val[1] |= ((set_reset & 2) ? value : 0)
2712 & BX_VGA_THIS s.graphics_ctrl.latch[1];
2713 new_val[2] |= ((set_reset & 4) ? value : 0)
2714 & BX_VGA_THIS s.graphics_ctrl.latch[2];
2715 new_val[3] |= ((set_reset & 8) ? value : 0)
2716 & BX_VGA_THIS s.graphics_ctrl.latch[3];
2717 break;
2718 case 2: // OR
2719 new_val[0] |= ((set_reset & 1) ? value : 0)
2720 | BX_VGA_THIS s.graphics_ctrl.latch[0];
2721 new_val[1] |= ((set_reset & 2) ? value : 0)
2722 | BX_VGA_THIS s.graphics_ctrl.latch[1];
2723 new_val[2] |= ((set_reset & 4) ? value : 0)
2724 | BX_VGA_THIS s.graphics_ctrl.latch[2];
2725 new_val[3] |= ((set_reset & 8) ? value : 0)
2726 | BX_VGA_THIS s.graphics_ctrl.latch[3];
2727 break;
2728 case 3: // XOR
2729 new_val[0] |= ((set_reset & 1) ? value : 0)
2730 ^ BX_VGA_THIS s.graphics_ctrl.latch[0];
2731 new_val[1] |= ((set_reset & 2) ? value : 0)
2732 ^ BX_VGA_THIS s.graphics_ctrl.latch[1];
2733 new_val[2] |= ((set_reset & 4) ? value : 0)
2734 ^ BX_VGA_THIS s.graphics_ctrl.latch[2];
2735 new_val[3] |= ((set_reset & 8) ? value : 0)
2736 ^ BX_VGA_THIS s.graphics_ctrl.latch[3];
2737 break;
2738 }
2739 }
2740 break;
2741
2742 default:
2743 BX_PANIC(("vga_mem_write: write mode %u ?",
2744 (unsigned) BX_VGA_THIS s.graphics_ctrl.write_mode));
2745 }
2746
2747 if (BX_VGA_THIS s.sequencer.map_mask & 0x0f) {
2748 BX_VGA_THIS s.vga_mem_updated = 1;
2749 if (BX_VGA_THIS s.sequencer.map_mask & 0x01)
2750 plane0[offset] = new_val[0];
2751 if (BX_VGA_THIS s.sequencer.map_mask & 0x02)
2752 plane1[offset] = new_val[1];
2753 if (BX_VGA_THIS s.sequencer.map_mask & 0x04) {
2754 if ((offset & 0xe000) == BX_VGA_THIS s.charmap_address) {
2755 bx_gui->set_text_charbyte((offset & 0x1fff), new_val[2]);
2756 }
2757 plane2[offset] = new_val[2];
2758 }
2759 if (BX_VGA_THIS s.sequencer.map_mask & 0x08)
2760 plane3[offset] = new_val[3];
2761
2762 unsigned x_tileno, y_tileno;
2763
2764 if (BX_VGA_THIS s.graphics_ctrl.shift_reg == 2) {
2765 offset -= start_addr;
2766 x_tileno = (offset % BX_VGA_THIS s.line_offset) * 4 / (X_TILESIZE / 2);
2767 if (BX_VGA_THIS s.y_doublescan) {
2768 y_tileno = (offset / BX_VGA_THIS s.line_offset) / (Y_TILESIZE / 2);
2769 } else {
2770 y_tileno = (offset / BX_VGA_THIS s.line_offset) / Y_TILESIZE;
2771 }
2772 SET_TILE_UPDATED (x_tileno, y_tileno, 1);
2773 } else {
2774 if (BX_VGA_THIS s.line_compare < BX_VGA_THIS s.vertical_display_end) {
2775 if (BX_VGA_THIS s.line_offset > 0) {
2776 if (BX_VGA_THIS s.x_dotclockdiv2) {
2777 x_tileno = (offset % BX_VGA_THIS s.line_offset) / (X_TILESIZE / 16);
2778 } else {
2779 x_tileno = (offset % BX_VGA_THIS s.line_offset) / (X_TILESIZE / 8);
2780 }
2781 if (BX_VGA_THIS s.y_doublescan) {
2782 y_tileno = ((offset / BX_VGA_THIS s.line_offset) * 2 + BX_VGA_THIS s.line_compare + 1) / Y_TILESIZE;
2783 } else {
2784 y_tileno = ((offset / BX_VGA_THIS s.line_offset) + BX_VGA_THIS s.line_compare + 1) / Y_TILESIZE;
2785 }
2786 SET_TILE_UPDATED (x_tileno, y_tileno, 1);
2787 }
2788 }
2789 if (offset >= start_addr) {
2790 offset -= start_addr;
2791 if (BX_VGA_THIS s.line_offset > 0) {
2792 if (BX_VGA_THIS s.x_dotclockdiv2) {
2793 x_tileno = (offset % BX_VGA_THIS s.line_offset) / (X_TILESIZE / 16);
2794 } else {
2795 x_tileno = (offset % BX_VGA_THIS s.line_offset) / (X_TILESIZE / 8);
2796 }
2797 if (BX_VGA_THIS s.y_doublescan) {
2798 y_tileno = (offset / BX_VGA_THIS s.line_offset) / (Y_TILESIZE / 2);
2799 } else {
2800 y_tileno = (offset / BX_VGA_THIS s.line_offset) / Y_TILESIZE;
2801 }
2802 SET_TILE_UPDATED (x_tileno, y_tileno, 1);
2803 }
2804 }
2805 }
2806 }
2807 }
2808
2809 void bx_vga_c::get_text_snapshot(Bit8u **text_snapshot, unsigned *txHeight,
2810 unsigned *txWidth)
2811 {
2812 unsigned VDE, MSL;
2813
2814 if (!BX_VGA_THIS s.graphics_ctrl.graphics_alpha) {
2815 *text_snapshot = &BX_VGA_THIS s.text_snapshot[0];
2816 VDE = BX_VGA_THIS s.vertical_display_end;
2817 MSL = BX_VGA_THIS s.CRTC.reg[0x09] & 0x1f;
2818 *txHeight = (VDE+1)/(MSL+1);
2819 *txWidth = BX_VGA_THIS s.CRTC.reg[1] + 1;
2820 } else {
2821 *txHeight = 0;
2822 *txWidth = 0;
2823 }
2824 }
2825
2826 Bit8u bx_vga_c::get_actl_palette_idx(Bit8u index)
2827 {
2828 return BX_VGA_THIS s.attribute_ctrl.palette_reg[index];
2829 }
2830
2831 #if BX_DEBUGGER
2832 void bx_vga_c::debug_dump(void)
2833 {
2834 dbg_printf("s.misc_output.color_emulation = %u\n",
2835 (unsigned) BX_VGA_THIS s.misc_output.color_emulation);
2836 dbg_printf("s.misc_output.enable_ram = %u\n",
2837 (unsigned) BX_VGA_THIS s.misc_output.enable_ram);
2838 dbg_printf("s.misc_output.clock_select = %u ",
2839 (unsigned) BX_VGA_THIS s.misc_output.clock_select);
2840 if (BX_VGA_THIS s.misc_output.clock_select == 0)
2841 dbg_printf("(25Mhz 640 horiz pixel clock)\n");
2842 else
2843 dbg_printf("(28Mhz 720 horiz pixel clock)\n");
2844 dbg_printf("s.misc_output.select_high_bank = %u\n",
2845 (unsigned) BX_VGA_THIS s.misc_output.select_high_bank);
2846 dbg_printf("s.misc_output.horiz_sync_pol = %u\n",
2847 (unsigned) BX_VGA_THIS s.misc_output.horiz_sync_pol);
2848 dbg_printf("s.misc_output.vert_sync_pol = %u ",
2849 (unsigned) BX_VGA_THIS s.misc_output.vert_sync_pol);
2850 switch ((BX_VGA_THIS s.misc_output.vert_sync_pol << 1) |
2851 BX_VGA_THIS s.misc_output.horiz_sync_pol) {
2852 case 1: dbg_printf("(400 lines)\n"); break;
2853 case 2: dbg_printf("(350 lines)\n"); break;
2854 case 3: dbg_printf("(480 lines)\n"); break;
2855 default: dbg_printf("(reserved)\n");
2856 }
2857
2858 dbg_printf("s.graphics_ctrl.odd_even = %u\n",
2859 (unsigned) BX_VGA_THIS s.graphics_ctrl.odd_even);
2860 dbg_printf("s.graphics_ctrl.chain_odd_even = %u\n",
2861 (unsigned) BX_VGA_THIS s.graphics_ctrl.chain_odd_even);
2862 dbg_printf("s.graphics_ctrl.shift_reg = %u\n",
2863 (unsigned) BX_VGA_THIS s.graphics_ctrl.shift_reg);
2864 dbg_printf("s.graphics_ctrl.graphics_alpha = %u\n",
2865 (unsigned) BX_VGA_THIS s.graphics_ctrl.graphics_alpha);
2866 dbg_printf("s.graphics_ctrl.memory_mapping = %u ",
2867 (unsigned) BX_VGA_THIS s.graphics_ctrl.memory_mapping);
2868 switch (BX_VGA_THIS s.graphics_ctrl.memory_mapping) {
2869 case 1: dbg_printf("(A0000-AFFFF)\n"); break;
2870 case 2: dbg_printf("(B0000-B7FFF)\n"); break;
2871 case 3: dbg_printf("(B8000-BFFFF)\n"); break;
2872 default: dbg_printf("(A0000-BFFFF)\n"); break;
2873 }
2874
2875 dbg_printf("s.sequencer.extended_mem = %u\n",
2876 (unsigned) BX_VGA_THIS s.sequencer.extended_mem);
2877 dbg_printf("s.sequencer.odd_even = %u (inverted)\n",
2878 (unsigned) BX_VGA_THIS s.sequencer.odd_even);
2879 dbg_printf("s.sequencer.chain_four = %u\n",
2880 (unsigned) BX_VGA_THIS s.sequencer.chain_four);
2881
2882 dbg_printf("s.attribute_ctrl.video_enabled = %u\n",
2883 (unsigned) BX_VGA_THIS s.attribute_ctrl.video_enabled);
2884 dbg_printf("s.attribute_ctrl.mode_ctrl.graphics_alpha = %u\n",
2885 (unsigned) BX_VGA_THIS s.attribute_ctrl.mode_ctrl.graphics_alpha);
2886 dbg_printf("s.attribute_ctrl.mode_ctrl.display_type = %u\n",
2887 (unsigned) BX_VGA_THIS s.attribute_ctrl.mode_ctrl.display_type);
2888 dbg_printf("s.attribute_ctrl.mode_ctrl.internal_palette_size = %u\n",
2889 (unsigned) BX_VGA_THIS s.attribute_ctrl.mode_ctrl.internal_palette_size);
2890 dbg_printf("s.attribute_ctrl.mode_ctrl.pixel_clock_select = %u\n",
2891 (unsigned) BX_VGA_THIS s.attribute_ctrl.mode_ctrl.pixel_clock_select);
2892 }
2893 #endif
2894
2895 void bx_vga_c::redraw_area(unsigned x0, unsigned y0, unsigned width,
2896 unsigned height)
2897 {
2898 unsigned xti, yti, xt0, xt1, yt0, yt1, xmax, ymax;
2899
2900 if ((width == 0) || (height == 0)) {
2901 return;
2902 }
2903
2904 BX_VGA_THIS s.vga_mem_updated = 1;
2905
2906 #if BX_SUPPORT_VBE
2907 if (BX_VGA_THIS s.graphics_ctrl.graphics_alpha || BX_VGA_THIS vbe.enabled) {
2908 #else
2909 if (BX_VGA_THIS s.graphics_ctrl.graphics_alpha) {
2910 #endif
2911 // graphics mode
2912 xmax = old_iWidth;
2913 ymax = old_iHeight;
2914 #if BX_SUPPORT_VBE
2915 if (BX_VGA_THIS vbe.enabled) {
2916 xmax = BX_VGA_THIS vbe.xres;
2917 ymax = BX_VGA_THIS vbe.yres;
2918 }
2919 #endif
2920 xt0 = x0 / X_TILESIZE;
2921 yt0 = y0 / Y_TILESIZE;
2922 if (x0 < xmax) {
2923 xt1 = (x0 + width - 1) / X_TILESIZE;
2924 } else {
2925 xt1 = (xmax - 1) / X_TILESIZE;
2926 }
2927 if (y0 < ymax) {
2928 yt1 = (y0 + height - 1) / Y_TILESIZE;
2929 } else {
2930 yt1 = (ymax - 1) / Y_TILESIZE;
2931 }
2932 for (yti=yt0; yti<=yt1; yti++) {
2933 for (xti=xt0; xti<=xt1; xti++) {
2934 SET_TILE_UPDATED (xti, yti, 1);
2935 }
2936 }
2937
2938 } else {
2939 // text mode
2940 memset(BX_VGA_THIS s.text_snapshot, 0,
2941 sizeof(BX_VGA_THIS s.text_snapshot));
2942 }
2943 }
2944
2945
2946 #if BX_SUPPORT_VBE
2947 bx_bool bx_vga_c::vbe_set_base_addr(Bit32u *addr, Bit8u *pci_conf)
2948 {
2949 if (DEV_pci_set_base_mem(BX_VGA_THIS_PTR, mem_read_handler,
2950 mem_write_handler,
2951 addr, pci_conf, VBE_DISPI_TOTAL_VIDEO_MEMORY_BYTES)) {
2952 BX_VGA_THIS vbe.base_address = *addr;
2953 return 1;
2954 }
2955 return 0;
2956 }
2957
2958 Bit8u BX_CPP_AttrRegparmN(1)
2959 bx_vga_c::vbe_mem_read(bx_phy_address addr)
2960 {
2961 Bit32u offset;
2962
2963 if (addr >= BX_VGA_THIS vbe.base_address)
2964 {
2965 // LFB read
2966 offset = addr - BX_VGA_THIS vbe.base_address;
2967 }
2968 else
2969 {
2970 // banked mode read
2971 offset = BX_VGA_THIS vbe.bank*65536 + addr - 0xA0000;
2972 }
2973
2974 // check for out of memory read
2975 if (offset > VBE_DISPI_TOTAL_VIDEO_MEMORY_BYTES)
2976 return 0;
2977
2978 return (BX_VGA_THIS s.memory[offset]);
2979 }
2980
2981 void BX_CPP_AttrRegparmN(2)
2982 bx_vga_c::vbe_mem_write(bx_phy_address addr, Bit8u value)
2983 {
2984 Bit32u offset;
2985 unsigned x_tileno, y_tileno;
2986
2987 if (BX_VGA_THIS vbe.lfb_enabled)
2988 {
2989 if (addr >= BX_VGA_THIS vbe.base_address)
2990 {
2991 // LFB write
2992 offset = addr - BX_VGA_THIS vbe.base_address;
2993 }
2994 else
2995 {
2996 // banked mode write while in LFB mode -> ignore
2997 return;
2998 }
2999 }
3000 else
3001 {
3002 if (addr < BX_VGA_THIS vbe.base_address)
3003 {
3004 // banked mode write
3005 offset = (BX_VGA_THIS vbe.bank*65536) + (addr - 0xA0000);
3006 }
3007 else
3008 {
3009 // LFB write while in banked mode -> ignore
3010 return;
3011 }
3012 }
3013
3014 // check for out of memory write
3015 if (offset < VBE_DISPI_TOTAL_VIDEO_MEMORY_BYTES)
3016 {
3017 BX_VGA_THIS s.memory[offset]=value;
3018 }
3019 else
3020 {
3021 // make sure we don't flood the logfile
3022 static int count=0;
3023 if (count<100)
3024 {
3025 count ++;
3026 BX_INFO(("VBE_mem_write out of video memory write at %x",offset));
3027 }
3028 }
3029
3030 offset-=BX_VGA_THIS vbe.virtual_start;
3031
3032 // only update the UI when writing 'onscreen'
3033 if (offset < BX_VGA_THIS vbe.visible_screen_size)
3034 {
3035 y_tileno = ((offset / BX_VGA_THIS vbe.bpp_multiplier) / BX_VGA_THIS vbe.virtual_xres) / Y_TILESIZE;
3036 x_tileno = ((offset / BX_VGA_THIS vbe.bpp_multiplier) % BX_VGA_THIS vbe.virtual_xres) / X_TILESIZE;
3037
3038 if ((y_tileno < BX_NUM_Y_TILES) && (x_tileno < BX_NUM_X_TILES))
3039 {
3040 BX_VGA_THIS s.vga_mem_updated = 1;
3041 SET_TILE_UPDATED (x_tileno, y_tileno, 1);
3042 }
3043 }
3044 }
3045
3046 Bit32u bx_vga_c::vbe_read_handler(void *this_ptr, Bit32u address, unsigned io_len)
3047 {
3048 #if BX_USE_VGA_SMF == 0
3049 bx_vga_c *class_ptr = (bx_vga_c *) this_ptr;
3050 return class_ptr->vbe_read(address, io_len);
3051 }
3052
3053 Bit32u bx_vga_c::vbe_read(Bit32u address, unsigned io_len)
3054 {
3055 #else
3056 UNUSED(this_ptr);
3057 #endif // BX_USE_VGA_SMF == 0
3058 Bit16u retval;
3059
3060 // BX_INFO(("VBE_read %x (len %x)", address, io_len));
3061
3062 if (address==VBE_DISPI_IOPORT_INDEX)
3063 {
3064 // index register
3065 return (Bit32u) BX_VGA_THIS vbe.curindex;
3066 }
3067 else
3068 {
3069 // data register read
3070
3071 switch (BX_VGA_THIS vbe.curindex)
3072 {
3073 case VBE_DISPI_INDEX_ID: // Display Interface ID check
3074 return BX_VGA_THIS vbe.cur_dispi;
3075
3076 case VBE_DISPI_INDEX_XRES: // x resolution
3077 if (BX_VGA_THIS vbe.get_capabilities) {
3078 return BX_VGA_THIS vbe.max_xres;
3079 } else {
3080 return BX_VGA_THIS vbe.xres;
3081 }
3082
3083 case VBE_DISPI_INDEX_YRES: // y resolution
3084 if (BX_VGA_THIS vbe.get_capabilities) {
3085 return BX_VGA_THIS vbe.max_yres;
3086 } else {
3087 return BX_VGA_THIS vbe.yres;
3088 }
3089
3090 case VBE_DISPI_INDEX_BPP: // bpp
3091 if (BX_VGA_THIS vbe.get_capabilities) {
3092 return BX_VGA_THIS vbe.max_bpp;
3093 } else {
3094 return BX_VGA_THIS vbe.bpp;
3095 }
3096
3097 case VBE_DISPI_INDEX_ENABLE: // vbe enabled
3098 retval = BX_VGA_THIS vbe.enabled;
3099 if (BX_VGA_THIS vbe.get_capabilities)
3100 retval |= VBE_DISPI_GETCAPS;
3101 if (BX_VGA_THIS vbe.dac_8bit)
3102 retval |= VBE_DISPI_8BIT_DAC;
3103 return retval;
3104
3105 case VBE_DISPI_INDEX_BANK: // current bank
3106 return BX_VGA_THIS vbe.bank;
3107
3108 case VBE_DISPI_INDEX_X_OFFSET:
3109 return BX_VGA_THIS vbe.offset_x;
3110
3111 case VBE_DISPI_INDEX_Y_OFFSET:
3112 return BX_VGA_THIS vbe.offset_y;
3113
3114 case VBE_DISPI_INDEX_VIRT_WIDTH:
3115 return BX_VGA_THIS vbe.virtual_xres;
3116
3117 case VBE_DISPI_INDEX_VIRT_HEIGHT:
3118 return BX_VGA_THIS vbe.virtual_yres;
3119
3120 case VBE_DISPI_INDEX_VIDEO_MEMORY_64K:
3121 return (VBE_DISPI_TOTAL_VIDEO_MEMORY_KB >> 6);
3122
3123 default:
3124 BX_PANIC(("VBE unknown data read index 0x%x",BX_VGA_THIS vbe.curindex));
3125 break;
3126 }
3127 }
3128 BX_PANIC(("VBE_read shouldn't reach this"));
3129 return 0; /* keep compiler happy */
3130 }
3131
3132 void bx_vga_c::vbe_write_handler(void *this_ptr, Bit32u address, Bit32u value, unsigned io_len)
3133 {
3134 #if BX_USE_VGA_SMF == 0
3135 bx_vga_c *class_ptr = (bx_vga_c *) this_ptr;
3136 class_ptr->vbe_write(address, value, io_len);
3137 }
3138
3139 Bit32u bx_vga_c::vbe_write(Bit32u address, Bit32u value, unsigned io_len)
3140 {
3141 #else
3142 UNUSED(this_ptr);
3143 #endif
3144 bx_bool new_vbe_8bit_dac;
3145 bx_bool needs_update = 0;
3146 unsigned i;
3147
3148 // BX_INFO(("VBE_write %x = %x (len %x)", address, value, io_len));
3149
3150 switch(address)
3151 {
3152 // index register
3153 case VBE_DISPI_IOPORT_INDEX:
3154
3155 BX_VGA_THIS vbe.curindex = (Bit16u) value;
3156 break;
3157
3158 // data register
3159 // FIXME: maybe do some 'sanity' checks on received data?
3160 case VBE_DISPI_IOPORT_DATA:
3161 switch (BX_VGA_THIS vbe.curindex)
3162 {
3163 case VBE_DISPI_INDEX_ID: // Display Interface ID check
3164 {
3165 if ((value == VBE_DISPI_ID0) ||
3166 (value == VBE_DISPI_ID1) ||
3167 (value == VBE_DISPI_ID2) ||
3168 (value == VBE_DISPI_ID3) ||
3169 (value == VBE_DISPI_ID4) ||
3170 (value == VBE_DISPI_ID5))
3171 {
3172 // allow backwards compatible with previous dispi bioses
3173 BX_VGA_THIS vbe.cur_dispi=value;
3174 }
3175 else
3176 {
3177 BX_PANIC(("VBE unknown Display Interface %x", value));
3178 }
3179
3180 // make sure we don't flood the logfile
3181 static int count=0;
3182 if (count < 100)
3183 {
3184 count++;
3185 BX_INFO(("VBE known Display Interface %x", value));
3186 }
3187 } break;
3188
3189 case VBE_DISPI_INDEX_XRES: // set xres
3190 {
3191 // check that we don't set xres during vbe enabled
3192 if (!BX_VGA_THIS vbe.enabled)
3193 {
3194 // check for within max xres range
3195 if (value <= VBE_DISPI_MAX_XRES)
3196 {
3197 BX_VGA_THIS vbe.xres=(Bit16u) value;
3198 BX_INFO(("VBE set xres (%d)", value));
3199 }
3200 else
3201 {
3202 BX_INFO(("VBE set xres more then max xres (%d)", value));
3203 }
3204 }
3205 else
3206 {
3207 BX_ERROR(("VBE set xres during vbe enabled!"));
3208 }
3209 } break;
3210
3211 case VBE_DISPI_INDEX_YRES: // set yres
3212 {
3213 // check that we don't set yres during vbe enabled
3214 if (!BX_VGA_THIS vbe.enabled)
3215 {
3216 // check for within max yres range
3217 if (value <= VBE_DISPI_MAX_YRES)
3218 {
3219 BX_VGA_THIS vbe.yres=(Bit16u) value;
3220 BX_INFO(("VBE set yres (%d)", value));
3221 }
3222 else
3223 {
3224 BX_INFO(("VBE set yres more then max yres (%d)", value));
3225 }
3226 }
3227 else
3228 {
3229 BX_ERROR(("VBE set yres during vbe enabled!"));
3230 }
3231 } break;
3232
3233 case VBE_DISPI_INDEX_BPP: // set bpp
3234 {
3235 // check that we don't set bpp during vbe enabled
3236 if (!BX_VGA_THIS vbe.enabled)
3237 {
3238 // for backward compatiblity
3239 if (value == 0) value = VBE_DISPI_BPP_8;
3240 // check for correct bpp range
3241 if ((value == VBE_DISPI_BPP_4) || (value == VBE_DISPI_BPP_8) || (value == VBE_DISPI_BPP_15) ||
3242 (value == VBE_DISPI_BPP_16) || (value == VBE_DISPI_BPP_24) || (value == VBE_DISPI_BPP_32))
3243 {
3244 BX_VGA_THIS vbe.bpp=(Bit16u) value;
3245 BX_INFO(("VBE set bpp (%d)", value));
3246 }
3247 else
3248 {
3249 BX_ERROR(("VBE set bpp with unknown bpp (%d)", value));
3250 }
3251 }
3252 else
3253 {
3254 BX_ERROR(("VBE set bpp during vbe enabled!"));
3255 }
3256 } break;
3257
3258 case VBE_DISPI_INDEX_BANK: // set bank
3259 {
3260 value=value & 0xff; // FIXME lobyte = vbe bank A?
3261 unsigned divider = (BX_VGA_THIS vbe.bpp!=VBE_DISPI_BPP_4)?64:256;
3262 // check for max bank nr
3263 if (value < (VBE_DISPI_TOTAL_VIDEO_MEMORY_KB / divider))
3264 {
3265 if (!BX_VGA_THIS vbe.lfb_enabled)
3266 {
3267 BX_DEBUG(("VBE set bank to %d", value));
3268 BX_VGA_THIS vbe.bank=value;
3269 }
3270 else
3271 {
3272 BX_ERROR(("VBE set bank in LFB mode ignored"));
3273 }
3274 }
3275 else
3276 {
3277 BX_ERROR(("VBE set invalid bank (%d)", value));
3278 }
3279 } break;
3280
3281 case VBE_DISPI_INDEX_ENABLE: // enable video
3282 {
3283 if ((value & VBE_DISPI_ENABLED) && !BX_VGA_THIS vbe.enabled)
3284 {
3285 unsigned depth=0;
3286
3287 // setup virtual resolution to be the same as current reso
3288 BX_VGA_THIS vbe.virtual_yres=BX_VGA_THIS vbe.yres;
3289 BX_VGA_THIS vbe.virtual_xres=BX_VGA_THIS vbe.xres;
3290
3291 // reset offset
3292 BX_VGA_THIS vbe.offset_x=0;
3293 BX_VGA_THIS vbe.offset_y=0;
3294 BX_VGA_THIS vbe.virtual_start=0;
3295
3296 switch((BX_VGA_THIS vbe.bpp))
3297 {
3298 // Default pixel sizes
3299 case VBE_DISPI_BPP_8:
3300 BX_VGA_THIS vbe.bpp_multiplier = 1;
3301 BX_VGA_THIS s.line_offset = BX_VGA_THIS vbe.virtual_xres;
3302 depth=8;
3303 break;
3304
3305 case VBE_DISPI_BPP_4:
3306 BX_VGA_THIS vbe.bpp_multiplier = 1;
3307 BX_VGA_THIS s.line_offset = (BX_VGA_THIS vbe.virtual_xres >> 3);
3308 depth=4;
3309 break;
3310
3311 case VBE_DISPI_BPP_15:
3312 BX_VGA_THIS vbe.bpp_multiplier = 2;
3313 BX_VGA_THIS s.line_offset = BX_VGA_THIS vbe.virtual_xres * 2;
3314 depth=15;
3315 break;
3316
3317 case VBE_DISPI_BPP_16:
3318 BX_VGA_THIS vbe.bpp_multiplier = 2;
3319 BX_VGA_THIS s.line_offset = BX_VGA_THIS vbe.virtual_xres * 2;
3320 depth=16;
3321 break;
3322
3323 case VBE_DISPI_BPP_24:
3324 BX_VGA_THIS vbe.bpp_multiplier = 3;
3325 BX_VGA_THIS s.line_offset = BX_VGA_THIS vbe.virtual_xres * 3;
3326 depth=24;
3327 break;
3328
3329 case VBE_DISPI_BPP_32:
3330 BX_VGA_THIS vbe.bpp_multiplier = 4;
3331 BX_VGA_THIS s.line_offset = BX_VGA_THIS vbe.virtual_xres << 2;
3332 depth=32;
3333 break;
3334 }
3335 BX_VGA_THIS vbe.visible_screen_size = BX_VGA_THIS s.line_offset * BX_VGA_THIS vbe.yres;
3336
3337 BX_INFO(("VBE enabling x %d, y %d, bpp %d, %u bytes visible", BX_VGA_THIS vbe.xres, BX_VGA_THIS vbe.yres, BX_VGA_THIS vbe.bpp, BX_VGA_THIS vbe.visible_screen_size));
3338
3339 if (depth > 4)
3340 {
3341 BX_VGA_THIS vbe.lfb_enabled=(bx_bool)(value & VBE_DISPI_LFB_ENABLED);
3342 if ((value & VBE_DISPI_NOCLEARMEM) == 0)
3343 {
3344 memset(BX_VGA_THIS s.memory, 0, BX_VGA_THIS vbe.visible_screen_size);
3345 }
3346 bx_gui->dimension_update(BX_VGA_THIS vbe.xres, BX_VGA_THIS vbe.yres, 0, 0, depth);
3347 BX_VGA_THIS s.last_bpp = depth;
3348 }
3349 }
3350 else if (((value & VBE_DISPI_ENABLED) == 0) && BX_VGA_THIS vbe.enabled)
3351 {
3352 BX_INFO(("VBE disabling"));
3353 BX_VGA_THIS vbe.lfb_enabled=0;
3354 }
3355 BX_VGA_THIS vbe.enabled=(bx_bool)(value & VBE_DISPI_ENABLED);
3356 BX_VGA_THIS vbe.get_capabilities=(bx_bool)((value & VBE_DISPI_GETCAPS) != 0);
3357 new_vbe_8bit_dac=(bx_bool)((value & VBE_DISPI_8BIT_DAC) != 0);
3358 if (new_vbe_8bit_dac != BX_VGA_THIS vbe.dac_8bit)
3359 {
3360 if (new_vbe_8bit_dac)
3361 {
3362 for (i=0; i<256; i++)
3363 {
3364 BX_VGA_THIS s.pel.data[i].red <<= 2;
3365 BX_VGA_THIS s.pel.data[i].green <<= 2;
3366 BX_VGA_THIS s.pel.data[i].blue <<= 2;
3367 }
3368 BX_INFO(("DAC in 8 bit mode"));
3369 }
3370 else
3371 {
3372 for (i=0; i<256; i++)
3373 {
3374 BX_VGA_THIS s.pel.data[i].red >>= 2;
3375 BX_VGA_THIS s.pel.data[i].green >>= 2;
3376 BX_VGA_THIS s.pel.data[i].blue >>= 2;
3377 }
3378 BX_INFO(("DAC in standard mode"));
3379 }
3380 BX_VGA_THIS vbe.dac_8bit=new_vbe_8bit_dac;
3381 needs_update = 1;
3382 }
3383 } break;
3384
3385 case VBE_DISPI_INDEX_X_OFFSET:
3386 {
3387 BX_DEBUG(("VBE offset x %d", value));
3388 BX_VGA_THIS vbe.offset_x=(Bit16u)value;
3389
3390 BX_VGA_THIS vbe.virtual_start = BX_VGA_THIS vbe.offset_y * BX_VGA_THIS s.line_offset;
3391 if (BX_VGA_THIS vbe.bpp != VBE_DISPI_BPP_4) {
3392 BX_VGA_THIS vbe.virtual_start += (BX_VGA_THIS vbe.offset_x * BX_VGA_THIS vbe.bpp_multiplier);
3393 } else {
3394 BX_VGA_THIS vbe.virtual_start += (BX_VGA_THIS vbe.offset_x >> 3);
3395 }
3396 needs_update = 1;
3397 } break;
3398
3399 case VBE_DISPI_INDEX_Y_OFFSET:
3400 {
3401 BX_DEBUG(("VBE offset y %d", value));
3402
3403 Bit32u new_screen_start = value * BX_VGA_THIS s.line_offset;
3404 if (BX_VGA_THIS vbe.bpp != VBE_DISPI_BPP_4) {
3405 if ((new_screen_start + BX_VGA_THIS vbe.visible_screen_size) > VBE_DISPI_TOTAL_VIDEO_MEMORY_BYTES)
3406 {
3407 BX_PANIC(("VBE offset y %d out of bounds", value));
3408 break;
3409 }
3410 new_screen_start += (BX_VGA_THIS vbe.offset_x * BX_VGA_THIS vbe.bpp_multiplier);
3411 } else {
3412 if ((new_screen_start + BX_VGA_THIS vbe.visible_screen_size) > (VBE_DISPI_TOTAL_VIDEO_MEMORY_BYTES / 4))
3413 {
3414 BX_PANIC(("VBE offset y %d out of bounds", value));
3415 break;
3416 }
3417 new_screen_start += (BX_VGA_THIS vbe.offset_x >> 3);
3418 }
3419 BX_VGA_THIS vbe.virtual_start = new_screen_start;
3420 BX_VGA_THIS vbe.offset_y = (Bit16u)value;
3421 needs_update = 1;
3422 } break;
3423
3424 case VBE_DISPI_INDEX_VIRT_WIDTH:
3425 {
3426 BX_INFO(("VBE requested virtual width %d", value));
3427
3428 // calculate virtual width & height dimensions
3429 // req:
3430 // virt_width > xres
3431 // virt_height >=yres
3432 // virt_width*virt_height < MAX_VIDEO_MEMORY
3433
3434 // basicly 2 situations
3435
3436 // situation 1:
3437 // MAX_VIDEO_MEMORY / virt_width >= yres
3438 // adjust result height
3439 // else
3440 // adjust result width based upon virt_height=yres
3441 Bit16u new_width=value;
3442 Bit16u new_height;
3443 if (BX_VGA_THIS vbe.bpp != VBE_DISPI_BPP_4) {
3444 new_height=(VBE_DISPI_TOTAL_VIDEO_MEMORY_BYTES / BX_VGA_THIS vbe.bpp_multiplier) / new_width;
3445 } else {
3446 new_height=(VBE_DISPI_TOTAL_VIDEO_MEMORY_BYTES * 2) / new_width;
3447 }
3448 if (new_height >=BX_VGA_THIS vbe.yres)
3449 {
3450 // we have a decent virtual width & new_height
3451 BX_INFO(("VBE decent virtual height %d",new_height));
3452 }
3453 else
3454 {
3455 // no decent virtual height: adjust width & height
3456 new_height=BX_VGA_THIS vbe.yres;
3457 if (BX_VGA_THIS vbe.bpp != VBE_DISPI_BPP_4) {
3458 new_width=(VBE_DISPI_TOTAL_VIDEO_MEMORY_BYTES / BX_VGA_THIS vbe.bpp_multiplier) / new_height;
3459 } else {
3460 new_width=(VBE_DISPI_TOTAL_VIDEO_MEMORY_BYTES * 2) / new_height;
3461 }
3462
3463 BX_INFO(("VBE recalc virtual width %d height %d",new_width, new_height));
3464 }
3465
3466 BX_VGA_THIS vbe.virtual_xres=new_width;
3467 BX_VGA_THIS vbe.virtual_yres=new_height;
3468 if (BX_VGA_THIS vbe.bpp != VBE_DISPI_BPP_4) {
3469 BX_VGA_THIS s.line_offset = BX_VGA_THIS vbe.virtual_xres * BX_VGA_THIS vbe.bpp_multiplier;
3470 } else {
3471 BX_VGA_THIS s.line_offset = BX_VGA_THIS vbe.virtual_xres >> 3;
3472 }
3473 BX_VGA_THIS vbe.visible_screen_size = BX_VGA_THIS s.line_offset * BX_VGA_THIS vbe.yres;
3474
3475 } break;
3476 case VBE_DISPI_INDEX_VIRT_HEIGHT:
3477 BX_ERROR(("VBE: write to virtual height register ignored"));
3478 break;
3479 default:
3480 BX_ERROR(("VBE: write unsupported register at index 0x%x",BX_VGA_THIS vbe.curindex));
3481 break;
3482 }
3483 if (needs_update) {
3484 BX_VGA_THIS s.vga_mem_updated = 1;
3485 for (unsigned xti = 0; xti < BX_NUM_X_TILES; xti++) {
3486 for (unsigned yti = 0; yti < BX_NUM_Y_TILES; yti++) {
3487 SET_TILE_UPDATED (xti, yti, 1);
3488 }
3489 }
3490 }
3491 break;
3492
3493 } // end switch address
3494 }
3495
3496 #endif
3497
This page was automatically generated by the
LXR engine.
Visit the LXR main site for more
information.