1 /////////////////////////////////////////////////////////////////////////
2 // $Id: vga.cc,v 1.154 2008/09/18 20:16:27 sshwarts Exp $
3 /////////////////////////////////////////////////////////////////////////
5 // Copyright (C) 2002 MandrakeSoft S.A.
9 // 75002 Paris - France
10 // http://www.linux-mandrake.com/
11 // http://www.mandrakesoft.com/
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.
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.
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
26 /////////////////////////////////////////////////////////////////////////
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.
35 #define LOG_THIS theVga->
37 #define VGA_TRACE_FEATURE
39 // Only reference the array if the tile numbers are within the bounds
40 // of the array. If out of bounds, do nothing.
41 #define SET_TILE_UPDATED(xtile, ytile, value) \
43 if (((xtile) < BX_NUM_X_TILES) && ((ytile) < BX_NUM_Y_TILES)) \
44 BX_VGA_THIS s.vga_tile_updated[(xtile)][(ytile)] = value; \
47 // Only reference the array if the tile numbers are within the bounds
48 // of the array. If out of bounds, return 0.
49 #define GET_TILE_UPDATED(xtile,ytile) \
50 ((((xtile) < BX_NUM_X_TILES) && ((ytile) < BX_NUM_Y_TILES))? \
51 BX_VGA_THIS s.vga_tile_updated[(xtile)][(ytile)] \
54 static const Bit16u charmap_offset
[8] = {
55 0x0000, 0x4000, 0x8000, 0xc000,
56 0x2000, 0x6000, 0xa000, 0xe000
59 static const Bit8u ccdat
[16][4] = {
60 { 0x00, 0x00, 0x00, 0x00 },
61 { 0xff, 0x00, 0x00, 0x00 },
62 { 0x00, 0xff, 0x00, 0x00 },
63 { 0xff, 0xff, 0x00, 0x00 },
64 { 0x00, 0x00, 0xff, 0x00 },
65 { 0xff, 0x00, 0xff, 0x00 },
66 { 0x00, 0xff, 0xff, 0x00 },
67 { 0xff, 0xff, 0xff, 0x00 },
68 { 0x00, 0x00, 0x00, 0xff },
69 { 0xff, 0x00, 0x00, 0xff },
70 { 0x00, 0xff, 0x00, 0xff },
71 { 0xff, 0xff, 0x00, 0xff },
72 { 0x00, 0x00, 0xff, 0xff },
73 { 0xff, 0x00, 0xff, 0xff },
74 { 0x00, 0xff, 0xff, 0xff },
75 { 0xff, 0xff, 0xff, 0xff },
78 bx_vga_c
*theVga
= NULL
;
80 unsigned old_iHeight
= 0, old_iWidth
= 0, old_MSL
= 0;
82 #if BX_SUPPORT_CLGD54XX
83 void libvga_set_smf_pointer(bx_vga_c
*theVga_ptr
)
87 #else // BX_SUPPORT_CLGD54XX
88 int libvga_LTX_plugin_init(plugin_t
*plugin
, plugintype_t type
, int argc
, char *argv
[])
90 theVga
= new bx_vga_c();
91 bx_devices
.pluginVgaDevice
= theVga
;
92 BX_REGISTER_DEVICE_DEVMODEL(plugin
, type
, theVga
, BX_PLUGIN_VGA
);
96 void libvga_LTX_plugin_fini(void)
100 #endif // BX_SUPPORT_CLGD54XX
105 s
.vga_mem_updated
= 0;
106 s
.x_tilesize
= X_TILESIZE
;
107 s
.y_tilesize
= Y_TILESIZE
;
108 timer_id
= BX_NULL_TIMER_HANDLE
;
112 bx_vga_c::~bx_vga_c()
114 if (s
.memory
!= NULL
) {
118 SIM
->get_param_num(BXPN_VGA_UPDATE_INTERVAL
)->set_handler(NULL
);
122 void bx_vga_c::init(void)
127 Bit16u max_xres
, max_yres
, max_bpp
;
139 BX_VGA_THIS extension_init
= 0;
140 BX_VGA_THIS extension_checked
= 0;
141 #if !BX_SUPPORT_CLGD54XX
142 BX_VGA_THIS
init_iohandlers(read_handler
,write_handler
);
145 DEV_register_memory_handlers(theVga
, mem_read_handler
, mem_write_handler
,
148 BX_VGA_THIS s
.vga_enabled
= 1;
149 BX_VGA_THIS s
.misc_output
.color_emulation
= 1;
150 BX_VGA_THIS s
.misc_output
.enable_ram
= 1;
151 BX_VGA_THIS s
.misc_output
.clock_select
= 0;
152 BX_VGA_THIS s
.misc_output
.select_high_bank
= 0;
153 BX_VGA_THIS s
.misc_output
.horiz_sync_pol
= 1;
154 BX_VGA_THIS s
.misc_output
.vert_sync_pol
= 1;
156 BX_VGA_THIS s
.attribute_ctrl
.mode_ctrl
.graphics_alpha
= 0;
157 BX_VGA_THIS s
.attribute_ctrl
.mode_ctrl
.display_type
= 0;
158 BX_VGA_THIS s
.attribute_ctrl
.mode_ctrl
.enable_line_graphics
= 1;
159 BX_VGA_THIS s
.attribute_ctrl
.mode_ctrl
.blink_intensity
= 0;
160 BX_VGA_THIS s
.attribute_ctrl
.mode_ctrl
.pixel_panning_compat
= 0;
161 BX_VGA_THIS s
.attribute_ctrl
.mode_ctrl
.pixel_clock_select
= 0;
162 BX_VGA_THIS s
.attribute_ctrl
.mode_ctrl
.internal_palette_size
= 0;
164 BX_VGA_THIS s
.line_offset
=80;
165 BX_VGA_THIS s
.line_compare
=1023;
166 BX_VGA_THIS s
.vertical_display_end
=399;
168 for (i
=0; i
<=0x18; i
++)
169 BX_VGA_THIS s
.CRTC
.reg
[i
] = 0;
170 BX_VGA_THIS s
.CRTC
.address
= 0;
171 BX_VGA_THIS s
.CRTC
.write_protect
= 0;
173 BX_VGA_THIS s
.attribute_ctrl
.flip_flop
= 0;
174 BX_VGA_THIS s
.attribute_ctrl
.address
= 0;
175 BX_VGA_THIS s
.attribute_ctrl
.video_enabled
= 1;
177 BX_VGA_THIS s
.attribute_ctrl
.palette_reg
[i
] = 0;
178 BX_VGA_THIS s
.attribute_ctrl
.overscan_color
= 0;
179 BX_VGA_THIS s
.attribute_ctrl
.color_plane_enable
= 0x0f;
180 BX_VGA_THIS s
.attribute_ctrl
.horiz_pel_panning
= 0;
181 BX_VGA_THIS s
.attribute_ctrl
.color_select
= 0;
183 for (i
=0; i
<256; i
++) {
184 BX_VGA_THIS s
.pel
.data
[i
].red
= 0;
185 BX_VGA_THIS s
.pel
.data
[i
].green
= 0;
186 BX_VGA_THIS s
.pel
.data
[i
].blue
= 0;
188 BX_VGA_THIS s
.pel
.write_data_register
= 0;
189 BX_VGA_THIS s
.pel
.write_data_cycle
= 0;
190 BX_VGA_THIS s
.pel
.read_data_register
= 0;
191 BX_VGA_THIS s
.pel
.read_data_cycle
= 0;
192 BX_VGA_THIS s
.pel
.dac_state
= 0x01;
193 BX_VGA_THIS s
.pel
.mask
= 0xff;
195 BX_VGA_THIS s
.graphics_ctrl
.index
= 0;
196 BX_VGA_THIS s
.graphics_ctrl
.set_reset
= 0;
197 BX_VGA_THIS s
.graphics_ctrl
.enable_set_reset
= 0;
198 BX_VGA_THIS s
.graphics_ctrl
.color_compare
= 0;
199 BX_VGA_THIS s
.graphics_ctrl
.data_rotate
= 0;
200 BX_VGA_THIS s
.graphics_ctrl
.raster_op
= 0;
201 BX_VGA_THIS s
.graphics_ctrl
.read_map_select
= 0;
202 BX_VGA_THIS s
.graphics_ctrl
.write_mode
= 0;
203 BX_VGA_THIS s
.graphics_ctrl
.read_mode
= 0;
204 BX_VGA_THIS s
.graphics_ctrl
.odd_even
= 0;
205 BX_VGA_THIS s
.graphics_ctrl
.chain_odd_even
= 0;
206 BX_VGA_THIS s
.graphics_ctrl
.shift_reg
= 0;
207 BX_VGA_THIS s
.graphics_ctrl
.graphics_alpha
= 0;
208 BX_VGA_THIS s
.graphics_ctrl
.memory_mapping
= 2; // monochrome text mode
209 BX_VGA_THIS s
.graphics_ctrl
.color_dont_care
= 0;
210 BX_VGA_THIS s
.graphics_ctrl
.bitmask
= 0;
211 for (i
=0; i
<4; i
++) {
212 BX_VGA_THIS s
.graphics_ctrl
.latch
[i
] = 0;
215 BX_VGA_THIS s
.sequencer
.index
= 0;
216 BX_VGA_THIS s
.sequencer
.map_mask
= 0;
217 BX_VGA_THIS s
.sequencer
.reset1
= 1;
218 BX_VGA_THIS s
.sequencer
.reset2
= 1;
219 BX_VGA_THIS s
.sequencer
.reg1
= 0;
220 BX_VGA_THIS s
.sequencer
.char_map_select
= 0;
221 BX_VGA_THIS s
.sequencer
.extended_mem
= 1; // display mem greater than 64K
222 BX_VGA_THIS s
.sequencer
.odd_even
= 1; // use sequential addressing mode
223 BX_VGA_THIS s
.sequencer
.chain_four
= 0; // use map mask & read map select
225 extname
= SIM
->get_param_string(BXPN_VGA_EXTENSION
)->getptr();
226 if ((strlen(extname
) == 0) || (!strcmp(extname
, "none"))) {
227 BX_VGA_THIS s
.memsize
= 0x40000;
228 if (BX_VGA_THIS s
.memory
== NULL
)
229 BX_VGA_THIS s
.memory
= new Bit8u
[BX_VGA_THIS s
.memsize
];
230 memset(BX_VGA_THIS s
.memory
, 0, BX_VGA_THIS s
.memsize
);
233 BX_VGA_THIS s
.vga_mem_updated
= 0;
234 for (y
=0; y
<480/Y_TILESIZE
; y
++)
235 for (x
=0; x
<640/X_TILESIZE
; x
++)
236 SET_TILE_UPDATED (x
, y
, 0);
238 memset(argv
, 0, sizeof(argv
));
240 argv
[0] = (char *)"bochs";
241 len
= strlen(SIM
->get_param_string(BXPN_DISPLAYLIB_OPTIONS
)->getptr());
243 char *options
= new char[len
+ 1];
244 strcpy(options
, SIM
->get_param_string(BXPN_DISPLAYLIB_OPTIONS
)->getptr());
245 ptr
= strtok(options
, ",");
248 for (i
=0; i
<strlen(ptr
); i
++) {
249 if (!isspace(ptr
[i
])) string
[string_i
++] = ptr
[i
];
251 string
[string_i
] = '\0';
252 if (argv
[argc
] != NULL
) {
257 argv
[argc
++] = strdup(string
);
259 BX_PANIC (("too many parameters, max is 16\n"));
261 ptr
= strtok(NULL
, ",");
265 bx_gui
->init(argc
, argv
, BX_VGA_THIS s
.x_tilesize
, BX_VGA_THIS s
.y_tilesize
);
266 for (i
= 1; i
< (unsigned)argc
; i
++)
275 #if !BX_SUPPORT_CLGD54XX
276 BX_VGA_THIS
init_systemtimer(timer_handler
, vga_param_handler
);
277 #endif // !BX_SUPPORT_CLGD54XX
279 /* video card with BIOS ROM */
280 DEV_cmos_set_reg(0x14, (DEV_cmos_get_reg(0x14) & 0xcf) | 0x00);
282 BX_VGA_THIS s
.charmap_address
= 0;
283 BX_VGA_THIS s
.x_dotclockdiv2
= 0;
284 BX_VGA_THIS s
.y_doublescan
= 0;
285 BX_VGA_THIS s
.last_bpp
= 8;
288 // The following is for the vbe display extension
290 BX_VGA_THIS s
.vbe_enabled
=0;
291 BX_VGA_THIS s
.vbe_8bit_dac
=0;
292 if (!strcmp(extname
, "vbe")) {
293 for (addr
=VBE_DISPI_IOPORT_INDEX
; addr
<=VBE_DISPI_IOPORT_DATA
; addr
++) {
294 DEV_register_ioread_handler(this, vbe_read_handler
, addr
, "vga video", 7);
295 DEV_register_iowrite_handler(this, vbe_write_handler
, addr
, "vga video", 7);
297 if (!BX_SUPPORT_PCIUSB
|| !SIM
->get_param_bool(BXPN_USB1_ENABLED
)->get()) {
298 for (addr
=VBE_DISPI_IOPORT_INDEX_OLD
; addr
<=VBE_DISPI_IOPORT_DATA_OLD
; addr
++) {
299 DEV_register_ioread_handler(this, vbe_read_handler
, addr
, "vga video", 7);
300 DEV_register_iowrite_handler(this, vbe_write_handler
, addr
, "vga video", 7);
303 DEV_register_memory_handlers(theVga
, mem_read_handler
, mem_write_handler
,
304 VBE_DISPI_LFB_PHYSICAL_ADDRESS
,
305 VBE_DISPI_LFB_PHYSICAL_ADDRESS
+ VBE_DISPI_TOTAL_VIDEO_MEMORY_BYTES
- 1);
307 if (BX_VGA_THIS s
.memory
== NULL
)
308 BX_VGA_THIS s
.memory
= new Bit8u
[VBE_DISPI_TOTAL_VIDEO_MEMORY_BYTES
];
309 memset(BX_VGA_THIS s
.memory
, 0, VBE_DISPI_TOTAL_VIDEO_MEMORY_BYTES
);
310 BX_VGA_THIS s
.memsize
= VBE_DISPI_TOTAL_VIDEO_MEMORY_BYTES
;
311 BX_VGA_THIS s
.vbe_cur_dispi
=VBE_DISPI_ID0
;
312 BX_VGA_THIS s
.vbe_xres
=640;
313 BX_VGA_THIS s
.vbe_yres
=480;
314 BX_VGA_THIS s
.vbe_bpp
=8;
315 BX_VGA_THIS s
.vbe_bank
=0;
316 BX_VGA_THIS s
.vbe_curindex
=0;
317 BX_VGA_THIS s
.vbe_offset_x
=0;
318 BX_VGA_THIS s
.vbe_offset_y
=0;
319 BX_VGA_THIS s
.vbe_virtual_xres
=640;
320 BX_VGA_THIS s
.vbe_virtual_yres
=480;
321 BX_VGA_THIS s
.vbe_bpp_multiplier
=1;
322 BX_VGA_THIS s
.vbe_virtual_start
=0;
323 BX_VGA_THIS s
.vbe_lfb_enabled
=0;
324 BX_VGA_THIS s
.vbe_get_capabilities
=0;
325 bx_gui
->get_capabilities(&max_xres
, &max_yres
, &max_bpp
);
326 if (max_xres
> VBE_DISPI_MAX_XRES
) {
327 BX_VGA_THIS s
.vbe_max_xres
=VBE_DISPI_MAX_XRES
;
329 BX_VGA_THIS s
.vbe_max_xres
=max_xres
;
331 if (max_yres
> VBE_DISPI_MAX_YRES
) {
332 BX_VGA_THIS s
.vbe_max_yres
=VBE_DISPI_MAX_YRES
;
334 BX_VGA_THIS s
.vbe_max_yres
=max_yres
;
336 if (max_bpp
> VBE_DISPI_MAX_BPP
) {
337 BX_VGA_THIS s
.vbe_max_bpp
=VBE_DISPI_MAX_BPP
;
339 BX_VGA_THIS s
.vbe_max_bpp
=max_bpp
;
341 BX_VGA_THIS extension_init
= 1;
343 BX_INFO(("VBE Bochs Display Extension Enabled"));
348 void bx_vga_c::init_iohandlers(bx_read_handler_t f_read
, bx_write_handler_t f_write
)
351 Bit8u io_mask
[16] = {3, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1};
352 for (addr
=0x03B4; addr
<=0x03B5; addr
++) {
353 DEV_register_ioread_handler(this, f_read
, addr
, "vga video", 1);
354 DEV_register_iowrite_handler(this, f_write
, addr
, "vga video", 3);
357 for (addr
=0x03BA; addr
<=0x03BA; addr
++) {
358 DEV_register_ioread_handler(this, f_read
, addr
, "vga video", 1);
359 DEV_register_iowrite_handler(this, f_write
, addr
, "vga video", 3);
363 for (addr
=0x03C0; addr
<=0x03CF; addr
++) {
364 DEV_register_ioread_handler(this, f_read
, addr
, "vga video", io_mask
[i
++]);
365 DEV_register_iowrite_handler(this, f_write
, addr
, "vga video", 3);
368 for (addr
=0x03D4; addr
<=0x03D5; addr
++) {
369 DEV_register_ioread_handler(this, f_read
, addr
, "vga video", 3);
370 DEV_register_iowrite_handler(this, f_write
, addr
, "vga video", 3);
373 for (addr
=0x03DA; addr
<=0x03DA; addr
++) {
374 DEV_register_ioread_handler(this, f_read
, addr
, "vga video", 1);
375 DEV_register_iowrite_handler(this, f_write
, addr
, "vga video", 3);
379 void bx_vga_c::init_systemtimer(bx_timer_handler_t f_timer
, param_event_handler f_param
)
381 bx_param_num_c
*vga_update_interval
= SIM
->get_param_num(BXPN_VGA_UPDATE_INTERVAL
);
382 Bit64u interval
= vga_update_interval
->get();
383 BX_INFO(("interval=" FMT_LL
"u", interval
));
384 if (BX_VGA_THIS timer_id
== BX_NULL_TIMER_HANDLE
) {
385 BX_VGA_THIS timer_id
= bx_pc_system
.register_timer(this, f_timer
,
386 (Bit32u
)interval
, 1, 1, "vga");
387 vga_update_interval
->set_handler(f_param
);
388 vga_update_interval
->set_runtime_param(1);
390 if (interval
< 300000) {
391 BX_VGA_THIS s
.blink_counter
= 300000 / (unsigned)interval
;
393 BX_VGA_THIS s
.blink_counter
= 1;
397 void bx_vga_c::reset(unsigned type
)
399 if (!BX_VGA_THIS extension_checked
) {
400 char *strptr
= SIM
->get_param_string(BXPN_VGA_EXTENSION
)->getptr();
401 if (!BX_VGA_THIS extension_init
&&
402 (strlen(strptr
) > 0) &&
403 strcmp(strptr
, "none")) {
404 BX_PANIC(("unknown display extension: %s", strptr
));
406 BX_VGA_THIS extension_checked
= 1;
410 void bx_vga_c::register_state(void)
414 bx_list_c
*parent
, *reg
;
416 parent
= SIM
->get_bochs_root();
417 #if BX_SUPPORT_CLGD54XX
418 if (!strcmp(SIM
->get_param_string(BXPN_VGA_EXTENSION
)->getptr(), "cirrus")) {
419 parent
= (bx_list_c
*)SIM
->get_param("svga_cirrus", parent
);;
422 bx_list_c
*list
= new bx_list_c(parent
, "vga", "VGA Adapter State", 17);
423 bx_list_c
*misc
= new bx_list_c(list
, "misc_output", 6);
424 new bx_shadow_bool_c(misc
, "color_emulation", &BX_VGA_THIS s
.misc_output
.color_emulation
);
425 new bx_shadow_bool_c(misc
, "enable_ram", &BX_VGA_THIS s
.misc_output
.enable_ram
);
426 new bx_shadow_num_c(misc
, "clock_select", &BX_VGA_THIS s
.misc_output
.clock_select
);
427 new bx_shadow_bool_c(misc
, "select_high_bank", &BX_VGA_THIS s
.misc_output
.select_high_bank
);
428 new bx_shadow_bool_c(misc
, "horiz_sync_pol", &BX_VGA_THIS s
.misc_output
.horiz_sync_pol
);
429 new bx_shadow_bool_c(misc
, "vert_sync_pol", &BX_VGA_THIS s
.misc_output
.vert_sync_pol
);
430 bx_list_c
*crtc
= new bx_list_c(list
, "CRTC", 3);
431 new bx_shadow_num_c(crtc
, "address", &BX_VGA_THIS s
.CRTC
.address
, BASE_HEX
);
432 reg
= new bx_list_c(crtc
, "reg", 0x19);
433 for (i
=0; i
<=0x18; i
++) {
434 sprintf(name
, "0x%02x", i
);
435 new bx_shadow_num_c(reg
, name
, &BX_VGA_THIS s
.CRTC
.reg
[i
], BASE_HEX
);
437 new bx_shadow_bool_c(crtc
, "write_protect", &BX_VGA_THIS s
.CRTC
.write_protect
);
438 bx_list_c
*actl
= new bx_list_c(list
, "attribute_ctrl", 9);
439 new bx_shadow_bool_c(actl
, "flip_flop", &BX_VGA_THIS s
.attribute_ctrl
.flip_flop
);
440 new bx_shadow_num_c(actl
, "address", &BX_VGA_THIS s
.attribute_ctrl
.address
, BASE_HEX
);
441 new bx_shadow_bool_c(actl
, "video_enabled", &BX_VGA_THIS s
.attribute_ctrl
.video_enabled
);
442 reg
= new bx_list_c(actl
, "palette_reg", 16);
443 for (i
=0; i
<16; i
++) {
444 sprintf(name
, "0x%02x", i
);
445 new bx_shadow_num_c(reg
, name
, &BX_VGA_THIS s
.attribute_ctrl
.palette_reg
[i
], BASE_HEX
);
447 new bx_shadow_num_c(actl
, "overscan_color", &BX_VGA_THIS s
.attribute_ctrl
.overscan_color
, BASE_HEX
);
448 new bx_shadow_num_c(actl
, "color_plane_enable", &BX_VGA_THIS s
.attribute_ctrl
.color_plane_enable
, BASE_HEX
);
449 new bx_shadow_num_c(actl
, "horiz_pel_panning", &BX_VGA_THIS s
.attribute_ctrl
.horiz_pel_panning
, BASE_HEX
);
450 new bx_shadow_num_c(actl
, "color_select", &BX_VGA_THIS s
.attribute_ctrl
.color_select
, BASE_HEX
);
451 bx_list_c
*mode
= new bx_list_c(actl
, "mode_ctrl", 7);
452 new bx_shadow_bool_c(mode
, "graphics_alpha", &BX_VGA_THIS s
.attribute_ctrl
.mode_ctrl
.graphics_alpha
);
453 new bx_shadow_bool_c(mode
, "display_type", &BX_VGA_THIS s
.attribute_ctrl
.mode_ctrl
.display_type
);
454 new bx_shadow_bool_c(mode
, "enable_line_graphics", &BX_VGA_THIS s
.attribute_ctrl
.mode_ctrl
.enable_line_graphics
);
455 new bx_shadow_bool_c(mode
, "blink_intensity", &BX_VGA_THIS s
.attribute_ctrl
.mode_ctrl
.blink_intensity
);
456 new bx_shadow_bool_c(mode
, "pixel_panning_compat", &BX_VGA_THIS s
.attribute_ctrl
.mode_ctrl
.pixel_panning_compat
);
457 new bx_shadow_bool_c(mode
, "pixel_clock_select", &BX_VGA_THIS s
.attribute_ctrl
.mode_ctrl
.pixel_clock_select
);
458 new bx_shadow_bool_c(mode
, "internal_palette_size", &BX_VGA_THIS s
.attribute_ctrl
.mode_ctrl
.internal_palette_size
);
459 bx_list_c
*pel
= new bx_list_c(list
, "pel", 6);
460 new bx_shadow_num_c(pel
, "write_data_register", &BX_VGA_THIS s
.pel
.write_data_register
, BASE_HEX
);
461 new bx_shadow_num_c(pel
, "write_data_cycle", &BX_VGA_THIS s
.pel
.write_data_cycle
);
462 new bx_shadow_num_c(pel
, "read_data_register", &BX_VGA_THIS s
.pel
.read_data_register
, BASE_HEX
);
463 new bx_shadow_num_c(pel
, "read_data_cycle", &BX_VGA_THIS s
.pel
.read_data_cycle
);
464 new bx_shadow_num_c(pel
, "dac_state", &BX_VGA_THIS s
.pel
.dac_state
);
465 new bx_shadow_num_c(pel
, "mask", &BX_VGA_THIS s
.pel
.mask
, BASE_HEX
);
466 new bx_shadow_data_c(list
, "pel_data", &BX_VGA_THIS s
.pel
.data
[0].red
, sizeof(BX_VGA_THIS s
.pel
.data
));
467 bx_list_c
*gfxc
= new bx_list_c(list
, "graphics_ctrl", 20);
468 new bx_shadow_num_c(gfxc
, "index", &BX_VGA_THIS s
.graphics_ctrl
.index
);
469 new bx_shadow_num_c(gfxc
, "set_reset", &BX_VGA_THIS s
.graphics_ctrl
.set_reset
);
470 new bx_shadow_num_c(gfxc
, "enable_set_reset", &BX_VGA_THIS s
.graphics_ctrl
.enable_set_reset
);
471 new bx_shadow_num_c(gfxc
, "color_compare", &BX_VGA_THIS s
.graphics_ctrl
.color_compare
);
472 new bx_shadow_num_c(gfxc
, "data_rotate", &BX_VGA_THIS s
.graphics_ctrl
.data_rotate
);
473 new bx_shadow_num_c(gfxc
, "raster_op", &BX_VGA_THIS s
.graphics_ctrl
.raster_op
);
474 new bx_shadow_num_c(gfxc
, "read_map_select", &BX_VGA_THIS s
.graphics_ctrl
.read_map_select
);
475 new bx_shadow_num_c(gfxc
, "write_mode", &BX_VGA_THIS s
.graphics_ctrl
.write_mode
);
476 new bx_shadow_num_c(gfxc
, "read_mode", &BX_VGA_THIS s
.graphics_ctrl
.read_mode
);
477 new bx_shadow_bool_c(gfxc
, "odd_even", &BX_VGA_THIS s
.graphics_ctrl
.odd_even
);
478 new bx_shadow_bool_c(gfxc
, "chain_odd_even", &BX_VGA_THIS s
.graphics_ctrl
.chain_odd_even
);
479 new bx_shadow_num_c(gfxc
, "shift_reg", &BX_VGA_THIS s
.graphics_ctrl
.shift_reg
);
480 new bx_shadow_bool_c(gfxc
, "graphics_alpha", &BX_VGA_THIS s
.graphics_ctrl
.graphics_alpha
);
481 new bx_shadow_num_c(gfxc
, "memory_mapping", &BX_VGA_THIS s
.graphics_ctrl
.memory_mapping
);
482 new bx_shadow_num_c(gfxc
, "color_dont_care", &BX_VGA_THIS s
.graphics_ctrl
.color_dont_care
, BASE_HEX
);
483 new bx_shadow_num_c(gfxc
, "bitmask", &BX_VGA_THIS s
.graphics_ctrl
.bitmask
, BASE_HEX
);
484 new bx_shadow_num_c(gfxc
, "latch0", &BX_VGA_THIS s
.graphics_ctrl
.latch
[0], BASE_HEX
);
485 new bx_shadow_num_c(gfxc
, "latch1", &BX_VGA_THIS s
.graphics_ctrl
.latch
[1], BASE_HEX
);
486 new bx_shadow_num_c(gfxc
, "latch2", &BX_VGA_THIS s
.graphics_ctrl
.latch
[2], BASE_HEX
);
487 new bx_shadow_num_c(gfxc
, "latch3", &BX_VGA_THIS s
.graphics_ctrl
.latch
[3], BASE_HEX
);
488 bx_list_c
*sequ
= new bx_list_c(list
, "sequencer", 13);
489 new bx_shadow_num_c(sequ
, "index", &BX_VGA_THIS s
.sequencer
.index
);
490 new bx_shadow_num_c(sequ
, "map_mask", &BX_VGA_THIS s
.sequencer
.map_mask
);
491 new bx_shadow_bool_c(sequ
, "reset1", &BX_VGA_THIS s
.sequencer
.reset1
);
492 new bx_shadow_bool_c(sequ
, "reset2", &BX_VGA_THIS s
.sequencer
.reset2
);
493 new bx_shadow_num_c(sequ
, "reg1", &BX_VGA_THIS s
.sequencer
.reg1
, BASE_HEX
);
494 new bx_shadow_num_c(sequ
, "char_map_select", &BX_VGA_THIS s
.sequencer
.char_map_select
);
495 new bx_shadow_bool_c(sequ
, "extended_mem", &BX_VGA_THIS s
.sequencer
.extended_mem
);
496 new bx_shadow_bool_c(sequ
, "odd_even", &BX_VGA_THIS s
.sequencer
.odd_even
);
497 new bx_shadow_bool_c(sequ
, "chain_four", &BX_VGA_THIS s
.sequencer
.chain_four
);
498 new bx_shadow_bool_c(list
, "enabled", &BX_VGA_THIS s
.vga_enabled
);
499 new bx_shadow_num_c(list
, "line_offset", &BX_VGA_THIS s
.line_offset
);
500 new bx_shadow_num_c(list
, "line_compare", &BX_VGA_THIS s
.line_compare
);
501 new bx_shadow_num_c(list
, "vertical_display_end", &BX_VGA_THIS s
.vertical_display_end
);
502 new bx_shadow_num_c(list
, "charmap_address", &BX_VGA_THIS s
.charmap_address
);
503 new bx_shadow_bool_c(list
, "x_dotclockdiv2", &BX_VGA_THIS s
.x_dotclockdiv2
);
504 new bx_shadow_bool_c(list
, "y_doublescan", &BX_VGA_THIS s
.y_doublescan
);
505 new bx_shadow_num_c(list
, "last_bpp", &BX_VGA_THIS s
.last_bpp
);
506 new bx_shadow_data_c(list
, "memory", BX_VGA_THIS s
.memory
, BX_VGA_THIS s
.memsize
);
508 if (!strcmp(SIM
->get_param_string(BXPN_VGA_EXTENSION
)->getptr(), "vbe")) {
509 bx_list_c
*vbe
= new bx_list_c(list
, "vbe", 18);
510 new bx_shadow_num_c(vbe
, "cur_dispi", &BX_VGA_THIS s
.vbe_cur_dispi
, BASE_HEX
);
511 new bx_shadow_num_c(vbe
, "xres", &BX_VGA_THIS s
.vbe_xres
);
512 new bx_shadow_num_c(vbe
, "yres", &BX_VGA_THIS s
.vbe_yres
);
513 new bx_shadow_num_c(vbe
, "bpp", &BX_VGA_THIS s
.vbe_bpp
);
514 new bx_shadow_num_c(vbe
, "bank", &BX_VGA_THIS s
.vbe_bank
);
515 new bx_shadow_bool_c(vbe
, "enabled", &BX_VGA_THIS s
.vbe_enabled
);
516 new bx_shadow_num_c(vbe
, "curindex", &BX_VGA_THIS s
.vbe_curindex
);
517 new bx_shadow_num_c(vbe
, "visible_screen_size", &BX_VGA_THIS s
.vbe_visible_screen_size
);
518 new bx_shadow_num_c(vbe
, "offset_x", &BX_VGA_THIS s
.vbe_offset_x
);
519 new bx_shadow_num_c(vbe
, "offset_y", &BX_VGA_THIS s
.vbe_offset_y
);
520 new bx_shadow_num_c(vbe
, "virtual_xres", &BX_VGA_THIS s
.vbe_virtual_xres
);
521 new bx_shadow_num_c(vbe
, "virtual_yres", &BX_VGA_THIS s
.vbe_virtual_yres
);
522 new bx_shadow_num_c(vbe
, "virtual_start", &BX_VGA_THIS s
.vbe_virtual_start
);
523 new bx_shadow_num_c(vbe
, "bpp_multiplier", &BX_VGA_THIS s
.vbe_bpp_multiplier
);
524 new bx_shadow_bool_c(vbe
, "lfb_enabled", &BX_VGA_THIS s
.vbe_lfb_enabled
);
525 new bx_shadow_bool_c(vbe
, "get_capabilities", &BX_VGA_THIS s
.vbe_get_capabilities
);
526 new bx_shadow_bool_c(vbe
, "8bit_dac", &BX_VGA_THIS s
.vbe_8bit_dac
);
531 void bx_vga_c::after_restore_state(void)
533 for (unsigned i
=0; i
<256; i
++) {
535 if (BX_VGA_THIS s
.vbe_8bit_dac
) {
536 bx_gui
->palette_change(i
, BX_VGA_THIS s
.pel
.data
[i
].red
,
537 BX_VGA_THIS s
.pel
.data
[i
].green
,
538 BX_VGA_THIS s
.pel
.data
[i
].blue
);
543 bx_gui
->palette_change(i
, BX_VGA_THIS s
.pel
.data
[i
].red
<<2,
544 BX_VGA_THIS s
.pel
.data
[i
].green
<<2,
545 BX_VGA_THIS s
.pel
.data
[i
].blue
<<2);
548 bx_gui
->set_text_charmap(&BX_VGA_THIS s
.memory
[0x20000 + BX_VGA_THIS s
.charmap_address
]);
549 old_iWidth
= BX_MAX_XRES
;
550 old_iHeight
= BX_MAX_YRES
;
551 BX_VGA_THIS
redraw_area(0, 0, BX_MAX_XRES
, BX_MAX_YRES
);
553 if (BX_VGA_THIS s
.vbe_enabled
) {
554 bx_gui
->dimension_update(BX_VGA_THIS s
.vbe_xres
, BX_VGA_THIS s
.vbe_yres
, 0, 0,
555 BX_VGA_THIS s
.vbe_bpp
);
558 BX_VGA_THIS
update();
562 void bx_vga_c::determine_screen_dimensions(unsigned *piHeight
, unsigned *piWidth
)
566 for (i
= 0 ; i
< 0x20 ; i
++)
567 ai
[i
] = BX_VGA_THIS s
.CRTC
.reg
[i
];
570 v
= (ai
[18] | ((ai
[7] & 0x02) << 7) | ((ai
[7] & 0x40) << 3)) + 1;
572 if (BX_VGA_THIS s
.graphics_ctrl
.shift_reg
== 0)
577 if (BX_VGA_THIS s
.CRTC
.reg
[6] == 0xBF)
579 if (BX_VGA_THIS s
.CRTC
.reg
[23] == 0xA3 &&
580 BX_VGA_THIS s
.CRTC
.reg
[20] == 0x40 &&
581 BX_VGA_THIS s
.CRTC
.reg
[9] == 0x41)
587 if (BX_VGA_THIS s
.x_dotclockdiv2
) h
<<= 1;
592 else if ((h
>= 640) && (v
>= 480)) {
597 else if (BX_VGA_THIS s
.graphics_ctrl
.shift_reg
== 2)
600 if (BX_VGA_THIS s
.sequencer
.chain_four
)
613 if (BX_VGA_THIS s
.x_dotclockdiv2
) h
<<= 1;
619 // static IO port read callback handler
620 // redirects to non-static class handler to avoid virtual functions
622 Bit32u
bx_vga_c::read_handler(void *this_ptr
, Bit32u address
, unsigned io_len
)
624 #if BX_USE_VGA_SMF == 0
625 bx_vga_c
*class_ptr
= (bx_vga_c
*) this_ptr
;
626 return class_ptr
->read(address
, io_len
);
629 Bit32u
bx_vga_c::read(Bit32u address
, unsigned io_len
)
633 #endif // BX_USE_VGA_SMF == 0
634 bx_bool horiz_retrace
= 0, vert_retrace
= 0;
636 Bit16u ret16
, vertres
;
639 #if defined(VGA_TRACE_FEATURE)
641 #define RETURN(x) do { ret = (x); goto read_return; } while (0)
643 #define RETURN return
648 ret16
= bx_vga_c::read_handler(0, address
, 1);
649 ret16
|= (bx_vga_c::read_handler(0, address
+1, 1)) << 8;
651 ret16
= bx_vga_c::read(address
, 1);
652 ret16
|= (bx_vga_c::read(address
+1, 1) << 8;
658 if (bx_options
.videomode
== BX_VIDEO_DIRECT
)
660 return _inp(address
);
664 #if !defined(VGA_TRACE_FEATURE)
665 BX_DEBUG(("io read from 0x%04x", (unsigned) address
));
668 if ((address
>= 0x03b0) && (address
<= 0x03bf) &&
669 (BX_VGA_THIS s
.misc_output
.color_emulation
)) {
672 if ((address
>= 0x03d0) && (address
<= 0x03df) &&
673 (BX_VGA_THIS s
.misc_output
.color_emulation
==0)) {
678 case 0x03ba: /* Input Status 1 (monochrome emulation modes) */
679 case 0x03ca: /* Feature Control ??? */
680 case 0x03da: /* Input Status 1 (color emulation modes) */
681 // bit3: Vertical Retrace
682 // 0 = display is in the display mode
683 // 1 = display is in the vertical retrace mode
684 // bit0: Display Enable
685 // 0 = display is in the display mode
686 // 1 = display is not in the display mode; either the
687 // horizontal or vertical retrace period is active
689 // using 72 Hz vertical frequency
690 usec
= bx_pc_system
.time_usec();
691 switch ((BX_VGA_THIS s
.misc_output
.vert_sync_pol
<< 1) | BX_VGA_THIS s
.misc_output
.horiz_sync_pol
)
693 case 0: vertres
= 200; break;
694 case 1: vertres
= 400; break;
695 case 2: vertres
= 350; break;
696 default: vertres
= 480; break;
698 if ((usec
% 13888) < 70) {
701 if ((usec
% (13888 / vertres
)) == 0) {
706 if (horiz_retrace
|| vert_retrace
)
711 /* reading this port resets the flip-flop to address mode */
712 BX_VGA_THIS s
.attribute_ctrl
.flip_flop
= 0;
718 if (BX_VGA_THIS s
.attribute_ctrl
.flip_flop
== 0) {
719 //BX_INFO(("io read: 0x3c0: flip_flop = 0"));
721 (BX_VGA_THIS s
.attribute_ctrl
.video_enabled
<< 5) |
722 BX_VGA_THIS s
.attribute_ctrl
.address
;
726 BX_ERROR(("io read: 0x3c0: flip_flop != 0"));
732 switch (BX_VGA_THIS s
.attribute_ctrl
.address
) {
733 case 0x00: case 0x01: case 0x02: case 0x03:
734 case 0x04: case 0x05: case 0x06: case 0x07:
735 case 0x08: case 0x09: case 0x0a: case 0x0b:
736 case 0x0c: case 0x0d: case 0x0e: case 0x0f:
737 retval
= BX_VGA_THIS s
.attribute_ctrl
.palette_reg
[BX_VGA_THIS s
.attribute_ctrl
.address
];
740 case 0x10: /* mode control register */
742 (BX_VGA_THIS s
.attribute_ctrl
.mode_ctrl
.graphics_alpha
<< 0) |
743 (BX_VGA_THIS s
.attribute_ctrl
.mode_ctrl
.display_type
<< 1) |
744 (BX_VGA_THIS s
.attribute_ctrl
.mode_ctrl
.enable_line_graphics
<< 2) |
745 (BX_VGA_THIS s
.attribute_ctrl
.mode_ctrl
.blink_intensity
<< 3) |
746 (BX_VGA_THIS s
.attribute_ctrl
.mode_ctrl
.pixel_panning_compat
<< 5) |
747 (BX_VGA_THIS s
.attribute_ctrl
.mode_ctrl
.pixel_clock_select
<< 6) |
748 (BX_VGA_THIS s
.attribute_ctrl
.mode_ctrl
.internal_palette_size
<< 7);
751 case 0x11: /* overscan color register */
752 RETURN(BX_VGA_THIS s
.attribute_ctrl
.overscan_color
);
754 case 0x12: /* color plane enable */
755 RETURN(BX_VGA_THIS s
.attribute_ctrl
.color_plane_enable
);
757 case 0x13: /* horizontal PEL panning register */
758 RETURN(BX_VGA_THIS s
.attribute_ctrl
.horiz_pel_panning
);
760 case 0x14: /* color select register */
761 RETURN(BX_VGA_THIS s
.attribute_ctrl
.color_select
);
764 BX_INFO(("io read: 0x3c1: unknown register 0x%02x",
765 (unsigned) BX_VGA_THIS s
.attribute_ctrl
.address
));
770 case 0x03c2: /* Input Status 0 */
771 BX_DEBUG(("io read 0x3c2: input status #0: ignoring"));
775 case 0x03c3: /* VGA Enable Register */
776 RETURN(BX_VGA_THIS s
.vga_enabled
);
779 case 0x03c4: /* Sequencer Index Register */
780 RETURN(BX_VGA_THIS s
.sequencer
.index
);
783 case 0x03c5: /* Sequencer Registers 00..04 */
784 switch (BX_VGA_THIS s
.sequencer
.index
) {
785 case 0: /* sequencer: reset */
786 BX_DEBUG(("io read 0x3c5: sequencer reset"));
787 RETURN(BX_VGA_THIS s
.sequencer
.reset1
| (BX_VGA_THIS s
.sequencer
.reset2
<<1));
789 case 1: /* sequencer: clocking mode */
790 BX_DEBUG(("io read 0x3c5: sequencer clocking mode"));
791 RETURN(BX_VGA_THIS s
.sequencer
.reg1
);
793 case 2: /* sequencer: map mask register */
794 RETURN(BX_VGA_THIS s
.sequencer
.map_mask
);
796 case 3: /* sequencer: character map select register */
797 RETURN(BX_VGA_THIS s
.sequencer
.char_map_select
);
799 case 4: /* sequencer: memory mode register */
801 (BX_VGA_THIS s
.sequencer
.extended_mem
<< 1) |
802 (BX_VGA_THIS s
.sequencer
.odd_even
<< 2) |
803 (BX_VGA_THIS s
.sequencer
.chain_four
<< 3);
808 BX_DEBUG(("io read 0x3c5: index %u unhandled",
809 (unsigned) BX_VGA_THIS s
.sequencer
.index
));
814 case 0x03c6: /* PEL mask ??? */
815 RETURN(BX_VGA_THIS s
.pel
.mask
);
818 case 0x03c7: /* DAC state, read = 11b, write = 00b */
819 RETURN(BX_VGA_THIS s
.pel
.dac_state
);
822 case 0x03c8: /* PEL address write mode */
823 RETURN(BX_VGA_THIS s
.pel
.write_data_register
);
826 case 0x03c9: /* PEL Data Register, colors 00..FF */
827 if (BX_VGA_THIS s
.pel
.dac_state
== 0x03) {
828 switch (BX_VGA_THIS s
.pel
.read_data_cycle
) {
830 retval
= BX_VGA_THIS s
.pel
.data
[BX_VGA_THIS s
.pel
.read_data_register
].red
;
833 retval
= BX_VGA_THIS s
.pel
.data
[BX_VGA_THIS s
.pel
.read_data_register
].green
;
836 retval
= BX_VGA_THIS s
.pel
.data
[BX_VGA_THIS s
.pel
.read_data_register
].blue
;
839 retval
= 0; // keep compiler happy
841 BX_VGA_THIS s
.pel
.read_data_cycle
++;
842 if (BX_VGA_THIS s
.pel
.read_data_cycle
>= 3) {
843 BX_VGA_THIS s
.pel
.read_data_cycle
= 0;
844 BX_VGA_THIS s
.pel
.read_data_register
++;
853 case 0x03cc: /* Miscellaneous Output / Graphics 1 Position ??? */
855 ((BX_VGA_THIS s
.misc_output
.color_emulation
& 0x01) << 0) |
856 ((BX_VGA_THIS s
.misc_output
.enable_ram
& 0x01) << 1) |
857 ((BX_VGA_THIS s
.misc_output
.clock_select
& 0x03) << 2) |
858 ((BX_VGA_THIS s
.misc_output
.select_high_bank
& 0x01) << 5) |
859 ((BX_VGA_THIS s
.misc_output
.horiz_sync_pol
& 0x01) << 6) |
860 ((BX_VGA_THIS s
.misc_output
.vert_sync_pol
& 0x01) << 7);
864 case 0x03ce: /* Graphics Controller Index Register */
865 RETURN(BX_VGA_THIS s
.graphics_ctrl
.index
);
868 case 0x03cd: /* ??? */
869 BX_DEBUG(("io read from 03cd"));
873 case 0x03cf: /* Graphics Controller Registers 00..08 */
874 switch (BX_VGA_THIS s
.graphics_ctrl
.index
) {
875 case 0: /* Set/Reset */
876 RETURN(BX_VGA_THIS s
.graphics_ctrl
.set_reset
);
878 case 1: /* Enable Set/Reset */
879 RETURN(BX_VGA_THIS s
.graphics_ctrl
.enable_set_reset
);
881 case 2: /* Color Compare */
882 RETURN(BX_VGA_THIS s
.graphics_ctrl
.color_compare
);
884 case 3: /* Data Rotate */
886 ((BX_VGA_THIS s
.graphics_ctrl
.raster_op
& 0x03) << 3) |
887 ((BX_VGA_THIS s
.graphics_ctrl
.data_rotate
& 0x07) << 0);
890 case 4: /* Read Map Select */
891 RETURN(BX_VGA_THIS s
.graphics_ctrl
.read_map_select
);
895 ((BX_VGA_THIS s
.graphics_ctrl
.shift_reg
& 0x03) << 5) |
896 ((BX_VGA_THIS s
.graphics_ctrl
.odd_even
& 0x01) << 4) |
897 ((BX_VGA_THIS s
.graphics_ctrl
.read_mode
& 0x01) << 3) |
898 ((BX_VGA_THIS s
.graphics_ctrl
.write_mode
& 0x03) << 0);
900 if (BX_VGA_THIS s
.graphics_ctrl
.odd_even
||
901 BX_VGA_THIS s
.graphics_ctrl
.shift_reg
)
902 BX_DEBUG(("io read 0x3cf: reg 05 = 0x%02x", (unsigned) retval
));
905 case 6: /* Miscellaneous */
907 ((BX_VGA_THIS s
.graphics_ctrl
.memory_mapping
& 0x03) << 2) |
908 ((BX_VGA_THIS s
.graphics_ctrl
.odd_even
& 0x01) << 1) |
909 ((BX_VGA_THIS s
.graphics_ctrl
.graphics_alpha
& 0x01) << 0);
912 case 7: /* Color Don't Care */
913 RETURN(BX_VGA_THIS s
.graphics_ctrl
.color_dont_care
);
915 case 8: /* Bit Mask */
916 RETURN(BX_VGA_THIS s
.graphics_ctrl
.bitmask
);
920 BX_DEBUG(("io read: 0x3cf: index %u unhandled",
921 (unsigned) BX_VGA_THIS s
.graphics_ctrl
.index
));
926 case 0x03d4: /* CRTC Index Register (color emulation modes) */
927 RETURN(BX_VGA_THIS s
.CRTC
.address
);
930 case 0x03b5: /* CRTC Registers (monochrome emulation modes) */
931 case 0x03d5: /* CRTC Registers (color emulation modes) */
932 if (BX_VGA_THIS s
.CRTC
.address
> 0x18) {
933 BX_DEBUG(("io read: invalid CRTC register 0x%02x",
934 (unsigned) BX_VGA_THIS s
.CRTC
.address
));
937 RETURN(BX_VGA_THIS s
.CRTC
.reg
[BX_VGA_THIS s
.CRTC
.address
]);
940 case 0x03b4: /* CRTC Index Register (monochrome emulation modes) */
941 case 0x03cb: /* not sure but OpenBSD reads it a lot */
943 BX_INFO(("io read from vga port 0x%04x", (unsigned) address
));
944 RETURN(0); /* keep compiler happy */
947 #if defined(VGA_TRACE_FEATURE)
950 BX_DEBUG(("8-bit read from 0x%04x = 0x%02x", (unsigned) address
, ret
));
952 BX_DEBUG(("16-bit read from 0x%04x = 0x%04x", (unsigned) address
, ret
));
957 #if defined(VGA_TRACE_FEATURE)
961 // static IO port write callback handler
962 // redirects to non-static class handler to avoid virtual functions
964 void bx_vga_c::write_handler(void *this_ptr
, Bit32u address
, Bit32u value
, unsigned io_len
)
966 #if BX_USE_VGA_SMF == 0
967 bx_vga_c
*class_ptr
= (bx_vga_c
*) this_ptr
;
968 class_ptr
->write(address
, value
, io_len
, 0);
971 theVga
->write(address
, value
, io_len
, 0);
976 void bx_vga_c::write_handler_no_log(void *this_ptr
, Bit32u address
, Bit32u value
, unsigned io_len
)
979 theVga
->write(address
, value
, io_len
, 1);
983 void bx_vga_c::write(Bit32u address
, Bit32u value
, unsigned io_len
, bx_bool no_log
)
985 Bit8u charmap1
, charmap2
, prev_memory_mapping
;
986 bx_bool prev_video_enabled
, prev_line_graphics
, prev_int_pal_size
;
987 bx_bool prev_graphics_alpha
, prev_chain_odd_even
;
988 bx_bool needs_update
= 0;
990 #if defined(VGA_TRACE_FEATURE)
994 BX_DEBUG(("8-bit write to %04x = %02x", (unsigned)address
, (unsigned)value
));
997 BX_DEBUG(("16-bit write to %04x = %04x", (unsigned)address
, (unsigned)value
));
1000 BX_PANIC(("Weird VGA write size"));
1004 BX_DEBUG(("io write to 0x%04x = 0x%02x", (unsigned) address
,
1011 bx_vga_c::write_handler_no_log(0, address
, value
& 0xff, 1);
1012 bx_vga_c::write_handler_no_log(0, address
+1, (value
>> 8) & 0xff, 1);
1014 bx_vga_c::write(address
, value
& 0xff, 1, 1);
1015 bx_vga_c::write(address
+1, (value
>> 8) & 0xff, 1, 1);
1021 if (bx_options
.videomode
== BX_VIDEO_DIRECT
)
1023 _outp(address
, value
);
1028 if ((address
>= 0x03b0) && (address
<= 0x03bf) &&
1029 (BX_VGA_THIS s
.misc_output
.color_emulation
))
1031 if ((address
>= 0x03d0) && (address
<= 0x03df) &&
1032 (BX_VGA_THIS s
.misc_output
.color_emulation
==0))
1036 case 0x03ba: /* Feature Control (monochrome emulation modes) */
1037 #if !defined(VGA_TRACE_FEATURE)
1038 BX_DEBUG(("io write 3ba: feature control: ignoring"));
1042 case 0x03c0: /* Attribute Controller */
1043 if (BX_VGA_THIS s
.attribute_ctrl
.flip_flop
== 0) { /* address mode */
1044 prev_video_enabled
= BX_VGA_THIS s
.attribute_ctrl
.video_enabled
;
1045 BX_VGA_THIS s
.attribute_ctrl
.video_enabled
= (value
>> 5) & 0x01;
1046 #if !defined(VGA_TRACE_FEATURE)
1047 BX_DEBUG(("io write 3c0: video_enabled = %u",
1048 (unsigned) BX_VGA_THIS s
.attribute_ctrl
.video_enabled
));
1050 if (BX_VGA_THIS s
.attribute_ctrl
.video_enabled
== 0)
1051 bx_gui
->clear_screen();
1052 else if (!prev_video_enabled
) {
1053 #if !defined(VGA_TRACE_FEATURE)
1054 BX_DEBUG(("found enable transition"));
1058 value
&= 0x1f; /* address = bits 0..4 */
1059 BX_VGA_THIS s
.attribute_ctrl
.address
= value
;
1061 case 0x00: case 0x01: case 0x02: case 0x03:
1062 case 0x04: case 0x05: case 0x06: case 0x07:
1063 case 0x08: case 0x09: case 0x0a: case 0x0b:
1064 case 0x0c: case 0x0d: case 0x0e: case 0x0f:
1068 BX_DEBUG(("io write 0x3c0: address mode reg=0x%02x",
1072 else { /* data-write mode */
1073 switch (BX_VGA_THIS s
.attribute_ctrl
.address
) {
1074 case 0x00: case 0x01: case 0x02: case 0x03:
1075 case 0x04: case 0x05: case 0x06: case 0x07:
1076 case 0x08: case 0x09: case 0x0a: case 0x0b:
1077 case 0x0c: case 0x0d: case 0x0e: case 0x0f:
1078 if (value
!= BX_VGA_THIS s
.attribute_ctrl
.palette_reg
[BX_VGA_THIS s
.attribute_ctrl
.address
]) {
1079 BX_VGA_THIS s
.attribute_ctrl
.palette_reg
[BX_VGA_THIS s
.attribute_ctrl
.address
] =
1084 case 0x10: // mode control register
1085 prev_line_graphics
= BX_VGA_THIS s
.attribute_ctrl
.mode_ctrl
.enable_line_graphics
;
1086 prev_int_pal_size
= BX_VGA_THIS s
.attribute_ctrl
.mode_ctrl
.internal_palette_size
;
1087 BX_VGA_THIS s
.attribute_ctrl
.mode_ctrl
.graphics_alpha
=
1088 (value
>> 0) & 0x01;
1089 BX_VGA_THIS s
.attribute_ctrl
.mode_ctrl
.display_type
=
1090 (value
>> 1) & 0x01;
1091 BX_VGA_THIS s
.attribute_ctrl
.mode_ctrl
.enable_line_graphics
=
1092 (value
>> 2) & 0x01;
1093 BX_VGA_THIS s
.attribute_ctrl
.mode_ctrl
.blink_intensity
=
1094 (value
>> 3) & 0x01;
1095 BX_VGA_THIS s
.attribute_ctrl
.mode_ctrl
.pixel_panning_compat
=
1096 (value
>> 5) & 0x01;
1097 BX_VGA_THIS s
.attribute_ctrl
.mode_ctrl
.pixel_clock_select
=
1098 (value
>> 6) & 0x01;
1099 BX_VGA_THIS s
.attribute_ctrl
.mode_ctrl
.internal_palette_size
=
1100 (value
>> 7) & 0x01;
1101 if (((value
>> 2) & 0x01) != prev_line_graphics
) {
1102 bx_gui
->set_text_charmap(
1103 & BX_VGA_THIS s
.memory
[0x20000 + BX_VGA_THIS s
.charmap_address
]);
1104 BX_VGA_THIS s
.vga_mem_updated
= 1;
1106 if (((value
>> 7) & 0x01) != prev_int_pal_size
) {
1109 #if !defined(VGA_TRACE_FEATURE)
1110 BX_DEBUG(("io write 0x3c0: mode control: 0x%02x",
1114 case 0x11: // Overscan Color Register
1115 BX_VGA_THIS s
.attribute_ctrl
.overscan_color
= (value
& 0x3f);
1116 #if !defined(VGA_TRACE_FEATURE)
1117 BX_DEBUG(("io write 0x3c0: overscan color = 0x%02x",
1121 case 0x12: // Color Plane Enable Register
1122 BX_VGA_THIS s
.attribute_ctrl
.color_plane_enable
= (value
& 0x0f);
1124 #if !defined(VGA_TRACE_FEATURE)
1125 BX_DEBUG(("io write 0x3c0: color plane enable = 0x%02x",
1129 case 0x13: // Horizontal Pixel Panning Register
1130 BX_VGA_THIS s
.attribute_ctrl
.horiz_pel_panning
= (value
& 0x0f);
1132 #if !defined(VGA_TRACE_FEATURE)
1133 BX_DEBUG(("io write 0x3c0: horiz pel panning = 0x%02x",
1137 case 0x14: // Color Select Register
1138 BX_VGA_THIS s
.attribute_ctrl
.color_select
= (value
& 0x0f);
1140 #if !defined(VGA_TRACE_FEATURE)
1141 BX_DEBUG(("io write 0x3c0: color select = 0x%02x",
1142 (unsigned) BX_VGA_THIS s
.attribute_ctrl
.color_select
));
1146 BX_DEBUG(("io write 0x3c0: data-write mode 0x%02x",
1147 (unsigned) BX_VGA_THIS s
.attribute_ctrl
.address
));
1150 BX_VGA_THIS s
.attribute_ctrl
.flip_flop
= !BX_VGA_THIS s
.attribute_ctrl
.flip_flop
;
1153 case 0x03c2: // Miscellaneous Output Register
1154 BX_VGA_THIS s
.misc_output
.color_emulation
= (value
>> 0) & 0x01;
1155 BX_VGA_THIS s
.misc_output
.enable_ram
= (value
>> 1) & 0x01;
1156 BX_VGA_THIS s
.misc_output
.clock_select
= (value
>> 2) & 0x03;
1157 BX_VGA_THIS s
.misc_output
.select_high_bank
= (value
>> 5) & 0x01;
1158 BX_VGA_THIS s
.misc_output
.horiz_sync_pol
= (value
>> 6) & 0x01;
1159 BX_VGA_THIS s
.misc_output
.vert_sync_pol
= (value
>> 7) & 0x01;
1160 #if !defined(VGA_TRACE_FEATURE)
1161 BX_DEBUG(("io write 3c2:"));
1162 BX_DEBUG((" color_emulation (attempted) = %u",
1163 (value
>> 0) & 0x01));
1164 BX_DEBUG((" enable_ram = %u",
1165 (unsigned) BX_VGA_THIS s
.misc_output
.enable_ram
));
1166 BX_DEBUG((" clock_select = %u",
1167 (unsigned) BX_VGA_THIS s
.misc_output
.clock_select
));
1168 BX_DEBUG((" select_high_bank = %u",
1169 (unsigned) BX_VGA_THIS s
.misc_output
.select_high_bank
));
1170 BX_DEBUG((" horiz_sync_pol = %u",
1171 (unsigned) BX_VGA_THIS s
.misc_output
.horiz_sync_pol
));
1172 BX_DEBUG((" vert_sync_pol = %u",
1173 (unsigned) BX_VGA_THIS s
.misc_output
.vert_sync_pol
));
1177 case 0x03c3: // VGA enable
1178 // bit0: enables VGA display if set
1179 BX_VGA_THIS s
.vga_enabled
= value
& 0x01;
1180 #if !defined(VGA_TRACE_FEATURE)
1181 BX_DEBUG(("io write 0x03c3: VGA enable = %u", BX_VGA_THIS s
.vga_enabled
));
1185 case 0x03c4: /* Sequencer Index Register */
1187 BX_DEBUG(("io write 3c4: value > 4"));
1189 BX_VGA_THIS s
.sequencer
.index
= value
;
1192 case 0x03c5: /* Sequencer Registers 00..04 */
1193 switch (BX_VGA_THIS s
.sequencer
.index
) {
1194 case 0: /* sequencer: reset */
1195 #if !defined(VGA_TRACE_FEATURE)
1196 BX_DEBUG(("write 0x3c5: sequencer reset: value=0x%02x",
1199 if (BX_VGA_THIS s
.sequencer
.reset1
&& ((value
& 0x01) == 0)) {
1200 BX_VGA_THIS s
.sequencer
.char_map_select
= 0;
1201 BX_VGA_THIS s
.charmap_address
= 0;
1202 bx_gui
->set_text_charmap(
1203 & BX_VGA_THIS s
.memory
[0x20000 + BX_VGA_THIS s
.charmap_address
]);
1204 BX_VGA_THIS s
.vga_mem_updated
= 1;
1206 BX_VGA_THIS s
.sequencer
.reset1
= (value
>> 0) & 0x01;
1207 BX_VGA_THIS s
.sequencer
.reset2
= (value
>> 1) & 0x01;
1209 case 1: /* sequencer: clocking mode */
1210 #if !defined(VGA_TRACE_FEATURE)
1211 BX_DEBUG(("io write 0x3c5=0x%02x: clocking mode reg: ignoring",
1214 if ((value
& 0x20) > 0) {
1215 bx_gui
->clear_screen();
1216 } else if ((BX_VGA_THIS s
.sequencer
.reg1
& 0x20) > 0) {
1219 BX_VGA_THIS s
.sequencer
.reg1
= value
& 0x3d;
1220 BX_VGA_THIS s
.x_dotclockdiv2
= ((value
& 0x08) > 0);
1222 case 2: /* sequencer: map mask register */
1223 BX_VGA_THIS s
.sequencer
.map_mask
= (value
& 0x0f);
1225 case 3: /* sequencer: character map select register */
1226 BX_VGA_THIS s
.sequencer
.char_map_select
= value
& 0x3f;
1227 charmap1
= value
& 0x13;
1228 if (charmap1
> 3) charmap1
= (charmap1
& 3) + 4;
1229 charmap2
= (value
& 0x2C) >> 2;
1230 if (charmap2
> 3) charmap2
= (charmap2
& 3) + 4;
1231 if (BX_VGA_THIS s
.CRTC
.reg
[0x09] > 0) {
1232 BX_VGA_THIS s
.charmap_address
= charmap_offset
[charmap1
];
1233 bx_gui
->set_text_charmap(
1234 & BX_VGA_THIS s
.memory
[0x20000 + BX_VGA_THIS s
.charmap_address
]);
1235 BX_VGA_THIS s
.vga_mem_updated
= 1;
1237 if (charmap2
!= charmap1
)
1238 BX_INFO(("char map select: map #2 in block #%d unused", charmap2
));
1240 case 4: /* sequencer: memory mode register */
1241 BX_VGA_THIS s
.sequencer
.extended_mem
= (value
>> 1) & 0x01;
1242 BX_VGA_THIS s
.sequencer
.odd_even
= (value
>> 2) & 0x01;
1243 BX_VGA_THIS s
.sequencer
.chain_four
= (value
>> 3) & 0x01;
1245 #if !defined(VGA_TRACE_FEATURE)
1246 BX_DEBUG(("io write 0x3c5: memory mode:"));
1247 BX_DEBUG((" extended_mem = %u",
1248 (unsigned) BX_VGA_THIS s
.sequencer
.extended_mem
));
1249 BX_DEBUG((" odd_even = %u",
1250 (unsigned) BX_VGA_THIS s
.sequencer
.odd_even
));
1251 BX_DEBUG((" chain_four = %u",
1252 (unsigned) BX_VGA_THIS s
.sequencer
.chain_four
));
1256 BX_DEBUG(("io write 0x3c5: index 0x%02x unhandled",
1257 (unsigned) BX_VGA_THIS s
.sequencer
.index
));
1261 case 0x03c6: /* PEL mask */
1262 BX_VGA_THIS s
.pel
.mask
= value
;
1263 if (BX_VGA_THIS s
.pel
.mask
!= 0xff)
1264 BX_DEBUG(("io write 0x3c6: PEL mask=0x%02x != 0xFF", value
));
1265 // BX_VGA_THIS s.pel.mask should be and'd with final value before
1266 // indexing into color register BX_VGA_THIS s.pel.data[]
1269 case 0x03c7: // PEL address, read mode
1270 BX_VGA_THIS s
.pel
.read_data_register
= value
;
1271 BX_VGA_THIS s
.pel
.read_data_cycle
= 0;
1272 BX_VGA_THIS s
.pel
.dac_state
= 0x03;
1275 case 0x03c8: /* PEL address write mode */
1276 BX_VGA_THIS s
.pel
.write_data_register
= value
;
1277 BX_VGA_THIS s
.pel
.write_data_cycle
= 0;
1278 BX_VGA_THIS s
.pel
.dac_state
= 0x00;
1281 case 0x03c9: /* PEL Data Register, colors 00..FF */
1282 switch (BX_VGA_THIS s
.pel
.write_data_cycle
) {
1284 BX_VGA_THIS s
.pel
.data
[BX_VGA_THIS s
.pel
.write_data_register
].red
= value
;
1287 BX_VGA_THIS s
.pel
.data
[BX_VGA_THIS s
.pel
.write_data_register
].green
= value
;
1290 BX_VGA_THIS s
.pel
.data
[BX_VGA_THIS s
.pel
.write_data_register
].blue
= value
;
1293 if (BX_VGA_THIS s
.vbe_8bit_dac
) {
1294 needs_update
|= bx_gui
->palette_change(BX_VGA_THIS s
.pel
.write_data_register
,
1295 BX_VGA_THIS s
.pel
.data
[BX_VGA_THIS s
.pel
.write_data_register
].red
,
1296 BX_VGA_THIS s
.pel
.data
[BX_VGA_THIS s
.pel
.write_data_register
].green
,
1297 BX_VGA_THIS s
.pel
.data
[BX_VGA_THIS s
.pel
.write_data_register
].blue
);
1300 needs_update
|= bx_gui
->palette_change(BX_VGA_THIS s
.pel
.write_data_register
,
1301 BX_VGA_THIS s
.pel
.data
[BX_VGA_THIS s
.pel
.write_data_register
].red
<<2,
1302 BX_VGA_THIS s
.pel
.data
[BX_VGA_THIS s
.pel
.write_data_register
].green
<<2,
1303 BX_VGA_THIS s
.pel
.data
[BX_VGA_THIS s
.pel
.write_data_register
].blue
<<2);
1310 BX_VGA_THIS s
.pel
.write_data_cycle
++;
1311 if (BX_VGA_THIS s
.pel
.write_data_cycle
>= 3) {
1312 //BX_INFO(("BX_VGA_THIS s.pel.data[%u] {r=%u, g=%u, b=%u}",
1313 // (unsigned) BX_VGA_THIS s.pel.write_data_register,
1314 // (unsigned) BX_VGA_THIS s.pel.data[BX_VGA_THIS s.pel.write_data_register].red,
1315 // (unsigned) BX_VGA_THIS s.pel.data[BX_VGA_THIS s.pel.write_data_register].green,
1316 // (unsigned) BX_VGA_THIS s.pel.data[BX_VGA_THIS s.pel.write_data_register].blue);
1317 BX_VGA_THIS s
.pel
.write_data_cycle
= 0;
1318 BX_VGA_THIS s
.pel
.write_data_register
++;
1322 case 0x03ca: /* Graphics 2 Position (EGA) */
1323 // ignore, EGA only???
1326 case 0x03cc: /* Graphics 1 Position (EGA) */
1327 // ignore, EGA only???
1330 case 0x03cd: /* ??? */
1331 BX_DEBUG(("io write to 0x3cd = 0x%02x", (unsigned) value
));
1334 case 0x03ce: /* Graphics Controller Index Register */
1335 if (value
> 0x08) /* ??? */
1336 BX_DEBUG(("io write: 0x3ce: value > 8"));
1337 BX_VGA_THIS s
.graphics_ctrl
.index
= value
;
1340 case 0x03cf: /* Graphics Controller Registers 00..08 */
1341 switch (BX_VGA_THIS s
.graphics_ctrl
.index
) {
1342 case 0: /* Set/Reset */
1343 BX_VGA_THIS s
.graphics_ctrl
.set_reset
= value
& 0x0f;
1345 case 1: /* Enable Set/Reset */
1346 BX_VGA_THIS s
.graphics_ctrl
.enable_set_reset
= value
& 0x0f;
1348 case 2: /* Color Compare */
1349 BX_VGA_THIS s
.graphics_ctrl
.color_compare
= value
& 0x0f;
1351 case 3: /* Data Rotate */
1352 BX_VGA_THIS s
.graphics_ctrl
.data_rotate
= value
& 0x07;
1353 BX_VGA_THIS s
.graphics_ctrl
.raster_op
= (value
>> 3) & 0x03;
1355 case 4: /* Read Map Select */
1356 BX_VGA_THIS s
.graphics_ctrl
.read_map_select
= value
& 0x03;
1357 #if !defined(VGA_TRACE_FEATURE)
1358 BX_DEBUG(("io write to 0x3cf = 0x%02x (RMS)", (unsigned) value
));
1362 BX_VGA_THIS s
.graphics_ctrl
.write_mode
= value
& 0x03;
1363 BX_VGA_THIS s
.graphics_ctrl
.read_mode
= (value
>> 3) & 0x01;
1364 BX_VGA_THIS s
.graphics_ctrl
.odd_even
= (value
>> 4) & 0x01;
1365 BX_VGA_THIS s
.graphics_ctrl
.shift_reg
= (value
>> 5) & 0x03;
1367 if (BX_VGA_THIS s
.graphics_ctrl
.odd_even
)
1368 BX_DEBUG(("io write: 0x3cf: mode reg: value = 0x%02x",
1370 if (BX_VGA_THIS s
.graphics_ctrl
.shift_reg
)
1371 BX_DEBUG(("io write: 0x3cf: mode reg: value = 0x%02x",
1374 case 6: /* Miscellaneous */
1375 prev_graphics_alpha
= BX_VGA_THIS s
.graphics_ctrl
.graphics_alpha
;
1376 prev_chain_odd_even
= BX_VGA_THIS s
.graphics_ctrl
.chain_odd_even
;
1377 prev_memory_mapping
= BX_VGA_THIS s
.graphics_ctrl
.memory_mapping
;
1379 BX_VGA_THIS s
.graphics_ctrl
.graphics_alpha
= value
& 0x01;
1380 BX_VGA_THIS s
.graphics_ctrl
.chain_odd_even
= (value
>> 1) & 0x01;
1381 BX_VGA_THIS s
.graphics_ctrl
.memory_mapping
= (value
>> 2) & 0x03;
1382 #if !defined(VGA_TRACE_FEATURE)
1383 BX_DEBUG(("memory_mapping set to %u",
1384 (unsigned) BX_VGA_THIS s
.graphics_ctrl
.memory_mapping
));
1385 BX_DEBUG(("graphics mode set to %u",
1386 (unsigned) BX_VGA_THIS s
.graphics_ctrl
.graphics_alpha
));
1387 BX_DEBUG(("odd_even mode set to %u",
1388 (unsigned) BX_VGA_THIS s
.graphics_ctrl
.odd_even
));
1389 BX_DEBUG(("io write: 0x3cf: misc reg: value = 0x%02x",
1392 if (prev_memory_mapping
!= BX_VGA_THIS s
.graphics_ctrl
.memory_mapping
)
1394 if (prev_graphics_alpha
!= BX_VGA_THIS s
.graphics_ctrl
.graphics_alpha
) {
1399 case 7: /* Color Don't Care */
1400 BX_VGA_THIS s
.graphics_ctrl
.color_dont_care
= value
& 0x0f;
1402 case 8: /* Bit Mask */
1403 BX_VGA_THIS s
.graphics_ctrl
.bitmask
= value
;
1407 BX_DEBUG(("io write: 0x3cf: index %u unhandled",
1408 (unsigned) BX_VGA_THIS s
.graphics_ctrl
.index
));
1412 case 0x03b4: /* CRTC Index Register (monochrome emulation modes) */
1413 case 0x03d4: /* CRTC Index Register (color emulation modes) */
1414 BX_VGA_THIS s
.CRTC
.address
= value
& 0x7f;
1415 if (BX_VGA_THIS s
.CRTC
.address
> 0x18)
1416 BX_DEBUG(("write: invalid CRTC register 0x%02x selected",
1417 (unsigned) BX_VGA_THIS s
.CRTC
.address
));
1420 case 0x03b5: /* CRTC Registers (monochrome emulation modes) */
1421 case 0x03d5: /* CRTC Registers (color emulation modes) */
1422 if (BX_VGA_THIS s
.CRTC
.address
> 0x18) {
1423 BX_DEBUG(("write: invalid CRTC register 0x%02x ignored",
1424 (unsigned) BX_VGA_THIS s
.CRTC
.address
));
1427 if (BX_VGA_THIS s
.CRTC
.write_protect
&& (BX_VGA_THIS s
.CRTC
.address
< 0x08)) {
1428 if (BX_VGA_THIS s
.CRTC
.address
== 0x07) {
1429 BX_VGA_THIS s
.CRTC
.reg
[BX_VGA_THIS s
.CRTC
.address
] &= ~0x10;
1430 BX_VGA_THIS s
.CRTC
.reg
[BX_VGA_THIS s
.CRTC
.address
] |= (value
& 0x10);
1431 BX_VGA_THIS s
.line_compare
&= 0x2ff;
1432 if (BX_VGA_THIS s
.CRTC
.reg
[0x07] & 0x10) BX_VGA_THIS s
.line_compare
|= 0x100;
1439 if (value
!= BX_VGA_THIS s
.CRTC
.reg
[BX_VGA_THIS s
.CRTC
.address
]) {
1440 BX_VGA_THIS s
.CRTC
.reg
[BX_VGA_THIS s
.CRTC
.address
] = value
;
1441 switch (BX_VGA_THIS s
.CRTC
.address
) {
1443 BX_VGA_THIS s
.vertical_display_end
&= 0xff;
1444 if (BX_VGA_THIS s
.CRTC
.reg
[0x07] & 0x02) BX_VGA_THIS s
.vertical_display_end
|= 0x100;
1445 if (BX_VGA_THIS s
.CRTC
.reg
[0x07] & 0x40) BX_VGA_THIS s
.vertical_display_end
|= 0x200;
1446 BX_VGA_THIS s
.line_compare
&= 0x2ff;
1447 if (BX_VGA_THIS s
.CRTC
.reg
[0x07] & 0x10) BX_VGA_THIS s
.line_compare
|= 0x100;
1451 // Vertical pel panning change
1455 BX_VGA_THIS s
.y_doublescan
= ((value
& 0x9f) > 0);
1456 BX_VGA_THIS s
.line_compare
&= 0x1ff;
1457 if (BX_VGA_THIS s
.CRTC
.reg
[0x09] & 0x40) BX_VGA_THIS s
.line_compare
|= 0x200;
1464 // Cursor size / location change
1465 BX_VGA_THIS s
.vga_mem_updated
= 1;
1469 // Start address change
1470 if (BX_VGA_THIS s
.graphics_ctrl
.graphics_alpha
) {
1473 BX_VGA_THIS s
.vga_mem_updated
= 1;
1477 BX_VGA_THIS s
.CRTC
.write_protect
= ((BX_VGA_THIS s
.CRTC
.reg
[0x11] & 0x80) > 0);
1480 BX_VGA_THIS s
.vertical_display_end
&= 0x300;
1481 BX_VGA_THIS s
.vertical_display_end
|= BX_VGA_THIS s
.CRTC
.reg
[0x12];
1487 if (!BX_VGA_THIS s
.vbe_enabled
|| (BX_VGA_THIS s
.vbe_bpp
== VBE_DISPI_BPP_4
))
1490 // Line offset change
1491 BX_VGA_THIS s
.line_offset
= BX_VGA_THIS s
.CRTC
.reg
[0x13] << 1;
1492 if (BX_VGA_THIS s
.CRTC
.reg
[0x14] & 0x40) BX_VGA_THIS s
.line_offset
<<= 2;
1493 else if ((BX_VGA_THIS s
.CRTC
.reg
[0x17] & 0x40) == 0) BX_VGA_THIS s
.line_offset
<<= 1;
1498 BX_VGA_THIS s
.line_compare
&= 0x300;
1499 BX_VGA_THIS s
.line_compare
|= BX_VGA_THIS s
.CRTC
.reg
[0x18];
1507 case 0x03da: /* Feature Control (color emulation modes) */
1508 BX_DEBUG(("io write: 3da: ignoring: feature ctrl & vert sync"));
1513 BX_ERROR(("unsupported io write to port 0x%04x, val=0x%02x",
1514 (unsigned) address
, (unsigned) value
));
1518 // Mark all video as updated so the changes will go through
1519 BX_VGA_THIS
redraw_area(0, 0, old_iWidth
, old_iHeight
);
1523 Bit64s
bx_vga_c::vga_param_handler(bx_param_c
*param
, int set
, Bit64s val
)
1525 // handler for runtime parameter 'vga_update_interval'
1527 BX_INFO (("Changing timer interval to %d", (Bit32u
)val
));
1528 BX_VGA_THIS
timer_handler (theVga
);
1529 bx_pc_system
.activate_timer (BX_VGA_THIS timer_id
, (Bit32u
)val
, 1);
1534 void bx_vga_c::trigger_timer(void *this_ptr
)
1536 timer_handler(this_ptr
);
1539 void bx_vga_c::timer_handler(void *this_ptr
)
1541 #if BX_USE_VGA_SMF == 0
1542 bx_vga_c
*class_ptr
= (bx_vga_c
*) this_ptr
;
1546 void bx_vga_c::timer(void)
1556 void bx_vga_c::update(void)
1558 unsigned iHeight
, iWidth
;
1560 /* no screen update necessary */
1561 if ((BX_VGA_THIS s
.vga_mem_updated
==0) && BX_VGA_THIS s
.graphics_ctrl
.graphics_alpha
)
1564 /* skip screen update when vga/video is disabled or the sequencer is in reset mode */
1565 if (!BX_VGA_THIS s
.vga_enabled
|| !BX_VGA_THIS s
.attribute_ctrl
.video_enabled
1566 || !BX_VGA_THIS s
.sequencer
.reset2
|| !BX_VGA_THIS s
.sequencer
.reset1
1567 || (BX_VGA_THIS s
.sequencer
.reg1
& 0x20))
1570 /* skip screen update if the vertical retrace is in progress
1571 (using 72 Hz vertical frequency) */
1572 if ((bx_pc_system
.time_usec() % 13888) < 70)
1576 if ((BX_VGA_THIS s
.vbe_enabled
) && (BX_VGA_THIS s
.vbe_bpp
!= VBE_DISPI_BPP_4
))
1578 // specific VBE code display update code
1580 unsigned xc
, yc
, xti
, yti
;
1581 unsigned r
, c
, w
, h
;
1583 unsigned long red
, green
, blue
, colour
;
1584 Bit8u
* vid_ptr
, * vid_ptr2
;
1585 Bit8u
* tile_ptr
, * tile_ptr2
;
1586 bx_svga_tileinfo_t info
;
1587 Bit8u dac_size
= BX_VGA_THIS s
.vbe_8bit_dac
? 8 : 6;
1589 iWidth
=BX_VGA_THIS s
.vbe_xres
;
1590 iHeight
=BX_VGA_THIS s
.vbe_yres
;
1591 pitch
= BX_VGA_THIS s
.line_offset
;
1592 Bit8u
*disp_ptr
= &BX_VGA_THIS s
.memory
[BX_VGA_THIS s
.vbe_virtual_start
];
1594 if (bx_gui
->graphics_tile_info(&info
)) {
1595 if (info
.is_indexed
) {
1596 switch (BX_VGA_THIS s
.vbe_bpp
) {
1602 BX_ERROR(("current guest pixel format is unsupported on indexed colour host displays"));
1605 for (yc
=0, yti
= 0; yc
<iHeight
; yc
+=Y_TILESIZE
, yti
++) {
1606 for (xc
=0, xti
= 0; xc
<iWidth
; xc
+=X_TILESIZE
, xti
++) {
1607 if (GET_TILE_UPDATED (xti
, yti
)) {
1608 vid_ptr
= disp_ptr
+ (yc
* pitch
+ xc
);
1609 tile_ptr
= bx_gui
->graphics_tile_get(xc
, yc
, &w
, &h
);
1610 for (r
=0; r
<h
; r
++) {
1612 tile_ptr2
= tile_ptr
;
1613 for (c
=0; c
<w
; c
++) {
1615 for (i
=0; i
<(int)BX_VGA_THIS s
.vbe_bpp
; i
+=8) {
1616 colour
|= *(vid_ptr2
++) << i
;
1618 if (info
.is_little_endian
) {
1619 for (i
=0; i
<info
.bpp
; i
+=8) {
1620 *(tile_ptr2
++) = (Bit8u
)(colour
>> i
);
1624 for (i
=info
.bpp
-8; i
>-8; i
-=8) {
1625 *(tile_ptr2
++) = (Bit8u
)(colour
>> i
);
1630 tile_ptr
+= info
.pitch
;
1632 bx_gui
->graphics_tile_update_in_place(xc
, yc
, w
, h
);
1633 SET_TILE_UPDATED (xti
, yti
, 0);
1641 switch (BX_VGA_THIS s
.vbe_bpp
) {
1643 BX_ERROR(("cannot draw 4bpp SVGA"));
1646 for (yc
=0, yti
= 0; yc
<iHeight
; yc
+=Y_TILESIZE
, yti
++) {
1647 for (xc
=0, xti
= 0; xc
<iWidth
; xc
+=X_TILESIZE
, xti
++) {
1648 if (GET_TILE_UPDATED (xti
, yti
)) {
1649 vid_ptr
= disp_ptr
+ (yc
* pitch
+ xc
);
1650 tile_ptr
= bx_gui
->graphics_tile_get(xc
, yc
, &w
, &h
);
1651 for (r
=0; r
<h
; r
++) {
1653 tile_ptr2
= tile_ptr
;
1654 for (c
=0; c
<w
; c
++) {
1655 colour
= *(vid_ptr2
++);
1656 colour
= MAKE_COLOUR(
1657 BX_VGA_THIS s
.pel
.data
[colour
].red
, dac_size
, info
.red_shift
, info
.red_mask
,
1658 BX_VGA_THIS s
.pel
.data
[colour
].green
, dac_size
, info
.green_shift
, info
.green_mask
,
1659 BX_VGA_THIS s
.pel
.data
[colour
].blue
, dac_size
, info
.blue_shift
, info
.blue_mask
);
1660 if (info
.is_little_endian
) {
1661 for (i
=0; i
<info
.bpp
; i
+=8) {
1662 *(tile_ptr2
++) = (Bit8u
)(colour
>> i
);
1666 for (i
=info
.bpp
-8; i
>-8; i
-=8) {
1667 *(tile_ptr2
++) = (Bit8u
)(colour
>> i
);
1672 tile_ptr
+= info
.pitch
;
1674 bx_gui
->graphics_tile_update_in_place(xc
, yc
, w
, h
);
1675 SET_TILE_UPDATED (xti
, yti
, 0);
1681 for (yc
=0, yti
= 0; yc
<iHeight
; yc
+=Y_TILESIZE
, yti
++) {
1682 for (xc
=0, xti
= 0; xc
<iWidth
; xc
+=X_TILESIZE
, xti
++) {
1683 if (GET_TILE_UPDATED (xti
, yti
)) {
1684 vid_ptr
= disp_ptr
+ (yc
* pitch
+ (xc
<<1));
1685 tile_ptr
= bx_gui
->graphics_tile_get(xc
, yc
, &w
, &h
);
1686 for (r
=0; r
<h
; r
++) {
1688 tile_ptr2
= tile_ptr
;
1689 for (c
=0; c
<w
; c
++) {
1690 colour
= *(vid_ptr2
++);
1691 colour
|= *(vid_ptr2
++) << 8;
1692 colour
= MAKE_COLOUR(
1693 colour
& 0x001f, 5, info
.blue_shift
, info
.blue_mask
,
1694 colour
& 0x03e0, 10, info
.green_shift
, info
.green_mask
,
1695 colour
& 0x7c00, 15, info
.red_shift
, info
.red_mask
);
1696 if (info
.is_little_endian
) {
1697 for (i
=0; i
<info
.bpp
; i
+=8) {
1698 *(tile_ptr2
++) = (Bit8u
)(colour
>> i
);
1702 for (i
=info
.bpp
-8; i
>-8; i
-=8) {
1703 *(tile_ptr2
++) = (Bit8u
)(colour
>> i
);
1708 tile_ptr
+= info
.pitch
;
1710 bx_gui
->graphics_tile_update_in_place(xc
, yc
, w
, h
);
1711 SET_TILE_UPDATED (xti
, yti
, 0);
1717 for (yc
=0, yti
= 0; yc
<iHeight
; yc
+=Y_TILESIZE
, yti
++) {
1718 for (xc
=0, xti
= 0; xc
<iWidth
; xc
+=X_TILESIZE
, xti
++) {
1719 if (GET_TILE_UPDATED (xti
, yti
)) {
1720 vid_ptr
= disp_ptr
+ (yc
* pitch
+ (xc
<<1));
1721 tile_ptr
= bx_gui
->graphics_tile_get(xc
, yc
, &w
, &h
);
1722 for (r
=0; r
<h
; r
++) {
1724 tile_ptr2
= tile_ptr
;
1725 for (c
=0; c
<w
; c
++) {
1726 colour
= *(vid_ptr2
++);
1727 colour
|= *(vid_ptr2
++) << 8;
1728 colour
= MAKE_COLOUR(
1729 colour
& 0x001f, 5, info
.blue_shift
, info
.blue_mask
,
1730 colour
& 0x07e0, 11, info
.green_shift
, info
.green_mask
,
1731 colour
& 0xf800, 16, info
.red_shift
, info
.red_mask
);
1732 if (info
.is_little_endian
) {
1733 for (i
=0; i
<info
.bpp
; i
+=8) {
1734 *(tile_ptr2
++) = (Bit8u
)(colour
>> i
);
1738 for (i
=info
.bpp
-8; i
>-8; i
-=8) {
1739 *(tile_ptr2
++) = (Bit8u
)(colour
>> i
);
1744 tile_ptr
+= info
.pitch
;
1746 bx_gui
->graphics_tile_update_in_place(xc
, yc
, w
, h
);
1747 SET_TILE_UPDATED (xti
, yti
, 0);
1753 for (yc
=0, yti
= 0; yc
<iHeight
; yc
+=Y_TILESIZE
, yti
++) {
1754 for (xc
=0, xti
= 0; xc
<iWidth
; xc
+=X_TILESIZE
, xti
++) {
1755 if (GET_TILE_UPDATED (xti
, yti
)) {
1756 vid_ptr
= disp_ptr
+ (yc
* pitch
+ 3*xc
);
1757 tile_ptr
= bx_gui
->graphics_tile_get(xc
, yc
, &w
, &h
);
1758 for (r
=0; r
<h
; r
++) {
1760 tile_ptr2
= tile_ptr
;
1761 for (c
=0; c
<w
; c
++) {
1762 blue
= *(vid_ptr2
++);
1763 green
= *(vid_ptr2
++);
1764 red
= *(vid_ptr2
++);
1765 colour
= MAKE_COLOUR(
1766 red
, 8, info
.red_shift
, info
.red_mask
,
1767 green
, 8, info
.green_shift
, info
.green_mask
,
1768 blue
, 8, info
.blue_shift
, info
.blue_mask
);
1769 if (info
.is_little_endian
) {
1770 for (i
=0; i
<info
.bpp
; i
+=8) {
1771 *(tile_ptr2
++) = (Bit8u
)(colour
>> i
);
1775 for (i
=info
.bpp
-8; i
>-8; i
-=8) {
1776 *(tile_ptr2
++) = (Bit8u
)(colour
>> i
);
1781 tile_ptr
+= info
.pitch
;
1783 bx_gui
->graphics_tile_update_in_place(xc
, yc
, w
, h
);
1784 SET_TILE_UPDATED (xti
, yti
, 0);
1790 for (yc
=0, yti
= 0; yc
<iHeight
; yc
+=Y_TILESIZE
, yti
++) {
1791 for (xc
=0, xti
= 0; xc
<iWidth
; xc
+=X_TILESIZE
, xti
++) {
1792 if (GET_TILE_UPDATED (xti
, yti
)) {
1793 vid_ptr
= disp_ptr
+ (yc
* pitch
+ (xc
<<2));
1794 tile_ptr
= bx_gui
->graphics_tile_get(xc
, yc
, &w
, &h
);
1795 for (r
=0; r
<h
; r
++) {
1797 tile_ptr2
= tile_ptr
;
1798 for (c
=0; c
<w
; c
++) {
1799 blue
= *(vid_ptr2
++);
1800 green
= *(vid_ptr2
++);
1801 red
= *(vid_ptr2
++);
1803 colour
= MAKE_COLOUR(
1804 red
, 8, info
.red_shift
, info
.red_mask
,
1805 green
, 8, info
.green_shift
, info
.green_mask
,
1806 blue
, 8, info
.blue_shift
, info
.blue_mask
);
1807 if (info
.is_little_endian
) {
1808 for (i
=0; i
<info
.bpp
; i
+=8) {
1809 *(tile_ptr2
++) = (Bit8u
)(colour
>> i
);
1813 for (i
=info
.bpp
-8; i
>-8; i
-=8) {
1814 *(tile_ptr2
++) = (Bit8u
)(colour
>> i
);
1819 tile_ptr
+= info
.pitch
;
1821 bx_gui
->graphics_tile_update_in_place(xc
, yc
, w
, h
);
1822 SET_TILE_UPDATED (xti
, yti
, 0);
1829 old_iWidth
= iWidth
;
1830 old_iHeight
= iHeight
;
1831 BX_VGA_THIS s
.vga_mem_updated
= 0;
1834 BX_PANIC(("cannot get svga tile info"));
1837 // after a vbe display update, don't try to do any 'normal vga' updates anymore
1841 // fields that effect the way video memory is serialized into screen output:
1842 // GRAPHICS CONTROLLER:
1843 // BX_VGA_THIS s.graphics_ctrl.shift_reg:
1844 // 0: output data in standard VGA format or CGA-compatible 640x200 2 color
1845 // graphics mode (mode 6)
1846 // 1: output data in CGA-compatible 320x200 4 color graphics mode
1848 // 2: output data 8 bits at a time from the 4 bit planes
1849 // (mode 13 and variants like modeX)
1851 // if (BX_VGA_THIS s.vga_mem_updated==0 || BX_VGA_THIS s.attribute_ctrl.video_enabled == 0)
1853 if (BX_VGA_THIS s
.graphics_ctrl
.graphics_alpha
) {
1855 unsigned bit_no
, r
, c
, x
, y
;
1856 unsigned long byte_offset
, start_addr
;
1857 unsigned xc
, yc
, xti
, yti
;
1859 start_addr
= (BX_VGA_THIS s
.CRTC
.reg
[0x0c] << 8) | BX_VGA_THIS s
.CRTC
.reg
[0x0d];
1861 //BX_DEBUG(("update: shiftreg=%u, chain4=%u, mapping=%u",
1862 // (unsigned) BX_VGA_THIS s.graphics_ctrl.shift_reg,
1863 // (unsigned) BX_VGA_THIS s.sequencer.chain_four,
1864 // (unsigned) BX_VGA_THIS s.graphics_ctrl.memory_mapping);
1866 determine_screen_dimensions(&iHeight
, &iWidth
);
1867 if((iWidth
!= old_iWidth
) || (iHeight
!= old_iHeight
) ||
1868 (BX_VGA_THIS s
.last_bpp
> 8))
1870 bx_gui
->dimension_update(iWidth
, iHeight
);
1871 old_iWidth
= iWidth
;
1872 old_iHeight
= iHeight
;
1873 BX_VGA_THIS s
.last_bpp
= 8;
1876 switch (BX_VGA_THIS s
.graphics_ctrl
.shift_reg
) {
1878 Bit8u attribute
, palette_reg_val
, DAC_regno
;
1879 unsigned long line_compare
;
1880 Bit8u
*plane0
, *plane1
, *plane2
, *plane3
;
1882 if (BX_VGA_THIS s
.graphics_ctrl
.memory_mapping
== 3) { // CGA 640x200x2
1884 for (yc
=0, yti
=0; yc
<iHeight
; yc
+=Y_TILESIZE
, yti
++) {
1885 for (xc
=0, xti
=0; xc
<iWidth
; xc
+=X_TILESIZE
, xti
++) {
1886 if (GET_TILE_UPDATED (xti
, yti
)) {
1887 for (r
=0; r
<Y_TILESIZE
; r
++) {
1889 if (BX_VGA_THIS s
.y_doublescan
) y
>>= 1;
1890 for (c
=0; c
<X_TILESIZE
; c
++) {
1894 byte_offset
= start_addr
+ ((y
& 1) << 13);
1895 /* to the start of the line */
1896 byte_offset
+= (320 / 4) * (y
/ 2);
1897 /* to the byte start */
1898 byte_offset
+= (x
/ 8);
1900 bit_no
= 7 - (x
% 8);
1901 palette_reg_val
= (((BX_VGA_THIS s
.memory
[byte_offset
]) >> bit_no
) & 1);
1902 DAC_regno
= BX_VGA_THIS s
.attribute_ctrl
.palette_reg
[palette_reg_val
];
1903 BX_VGA_THIS s
.tile
[r
*X_TILESIZE
+ c
] = DAC_regno
;
1906 SET_TILE_UPDATED (xti
, yti
, 0);
1907 bx_gui
->graphics_tile_update(BX_VGA_THIS s
.tile
, xc
, yc
);
1911 } else { // output data in serial fashion with each display plane
1912 // output on its associated serial output. Standard EGA/VGA format
1915 if (BX_VGA_THIS s
.vbe_enabled
)
1917 plane0
= &BX_VGA_THIS s
.memory
[0<<VBE_DISPI_4BPP_PLANE_SHIFT
];
1918 plane1
= &BX_VGA_THIS s
.memory
[1<<VBE_DISPI_4BPP_PLANE_SHIFT
];
1919 plane2
= &BX_VGA_THIS s
.memory
[2<<VBE_DISPI_4BPP_PLANE_SHIFT
];
1920 plane3
= &BX_VGA_THIS s
.memory
[3<<VBE_DISPI_4BPP_PLANE_SHIFT
];
1921 start_addr
= BX_VGA_THIS s
.vbe_virtual_start
;
1922 line_compare
= 0xffff;
1927 plane0
= &BX_VGA_THIS s
.memory
[0<<16];
1928 plane1
= &BX_VGA_THIS s
.memory
[1<<16];
1929 plane2
= &BX_VGA_THIS s
.memory
[2<<16];
1930 plane3
= &BX_VGA_THIS s
.memory
[3<<16];
1931 line_compare
= BX_VGA_THIS s
.line_compare
;
1932 if (BX_VGA_THIS s
.y_doublescan
) line_compare
>>= 1;
1935 for (yc
=0, yti
=0; yc
<iHeight
; yc
+=Y_TILESIZE
, yti
++) {
1936 for (xc
=0, xti
=0; xc
<iWidth
; xc
+=X_TILESIZE
, xti
++) {
1937 if (GET_TILE_UPDATED (xti
, yti
)) {
1938 for (r
=0; r
<Y_TILESIZE
; r
++) {
1940 if (BX_VGA_THIS s
.y_doublescan
) y
>>= 1;
1941 for (c
=0; c
<X_TILESIZE
; c
++) {
1943 if (BX_VGA_THIS s
.x_dotclockdiv2
) x
>>= 1;
1944 bit_no
= 7 - (x
% 8);
1945 if (y
> line_compare
) {
1946 byte_offset
= x
/ 8 +
1947 ((y
- line_compare
- 1) * BX_VGA_THIS s
.line_offset
);
1949 byte_offset
= start_addr
+ x
/ 8 +
1950 (y
* BX_VGA_THIS s
.line_offset
);
1953 (((plane0
[byte_offset
] >> bit_no
) & 0x01) << 0) |
1954 (((plane1
[byte_offset
] >> bit_no
) & 0x01) << 1) |
1955 (((plane2
[byte_offset
] >> bit_no
) & 0x01) << 2) |
1956 (((plane3
[byte_offset
] >> bit_no
) & 0x01) << 3);
1958 attribute
&= BX_VGA_THIS s
.attribute_ctrl
.color_plane_enable
;
1959 // undocumented feature ???: colors 0..7 high intensity, colors 8..15 blinking
1960 // using low/high intensity. Blinking is not implemented yet.
1961 if (BX_VGA_THIS s
.attribute_ctrl
.mode_ctrl
.blink_intensity
) attribute
^= 0x08;
1962 palette_reg_val
= BX_VGA_THIS s
.attribute_ctrl
.palette_reg
[attribute
];
1963 if (BX_VGA_THIS s
.attribute_ctrl
.mode_ctrl
.internal_palette_size
) {
1964 // use 4 lower bits from palette register
1965 // use 4 higher bits from color select register
1966 // 16 banks of 16-color registers
1967 DAC_regno
= (palette_reg_val
& 0x0f) |
1968 (BX_VGA_THIS s
.attribute_ctrl
.color_select
<< 4);
1971 // use 6 lower bits from palette register
1972 // use 2 higher bits from color select register
1973 // 4 banks of 64-color registers
1974 DAC_regno
= (palette_reg_val
& 0x3f) |
1975 ((BX_VGA_THIS s
.attribute_ctrl
.color_select
& 0x0c) << 4);
1977 // DAC_regno &= video DAC mask register ???
1979 BX_VGA_THIS s
.tile
[r
*X_TILESIZE
+ c
] = DAC_regno
;
1982 SET_TILE_UPDATED (xti
, yti
, 0);
1983 bx_gui
->graphics_tile_update(BX_VGA_THIS s
.tile
, xc
, yc
);
1990 case 1: // output the data in a CGA-compatible 320x200 4 color graphics
1991 // mode. (modes 4 & 5)
1993 /* CGA 320x200x4 start */
1995 for (yc
=0, yti
=0; yc
<iHeight
; yc
+=Y_TILESIZE
, yti
++) {
1996 for (xc
=0, xti
=0; xc
<iWidth
; xc
+=X_TILESIZE
, xti
++) {
1997 if (GET_TILE_UPDATED (xti
, yti
)) {
1998 for (r
=0; r
<Y_TILESIZE
; r
++) {
2000 if (BX_VGA_THIS s
.y_doublescan
) y
>>= 1;
2001 for (c
=0; c
<X_TILESIZE
; c
++) {
2004 if (BX_VGA_THIS s
.x_dotclockdiv2
) x
>>= 1;
2006 byte_offset
= start_addr
+ ((y
& 1) << 13);
2007 /* to the start of the line */
2008 byte_offset
+= (320 / 4) * (y
/ 2);
2009 /* to the byte start */
2010 byte_offset
+= (x
/ 4);
2012 attribute
= 6 - 2*(x
% 4);
2013 palette_reg_val
= (BX_VGA_THIS s
.memory
[byte_offset
]) >> attribute
;
2014 palette_reg_val
&= 3;
2015 DAC_regno
= BX_VGA_THIS s
.attribute_ctrl
.palette_reg
[palette_reg_val
];
2016 BX_VGA_THIS s
.tile
[r
*X_TILESIZE
+ c
] = DAC_regno
;
2019 SET_TILE_UPDATED (xti
, yti
, 0);
2020 bx_gui
->graphics_tile_update(BX_VGA_THIS s
.tile
, xc
, yc
);
2024 /* CGA 320x200x4 end */
2028 case 2: // output the data eight bits at a time from the 4 bit plane
2029 // (format for VGA mode 13 hex)
2030 case 3: // FIXME: is this really the same ???
2032 if (BX_VGA_THIS s
.sequencer
.chain_four
) {
2033 unsigned long pixely
, pixelx
, plane
;
2035 if (BX_VGA_THIS s
.misc_output
.select_high_bank
!= 1)
2036 BX_PANIC(("update: select_high_bank != 1"));
2038 for (yc
=0, yti
=0; yc
<iHeight
; yc
+=Y_TILESIZE
, yti
++) {
2039 for (xc
=0, xti
=0; xc
<iWidth
; xc
+=X_TILESIZE
, xti
++) {
2040 if (GET_TILE_UPDATED (xti
, yti
)) {
2041 for (r
=0; r
<Y_TILESIZE
; r
++) {
2043 if (BX_VGA_THIS s
.y_doublescan
) pixely
>>= 1;
2044 for (c
=0; c
<X_TILESIZE
; c
++) {
2045 pixelx
= (xc
+ c
) >> 1;
2046 plane
= (pixelx
% 4);
2047 byte_offset
= start_addr
+ (plane
* 65536) +
2048 (pixely
* BX_VGA_THIS s
.line_offset
) + (pixelx
& ~0x03);
2049 color
= BX_VGA_THIS s
.memory
[byte_offset
];
2050 BX_VGA_THIS s
.tile
[r
*X_TILESIZE
+ c
] = color
;
2053 SET_TILE_UPDATED (xti
, yti
, 0);
2054 bx_gui
->graphics_tile_update(BX_VGA_THIS s
.tile
, xc
, yc
);
2060 else { // chain_four == 0, modeX
2061 unsigned long pixely
, pixelx
, plane
;
2063 for (yc
=0, yti
=0; yc
<iHeight
; yc
+=Y_TILESIZE
, yti
++) {
2064 for (xc
=0, xti
=0; xc
<iWidth
; xc
+=X_TILESIZE
, xti
++) {
2065 if (GET_TILE_UPDATED (xti
, yti
)) {
2066 for (r
=0; r
<Y_TILESIZE
; r
++) {
2068 if (BX_VGA_THIS s
.y_doublescan
) pixely
>>= 1;
2069 for (c
=0; c
<X_TILESIZE
; c
++) {
2070 pixelx
= (xc
+ c
) >> 1;
2071 plane
= (pixelx
% 4);
2072 byte_offset
= (plane
* 65536) +
2073 (pixely
* BX_VGA_THIS s
.line_offset
)
2075 color
= BX_VGA_THIS s
.memory
[start_addr
+ byte_offset
];
2076 BX_VGA_THIS s
.tile
[r
*X_TILESIZE
+ c
] = color
;
2079 SET_TILE_UPDATED (xti
, yti
, 0);
2080 bx_gui
->graphics_tile_update(BX_VGA_THIS s
.tile
, xc
, yc
);
2088 BX_PANIC(("update: shift_reg == %u", (unsigned)
2089 BX_VGA_THIS s
.graphics_ctrl
.shift_reg
));
2092 BX_VGA_THIS s
.vga_mem_updated
= 0;
2097 unsigned long start_address
;
2098 unsigned long cursor_address
, cursor_x
, cursor_y
;
2099 bx_vga_tminfo_t tm_info
;
2100 unsigned VDE
, MSL
, cols
, rows
, cWidth
;
2101 static unsigned cs_counter
= 1;
2102 static bx_bool cs_visible
= 0;
2103 bx_bool cs_toggle
= 0;
2106 if ((BX_VGA_THIS s
.vga_mem_updated
==0) && (cs_counter
> 0))
2109 tm_info
.start_address
= 2*((BX_VGA_THIS s
.CRTC
.reg
[12] << 8) +
2110 BX_VGA_THIS s
.CRTC
.reg
[13]);
2111 tm_info
.cs_start
= BX_VGA_THIS s
.CRTC
.reg
[0x0a] & 0x3f;
2112 if (cs_counter
== 0) {
2114 cs_visible
= !cs_visible
;
2115 cs_counter
= BX_VGA_THIS s
.blink_counter
;
2118 tm_info
.cs_start
|= 0x20;
2120 tm_info
.cs_end
= BX_VGA_THIS s
.CRTC
.reg
[0x0b] & 0x1f;
2121 tm_info
.line_offset
= BX_VGA_THIS s
.CRTC
.reg
[0x13] << 2;
2122 tm_info
.line_compare
= BX_VGA_THIS s
.line_compare
;
2123 tm_info
.h_panning
= BX_VGA_THIS s
.attribute_ctrl
.horiz_pel_panning
& 0x0f;
2124 tm_info
.v_panning
= BX_VGA_THIS s
.CRTC
.reg
[0x08] & 0x1f;
2125 tm_info
.line_graphics
= BX_VGA_THIS s
.attribute_ctrl
.mode_ctrl
.enable_line_graphics
;
2126 tm_info
.split_hpanning
= BX_VGA_THIS s
.attribute_ctrl
.mode_ctrl
.pixel_panning_compat
;
2127 tm_info
.blink_flags
= 0;
2128 if (BX_VGA_THIS s
.attribute_ctrl
.mode_ctrl
.blink_intensity
) {
2129 tm_info
.blink_flags
|= BX_TEXT_BLINK_MODE
;
2131 tm_info
.blink_flags
|= BX_TEXT_BLINK_TOGGLE
;
2133 tm_info
.blink_flags
|= BX_TEXT_BLINK_STATE
;
2135 if ((BX_VGA_THIS s
.sequencer
.reg1
& 0x01) == 0) {
2136 if (tm_info
.h_panning
>= 8)
2137 tm_info
.h_panning
= 0;
2139 tm_info
.h_panning
++;
2141 tm_info
.h_panning
&= 0x07;
2144 // Verticle Display End: find out how many lines are displayed
2145 VDE
= BX_VGA_THIS s
.vertical_display_end
;
2146 // Maximum Scan Line: height of character cell
2147 MSL
= BX_VGA_THIS s
.CRTC
.reg
[0x09] & 0x1f;
2149 BX_ERROR(("character height = 1, skipping text update"));
2152 cols
= BX_VGA_THIS s
.CRTC
.reg
[1] + 1;
2153 if ((MSL
== 1) && (VDE
== 399)) {
2154 // emulated CGA graphics mode 160x100x16 colors
2157 rows
= (VDE
+1)/(MSL
+1);
2158 if (rows
> BX_MAX_TEXT_LINES
) {
2159 BX_PANIC(("text rows>%d: %d",BX_MAX_TEXT_LINES
,rows
));
2162 cWidth
= ((BX_VGA_THIS s
.sequencer
.reg1
& 0x01) == 1) ? 8 : 9;
2163 iWidth
= cWidth
* cols
;
2165 if ((iWidth
!= old_iWidth
) || (iHeight
!= old_iHeight
) || (MSL
!= old_MSL
) ||
2166 (BX_VGA_THIS s
.last_bpp
> 8))
2168 bx_gui
->dimension_update(iWidth
, iHeight
, MSL
+1, cWidth
);
2169 old_iWidth
= iWidth
;
2170 old_iHeight
= iHeight
;
2172 BX_VGA_THIS s
.last_bpp
= 8;
2174 // pass old text snapshot & new VGA memory contents
2175 start_address
= tm_info
.start_address
;
2176 cursor_address
= 2*((BX_VGA_THIS s
.CRTC
.reg
[0x0e] << 8) +
2177 BX_VGA_THIS s
.CRTC
.reg
[0x0f]);
2178 if (cursor_address
< start_address
) {
2182 cursor_x
= ((cursor_address
- start_address
)/2) % (iWidth
/cWidth
);
2183 cursor_y
= ((cursor_address
- start_address
)/2) / (iWidth
/cWidth
);
2185 bx_gui
->text_update(BX_VGA_THIS s
.text_snapshot
,
2186 &BX_VGA_THIS s
.memory
[start_address
],
2187 cursor_x
, cursor_y
, tm_info
);
2188 if (BX_VGA_THIS s
.vga_mem_updated
) {
2189 // screen updated, copy new VGA memory contents into text snapshot
2190 memcpy(BX_VGA_THIS s
.text_snapshot
,
2191 &BX_VGA_THIS s
.memory
[start_address
],
2192 tm_info
.line_offset
*rows
);
2193 BX_VGA_THIS s
.vga_mem_updated
= 0;
2198 bx_bool
bx_vga_c::mem_read_handler(bx_phy_address addr
, unsigned len
, void *data
, void *param
)
2201 #ifdef BX_LITTLE_ENDIAN
2202 data_ptr
= (Bit8u
*) data
;
2203 #else // BX_BIG_ENDIAN
2204 data_ptr
= (Bit8u
*) data
+ (len
- 1);
2206 for (unsigned i
= 0; i
< len
; i
++) {
2207 *data_ptr
= theVga
->mem_read(addr
);
2209 #ifdef BX_LITTLE_ENDIAN
2211 #else // BX_BIG_ENDIAN
2218 Bit8u
bx_vga_c::mem_read(bx_phy_address addr
)
2221 Bit8u
*plane0
, *plane1
, *plane2
, *plane3
;
2224 // if in a vbe enabled mode, read from the vbe_memory
2225 if ((BX_VGA_THIS s
.vbe_enabled
) && (BX_VGA_THIS s
.vbe_bpp
!= VBE_DISPI_BPP_4
))
2227 return vbe_mem_read(addr
);
2229 else if (addr
>= VBE_DISPI_LFB_PHYSICAL_ADDRESS
)
2235 #if defined(VGA_TRACE_FEATURE)
2236 // BX_DEBUG(("8-bit memory read from 0x%08x", addr));
2242 #error Fix the code for plugins
2245 if (bx_options
.videomode
== BX_VIDEO_DIRECT
)
2248 value
= devices
->mem
->video
[addr
-0xA0000];
2253 switch (BX_VGA_THIS s
.graphics_ctrl
.memory_mapping
) {
2254 case 1: // 0xA0000 .. 0xAFFFF
2255 if (addr
> 0xAFFFF) return 0xff;
2256 offset
= addr
& 0xFFFF;
2258 case 2: // 0xB0000 .. 0xB7FFF
2259 if ((addr
< 0xB0000) || (addr
> 0xB7FFF)) return 0xff;
2260 offset
= addr
& 0x7FFF;
2262 case 3: // 0xB8000 .. 0xBFFFF
2263 if (addr
< 0xB8000) return 0xff;
2264 offset
= addr
& 0x7FFF;
2266 default: // 0xA0000 .. 0xBFFFF
2267 offset
= addr
& 0x1FFFF;
2270 if (BX_VGA_THIS s
.sequencer
.chain_four
) {
2271 // Mode 13h: 320 x 200 256 color mode: chained pixel representation
2272 return BX_VGA_THIS s
.memory
[(offset
& ~0x03) + (offset
% 4)*65536];
2276 if (BX_VGA_THIS s
.vbe_enabled
)
2278 plane0
= &BX_VGA_THIS s
.memory
[(0<<VBE_DISPI_4BPP_PLANE_SHIFT
) + (BX_VGA_THIS s
.vbe_bank
<<16)];
2279 plane1
= &BX_VGA_THIS s
.memory
[(1<<VBE_DISPI_4BPP_PLANE_SHIFT
) + (BX_VGA_THIS s
.vbe_bank
<<16)];
2280 plane2
= &BX_VGA_THIS s
.memory
[(2<<VBE_DISPI_4BPP_PLANE_SHIFT
) + (BX_VGA_THIS s
.vbe_bank
<<16)];
2281 plane3
= &BX_VGA_THIS s
.memory
[(3<<VBE_DISPI_4BPP_PLANE_SHIFT
) + (BX_VGA_THIS s
.vbe_bank
<<16)];
2286 plane0
= &BX_VGA_THIS s
.memory
[0<<16];
2287 plane1
= &BX_VGA_THIS s
.memory
[1<<16];
2288 plane2
= &BX_VGA_THIS s
.memory
[2<<16];
2289 plane3
= &BX_VGA_THIS s
.memory
[3<<16];
2292 /* addr between 0xA0000 and 0xAFFFF */
2293 switch (BX_VGA_THIS s
.graphics_ctrl
.read_mode
) {
2294 case 0: /* read mode 0 */
2295 BX_VGA_THIS s
.graphics_ctrl
.latch
[0] = plane0
[offset
];
2296 BX_VGA_THIS s
.graphics_ctrl
.latch
[1] = plane1
[offset
];
2297 BX_VGA_THIS s
.graphics_ctrl
.latch
[2] = plane2
[offset
];
2298 BX_VGA_THIS s
.graphics_ctrl
.latch
[3] = plane3
[offset
];
2299 return(BX_VGA_THIS s
.graphics_ctrl
.latch
[BX_VGA_THIS s
.graphics_ctrl
.read_map_select
]);
2302 case 1: /* read mode 1 */
2304 Bit8u color_compare
, color_dont_care
;
2305 Bit8u latch0
, latch1
, latch2
, latch3
, retval
;
2307 color_compare
= BX_VGA_THIS s
.graphics_ctrl
.color_compare
& 0x0f;
2308 color_dont_care
= BX_VGA_THIS s
.graphics_ctrl
.color_dont_care
& 0x0f;
2309 latch0
= BX_VGA_THIS s
.graphics_ctrl
.latch
[0] = plane0
[offset
];
2310 latch1
= BX_VGA_THIS s
.graphics_ctrl
.latch
[1] = plane1
[offset
];
2311 latch2
= BX_VGA_THIS s
.graphics_ctrl
.latch
[2] = plane2
[offset
];
2312 latch3
= BX_VGA_THIS s
.graphics_ctrl
.latch
[3] = plane3
[offset
];
2314 latch0
^= ccdat
[color_compare
][0];
2315 latch1
^= ccdat
[color_compare
][1];
2316 latch2
^= ccdat
[color_compare
][2];
2317 latch3
^= ccdat
[color_compare
][3];
2319 latch0
&= ccdat
[color_dont_care
][0];
2320 latch1
&= ccdat
[color_dont_care
][1];
2321 latch2
&= ccdat
[color_dont_care
][2];
2322 latch3
&= ccdat
[color_dont_care
][3];
2324 retval
= ~(latch0
| latch1
| latch2
| latch3
);
2334 bx_bool
bx_vga_c::mem_write_handler(bx_phy_address addr
, unsigned len
, void *data
, void *param
)
2337 #ifdef BX_LITTLE_ENDIAN
2338 data_ptr
= (Bit8u
*) data
;
2339 #else // BX_BIG_ENDIAN
2340 data_ptr
= (Bit8u
*) data
+ (len
- 1);
2342 for (unsigned i
= 0; i
< len
; i
++) {
2343 theVga
->mem_write(addr
, *data_ptr
);
2345 #ifdef BX_LITTLE_ENDIAN
2347 #else // BX_BIG_ENDIAN
2354 void bx_vga_c::mem_write(bx_phy_address addr
, Bit8u value
)
2358 unsigned start_addr
;
2359 Bit8u
*plane0
, *plane1
, *plane2
, *plane3
;
2362 // if in a vbe enabled mode, write to the vbe_memory
2363 if ((BX_VGA_THIS s
.vbe_enabled
) && (BX_VGA_THIS s
.vbe_bpp
!= VBE_DISPI_BPP_4
))
2365 vbe_mem_write(addr
, value
);
2368 else if (addr
>= VBE_DISPI_LFB_PHYSICAL_ADDRESS
)
2374 #if defined(VGA_TRACE_FEATURE)
2375 //BX_DEBUG(("8-bit memory write to %08x = %02x", addr, value));
2381 #error Fix the code for plugins
2384 if (bx_options
.videomode
== BX_VIDEO_DIRECT
)
2386 devices
->mem
->video
[addr
-0xA0000] = value
;
2391 switch (BX_VGA_THIS s
.graphics_ctrl
.memory_mapping
) {
2392 case 1: // 0xA0000 .. 0xAFFFF
2393 if (addr
> 0xAFFFF) return;
2394 offset
= addr
- 0xA0000;
2396 case 2: // 0xB0000 .. 0xB7FFF
2397 if ((addr
< 0xB0000) || (addr
> 0xB7FFF)) return;
2398 offset
= addr
- 0xB0000;
2400 case 3: // 0xB8000 .. 0xBFFFF
2401 if (addr
< 0xB8000) return;
2402 offset
= addr
- 0xB8000;
2404 default: // 0xA0000 .. 0xBFFFF
2405 offset
= addr
- 0xA0000;
2408 start_addr
= (BX_VGA_THIS s
.CRTC
.reg
[0x0c] << 8) | BX_VGA_THIS s
.CRTC
.reg
[0x0d];
2410 if (BX_VGA_THIS s
.graphics_ctrl
.graphics_alpha
) {
2411 if (BX_VGA_THIS s
.graphics_ctrl
.memory_mapping
== 3) { // 0xB8000 .. 0xBFFFF
2412 unsigned x_tileno
, x_tileno2
, y_tileno
;
2414 /* CGA 320x200x4 / 640x200x2 start */
2415 BX_VGA_THIS s
.memory
[offset
] = value
;
2416 offset
-= start_addr
;
2417 if (offset
>=0x2000) {
2418 y_tileno
= offset
- 0x2000;
2419 y_tileno
/= (320/4);
2420 y_tileno
<<= 1; //2 * y_tileno;
2422 x_tileno
= (offset
- 0x2000) % (320/4);
2423 x_tileno
<<= 2; //*= 4;
2425 y_tileno
= offset
/ (320/4);
2426 y_tileno
<<= 1; //2 * y_tileno;
2427 x_tileno
= offset
% (320/4);
2428 x_tileno
<<= 2; //*=4;
2431 if (BX_VGA_THIS s
.graphics_ctrl
.shift_reg
==0) {
2437 if (BX_VGA_THIS s
.x_dotclockdiv2
) {
2438 x_tileno
/=(X_TILESIZE
/2);
2439 x_tileno2
/=(X_TILESIZE
/2);
2441 x_tileno
/=X_TILESIZE
;
2442 x_tileno2
/=X_TILESIZE
;
2444 if (BX_VGA_THIS s
.y_doublescan
) {
2445 y_tileno
/=(Y_TILESIZE
/2);
2447 y_tileno
/=Y_TILESIZE
;
2449 BX_VGA_THIS s
.vga_mem_updated
= 1;
2450 SET_TILE_UPDATED (x_tileno
, y_tileno
, 1);
2451 if (x_tileno2
!=x_tileno
) {
2452 SET_TILE_UPDATED (x_tileno2
, y_tileno
, 1);
2455 /* CGA 320x200x4 / 640x200x2 end */
2457 else if (BX_VGA_THIS s
.graphics_ctrl
.memory_mapping
!= 1) {
2458 BX_PANIC(("mem_write: graphics: mapping = %u",
2459 (unsigned) BX_VGA_THIS s
.graphics_ctrl
.memory_mapping
));
2463 if (BX_VGA_THIS s
.sequencer
.chain_four
) {
2464 unsigned x_tileno
, y_tileno
;
2466 // 320 x 200 256 color mode: chained pixel representation
2467 BX_VGA_THIS s
.memory
[(offset
& ~0x03) + (offset
% 4)*65536] = value
;
2468 if (BX_VGA_THIS s
.line_offset
> 0) {
2469 offset
-= start_addr
;
2470 x_tileno
= (offset
% BX_VGA_THIS s
.line_offset
) / (X_TILESIZE
/2);
2471 if (BX_VGA_THIS s
.y_doublescan
) {
2472 y_tileno
= (offset
/ BX_VGA_THIS s
.line_offset
) / (Y_TILESIZE
/2);
2474 y_tileno
= (offset
/ BX_VGA_THIS s
.line_offset
) / Y_TILESIZE
;
2476 BX_VGA_THIS s
.vga_mem_updated
= 1;
2477 SET_TILE_UPDATED (x_tileno
, y_tileno
, 1);
2483 /* addr between 0xA0000 and 0xAFFFF */
2486 if (BX_VGA_THIS s
.vbe_enabled
)
2488 plane0
= &BX_VGA_THIS s
.memory
[(0<<VBE_DISPI_4BPP_PLANE_SHIFT
) + (BX_VGA_THIS s
.vbe_bank
<<16)];
2489 plane1
= &BX_VGA_THIS s
.memory
[(1<<VBE_DISPI_4BPP_PLANE_SHIFT
) + (BX_VGA_THIS s
.vbe_bank
<<16)];
2490 plane2
= &BX_VGA_THIS s
.memory
[(2<<VBE_DISPI_4BPP_PLANE_SHIFT
) + (BX_VGA_THIS s
.vbe_bank
<<16)];
2491 plane3
= &BX_VGA_THIS s
.memory
[(3<<VBE_DISPI_4BPP_PLANE_SHIFT
) + (BX_VGA_THIS s
.vbe_bank
<<16)];
2496 plane0
= &BX_VGA_THIS s
.memory
[0<<16];
2497 plane1
= &BX_VGA_THIS s
.memory
[1<<16];
2498 plane2
= &BX_VGA_THIS s
.memory
[2<<16];
2499 plane3
= &BX_VGA_THIS s
.memory
[3<<16];
2502 switch (BX_VGA_THIS s
.graphics_ctrl
.write_mode
) {
2505 case 0: /* write mode 0 */
2507 const Bit8u bitmask
= BX_VGA_THIS s
.graphics_ctrl
.bitmask
;
2508 const Bit8u set_reset
= BX_VGA_THIS s
.graphics_ctrl
.set_reset
;
2509 const Bit8u enable_set_reset
= BX_VGA_THIS s
.graphics_ctrl
.enable_set_reset
;
2510 /* perform rotate on CPU data in case its needed */
2511 if (BX_VGA_THIS s
.graphics_ctrl
.data_rotate
) {
2512 value
= (value
>> BX_VGA_THIS s
.graphics_ctrl
.data_rotate
) |
2513 (value
<< (8 - BX_VGA_THIS s
.graphics_ctrl
.data_rotate
));
2515 new_val
[0] = BX_VGA_THIS s
.graphics_ctrl
.latch
[0] & ~bitmask
;
2516 new_val
[1] = BX_VGA_THIS s
.graphics_ctrl
.latch
[1] & ~bitmask
;
2517 new_val
[2] = BX_VGA_THIS s
.graphics_ctrl
.latch
[2] & ~bitmask
;
2518 new_val
[3] = BX_VGA_THIS s
.graphics_ctrl
.latch
[3] & ~bitmask
;
2519 switch (BX_VGA_THIS s
.graphics_ctrl
.raster_op
) {
2521 new_val
[0] |= ((enable_set_reset
& 1)
2522 ? ((set_reset
& 1) ? bitmask
: 0)
2523 : (value
& bitmask
));
2524 new_val
[1] |= ((enable_set_reset
& 2)
2525 ? ((set_reset
& 2) ? bitmask
: 0)
2526 : (value
& bitmask
));
2527 new_val
[2] |= ((enable_set_reset
& 4)
2528 ? ((set_reset
& 4) ? bitmask
: 0)
2529 : (value
& bitmask
));
2530 new_val
[3] |= ((enable_set_reset
& 8)
2531 ? ((set_reset
& 8) ? bitmask
: 0)
2532 : (value
& bitmask
));
2535 new_val
[0] |= ((enable_set_reset
& 1)
2537 ? (BX_VGA_THIS s
.graphics_ctrl
.latch
[0] & bitmask
)
2539 : (value
& BX_VGA_THIS s
.graphics_ctrl
.latch
[0]) & bitmask
);
2540 new_val
[1] |= ((enable_set_reset
& 2)
2542 ? (BX_VGA_THIS s
.graphics_ctrl
.latch
[1] & bitmask
)
2544 : (value
& BX_VGA_THIS s
.graphics_ctrl
.latch
[1]) & bitmask
);
2545 new_val
[2] |= ((enable_set_reset
& 4)
2547 ? (BX_VGA_THIS s
.graphics_ctrl
.latch
[2] & bitmask
)
2549 : (value
& BX_VGA_THIS s
.graphics_ctrl
.latch
[2]) & bitmask
);
2550 new_val
[3] |= ((enable_set_reset
& 8)
2552 ? (BX_VGA_THIS s
.graphics_ctrl
.latch
[3] & bitmask
)
2554 : (value
& BX_VGA_THIS s
.graphics_ctrl
.latch
[3]) & bitmask
);
2558 |= ((enable_set_reset
& 1)
2561 : (BX_VGA_THIS s
.graphics_ctrl
.latch
[0] & bitmask
))
2562 : ((value
| BX_VGA_THIS s
.graphics_ctrl
.latch
[0]) & bitmask
));
2564 |= ((enable_set_reset
& 2)
2567 : (BX_VGA_THIS s
.graphics_ctrl
.latch
[1] & bitmask
))
2568 : ((value
| BX_VGA_THIS s
.graphics_ctrl
.latch
[1]) & bitmask
));
2570 |= ((enable_set_reset
& 4)
2573 : (BX_VGA_THIS s
.graphics_ctrl
.latch
[2] & bitmask
))
2574 : ((value
| BX_VGA_THIS s
.graphics_ctrl
.latch
[2]) & bitmask
));
2576 |= ((enable_set_reset
& 8)
2579 : (BX_VGA_THIS s
.graphics_ctrl
.latch
[3] & bitmask
))
2580 : ((value
| BX_VGA_THIS s
.graphics_ctrl
.latch
[3]) & bitmask
));
2584 |= ((enable_set_reset
& 1)
2586 ? (~BX_VGA_THIS s
.graphics_ctrl
.latch
[0] & bitmask
)
2587 : (BX_VGA_THIS s
.graphics_ctrl
.latch
[0] & bitmask
))
2588 : (value
^ BX_VGA_THIS s
.graphics_ctrl
.latch
[0]) & bitmask
);
2590 |= ((enable_set_reset
& 2)
2592 ? (~BX_VGA_THIS s
.graphics_ctrl
.latch
[1] & bitmask
)
2593 : (BX_VGA_THIS s
.graphics_ctrl
.latch
[1] & bitmask
))
2594 : (value
^ BX_VGA_THIS s
.graphics_ctrl
.latch
[1]) & bitmask
);
2596 |= ((enable_set_reset
& 4)
2598 ? (~BX_VGA_THIS s
.graphics_ctrl
.latch
[2] & bitmask
)
2599 : (BX_VGA_THIS s
.graphics_ctrl
.latch
[2] & bitmask
))
2600 : (value
^ BX_VGA_THIS s
.graphics_ctrl
.latch
[2]) & bitmask
);
2602 |= ((enable_set_reset
& 8)
2604 ? (~BX_VGA_THIS s
.graphics_ctrl
.latch
[3] & bitmask
)
2605 : (BX_VGA_THIS s
.graphics_ctrl
.latch
[3] & bitmask
))
2606 : (value
^ BX_VGA_THIS s
.graphics_ctrl
.latch
[3]) & bitmask
);
2609 BX_PANIC(("vga_mem_write: write mode 0: op = %u",
2610 (unsigned) BX_VGA_THIS s
.graphics_ctrl
.raster_op
));
2615 case 1: /* write mode 1 */
2616 for (i
=0; i
<4; i
++) {
2617 new_val
[i
] = BX_VGA_THIS s
.graphics_ctrl
.latch
[i
];
2621 case 2: /* write mode 2 */
2623 const Bit8u bitmask
= BX_VGA_THIS s
.graphics_ctrl
.bitmask
;
2625 new_val
[0] = BX_VGA_THIS s
.graphics_ctrl
.latch
[0] & ~bitmask
;
2626 new_val
[1] = BX_VGA_THIS s
.graphics_ctrl
.latch
[1] & ~bitmask
;
2627 new_val
[2] = BX_VGA_THIS s
.graphics_ctrl
.latch
[2] & ~bitmask
;
2628 new_val
[3] = BX_VGA_THIS s
.graphics_ctrl
.latch
[3] & ~bitmask
;
2629 switch (BX_VGA_THIS s
.graphics_ctrl
.raster_op
) {
2631 new_val
[0] |= (value
& 1) ? bitmask
: 0;
2632 new_val
[1] |= (value
& 2) ? bitmask
: 0;
2633 new_val
[2] |= (value
& 4) ? bitmask
: 0;
2634 new_val
[3] |= (value
& 8) ? bitmask
: 0;
2637 new_val
[0] |= (value
& 1)
2638 ? (BX_VGA_THIS s
.graphics_ctrl
.latch
[0] & bitmask
)
2640 new_val
[1] |= (value
& 2)
2641 ? (BX_VGA_THIS s
.graphics_ctrl
.latch
[1] & bitmask
)
2643 new_val
[2] |= (value
& 4)
2644 ? (BX_VGA_THIS s
.graphics_ctrl
.latch
[2] & bitmask
)
2646 new_val
[3] |= (value
& 8)
2647 ? (BX_VGA_THIS s
.graphics_ctrl
.latch
[3] & bitmask
)
2651 new_val
[0] |= (value
& 1)
2653 : (BX_VGA_THIS s
.graphics_ctrl
.latch
[0] & bitmask
);
2654 new_val
[1] |= (value
& 2)
2656 : (BX_VGA_THIS s
.graphics_ctrl
.latch
[1] & bitmask
);
2657 new_val
[2] |= (value
& 4)
2659 : (BX_VGA_THIS s
.graphics_ctrl
.latch
[2] & bitmask
);
2660 new_val
[3] |= (value
& 8)
2662 : (BX_VGA_THIS s
.graphics_ctrl
.latch
[3] & bitmask
);
2665 new_val
[0] |= (value
& 1)
2666 ? (~BX_VGA_THIS s
.graphics_ctrl
.latch
[0] & bitmask
)
2667 : (BX_VGA_THIS s
.graphics_ctrl
.latch
[0] & bitmask
);
2668 new_val
[1] |= (value
& 2)
2669 ? (~BX_VGA_THIS s
.graphics_ctrl
.latch
[1] & bitmask
)
2670 : (BX_VGA_THIS s
.graphics_ctrl
.latch
[1] & bitmask
);
2671 new_val
[2] |= (value
& 4)
2672 ? (~BX_VGA_THIS s
.graphics_ctrl
.latch
[2] & bitmask
)
2673 : (BX_VGA_THIS s
.graphics_ctrl
.latch
[2] & bitmask
);
2674 new_val
[3] |= (value
& 8)
2675 ? (~BX_VGA_THIS s
.graphics_ctrl
.latch
[3] & bitmask
)
2676 : (BX_VGA_THIS s
.graphics_ctrl
.latch
[3] & bitmask
);
2682 case 3: /* write mode 3 */
2684 const Bit8u bitmask
= BX_VGA_THIS s
.graphics_ctrl
.bitmask
& value
;
2685 const Bit8u set_reset
= BX_VGA_THIS s
.graphics_ctrl
.set_reset
;
2687 /* perform rotate on CPU data */
2688 if (BX_VGA_THIS s
.graphics_ctrl
.data_rotate
) {
2689 value
= (value
>> BX_VGA_THIS s
.graphics_ctrl
.data_rotate
) |
2690 (value
<< (8 - BX_VGA_THIS s
.graphics_ctrl
.data_rotate
));
2692 new_val
[0] = BX_VGA_THIS s
.graphics_ctrl
.latch
[0] & ~bitmask
;
2693 new_val
[1] = BX_VGA_THIS s
.graphics_ctrl
.latch
[1] & ~bitmask
;
2694 new_val
[2] = BX_VGA_THIS s
.graphics_ctrl
.latch
[2] & ~bitmask
;
2695 new_val
[3] = BX_VGA_THIS s
.graphics_ctrl
.latch
[3] & ~bitmask
;
2699 switch (BX_VGA_THIS s
.graphics_ctrl
.raster_op
) {
2701 new_val
[0] |= (set_reset
& 1) ? value
: 0;
2702 new_val
[1] |= (set_reset
& 2) ? value
: 0;
2703 new_val
[2] |= (set_reset
& 4) ? value
: 0;
2704 new_val
[3] |= (set_reset
& 8) ? value
: 0;
2707 new_val
[0] |= ((set_reset
& 1) ? value
: 0)
2708 & BX_VGA_THIS s
.graphics_ctrl
.latch
[0];
2709 new_val
[1] |= ((set_reset
& 2) ? value
: 0)
2710 & BX_VGA_THIS s
.graphics_ctrl
.latch
[1];
2711 new_val
[2] |= ((set_reset
& 4) ? value
: 0)
2712 & BX_VGA_THIS s
.graphics_ctrl
.latch
[2];
2713 new_val
[3] |= ((set_reset
& 8) ? value
: 0)
2714 & BX_VGA_THIS s
.graphics_ctrl
.latch
[3];
2717 new_val
[0] |= ((set_reset
& 1) ? value
: 0)
2718 | BX_VGA_THIS s
.graphics_ctrl
.latch
[0];
2719 new_val
[1] |= ((set_reset
& 2) ? value
: 0)
2720 | BX_VGA_THIS s
.graphics_ctrl
.latch
[1];
2721 new_val
[2] |= ((set_reset
& 4) ? value
: 0)
2722 | BX_VGA_THIS s
.graphics_ctrl
.latch
[2];
2723 new_val
[3] |= ((set_reset
& 8) ? value
: 0)
2724 | BX_VGA_THIS s
.graphics_ctrl
.latch
[3];
2727 new_val
[0] |= ((set_reset
& 1) ? value
: 0)
2728 ^ BX_VGA_THIS s
.graphics_ctrl
.latch
[0];
2729 new_val
[1] |= ((set_reset
& 2) ? value
: 0)
2730 ^ BX_VGA_THIS s
.graphics_ctrl
.latch
[1];
2731 new_val
[2] |= ((set_reset
& 4) ? value
: 0)
2732 ^ BX_VGA_THIS s
.graphics_ctrl
.latch
[2];
2733 new_val
[3] |= ((set_reset
& 8) ? value
: 0)
2734 ^ BX_VGA_THIS s
.graphics_ctrl
.latch
[3];
2741 BX_PANIC(("vga_mem_write: write mode %u ?",
2742 (unsigned) BX_VGA_THIS s
.graphics_ctrl
.write_mode
));
2745 if (BX_VGA_THIS s
.sequencer
.map_mask
& 0x0f) {
2746 BX_VGA_THIS s
.vga_mem_updated
= 1;
2747 if (BX_VGA_THIS s
.sequencer
.map_mask
& 0x01)
2748 plane0
[offset
] = new_val
[0];
2749 if (BX_VGA_THIS s
.sequencer
.map_mask
& 0x02)
2750 plane1
[offset
] = new_val
[1];
2751 if (BX_VGA_THIS s
.sequencer
.map_mask
& 0x04) {
2752 if ((offset
& 0xe000) == BX_VGA_THIS s
.charmap_address
) {
2753 bx_gui
->set_text_charbyte((offset
& 0x1fff), new_val
[2]);
2755 plane2
[offset
] = new_val
[2];
2757 if (BX_VGA_THIS s
.sequencer
.map_mask
& 0x08)
2758 plane3
[offset
] = new_val
[3];
2760 unsigned x_tileno
, y_tileno
;
2762 if (BX_VGA_THIS s
.graphics_ctrl
.shift_reg
== 2) {
2763 offset
-= start_addr
;
2764 x_tileno
= (offset
% BX_VGA_THIS s
.line_offset
) * 4 / (X_TILESIZE
/ 2);
2765 if (BX_VGA_THIS s
.y_doublescan
) {
2766 y_tileno
= (offset
/ BX_VGA_THIS s
.line_offset
) / (Y_TILESIZE
/ 2);
2768 y_tileno
= (offset
/ BX_VGA_THIS s
.line_offset
) / Y_TILESIZE
;
2770 SET_TILE_UPDATED (x_tileno
, y_tileno
, 1);
2772 if (BX_VGA_THIS s
.line_compare
< BX_VGA_THIS s
.vertical_display_end
) {
2773 if (BX_VGA_THIS s
.line_offset
> 0) {
2774 if (BX_VGA_THIS s
.x_dotclockdiv2
) {
2775 x_tileno
= (offset
% BX_VGA_THIS s
.line_offset
) / (X_TILESIZE
/ 16);
2777 x_tileno
= (offset
% BX_VGA_THIS s
.line_offset
) / (X_TILESIZE
/ 8);
2779 if (BX_VGA_THIS s
.y_doublescan
) {
2780 y_tileno
= ((offset
/ BX_VGA_THIS s
.line_offset
) * 2 + BX_VGA_THIS s
.line_compare
+ 1) / Y_TILESIZE
;
2782 y_tileno
= ((offset
/ BX_VGA_THIS s
.line_offset
) + BX_VGA_THIS s
.line_compare
+ 1) / Y_TILESIZE
;
2784 SET_TILE_UPDATED (x_tileno
, y_tileno
, 1);
2787 if (offset
>= start_addr
) {
2788 offset
-= start_addr
;
2789 if (BX_VGA_THIS s
.line_offset
> 0) {
2790 if (BX_VGA_THIS s
.x_dotclockdiv2
) {
2791 x_tileno
= (offset
% BX_VGA_THIS s
.line_offset
) / (X_TILESIZE
/ 16);
2793 x_tileno
= (offset
% BX_VGA_THIS s
.line_offset
) / (X_TILESIZE
/ 8);
2795 if (BX_VGA_THIS s
.y_doublescan
) {
2796 y_tileno
= (offset
/ BX_VGA_THIS s
.line_offset
) / (Y_TILESIZE
/ 2);
2798 y_tileno
= (offset
/ BX_VGA_THIS s
.line_offset
) / Y_TILESIZE
;
2800 SET_TILE_UPDATED (x_tileno
, y_tileno
, 1);
2807 void bx_vga_c::get_text_snapshot(Bit8u
**text_snapshot
, unsigned *txHeight
,
2812 if (!BX_VGA_THIS s
.graphics_ctrl
.graphics_alpha
) {
2813 *text_snapshot
= &BX_VGA_THIS s
.text_snapshot
[0];
2814 VDE
= BX_VGA_THIS s
.vertical_display_end
;
2815 MSL
= BX_VGA_THIS s
.CRTC
.reg
[0x09] & 0x1f;
2816 *txHeight
= (VDE
+1)/(MSL
+1);
2817 *txWidth
= BX_VGA_THIS s
.CRTC
.reg
[1] + 1;
2824 Bit8u
bx_vga_c::get_actl_palette_idx(Bit8u index
)
2826 return BX_VGA_THIS s
.attribute_ctrl
.palette_reg
[index
];
2829 void bx_vga_c::dump_status(void)
2832 dbg_printf("s.misc_output.color_emulation = %u\n",
2833 (unsigned) BX_VGA_THIS s
.misc_output
.color_emulation
);
2834 dbg_printf("s.misc_output.enable_ram = %u\n",
2835 (unsigned) BX_VGA_THIS s
.misc_output
.enable_ram
);
2836 dbg_printf("s.misc_output.clock_select = %u ",
2837 (unsigned) BX_VGA_THIS s
.misc_output
.clock_select
);
2838 if (BX_VGA_THIS s
.misc_output
.clock_select
== 0)
2839 dbg_printf("(25Mhz 640 horiz pixel clock)\n");
2841 dbg_printf("(28Mhz 720 horiz pixel clock)\n");
2842 dbg_printf("s.misc_output.select_high_bank = %u\n",
2843 (unsigned) BX_VGA_THIS s
.misc_output
.select_high_bank
);
2844 dbg_printf("s.misc_output.horiz_sync_pol = %u\n",
2845 (unsigned) BX_VGA_THIS s
.misc_output
.horiz_sync_pol
);
2846 dbg_printf("s.misc_output.vert_sync_pol = %u ",
2847 (unsigned) BX_VGA_THIS s
.misc_output
.vert_sync_pol
);
2848 switch ((BX_VGA_THIS s
.misc_output
.vert_sync_pol
<< 1) |
2849 BX_VGA_THIS s
.misc_output
.horiz_sync_pol
) {
2850 case 1: dbg_printf("(400 lines)\n"); break;
2851 case 2: dbg_printf("(350 lines)\n"); break;
2852 case 3: dbg_printf("(480 lines)\n"); break;
2853 default: dbg_printf("(reserved)\n");
2856 dbg_printf("s.graphics_ctrl.odd_even = %u\n",
2857 (unsigned) BX_VGA_THIS s
.graphics_ctrl
.odd_even
);
2858 dbg_printf("s.graphics_ctrl.chain_odd_even = %u\n",
2859 (unsigned) BX_VGA_THIS s
.graphics_ctrl
.chain_odd_even
);
2860 dbg_printf("s.graphics_ctrl.shift_reg = %u\n",
2861 (unsigned) BX_VGA_THIS s
.graphics_ctrl
.shift_reg
);
2862 dbg_printf("s.graphics_ctrl.graphics_alpha = %u\n",
2863 (unsigned) BX_VGA_THIS s
.graphics_ctrl
.graphics_alpha
);
2864 dbg_printf("s.graphics_ctrl.memory_mapping = %u ",
2865 (unsigned) BX_VGA_THIS s
.graphics_ctrl
.memory_mapping
);
2866 switch (BX_VGA_THIS s
.graphics_ctrl
.memory_mapping
) {
2867 case 1: dbg_printf("(A0000-AFFFF)\n"); break;
2868 case 2: dbg_printf("(B0000-B7FFF)\n"); break;
2869 case 3: dbg_printf("(B8000-BFFFF)\n"); break;
2870 default: dbg_printf("(A0000-BFFFF)\n"); break;
2873 dbg_printf("s.sequencer.extended_mem = %u\n",
2874 (unsigned) BX_VGA_THIS s
.sequencer
.extended_mem
);
2875 dbg_printf("s.sequencer.odd_even = %u (inverted)\n",
2876 (unsigned) BX_VGA_THIS s
.sequencer
.odd_even
);
2877 dbg_printf("s.sequencer.chain_four = %u\n",
2878 (unsigned) BX_VGA_THIS s
.sequencer
.chain_four
);
2880 dbg_printf("s.attribute_ctrl.video_enabled = %u\n",
2881 (unsigned) BX_VGA_THIS s
.attribute_ctrl
.video_enabled
);
2882 dbg_printf("s.attribute_ctrl.mode_ctrl.graphics_alpha = %u\n",
2883 (unsigned) BX_VGA_THIS s
.attribute_ctrl
.mode_ctrl
.graphics_alpha
);
2884 dbg_printf("s.attribute_ctrl.mode_ctrl.display_type = %u\n",
2885 (unsigned) BX_VGA_THIS s
.attribute_ctrl
.mode_ctrl
.display_type
);
2886 dbg_printf("s.attribute_ctrl.mode_ctrl.internal_palette_size = %u\n",
2887 (unsigned) BX_VGA_THIS s
.attribute_ctrl
.mode_ctrl
.internal_palette_size
);
2888 dbg_printf("s.attribute_ctrl.mode_ctrl.pixel_clock_select = %u\n",
2889 (unsigned) BX_VGA_THIS s
.attribute_ctrl
.mode_ctrl
.pixel_clock_select
);
2893 void bx_vga_c::redraw_area(unsigned x0
, unsigned y0
, unsigned width
,
2896 unsigned xti
, yti
, xt0
, xt1
, yt0
, yt1
, xmax
, ymax
;
2898 if ((width
== 0) || (height
== 0)) {
2902 BX_VGA_THIS s
.vga_mem_updated
= 1;
2905 if (BX_VGA_THIS s
.graphics_ctrl
.graphics_alpha
|| BX_VGA_THIS s
.vbe_enabled
) {
2907 if (BX_VGA_THIS s
.graphics_ctrl
.graphics_alpha
) {
2913 if (BX_VGA_THIS s
.vbe_enabled
) {
2914 xmax
= BX_VGA_THIS s
.vbe_xres
;
2915 ymax
= BX_VGA_THIS s
.vbe_yres
;
2918 xt0
= x0
/ X_TILESIZE
;
2919 yt0
= y0
/ Y_TILESIZE
;
2921 xt1
= (x0
+ width
- 1) / X_TILESIZE
;
2923 xt1
= (xmax
- 1) / X_TILESIZE
;
2926 yt1
= (y0
+ height
- 1) / Y_TILESIZE
;
2928 yt1
= (ymax
- 1) / Y_TILESIZE
;
2930 for (yti
=yt0
; yti
<=yt1
; yti
++) {
2931 for (xti
=xt0
; xti
<=xt1
; xti
++) {
2932 SET_TILE_UPDATED (xti
, yti
, 1);
2938 memset(BX_VGA_THIS s
.text_snapshot
, 0,
2939 sizeof(BX_VGA_THIS s
.text_snapshot
));
2945 Bit8u
BX_CPP_AttrRegparmN(1)
2946 bx_vga_c::vbe_mem_read(bx_phy_address addr
)
2950 if (addr
>= VBE_DISPI_LFB_PHYSICAL_ADDRESS
)
2953 offset
= addr
- VBE_DISPI_LFB_PHYSICAL_ADDRESS
;
2958 offset
= BX_VGA_THIS s
.vbe_bank
*65536 + addr
- 0xA0000;
2961 // check for out of memory read
2962 if (offset
> VBE_DISPI_TOTAL_VIDEO_MEMORY_BYTES
)
2965 return (BX_VGA_THIS s
.memory
[offset
]);
2968 void BX_CPP_AttrRegparmN(2)
2969 bx_vga_c::vbe_mem_write(bx_phy_address addr
, Bit8u value
)
2972 unsigned x_tileno
, y_tileno
;
2974 if (BX_VGA_THIS s
.vbe_lfb_enabled
)
2976 if (addr
>= VBE_DISPI_LFB_PHYSICAL_ADDRESS
)
2979 offset
= addr
- VBE_DISPI_LFB_PHYSICAL_ADDRESS
;
2983 // banked mode write while in LFB mode -> ignore
2989 if (addr
< VBE_DISPI_LFB_PHYSICAL_ADDRESS
)
2991 // banked mode write
2992 offset
= (BX_VGA_THIS s
.vbe_bank
*65536) + (addr
- 0xA0000);
2996 // LFB write while in banked mode -> ignore
3001 // check for out of memory write
3002 if (offset
< VBE_DISPI_TOTAL_VIDEO_MEMORY_BYTES
)
3004 BX_VGA_THIS s
.memory
[offset
]=value
;
3008 // make sure we don't flood the logfile
3013 BX_INFO(("VBE_mem_write out of video memory write at %x",offset
));
3017 offset
-=BX_VGA_THIS s
.vbe_virtual_start
;
3019 // only update the UI when writing 'onscreen'
3020 if (offset
< BX_VGA_THIS s
.vbe_visible_screen_size
)
3022 y_tileno
= ((offset
/ BX_VGA_THIS s
.vbe_bpp_multiplier
) / BX_VGA_THIS s
.vbe_virtual_xres
) / Y_TILESIZE
;
3023 x_tileno
= ((offset
/ BX_VGA_THIS s
.vbe_bpp_multiplier
) % BX_VGA_THIS s
.vbe_virtual_xres
) / X_TILESIZE
;
3025 if ((y_tileno
< BX_NUM_Y_TILES
) && (x_tileno
< BX_NUM_X_TILES
))
3027 BX_VGA_THIS s
.vga_mem_updated
= 1;
3028 SET_TILE_UPDATED (x_tileno
, y_tileno
, 1);
3033 Bit32u
bx_vga_c::vbe_read_handler(void *this_ptr
, Bit32u address
, unsigned io_len
)
3035 #if BX_USE_VGA_SMF == 0
3036 bx_vga_c
*class_ptr
= (bx_vga_c
*) this_ptr
;
3037 return class_ptr
->vbe_read(address
, io_len
);
3040 Bit32u
bx_vga_c::vbe_read(Bit32u address
, unsigned io_len
)
3044 #endif // BX_USE_VGA_SMF == 0
3047 // BX_INFO(("VBE_read %x (len %x)", address, io_len));
3049 if ((address
==VBE_DISPI_IOPORT_INDEX
) ||
3050 (address
==VBE_DISPI_IOPORT_INDEX_OLD
))
3053 return (Bit32u
) BX_VGA_THIS s
.vbe_curindex
;
3057 // data register read
3059 switch (BX_VGA_THIS s
.vbe_curindex
)
3061 case VBE_DISPI_INDEX_ID
: // Display Interface ID check
3062 return BX_VGA_THIS s
.vbe_cur_dispi
;
3064 case VBE_DISPI_INDEX_XRES
: // x resolution
3065 if (BX_VGA_THIS s
.vbe_get_capabilities
) {
3066 return BX_VGA_THIS s
.vbe_max_xres
;
3068 return BX_VGA_THIS s
.vbe_xres
;
3071 case VBE_DISPI_INDEX_YRES
: // y resolution
3072 if (BX_VGA_THIS s
.vbe_get_capabilities
) {
3073 return BX_VGA_THIS s
.vbe_max_yres
;
3075 return BX_VGA_THIS s
.vbe_yres
;
3078 case VBE_DISPI_INDEX_BPP
: // bpp
3079 if (BX_VGA_THIS s
.vbe_get_capabilities
) {
3080 return BX_VGA_THIS s
.vbe_max_bpp
;
3082 return BX_VGA_THIS s
.vbe_bpp
;
3085 case VBE_DISPI_INDEX_ENABLE
: // vbe enabled
3086 retval
= BX_VGA_THIS s
.vbe_enabled
;
3087 if (BX_VGA_THIS s
.vbe_get_capabilities
)
3088 retval
|= VBE_DISPI_GETCAPS
;
3089 if (BX_VGA_THIS s
.vbe_8bit_dac
)
3090 retval
|= VBE_DISPI_8BIT_DAC
;
3093 case VBE_DISPI_INDEX_BANK
: // current bank
3094 return BX_VGA_THIS s
.vbe_bank
;
3096 case VBE_DISPI_INDEX_X_OFFSET
:
3097 return BX_VGA_THIS s
.vbe_offset_x
;
3099 case VBE_DISPI_INDEX_Y_OFFSET
:
3100 return BX_VGA_THIS s
.vbe_offset_y
;
3102 case VBE_DISPI_INDEX_VIRT_WIDTH
:
3103 return BX_VGA_THIS s
.vbe_virtual_xres
;
3105 case VBE_DISPI_INDEX_VIRT_HEIGHT
:
3106 return BX_VGA_THIS s
.vbe_virtual_yres
;
3109 BX_PANIC(("VBE unknown data read index 0x%x",BX_VGA_THIS s
.vbe_curindex
));
3113 BX_PANIC(("VBE_read shouldn't reach this"));
3114 return 0; /* keep compiler happy */
3117 void bx_vga_c::vbe_write_handler(void *this_ptr
, Bit32u address
, Bit32u value
, unsigned io_len
)
3119 #if BX_USE_VGA_SMF == 0
3120 bx_vga_c
*class_ptr
= (bx_vga_c
*) this_ptr
;
3121 class_ptr
->vbe_write(address
, value
, io_len
);
3124 Bit32u
bx_vga_c::vbe_write(Bit32u address
, Bit32u value
, unsigned io_len
)
3129 bx_bool new_vbe_8bit_dac
;
3130 bx_bool needs_update
= 0;
3133 // BX_INFO(("VBE_write %x = %x (len %x)", address, value, io_len));
3138 case VBE_DISPI_IOPORT_INDEX
:
3139 // legacy index register
3140 case VBE_DISPI_IOPORT_INDEX_OLD
:
3142 BX_VGA_THIS s
.vbe_curindex
= (Bit16u
) value
;
3146 // FIXME: maybe do some 'sanity' checks on received data?
3147 case VBE_DISPI_IOPORT_DATA
:
3148 // legacy data register
3149 case VBE_DISPI_IOPORT_DATA_OLD
:
3150 switch (BX_VGA_THIS s
.vbe_curindex
)
3152 case VBE_DISPI_INDEX_ID
: // Display Interface ID check
3154 if ((value
== VBE_DISPI_ID0
) ||
3155 (value
== VBE_DISPI_ID1
) ||
3156 (value
== VBE_DISPI_ID2
) ||
3157 (value
== VBE_DISPI_ID3
) ||
3158 (value
== VBE_DISPI_ID4
))
3160 // allow backwards compatible with previous dispi bioses
3161 BX_VGA_THIS s
.vbe_cur_dispi
=value
;
3165 BX_PANIC(("VBE unknown Display Interface %x", value
));
3168 // make sure we don't flood the logfile
3173 BX_INFO(("VBE known Display Interface %x", value
));
3177 case VBE_DISPI_INDEX_XRES
: // set xres
3179 // check that we don't set xres during vbe enabled
3180 if (!BX_VGA_THIS s
.vbe_enabled
)
3182 // check for within max xres range
3183 if (value
<= VBE_DISPI_MAX_XRES
)
3185 BX_VGA_THIS s
.vbe_xres
=(Bit16u
) value
;
3186 BX_INFO(("VBE set xres (%d)", value
));
3190 BX_INFO(("VBE set xres more then max xres (%d)", value
));
3195 BX_INFO(("VBE set xres during vbe enabled!"));
3199 case VBE_DISPI_INDEX_YRES
: // set yres
3201 // check that we don't set yres during vbe enabled
3202 if (!BX_VGA_THIS s
.vbe_enabled
)
3204 // check for within max yres range
3205 if (value
<= VBE_DISPI_MAX_YRES
)
3207 BX_VGA_THIS s
.vbe_yres
=(Bit16u
) value
;
3208 BX_INFO(("VBE set yres (%d)", value
));
3212 BX_INFO(("VBE set yres more then max yres (%d)", value
));
3217 BX_INFO(("VBE set yres during vbe enabled!"));
3221 case VBE_DISPI_INDEX_BPP
: // set bpp
3223 // check that we don't set bpp during vbe enabled
3224 if (!BX_VGA_THIS s
.vbe_enabled
)
3226 // for backward compatiblity
3227 if (value
== 0) value
= VBE_DISPI_BPP_8
;
3228 // check for correct bpp range
3229 if ((value
== VBE_DISPI_BPP_4
) || (value
== VBE_DISPI_BPP_8
) || (value
== VBE_DISPI_BPP_15
) ||
3230 (value
== VBE_DISPI_BPP_16
) || (value
== VBE_DISPI_BPP_24
) || (value
== VBE_DISPI_BPP_32
))
3232 BX_VGA_THIS s
.vbe_bpp
=(Bit16u
) value
;
3233 BX_INFO(("VBE set bpp (%d)", value
));
3237 BX_INFO(("VBE set bpp with unknown bpp (%d)", value
));
3242 BX_INFO(("VBE set bpp during vbe enabled!"));
3246 case VBE_DISPI_INDEX_BANK
: // set bank
3248 value
=value
& 0xff; // FIXME lobyte = vbe bank A?
3249 unsigned divider
= (BX_VGA_THIS s
.vbe_bpp
!=VBE_DISPI_BPP_4
)?64:256;
3250 // check for max bank nr
3251 if (value
< (VBE_DISPI_TOTAL_VIDEO_MEMORY_KB
/ divider
))
3253 if (!BX_VGA_THIS s
.vbe_lfb_enabled
)
3255 BX_DEBUG(("VBE set bank to %d", value
));
3256 BX_VGA_THIS s
.vbe_bank
=value
;
3260 BX_ERROR(("VBE set bank in LFB mode ignored"));
3265 BX_INFO(("VBE set invalid bank (%d)", value
));
3269 case VBE_DISPI_INDEX_ENABLE
: // enable video
3271 if ((value
& VBE_DISPI_ENABLED
) && !BX_VGA_THIS s
.vbe_enabled
)
3275 // setup virtual resolution to be the same as current reso
3276 BX_VGA_THIS s
.vbe_virtual_yres
=BX_VGA_THIS s
.vbe_yres
;
3277 BX_VGA_THIS s
.vbe_virtual_xres
=BX_VGA_THIS s
.vbe_xres
;
3280 BX_VGA_THIS s
.vbe_offset_x
=0;
3281 BX_VGA_THIS s
.vbe_offset_y
=0;
3282 BX_VGA_THIS s
.vbe_virtual_start
=0;
3284 switch((BX_VGA_THIS s
.vbe_bpp
))
3286 // Default pixel sizes
3287 case VBE_DISPI_BPP_8
:
3288 BX_VGA_THIS s
.vbe_bpp_multiplier
= 1;
3289 BX_VGA_THIS s
.line_offset
= BX_VGA_THIS s
.vbe_virtual_xres
;
3293 case VBE_DISPI_BPP_4
:
3294 BX_VGA_THIS s
.vbe_bpp_multiplier
= 1;
3295 BX_VGA_THIS s
.line_offset
= (BX_VGA_THIS s
.vbe_virtual_xres
>> 3);
3299 case VBE_DISPI_BPP_15
:
3300 BX_VGA_THIS s
.vbe_bpp_multiplier
= 2;
3301 BX_VGA_THIS s
.line_offset
= BX_VGA_THIS s
.vbe_virtual_xres
* 2;
3305 case VBE_DISPI_BPP_16
:
3306 BX_VGA_THIS s
.vbe_bpp_multiplier
= 2;
3307 BX_VGA_THIS s
.line_offset
= BX_VGA_THIS s
.vbe_virtual_xres
* 2;
3311 case VBE_DISPI_BPP_24
:
3312 BX_VGA_THIS s
.vbe_bpp_multiplier
= 3;
3313 BX_VGA_THIS s
.line_offset
= BX_VGA_THIS s
.vbe_virtual_xres
* 3;
3317 case VBE_DISPI_BPP_32
:
3318 BX_VGA_THIS s
.vbe_bpp_multiplier
= 4;
3319 BX_VGA_THIS s
.line_offset
= BX_VGA_THIS s
.vbe_virtual_xres
<< 2;
3323 BX_VGA_THIS s
.vbe_visible_screen_size
= BX_VGA_THIS s
.line_offset
* BX_VGA_THIS s
.vbe_yres
;
3325 BX_INFO(("VBE enabling x %d, y %d, bpp %d, %u bytes visible", BX_VGA_THIS s
.vbe_xres
, BX_VGA_THIS s
.vbe_yres
, BX_VGA_THIS s
.vbe_bpp
, BX_VGA_THIS s
.vbe_visible_screen_size
));
3329 BX_VGA_THIS s
.vbe_lfb_enabled
=(bx_bool
)(value
& VBE_DISPI_LFB_ENABLED
);
3330 if ((value
& VBE_DISPI_NOCLEARMEM
) == 0)
3332 memset(BX_VGA_THIS s
.memory
, 0, BX_VGA_THIS s
.vbe_visible_screen_size
);
3334 bx_gui
->dimension_update(BX_VGA_THIS s
.vbe_xres
, BX_VGA_THIS s
.vbe_yres
, 0, 0, depth
);
3335 BX_VGA_THIS s
.last_bpp
= depth
;
3338 else if (((value
& VBE_DISPI_ENABLED
) == 0) && BX_VGA_THIS s
.vbe_enabled
)
3340 BX_INFO(("VBE disabling"));
3341 BX_VGA_THIS s
.vbe_lfb_enabled
=0;
3343 BX_VGA_THIS s
.vbe_enabled
=(bx_bool
)(value
& VBE_DISPI_ENABLED
);
3344 BX_VGA_THIS s
.vbe_get_capabilities
=(bx_bool
)((value
& VBE_DISPI_GETCAPS
) != 0);
3345 new_vbe_8bit_dac
=(bx_bool
)((value
& VBE_DISPI_8BIT_DAC
) != 0);
3346 if (new_vbe_8bit_dac
!= BX_VGA_THIS s
.vbe_8bit_dac
)
3348 if (new_vbe_8bit_dac
)
3350 for (i
=0; i
<256; i
++)
3352 BX_VGA_THIS s
.pel
.data
[i
].red
<<= 2;
3353 BX_VGA_THIS s
.pel
.data
[i
].green
<<= 2;
3354 BX_VGA_THIS s
.pel
.data
[i
].blue
<<= 2;
3356 BX_INFO(("DAC in 8 bit mode"));
3360 for (i
=0; i
<256; i
++)
3362 BX_VGA_THIS s
.pel
.data
[i
].red
>>= 2;
3363 BX_VGA_THIS s
.pel
.data
[i
].green
>>= 2;
3364 BX_VGA_THIS s
.pel
.data
[i
].blue
>>= 2;
3366 BX_INFO(("DAC in standard mode"));
3368 BX_VGA_THIS s
.vbe_8bit_dac
=new_vbe_8bit_dac
;
3373 case VBE_DISPI_INDEX_X_OFFSET
:
3375 BX_DEBUG(("VBE offset x %d", value
));
3376 BX_VGA_THIS s
.vbe_offset_x
=(Bit16u
)value
;
3378 BX_VGA_THIS s
.vbe_virtual_start
= BX_VGA_THIS s
.vbe_offset_y
* BX_VGA_THIS s
.line_offset
;
3379 if (BX_VGA_THIS s
.vbe_bpp
!= VBE_DISPI_BPP_4
) {
3380 BX_VGA_THIS s
.vbe_virtual_start
+= (BX_VGA_THIS s
.vbe_offset_x
* BX_VGA_THIS s
.vbe_bpp_multiplier
);
3382 BX_VGA_THIS s
.vbe_virtual_start
+= (BX_VGA_THIS s
.vbe_offset_x
>> 3);
3387 case VBE_DISPI_INDEX_Y_OFFSET
:
3389 BX_DEBUG(("VBE offset y %d", value
));
3391 Bit32u new_screen_start
= value
* BX_VGA_THIS s
.line_offset
;
3392 if (BX_VGA_THIS s
.vbe_bpp
!= VBE_DISPI_BPP_4
) {
3393 if ((new_screen_start
+ BX_VGA_THIS s
.vbe_visible_screen_size
) > VBE_DISPI_TOTAL_VIDEO_MEMORY_BYTES
)
3395 BX_PANIC(("VBE offset y %d out of bounds", value
));
3398 new_screen_start
+= (BX_VGA_THIS s
.vbe_offset_x
* BX_VGA_THIS s
.vbe_bpp_multiplier
);
3400 if ((new_screen_start
+ BX_VGA_THIS s
.vbe_visible_screen_size
) > (VBE_DISPI_TOTAL_VIDEO_MEMORY_BYTES
/ 4))
3402 BX_PANIC(("VBE offset y %d out of bounds", value
));
3405 new_screen_start
+= (BX_VGA_THIS s
.vbe_offset_x
>> 3);
3407 BX_VGA_THIS s
.vbe_virtual_start
= new_screen_start
;
3408 BX_VGA_THIS s
.vbe_offset_y
= (Bit16u
)value
;
3412 case VBE_DISPI_INDEX_VIRT_WIDTH
:
3414 BX_INFO(("VBE requested virtual width %d", value
));
3416 // calculate virtual width & height dimensions
3418 // virt_width > xres
3419 // virt_height >=yres
3420 // virt_width*virt_height < MAX_VIDEO_MEMORY
3422 // basicly 2 situations
3425 // MAX_VIDEO_MEMORY / virt_width >= yres
3426 // adjust result height
3428 // adjust result width based upon virt_height=yres
3429 Bit16u new_width
=value
;
3431 if (BX_VGA_THIS s
.vbe_bpp
!= VBE_DISPI_BPP_4
) {
3432 new_height
=(VBE_DISPI_TOTAL_VIDEO_MEMORY_BYTES
/ BX_VGA_THIS s
.vbe_bpp_multiplier
) / new_width
;
3434 new_height
=(VBE_DISPI_TOTAL_VIDEO_MEMORY_BYTES
* 2) / new_width
;
3436 if (new_height
>=BX_VGA_THIS s
.vbe_yres
)
3438 // we have a decent virtual width & new_height
3439 BX_INFO(("VBE decent virtual height %d",new_height
));
3443 // no decent virtual height: adjust width & height
3444 new_height
=BX_VGA_THIS s
.vbe_yres
;
3445 if (BX_VGA_THIS s
.vbe_bpp
!= VBE_DISPI_BPP_4
) {
3446 new_width
=(VBE_DISPI_TOTAL_VIDEO_MEMORY_BYTES
/ BX_VGA_THIS s
.vbe_bpp_multiplier
) / new_height
;
3448 new_width
=(VBE_DISPI_TOTAL_VIDEO_MEMORY_BYTES
* 2) / new_height
;
3451 BX_INFO(("VBE recalc virtual width %d height %d",new_width
, new_height
));
3454 BX_VGA_THIS s
.vbe_virtual_xres
=new_width
;
3455 BX_VGA_THIS s
.vbe_virtual_yres
=new_height
;
3456 if (BX_VGA_THIS s
.vbe_bpp
!= VBE_DISPI_BPP_4
) {
3457 BX_VGA_THIS s
.line_offset
= BX_VGA_THIS s
.vbe_virtual_xres
* BX_VGA_THIS s
.vbe_bpp_multiplier
;
3459 BX_VGA_THIS s
.line_offset
= BX_VGA_THIS s
.vbe_virtual_xres
>> 3;
3461 BX_VGA_THIS s
.vbe_visible_screen_size
= BX_VGA_THIS s
.line_offset
* BX_VGA_THIS s
.vbe_yres
;
3465 case VBE_DISPI_INDEX_VIRT_HEIGHT:
3467 BX_INFO(("VBE virtual height %x", value));
3473 BX_PANIC(("VBE unknown data write index 0x%x",BX_VGA_THIS s
.vbe_curindex
));
3477 BX_VGA_THIS s
.vga_mem_updated
= 1;
3478 for (unsigned xti
= 0; xti
< BX_NUM_X_TILES
; xti
++) {
3479 for (unsigned yti
= 0; yti
< BX_NUM_Y_TILES
; yti
++) {
3480 SET_TILE_UPDATED (xti
, yti
, 1);
3486 } // end switch address