~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Bochs x86 Emulator
bochs/iodev/vga.cc

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

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.