2001-10-03 17:10:38 +04:00
|
|
|
/////////////////////////////////////////////////////////////////////////
|
2006-02-22 00:35:09 +03:00
|
|
|
// $Id: vga.cc,v 1.125 2006-02-21 21:35:09 vruppert Exp $
|
2001-10-03 17:10:38 +04:00
|
|
|
/////////////////////////////////////////////////////////////////////////
|
|
|
|
//
|
2002-01-20 03:28:09 +03:00
|
|
|
// Copyright (C) 2002 MandrakeSoft S.A.
|
2001-04-10 05:04:59 +04:00
|
|
|
//
|
|
|
|
// MandrakeSoft S.A.
|
|
|
|
// 43, rue d'Aboukir
|
|
|
|
// 75002 Paris - France
|
|
|
|
// http://www.linux-mandrake.com/
|
|
|
|
// http://www.mandrakesoft.com/
|
|
|
|
//
|
|
|
|
// This library is free software; you can redistribute it and/or
|
|
|
|
// modify it under the terms of the GNU Lesser General Public
|
|
|
|
// License as published by the Free Software Foundation; either
|
|
|
|
// version 2 of the License, or (at your option) any later version.
|
|
|
|
//
|
|
|
|
// This library is distributed in the hope that it will be useful,
|
|
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
// Lesser General Public License for more details.
|
|
|
|
//
|
|
|
|
// You should have received a copy of the GNU Lesser General Public
|
|
|
|
// License along with this library; if not, write to the Free Software
|
|
|
|
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
|
|
|
|
|
|
|
2002-10-25 01:07:56 +04:00
|
|
|
// Define BX_PLUGGABLE in files that can be compiled into plugins. For
|
|
|
|
// platforms that require a special tag on exported symbols, BX_PLUGGABLE
|
|
|
|
// is used to know when we are exporting symbols and when we are importing.
|
|
|
|
#define BX_PLUGGABLE
|
|
|
|
|
2004-06-19 19:20:15 +04:00
|
|
|
#include "iodev.h"
|
2002-10-25 01:07:56 +04:00
|
|
|
|
|
|
|
#define LOG_THIS theVga->
|
2001-04-10 05:04:59 +04:00
|
|
|
|
|
|
|
// (mch)
|
|
|
|
#define VGA_TRACE_FEATURE
|
|
|
|
|
2002-11-16 18:43:13 +03:00
|
|
|
// Only reference the array if the tile numbers are within the bounds
|
|
|
|
// of the array. If out of bounds, do nothing.
|
|
|
|
#define SET_TILE_UPDATED(xtile,ytile,value) \
|
|
|
|
do { \
|
2003-04-21 23:03:46 +04:00
|
|
|
if (((xtile) < BX_NUM_X_TILES) && ((ytile) < BX_NUM_Y_TILES)) \
|
2002-11-16 18:43:13 +03:00
|
|
|
BX_VGA_THIS s.vga_tile_updated[(xtile)][(ytile)] = value; \
|
|
|
|
} while (0)
|
|
|
|
|
|
|
|
// Only reference the array if the tile numbers are within the bounds
|
|
|
|
// of the array. If out of bounds, return 0.
|
|
|
|
#define GET_TILE_UPDATED(xtile,ytile) \
|
|
|
|
((((xtile) < BX_NUM_X_TILES) && ((ytile) < BX_NUM_Y_TILES))? \
|
|
|
|
BX_VGA_THIS s.vga_tile_updated[(xtile)][(ytile)] \
|
|
|
|
: 0)
|
|
|
|
|
2004-04-25 11:16:09 +04:00
|
|
|
static const Bit16u charmap_offset[8] = {
|
|
|
|
0x0000, 0x4000, 0x8000, 0xc000,
|
|
|
|
0x2000, 0x6000, 0xa000, 0xe000
|
|
|
|
};
|
|
|
|
|
2003-04-27 13:13:47 +04:00
|
|
|
static const Bit8u ccdat[16][4] = {
|
|
|
|
{ 0x00, 0x00, 0x00, 0x00 },
|
|
|
|
{ 0xff, 0x00, 0x00, 0x00 },
|
|
|
|
{ 0x00, 0xff, 0x00, 0x00 },
|
|
|
|
{ 0xff, 0xff, 0x00, 0x00 },
|
|
|
|
{ 0x00, 0x00, 0xff, 0x00 },
|
|
|
|
{ 0xff, 0x00, 0xff, 0x00 },
|
|
|
|
{ 0x00, 0xff, 0xff, 0x00 },
|
|
|
|
{ 0xff, 0xff, 0xff, 0x00 },
|
|
|
|
{ 0x00, 0x00, 0x00, 0xff },
|
|
|
|
{ 0xff, 0x00, 0x00, 0xff },
|
|
|
|
{ 0x00, 0xff, 0x00, 0xff },
|
|
|
|
{ 0xff, 0xff, 0x00, 0xff },
|
|
|
|
{ 0x00, 0x00, 0xff, 0xff },
|
|
|
|
{ 0xff, 0x00, 0xff, 0xff },
|
|
|
|
{ 0x00, 0xff, 0xff, 0xff },
|
|
|
|
{ 0xff, 0xff, 0xff, 0xff },
|
|
|
|
};
|
|
|
|
|
2002-10-25 01:07:56 +04:00
|
|
|
bx_vga_c *theVga = NULL;
|
2001-04-10 05:04:59 +04:00
|
|
|
|
2005-10-27 13:32:02 +04:00
|
|
|
unsigned old_iHeight = 0, old_iWidth = 0, old_MSL = 0;
|
2002-02-07 22:04:30 +03:00
|
|
|
|
2004-08-16 12:07:23 +04:00
|
|
|
#if BX_SUPPORT_CLGD54XX
|
|
|
|
void
|
|
|
|
libvga_set_smf_pointer(bx_vga_c *theVga_ptr)
|
|
|
|
{
|
|
|
|
theVga = theVga_ptr;
|
|
|
|
}
|
|
|
|
#else // BX_SUPPORT_CLGD54XX
|
2002-10-25 01:07:56 +04:00
|
|
|
int
|
|
|
|
libvga_LTX_plugin_init(plugin_t *plugin, plugintype_t type, int argc, char *argv[])
|
|
|
|
{
|
|
|
|
theVga = new bx_vga_c ();
|
|
|
|
bx_devices.pluginVgaDevice = theVga;
|
|
|
|
BX_REGISTER_DEVICE_DEVMODEL(plugin, type, theVga, BX_PLUGIN_VGA);
|
|
|
|
return(0); // Success
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
libvga_LTX_plugin_fini(void)
|
|
|
|
{
|
|
|
|
}
|
2004-08-16 12:07:23 +04:00
|
|
|
#endif // BX_SUPPORT_CLGD54XX
|
2002-10-25 01:07:56 +04:00
|
|
|
|
2001-04-10 05:04:59 +04:00
|
|
|
bx_vga_c::bx_vga_c(void)
|
|
|
|
{
|
2002-10-25 01:07:56 +04:00
|
|
|
put("VGA");
|
|
|
|
s.vga_mem_updated = 0;
|
|
|
|
s.x_tilesize = X_TILESIZE;
|
|
|
|
s.y_tilesize = Y_TILESIZE;
|
|
|
|
timer_id = BX_NULL_TIMER_HANDLE;
|
2005-10-27 21:53:41 +04:00
|
|
|
#if BX_SUPPORT_VBE
|
|
|
|
s.vbe_memory = NULL;
|
|
|
|
#endif
|
2001-04-10 05:04:59 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bx_vga_c::~bx_vga_c(void)
|
|
|
|
{
|
2005-10-27 21:53:41 +04:00
|
|
|
#if BX_SUPPORT_VBE
|
|
|
|
if (s.vbe_memory != NULL) {
|
|
|
|
delete [] s.vbe_memory;
|
|
|
|
}
|
|
|
|
#endif
|
2001-04-10 05:04:59 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
2002-10-25 01:07:56 +04:00
|
|
|
bx_vga_c::init(void)
|
2001-04-10 05:04:59 +04:00
|
|
|
{
|
2004-02-24 22:21:48 +03:00
|
|
|
unsigned i,string_i;
|
2001-04-10 05:04:59 +04:00
|
|
|
unsigned x,y;
|
2004-02-22 16:03:02 +03:00
|
|
|
#if BX_SUPPORT_VBE
|
|
|
|
Bit16u max_xres, max_yres, max_bpp;
|
|
|
|
#endif
|
2004-02-22 21:51:38 +03:00
|
|
|
int argc;
|
2004-02-24 22:21:48 +03:00
|
|
|
char *argv[16];
|
|
|
|
char *ptr;
|
|
|
|
char string[512];
|
2004-08-16 12:07:23 +04:00
|
|
|
#if BX_SUPPORT_VBE
|
2001-04-10 05:04:59 +04:00
|
|
|
unsigned addr;
|
2004-08-16 12:07:23 +04:00
|
|
|
#endif
|
2001-04-10 05:04:59 +04:00
|
|
|
|
2005-02-10 12:48:12 +03:00
|
|
|
BX_VGA_THIS extension_init = 0;
|
|
|
|
BX_VGA_THIS extension_checked = 0;
|
2004-08-16 12:07:23 +04:00
|
|
|
#if !BX_SUPPORT_CLGD54XX
|
|
|
|
BX_VGA_THIS init_iohandlers(read_handler,write_handler);
|
|
|
|
#endif // !BX_SUPPORT_CLGD54XX
|
2001-04-10 05:04:59 +04:00
|
|
|
|
2004-07-18 23:40:51 +04:00
|
|
|
DEV_register_memory_handlers(mem_read_handler, theVga, mem_write_handler,
|
|
|
|
theVga, 0xa0000, 0xbffff);
|
|
|
|
|
2006-01-07 15:10:59 +03:00
|
|
|
BX_VGA_THIS s.vga_enabled = 1;
|
2001-04-10 05:04:59 +04:00
|
|
|
BX_VGA_THIS s.misc_output.color_emulation = 1;
|
|
|
|
BX_VGA_THIS s.misc_output.enable_ram = 1;
|
|
|
|
BX_VGA_THIS s.misc_output.clock_select = 0;
|
|
|
|
BX_VGA_THIS s.misc_output.select_high_bank = 0;
|
|
|
|
BX_VGA_THIS s.misc_output.horiz_sync_pol = 1;
|
|
|
|
BX_VGA_THIS s.misc_output.vert_sync_pol = 1;
|
|
|
|
|
|
|
|
BX_VGA_THIS s.attribute_ctrl.mode_ctrl.graphics_alpha = 0;
|
|
|
|
BX_VGA_THIS s.attribute_ctrl.mode_ctrl.display_type = 0;
|
|
|
|
BX_VGA_THIS s.attribute_ctrl.mode_ctrl.enable_line_graphics = 1;
|
|
|
|
BX_VGA_THIS s.attribute_ctrl.mode_ctrl.blink_intensity = 0;
|
|
|
|
BX_VGA_THIS s.attribute_ctrl.mode_ctrl.pixel_panning_compat = 0;
|
|
|
|
BX_VGA_THIS s.attribute_ctrl.mode_ctrl.pixel_clock_select = 0;
|
|
|
|
BX_VGA_THIS s.attribute_ctrl.mode_ctrl.internal_palette_size = 0;
|
|
|
|
|
2003-04-28 22:15:31 +04:00
|
|
|
BX_VGA_THIS s.line_offset=80;
|
2003-05-02 11:32:06 +04:00
|
|
|
BX_VGA_THIS s.line_compare=1023;
|
|
|
|
BX_VGA_THIS s.vertical_display_end=399;
|
2001-04-10 05:04:59 +04:00
|
|
|
|
2003-11-02 19:34:10 +03:00
|
|
|
for (i=0; i<=0x18; i++)
|
2001-04-10 05:04:59 +04:00
|
|
|
BX_VGA_THIS s.CRTC.reg[i] = 0;
|
|
|
|
BX_VGA_THIS s.CRTC.address = 0;
|
2004-07-18 23:40:51 +04:00
|
|
|
BX_VGA_THIS s.CRTC.write_protect = 0;
|
2001-04-10 05:04:59 +04:00
|
|
|
|
|
|
|
BX_VGA_THIS s.attribute_ctrl.flip_flop = 0;
|
|
|
|
BX_VGA_THIS s.attribute_ctrl.address = 0;
|
|
|
|
BX_VGA_THIS s.attribute_ctrl.video_enabled = 1;
|
|
|
|
for (i=0; i<16; i++)
|
|
|
|
BX_VGA_THIS s.attribute_ctrl.palette_reg[i] = 0;
|
|
|
|
BX_VGA_THIS s.attribute_ctrl.overscan_color = 0;
|
|
|
|
BX_VGA_THIS s.attribute_ctrl.color_plane_enable = 0x0f;
|
|
|
|
BX_VGA_THIS s.attribute_ctrl.horiz_pel_panning = 0;
|
|
|
|
BX_VGA_THIS s.attribute_ctrl.color_select = 0;
|
|
|
|
|
|
|
|
for (i=0; i<256; i++) {
|
|
|
|
BX_VGA_THIS s.pel.data[i].red = 0;
|
|
|
|
BX_VGA_THIS s.pel.data[i].green = 0;
|
|
|
|
BX_VGA_THIS s.pel.data[i].blue = 0;
|
|
|
|
}
|
|
|
|
BX_VGA_THIS s.pel.write_data_register = 0;
|
|
|
|
BX_VGA_THIS s.pel.write_data_cycle = 0;
|
|
|
|
BX_VGA_THIS s.pel.read_data_register = 0;
|
|
|
|
BX_VGA_THIS s.pel.read_data_cycle = 0;
|
2003-01-11 14:18:04 +03:00
|
|
|
BX_VGA_THIS s.pel.dac_state = 0x01;
|
2001-04-10 05:04:59 +04:00
|
|
|
BX_VGA_THIS s.pel.mask = 0xff;
|
|
|
|
|
|
|
|
BX_VGA_THIS s.graphics_ctrl.index = 0;
|
|
|
|
BX_VGA_THIS s.graphics_ctrl.set_reset = 0;
|
|
|
|
BX_VGA_THIS s.graphics_ctrl.enable_set_reset = 0;
|
|
|
|
BX_VGA_THIS s.graphics_ctrl.color_compare = 0;
|
|
|
|
BX_VGA_THIS s.graphics_ctrl.data_rotate = 0;
|
|
|
|
BX_VGA_THIS s.graphics_ctrl.raster_op = 0;
|
|
|
|
BX_VGA_THIS s.graphics_ctrl.read_map_select = 0;
|
|
|
|
BX_VGA_THIS s.graphics_ctrl.write_mode = 0;
|
|
|
|
BX_VGA_THIS s.graphics_ctrl.read_mode = 0;
|
|
|
|
BX_VGA_THIS s.graphics_ctrl.odd_even = 0;
|
|
|
|
BX_VGA_THIS s.graphics_ctrl.chain_odd_even = 0;
|
|
|
|
BX_VGA_THIS s.graphics_ctrl.shift_reg = 0;
|
|
|
|
BX_VGA_THIS s.graphics_ctrl.graphics_alpha = 0;
|
|
|
|
BX_VGA_THIS s.graphics_ctrl.memory_mapping = 2; // monochrome text mode
|
|
|
|
BX_VGA_THIS s.graphics_ctrl.color_dont_care = 0;
|
|
|
|
BX_VGA_THIS s.graphics_ctrl.bitmask = 0;
|
|
|
|
for (i=0; i<4; i++) {
|
|
|
|
BX_VGA_THIS s.graphics_ctrl.latch[i] = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
BX_VGA_THIS s.sequencer.index = 0;
|
|
|
|
BX_VGA_THIS s.sequencer.map_mask = 0;
|
|
|
|
for (i=0; i<4; i++) {
|
|
|
|
BX_VGA_THIS s.sequencer.map_mask_bit[i] = 0;
|
|
|
|
}
|
2002-10-13 12:14:31 +04:00
|
|
|
BX_VGA_THIS s.sequencer.reset1 = 1;
|
|
|
|
BX_VGA_THIS s.sequencer.reset2 = 1;
|
2001-04-10 05:04:59 +04:00
|
|
|
BX_VGA_THIS s.sequencer.reg1 = 0;
|
|
|
|
BX_VGA_THIS s.sequencer.char_map_select = 0;
|
|
|
|
BX_VGA_THIS s.sequencer.extended_mem = 1; // display mem greater than 64K
|
|
|
|
BX_VGA_THIS s.sequencer.odd_even = 1; // use sequential addressing mode
|
|
|
|
BX_VGA_THIS s.sequencer.chain_four = 0; // use map mask & read map select
|
|
|
|
|
|
|
|
memset(BX_VGA_THIS s.vga_memory, 0, sizeof(BX_VGA_THIS s.vga_memory));
|
|
|
|
|
|
|
|
BX_VGA_THIS s.vga_mem_updated = 0;
|
|
|
|
for (y=0; y<480/Y_TILESIZE; y++)
|
|
|
|
for (x=0; x<640/X_TILESIZE; x++)
|
2002-11-16 18:43:13 +03:00
|
|
|
SET_TILE_UPDATED (x, y, 0);
|
2001-04-10 05:04:59 +04:00
|
|
|
|
2004-02-24 22:21:48 +03:00
|
|
|
memset(argv, 0, sizeof(argv));
|
2004-02-22 21:51:38 +03:00
|
|
|
argc = 1;
|
|
|
|
argv[0] = "bochs";
|
2006-02-22 00:35:09 +03:00
|
|
|
if (strlen(SIM->get_param_string(BXPN_DISPLAYLIB_OPTIONS)->getptr())) {
|
|
|
|
ptr = strtok(SIM->get_param_string(BXPN_DISPLAYLIB_OPTIONS)->getptr(), ",");
|
2004-02-24 22:21:48 +03:00
|
|
|
while (ptr) {
|
|
|
|
string_i = 0;
|
|
|
|
for (i=0; i<strlen(ptr); i++) {
|
|
|
|
if (!isspace(ptr[i])) string[string_i++] = ptr[i];
|
|
|
|
}
|
|
|
|
string[string_i] = '\0';
|
|
|
|
if (argv[argc] != NULL) {
|
|
|
|
free(argv[argc]);
|
|
|
|
argv[argc] = NULL;
|
|
|
|
}
|
|
|
|
if (argc < 16) {
|
|
|
|
argv[argc++] = strdup(string);
|
|
|
|
} else {
|
|
|
|
BX_PANIC (("too many parameters, max is 16\n"));
|
|
|
|
}
|
|
|
|
ptr = strtok(NULL, ",");
|
|
|
|
}
|
2004-02-22 21:51:38 +03:00
|
|
|
}
|
|
|
|
bx_gui->init(argc, argv, BX_VGA_THIS s.x_tilesize, BX_VGA_THIS s.y_tilesize);
|
2004-02-24 22:21:48 +03:00
|
|
|
for (i = 1; i < 16; i++)
|
|
|
|
{
|
|
|
|
if ( argv[i] != NULL )
|
|
|
|
{
|
|
|
|
free(argv[i]);
|
|
|
|
argv[i] = NULL;
|
|
|
|
}
|
2001-04-10 05:04:59 +04:00
|
|
|
}
|
|
|
|
|
2004-08-16 12:07:23 +04:00
|
|
|
#if !BX_SUPPORT_CLGD54XX
|
2005-11-27 20:49:59 +03:00
|
|
|
BX_VGA_THIS init_systemtimer(timer_handler, vga_param_handler);
|
2004-08-16 12:07:23 +04:00
|
|
|
#endif // !BX_SUPPORT_CLGD54XX
|
2001-04-10 05:04:59 +04:00
|
|
|
|
2002-10-25 01:07:56 +04:00
|
|
|
/* video card with BIOS ROM */
|
|
|
|
DEV_cmos_set_reg(0x14, (DEV_cmos_get_reg(0x14) & 0xcf) | 0x00);
|
2001-04-10 05:04:59 +04:00
|
|
|
|
2002-09-19 22:59:50 +04:00
|
|
|
BX_VGA_THIS s.charmap_address = 0;
|
2003-05-03 20:09:39 +04:00
|
|
|
BX_VGA_THIS s.x_dotclockdiv2 = 0;
|
2003-04-21 23:03:46 +04:00
|
|
|
BX_VGA_THIS s.y_doublescan = 0;
|
2005-10-27 13:32:02 +04:00
|
|
|
BX_VGA_THIS s.last_bpp = 8;
|
2003-04-21 23:03:46 +04:00
|
|
|
|
2002-03-10 07:51:24 +03:00
|
|
|
#if BX_SUPPORT_VBE
|
2005-02-01 22:16:39 +03:00
|
|
|
// The following is for the vbe display extension
|
|
|
|
|
|
|
|
BX_VGA_THIS s.vbe_enabled=0;
|
|
|
|
BX_VGA_THIS s.vbe_8bit_dac=0;
|
2006-02-22 00:35:09 +03:00
|
|
|
if (!strcmp(SIM->get_param_string(BXPN_VGA_EXTENSION)->getptr(), "vbe")) {
|
2005-02-01 22:16:39 +03:00
|
|
|
for (addr=VBE_DISPI_IOPORT_INDEX; addr<=VBE_DISPI_IOPORT_DATA; addr++) {
|
2004-08-23 22:47:25 +04:00
|
|
|
DEV_register_ioread_handler(this, vbe_read_handler, addr, "vga video", 7);
|
|
|
|
DEV_register_iowrite_handler(this, vbe_write_handler, addr, "vga video", 7);
|
|
|
|
}
|
2005-02-01 22:16:39 +03:00
|
|
|
if (!BX_SUPPORT_PCIUSB || !bx_options.usb[0].Oenabled->get()) {
|
|
|
|
for (addr=VBE_DISPI_IOPORT_INDEX_OLD; addr<=VBE_DISPI_IOPORT_DATA_OLD; addr++) {
|
|
|
|
DEV_register_ioread_handler(this, vbe_read_handler, addr, "vga video", 7);
|
|
|
|
DEV_register_iowrite_handler(this, vbe_write_handler, addr, "vga video", 7);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
DEV_register_memory_handlers(mem_read_handler, theVga, mem_write_handler,
|
|
|
|
theVga, VBE_DISPI_LFB_PHYSICAL_ADDRESS,
|
|
|
|
VBE_DISPI_LFB_PHYSICAL_ADDRESS + VBE_DISPI_TOTAL_VIDEO_MEMORY_BYTES - 1);
|
2005-10-27 21:53:41 +04:00
|
|
|
|
|
|
|
if (BX_VGA_THIS s.vbe_memory == NULL)
|
|
|
|
BX_VGA_THIS s.vbe_memory = new Bit8u[VBE_DISPI_TOTAL_VIDEO_MEMORY_BYTES];
|
|
|
|
memset(BX_VGA_THIS s.vbe_memory, 0, VBE_DISPI_TOTAL_VIDEO_MEMORY_BYTES);
|
2005-02-01 22:16:39 +03:00
|
|
|
BX_VGA_THIS s.vbe_cur_dispi=VBE_DISPI_ID0;
|
|
|
|
BX_VGA_THIS s.vbe_xres=640;
|
|
|
|
BX_VGA_THIS s.vbe_yres=480;
|
|
|
|
BX_VGA_THIS s.vbe_bpp=8;
|
|
|
|
BX_VGA_THIS s.vbe_bank=0;
|
|
|
|
BX_VGA_THIS s.vbe_curindex=0;
|
|
|
|
BX_VGA_THIS s.vbe_offset_x=0;
|
|
|
|
BX_VGA_THIS s.vbe_offset_y=0;
|
|
|
|
BX_VGA_THIS s.vbe_virtual_xres=640;
|
|
|
|
BX_VGA_THIS s.vbe_virtual_yres=480;
|
|
|
|
BX_VGA_THIS s.vbe_bpp_multiplier=1;
|
|
|
|
BX_VGA_THIS s.vbe_virtual_start=0;
|
|
|
|
BX_VGA_THIS s.vbe_lfb_enabled=0;
|
|
|
|
BX_VGA_THIS s.vbe_get_capabilities=0;
|
|
|
|
bx_gui->get_capabilities(&max_xres, &max_yres,
|
|
|
|
&max_bpp);
|
|
|
|
if (max_xres > VBE_DISPI_MAX_XRES) {
|
|
|
|
BX_VGA_THIS s.vbe_max_xres=VBE_DISPI_MAX_XRES;
|
|
|
|
} else {
|
|
|
|
BX_VGA_THIS s.vbe_max_xres=max_xres;
|
|
|
|
}
|
|
|
|
if (max_yres > VBE_DISPI_MAX_YRES) {
|
|
|
|
BX_VGA_THIS s.vbe_max_yres=VBE_DISPI_MAX_YRES;
|
|
|
|
} else {
|
|
|
|
BX_VGA_THIS s.vbe_max_yres=max_yres;
|
|
|
|
}
|
|
|
|
if (max_bpp > VBE_DISPI_MAX_BPP) {
|
|
|
|
BX_VGA_THIS s.vbe_max_bpp=VBE_DISPI_MAX_BPP;
|
|
|
|
} else {
|
|
|
|
BX_VGA_THIS s.vbe_max_bpp=max_bpp;
|
|
|
|
}
|
2005-02-10 12:48:12 +03:00
|
|
|
BX_VGA_THIS extension_init = 1;
|
2002-03-10 07:51:24 +03:00
|
|
|
|
2005-02-01 22:16:39 +03:00
|
|
|
BX_INFO(("VBE Bochs Display Extension Enabled"));
|
|
|
|
}
|
2002-03-10 07:51:24 +03:00
|
|
|
#endif
|
2001-04-10 05:04:59 +04:00
|
|
|
}
|
|
|
|
|
2004-08-16 12:07:23 +04:00
|
|
|
void
|
|
|
|
bx_vga_c::init_iohandlers(bx_read_handler_t f_read, bx_write_handler_t f_write)
|
|
|
|
{
|
|
|
|
unsigned addr, i;
|
|
|
|
Bit8u io_mask[16] = {3, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1};
|
|
|
|
for (addr=0x03B4; addr<=0x03B5; addr++) {
|
|
|
|
DEV_register_ioread_handler(this, f_read, addr, "vga video", 1);
|
|
|
|
DEV_register_iowrite_handler(this, f_write, addr, "vga video", 3);
|
|
|
|
}
|
|
|
|
|
|
|
|
for (addr=0x03BA; addr<=0x03BA; addr++) {
|
|
|
|
DEV_register_ioread_handler(this, f_read, addr, "vga video", 1);
|
|
|
|
DEV_register_iowrite_handler(this, f_write, addr, "vga video", 3);
|
|
|
|
}
|
|
|
|
|
|
|
|
i = 0;
|
|
|
|
for (addr=0x03C0; addr<=0x03CF; addr++) {
|
|
|
|
DEV_register_ioread_handler(this, f_read, addr, "vga video", io_mask[i++]);
|
|
|
|
DEV_register_iowrite_handler(this, f_write, addr, "vga video", 3);
|
|
|
|
}
|
|
|
|
|
|
|
|
for (addr=0x03D4; addr<=0x03D5; addr++) {
|
|
|
|
DEV_register_ioread_handler(this, f_read, addr, "vga video", 3);
|
|
|
|
DEV_register_iowrite_handler(this, f_write, addr, "vga video", 3);
|
|
|
|
}
|
|
|
|
|
|
|
|
for (addr=0x03DA; addr<=0x03DA; addr++) {
|
|
|
|
DEV_register_ioread_handler(this, f_read, addr, "vga video", 1);
|
|
|
|
DEV_register_iowrite_handler(this, f_write, addr, "vga video", 3);
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2005-11-27 20:49:59 +03:00
|
|
|
bx_vga_c::init_systemtimer(bx_timer_handler_t f_timer, param_event_handler f_param)
|
2004-08-16 12:07:23 +04:00
|
|
|
{
|
2006-02-22 00:35:09 +03:00
|
|
|
bx_param_num_c *vga_update_interval = SIM->get_param_num(BXPN_VGA_UPDATE_INTERVAL);
|
|
|
|
BX_INFO(("interval=%u", vga_update_interval->get()));
|
2004-08-16 12:07:23 +04:00
|
|
|
if (BX_VGA_THIS timer_id == BX_NULL_TIMER_HANDLE) {
|
|
|
|
BX_VGA_THIS timer_id = bx_pc_system.register_timer(this, f_timer,
|
2006-02-22 00:35:09 +03:00
|
|
|
vga_update_interval->get (), 1, 1, "vga");
|
|
|
|
vga_update_interval->set_handler (f_param);
|
|
|
|
vga_update_interval->set_runtime_param (1);
|
2004-08-16 12:07:23 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2002-08-27 23:54:46 +04:00
|
|
|
void
|
|
|
|
bx_vga_c::reset(unsigned type)
|
|
|
|
{
|
2005-02-10 12:48:12 +03:00
|
|
|
if (!BX_VGA_THIS extension_checked) {
|
2006-02-22 00:35:09 +03:00
|
|
|
char *strptr = SIM->get_param_string(BXPN_VGA_EXTENSION)->getptr();
|
2005-02-10 12:48:12 +03:00
|
|
|
if (!BX_VGA_THIS extension_init &&
|
2006-02-22 00:35:09 +03:00
|
|
|
(strlen(strptr) > 0) &&
|
|
|
|
strcmp(strptr, "none")) {
|
|
|
|
BX_PANIC(("unknown display extension: %s", strptr));
|
2005-02-10 12:48:12 +03:00
|
|
|
}
|
|
|
|
BX_VGA_THIS extension_checked = 1;
|
|
|
|
}
|
2002-08-27 23:54:46 +04:00
|
|
|
}
|
2001-04-10 05:04:59 +04:00
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
bx_vga_c::determine_screen_dimensions(unsigned *piHeight, unsigned *piWidth)
|
|
|
|
{
|
|
|
|
int ai[0x20];
|
2002-07-24 23:36:39 +04:00
|
|
|
int i,h,v;
|
2001-04-10 05:04:59 +04:00
|
|
|
for ( i = 0 ; i < 0x20 ; i++ )
|
|
|
|
ai[i] = BX_VGA_THIS s.CRTC.reg[i];
|
|
|
|
|
2002-07-24 23:36:39 +04:00
|
|
|
h = (ai[1] + 1) * 8;
|
|
|
|
v = (ai[18] | ((ai[7] & 0x02) << 7) | ((ai[7] & 0x40) << 3)) + 1;
|
|
|
|
|
2001-04-10 05:04:59 +04:00
|
|
|
if ( BX_VGA_THIS s.graphics_ctrl.shift_reg == 0 )
|
|
|
|
{
|
|
|
|
*piWidth = 640;
|
|
|
|
*piHeight = 480;
|
|
|
|
|
|
|
|
if ( BX_VGA_THIS s.CRTC.reg[6] == 0xBF )
|
|
|
|
{
|
|
|
|
if (BX_VGA_THIS s.CRTC.reg[23] == 0xA3 &&
|
|
|
|
BX_VGA_THIS s.CRTC.reg[20] == 0x40 &&
|
|
|
|
BX_VGA_THIS s.CRTC.reg[9] == 0x41)
|
|
|
|
{
|
|
|
|
*piWidth = 320;
|
|
|
|
*piHeight = 240;
|
|
|
|
}
|
2003-04-21 23:03:46 +04:00
|
|
|
else {
|
2003-05-03 20:09:39 +04:00
|
|
|
if (BX_VGA_THIS s.x_dotclockdiv2) h <<= 1;
|
2002-07-24 23:36:39 +04:00
|
|
|
*piWidth = h;
|
|
|
|
*piHeight = v;
|
2001-04-10 05:04:59 +04:00
|
|
|
}
|
|
|
|
}
|
2002-12-31 19:58:02 +03:00
|
|
|
else if ((h >= 640) && (v >= 480)) {
|
|
|
|
*piWidth = h;
|
|
|
|
*piHeight = v;
|
|
|
|
}
|
2001-04-10 05:04:59 +04:00
|
|
|
}
|
|
|
|
else if ( BX_VGA_THIS s.graphics_ctrl.shift_reg == 2 )
|
|
|
|
{
|
|
|
|
|
|
|
|
if ( BX_VGA_THIS s.sequencer.chain_four )
|
|
|
|
{
|
2003-04-25 22:51:55 +04:00
|
|
|
*piWidth = h;
|
|
|
|
*piHeight = v;
|
2001-04-10 05:04:59 +04:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2003-01-02 00:21:29 +03:00
|
|
|
*piWidth = h;
|
2002-07-24 23:36:39 +04:00
|
|
|
*piHeight = v;
|
2001-04-10 05:04:59 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2003-05-03 20:09:39 +04:00
|
|
|
if (BX_VGA_THIS s.x_dotclockdiv2) h <<= 1;
|
|
|
|
*piWidth = h;
|
|
|
|
*piHeight = v;
|
2001-04-10 05:04:59 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// static IO port read callback handler
|
|
|
|
// redirects to non-static class handler to avoid virtual functions
|
|
|
|
|
|
|
|
Bit32u
|
|
|
|
bx_vga_c::read_handler(void *this_ptr, Bit32u address, unsigned io_len)
|
|
|
|
{
|
|
|
|
#if !BX_USE_VGA_SMF
|
|
|
|
bx_vga_c *class_ptr = (bx_vga_c *) this_ptr;
|
|
|
|
|
|
|
|
return( class_ptr->read(address, io_len) );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Bit32u
|
|
|
|
bx_vga_c::read(Bit32u address, unsigned io_len)
|
|
|
|
{
|
|
|
|
#else
|
|
|
|
UNUSED(this_ptr);
|
|
|
|
#endif // !BX_USE_VGA_SMF
|
2003-05-09 19:32:28 +04:00
|
|
|
bx_bool horiz_retrace = 0, vert_retrace = 0;
|
|
|
|
Bit64u usec;
|
2004-07-18 23:40:51 +04:00
|
|
|
Bit16u ret16, vertres;
|
2001-04-10 05:04:59 +04:00
|
|
|
Bit8u retval;
|
|
|
|
|
|
|
|
#if defined(VGA_TRACE_FEATURE)
|
|
|
|
Bit32u ret = 0;
|
|
|
|
#define RETURN(x) do { ret = (x); goto read_return; } while (0)
|
|
|
|
#else
|
|
|
|
#define RETURN return
|
|
|
|
#endif
|
|
|
|
|
2004-07-18 23:40:51 +04:00
|
|
|
if (io_len == 2) {
|
|
|
|
#if BX_USE_VGA_SMF
|
|
|
|
ret16 = bx_vga_c::read_handler(0, address, 1);
|
|
|
|
ret16 |= (bx_vga_c::read_handler(0, address+1, 1)) << 8;
|
|
|
|
#else
|
|
|
|
ret16 = bx_vga_c::read(address, 1);
|
|
|
|
ret16 |= (bx_vga_c::read(address+1, 1) << 8;
|
|
|
|
#endif
|
|
|
|
RETURN(ret16);
|
|
|
|
}
|
|
|
|
|
2001-04-10 05:04:59 +04:00
|
|
|
#ifdef __OS2__
|
|
|
|
if ( bx_options.videomode == BX_VIDEO_DIRECT )
|
|
|
|
{
|
|
|
|
return _inp(address);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if !defined(VGA_TRACE_FEATURE)
|
2003-07-18 22:31:50 +04:00
|
|
|
BX_DEBUG(("io read from 0x%04x", (unsigned) address));
|
2001-04-10 05:04:59 +04:00
|
|
|
#endif
|
|
|
|
|
|
|
|
if ( (address >= 0x03b0) && (address <= 0x03bf) &&
|
|
|
|
(BX_VGA_THIS s.misc_output.color_emulation) ) {
|
|
|
|
RETURN(0xff);
|
|
|
|
}
|
|
|
|
if ( (address >= 0x03d0) && (address <= 0x03df) &&
|
|
|
|
(BX_VGA_THIS s.misc_output.color_emulation==0) ) {
|
|
|
|
RETURN(0xff);
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (address) {
|
|
|
|
case 0x03ba: /* Input Status 1 (monochrome emulation modes) */
|
|
|
|
case 0x03ca: /* Feature Control ??? */
|
|
|
|
case 0x03da: /* Input Status 1 (color emulation modes) */
|
|
|
|
// bit3: Vertical Retrace
|
|
|
|
// 0 = display is in the display mode
|
|
|
|
// 1 = display is in the vertical retrace mode
|
|
|
|
// bit0: Display Enable
|
|
|
|
// 0 = display is in the display mode
|
|
|
|
// 1 = display is not in the display mode; either the
|
|
|
|
// horizontal or vertical retrace period is active
|
|
|
|
|
2003-05-09 19:32:28 +04:00
|
|
|
// using 72 Hz vertical frequency
|
|
|
|
usec = bx_pc_system.time_usec();
|
|
|
|
switch ( ( BX_VGA_THIS s.misc_output.vert_sync_pol << 1) | BX_VGA_THIS s.misc_output.horiz_sync_pol )
|
|
|
|
{
|
|
|
|
case 0: vertres = 200; break;
|
|
|
|
case 1: vertres = 400; break;
|
|
|
|
case 2: vertres = 350; break;
|
|
|
|
default: vertres = 480; break;
|
|
|
|
}
|
|
|
|
if ((usec % 13888) < 70) {
|
|
|
|
vert_retrace = 1;
|
|
|
|
}
|
|
|
|
if ((usec % (13888 / vertres)) == 0) {
|
|
|
|
horiz_retrace = 1;
|
|
|
|
}
|
2001-04-10 05:04:59 +04:00
|
|
|
|
|
|
|
retval = 0;
|
|
|
|
if (horiz_retrace || vert_retrace)
|
|
|
|
retval = 0x01;
|
|
|
|
if (vert_retrace)
|
|
|
|
retval |= 0x08;
|
|
|
|
|
|
|
|
/* reading this port resets the flip-flop to address mode */
|
|
|
|
BX_VGA_THIS s.attribute_ctrl.flip_flop = 0;
|
|
|
|
RETURN(retval);
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
case 0x03c0: /* */
|
|
|
|
if (BX_VGA_THIS s.attribute_ctrl.flip_flop == 0) {
|
2003-07-18 22:31:50 +04:00
|
|
|
//BX_INFO(("io read: 0x3c0: flip_flop = 0"));
|
2001-04-10 05:04:59 +04:00
|
|
|
retval =
|
|
|
|
(BX_VGA_THIS s.attribute_ctrl.video_enabled << 5) |
|
|
|
|
BX_VGA_THIS s.attribute_ctrl.address;
|
|
|
|
RETURN(retval);
|
|
|
|
}
|
|
|
|
else {
|
2003-07-18 22:31:50 +04:00
|
|
|
BX_ERROR(("io read: 0x3c0: flip_flop != 0"));
|
2001-04-10 05:04:59 +04:00
|
|
|
return(0);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 0x03c1: /* */
|
|
|
|
switch (BX_VGA_THIS s.attribute_ctrl.address) {
|
|
|
|
case 0x00: case 0x01: case 0x02: case 0x03:
|
|
|
|
case 0x04: case 0x05: case 0x06: case 0x07:
|
|
|
|
case 0x08: case 0x09: case 0x0a: case 0x0b:
|
|
|
|
case 0x0c: case 0x0d: case 0x0e: case 0x0f:
|
|
|
|
retval = BX_VGA_THIS s.attribute_ctrl.palette_reg[BX_VGA_THIS s.attribute_ctrl.address];
|
|
|
|
RETURN(retval);
|
|
|
|
break;
|
|
|
|
case 0x10: /* mode control register */
|
|
|
|
retval =
|
|
|
|
(BX_VGA_THIS s.attribute_ctrl.mode_ctrl.graphics_alpha << 0) |
|
|
|
|
(BX_VGA_THIS s.attribute_ctrl.mode_ctrl.display_type << 1) |
|
|
|
|
(BX_VGA_THIS s.attribute_ctrl.mode_ctrl.enable_line_graphics << 2) |
|
|
|
|
(BX_VGA_THIS s.attribute_ctrl.mode_ctrl.blink_intensity << 3) |
|
|
|
|
(BX_VGA_THIS s.attribute_ctrl.mode_ctrl.pixel_panning_compat << 5) |
|
|
|
|
(BX_VGA_THIS s.attribute_ctrl.mode_ctrl.pixel_clock_select << 6) |
|
|
|
|
(BX_VGA_THIS s.attribute_ctrl.mode_ctrl.internal_palette_size << 7);
|
|
|
|
RETURN(retval);
|
|
|
|
break;
|
|
|
|
case 0x11: /* overscan color register */
|
|
|
|
RETURN(BX_VGA_THIS s.attribute_ctrl.overscan_color);
|
|
|
|
break;
|
|
|
|
case 0x12: /* color plane enable */
|
|
|
|
RETURN(BX_VGA_THIS s.attribute_ctrl.color_plane_enable);
|
|
|
|
break;
|
|
|
|
case 0x13: /* horizontal PEL panning register */
|
|
|
|
RETURN(BX_VGA_THIS s.attribute_ctrl.horiz_pel_panning);
|
|
|
|
break;
|
|
|
|
case 0x14: /* color select register */
|
|
|
|
RETURN(BX_VGA_THIS s.attribute_ctrl.color_select);
|
|
|
|
break;
|
|
|
|
default:
|
2003-07-18 22:31:50 +04:00
|
|
|
BX_INFO(("io read: 0x3c1: unknown register 0x%02x",
|
merge in BRANCH-io-cleanup.
To see the commit logs for this use either cvsweb or
cvs update -r BRANCH-io-cleanup and then 'cvs log' the various files.
In general this provides a generic interface for logging.
logfunctions:: is a class that is inherited by some classes, and also
. allocated as a standalone global called 'genlog'. All logging uses
. one of the ::info(), ::error(), ::ldebug(), ::panic() methods of this
. class through 'BX_INFO(), BX_ERROR(), BX_DEBUG(), BX_PANIC()' macros
. respectively.
.
. An example usage:
. BX_INFO(("Hello, World!\n"));
iofunctions:: is a class that is allocated once by default, and assigned
as the iofunction of each logfunctions instance. It is this class that
maintains the file descriptor and other output related code, at this
point using vfprintf(). At some future point, someone may choose to
write a gui 'console' for bochs to which messages would be redirected
simply by assigning a different iofunction class to the various logfunctions
objects.
More cleanup is coming, but this works for now. If you want to see alot
of debugging output, in main.cc, change onoff[LOGLEV_DEBUG]=0 to =1.
Comments, bugs, flames, to me: todd@fries.net
2001-05-15 18:49:57 +04:00
|
|
|
(unsigned) BX_VGA_THIS s.attribute_ctrl.address));
|
2001-04-10 05:04:59 +04:00
|
|
|
RETURN(0);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 0x03c2: /* Input Status 0 */
|
2003-07-18 22:31:50 +04:00
|
|
|
BX_DEBUG(("io read 0x3c2: input status #0: ignoring"));
|
2001-04-10 05:04:59 +04:00
|
|
|
RETURN(0);
|
|
|
|
break;
|
|
|
|
|
2001-04-10 06:16:18 +04:00
|
|
|
case 0x03c3: /* VGA Enable Register */
|
2006-01-07 15:10:59 +03:00
|
|
|
RETURN(BX_VGA_THIS s.vga_enabled);
|
2001-04-10 06:16:18 +04:00
|
|
|
break;
|
|
|
|
|
2001-04-10 05:04:59 +04:00
|
|
|
case 0x03c4: /* Sequencer Index Register */
|
|
|
|
RETURN(BX_VGA_THIS s.sequencer.index);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 0x03c5: /* Sequencer Registers 00..04 */
|
|
|
|
switch (BX_VGA_THIS s.sequencer.index) {
|
|
|
|
case 0: /* sequencer: reset */
|
2003-07-18 22:31:50 +04:00
|
|
|
BX_DEBUG(("io read 0x3c5: sequencer reset"));
|
2002-10-13 12:14:31 +04:00
|
|
|
RETURN(BX_VGA_THIS s.sequencer.reset1 | (BX_VGA_THIS s.sequencer.reset2<<1));
|
2001-04-10 05:04:59 +04:00
|
|
|
break;
|
|
|
|
case 1: /* sequencer: clocking mode */
|
2003-07-18 22:31:50 +04:00
|
|
|
BX_DEBUG(("io read 0x3c5: sequencer clocking mode"));
|
2001-04-10 05:04:59 +04:00
|
|
|
RETURN(BX_VGA_THIS s.sequencer.reg1);
|
|
|
|
break;
|
|
|
|
case 2: /* sequencer: map mask register */
|
|
|
|
RETURN(BX_VGA_THIS s.sequencer.map_mask);
|
|
|
|
break;
|
|
|
|
case 3: /* sequencer: character map select register */
|
|
|
|
RETURN(BX_VGA_THIS s.sequencer.char_map_select);
|
|
|
|
break;
|
|
|
|
case 4: /* sequencer: memory mode register */
|
|
|
|
retval =
|
|
|
|
(BX_VGA_THIS s.sequencer.extended_mem << 1) |
|
|
|
|
(BX_VGA_THIS s.sequencer.odd_even << 2) |
|
|
|
|
(BX_VGA_THIS s.sequencer.chain_four << 3);
|
|
|
|
RETURN(retval);
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
2003-07-18 22:31:50 +04:00
|
|
|
BX_DEBUG(("io read 0x3c5: index %u unhandled",
|
merge in BRANCH-io-cleanup.
To see the commit logs for this use either cvsweb or
cvs update -r BRANCH-io-cleanup and then 'cvs log' the various files.
In general this provides a generic interface for logging.
logfunctions:: is a class that is inherited by some classes, and also
. allocated as a standalone global called 'genlog'. All logging uses
. one of the ::info(), ::error(), ::ldebug(), ::panic() methods of this
. class through 'BX_INFO(), BX_ERROR(), BX_DEBUG(), BX_PANIC()' macros
. respectively.
.
. An example usage:
. BX_INFO(("Hello, World!\n"));
iofunctions:: is a class that is allocated once by default, and assigned
as the iofunction of each logfunctions instance. It is this class that
maintains the file descriptor and other output related code, at this
point using vfprintf(). At some future point, someone may choose to
write a gui 'console' for bochs to which messages would be redirected
simply by assigning a different iofunction class to the various logfunctions
objects.
More cleanup is coming, but this works for now. If you want to see alot
of debugging output, in main.cc, change onoff[LOGLEV_DEBUG]=0 to =1.
Comments, bugs, flames, to me: todd@fries.net
2001-05-15 18:49:57 +04:00
|
|
|
(unsigned) BX_VGA_THIS s.sequencer.index));
|
2001-04-10 05:04:59 +04:00
|
|
|
RETURN(0);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 0x03c6: /* PEL mask ??? */
|
|
|
|
RETURN(BX_VGA_THIS s.pel.mask);
|
|
|
|
break;
|
|
|
|
|
2003-01-11 14:18:04 +03:00
|
|
|
case 0x03c7: /* DAC state, read = 11b, write = 00b */
|
|
|
|
RETURN(BX_VGA_THIS s.pel.dac_state);
|
|
|
|
break;
|
|
|
|
|
2003-04-25 22:51:55 +04:00
|
|
|
case 0x03c8: /* PEL address write mode */
|
|
|
|
RETURN(BX_VGA_THIS s.pel.write_data_register);
|
|
|
|
break;
|
|
|
|
|
2001-04-10 05:04:59 +04:00
|
|
|
case 0x03c9: /* PEL Data Register, colors 00..FF */
|
2003-01-11 14:18:04 +03:00
|
|
|
if (BX_VGA_THIS s.pel.dac_state == 0x03) {
|
|
|
|
switch (BX_VGA_THIS s.pel.read_data_cycle) {
|
|
|
|
case 0:
|
|
|
|
retval = BX_VGA_THIS s.pel.data[BX_VGA_THIS s.pel.read_data_register].red;
|
|
|
|
break;
|
|
|
|
case 1:
|
|
|
|
retval = BX_VGA_THIS s.pel.data[BX_VGA_THIS s.pel.read_data_register].green;
|
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
retval = BX_VGA_THIS s.pel.data[BX_VGA_THIS s.pel.read_data_register].blue;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
retval = 0; // keep compiler happy
|
|
|
|
}
|
|
|
|
BX_VGA_THIS s.pel.read_data_cycle++;
|
|
|
|
if (BX_VGA_THIS s.pel.read_data_cycle >= 3) {
|
|
|
|
BX_VGA_THIS s.pel.read_data_cycle = 0;
|
|
|
|
BX_VGA_THIS s.pel.read_data_register++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
retval = 0x3f;
|
2001-04-10 05:04:59 +04:00
|
|
|
}
|
|
|
|
RETURN(retval);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 0x03cc: /* Miscellaneous Output / Graphics 1 Position ??? */
|
|
|
|
retval =
|
|
|
|
((BX_VGA_THIS s.misc_output.color_emulation & 0x01) << 0) |
|
|
|
|
((BX_VGA_THIS s.misc_output.enable_ram & 0x01) << 1) |
|
|
|
|
((BX_VGA_THIS s.misc_output.clock_select & 0x03) << 2) |
|
|
|
|
((BX_VGA_THIS s.misc_output.select_high_bank & 0x01) << 5) |
|
|
|
|
((BX_VGA_THIS s.misc_output.horiz_sync_pol & 0x01) << 6) |
|
|
|
|
((BX_VGA_THIS s.misc_output.vert_sync_pol & 0x01) << 7);
|
|
|
|
RETURN(retval);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 0x03ce: /* Graphics Controller Index Register */
|
|
|
|
RETURN(BX_VGA_THIS s.graphics_ctrl.index);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 0x03cd: /* ??? */
|
2001-05-30 22:56:02 +04:00
|
|
|
BX_DEBUG(("io read from 03cd"));
|
2001-04-10 05:04:59 +04:00
|
|
|
RETURN(0x00);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 0x03cf: /* Graphics Controller Registers 00..08 */
|
|
|
|
switch (BX_VGA_THIS s.graphics_ctrl.index) {
|
|
|
|
case 0: /* Set/Reset */
|
|
|
|
RETURN(BX_VGA_THIS s.graphics_ctrl.set_reset);
|
|
|
|
break;
|
|
|
|
case 1: /* Enable Set/Reset */
|
|
|
|
RETURN(BX_VGA_THIS s.graphics_ctrl.enable_set_reset);
|
|
|
|
break;
|
|
|
|
case 2: /* Color Compare */
|
|
|
|
RETURN(BX_VGA_THIS s.graphics_ctrl.color_compare);
|
|
|
|
break;
|
|
|
|
case 3: /* Data Rotate */
|
|
|
|
retval =
|
|
|
|
((BX_VGA_THIS s.graphics_ctrl.raster_op & 0x03) << 3) |
|
|
|
|
((BX_VGA_THIS s.graphics_ctrl.data_rotate & 0x07) << 0);
|
|
|
|
RETURN(retval);
|
|
|
|
break;
|
|
|
|
case 4: /* Read Map Select */
|
|
|
|
RETURN(BX_VGA_THIS s.graphics_ctrl.read_map_select);
|
|
|
|
break;
|
|
|
|
case 5: /* Mode */
|
|
|
|
retval =
|
|
|
|
((BX_VGA_THIS s.graphics_ctrl.shift_reg & 0x03) << 5) |
|
|
|
|
((BX_VGA_THIS s.graphics_ctrl.odd_even & 0x01 ) << 4) |
|
|
|
|
((BX_VGA_THIS s.graphics_ctrl.read_mode & 0x01) << 3) |
|
|
|
|
((BX_VGA_THIS s.graphics_ctrl.write_mode & 0x03) << 0);
|
|
|
|
|
2003-07-18 22:31:50 +04:00
|
|
|
if (BX_VGA_THIS s.graphics_ctrl.odd_even ||
|
|
|
|
BX_VGA_THIS s.graphics_ctrl.shift_reg)
|
|
|
|
BX_DEBUG(("io read 0x3cf: reg 05 = 0x%02x", (unsigned) retval));
|
2001-04-10 05:04:59 +04:00
|
|
|
RETURN(retval);
|
|
|
|
break;
|
|
|
|
case 6: /* Miscellaneous */
|
|
|
|
retval =
|
|
|
|
((BX_VGA_THIS s.graphics_ctrl.memory_mapping & 0x03 ) << 2) |
|
|
|
|
((BX_VGA_THIS s.graphics_ctrl.odd_even & 0x01) << 1) |
|
|
|
|
((BX_VGA_THIS s.graphics_ctrl.graphics_alpha & 0x01) << 0);
|
|
|
|
RETURN(retval);
|
|
|
|
break;
|
|
|
|
case 7: /* Color Don't Care */
|
|
|
|
RETURN(BX_VGA_THIS s.graphics_ctrl.color_dont_care);
|
|
|
|
break;
|
|
|
|
case 8: /* Bit Mask */
|
|
|
|
RETURN(BX_VGA_THIS s.graphics_ctrl.bitmask);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
/* ??? */
|
2003-07-18 22:31:50 +04:00
|
|
|
BX_DEBUG(("io read: 0x3cf: index %u unhandled",
|
merge in BRANCH-io-cleanup.
To see the commit logs for this use either cvsweb or
cvs update -r BRANCH-io-cleanup and then 'cvs log' the various files.
In general this provides a generic interface for logging.
logfunctions:: is a class that is inherited by some classes, and also
. allocated as a standalone global called 'genlog'. All logging uses
. one of the ::info(), ::error(), ::ldebug(), ::panic() methods of this
. class through 'BX_INFO(), BX_ERROR(), BX_DEBUG(), BX_PANIC()' macros
. respectively.
.
. An example usage:
. BX_INFO(("Hello, World!\n"));
iofunctions:: is a class that is allocated once by default, and assigned
as the iofunction of each logfunctions instance. It is this class that
maintains the file descriptor and other output related code, at this
point using vfprintf(). At some future point, someone may choose to
write a gui 'console' for bochs to which messages would be redirected
simply by assigning a different iofunction class to the various logfunctions
objects.
More cleanup is coming, but this works for now. If you want to see alot
of debugging output, in main.cc, change onoff[LOGLEV_DEBUG]=0 to =1.
Comments, bugs, flames, to me: todd@fries.net
2001-05-15 18:49:57 +04:00
|
|
|
(unsigned) BX_VGA_THIS s.graphics_ctrl.index));
|
2001-04-10 05:04:59 +04:00
|
|
|
RETURN(0);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 0x03d4: /* CRTC Index Register (color emulation modes) */
|
|
|
|
RETURN(BX_VGA_THIS s.CRTC.address);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 0x03b5: /* CRTC Registers (monochrome emulation modes) */
|
|
|
|
case 0x03d5: /* CRTC Registers (color emulation modes) */
|
2002-04-14 12:57:24 +04:00
|
|
|
if (BX_VGA_THIS s.CRTC.address > 0x18) {
|
2003-07-18 22:31:50 +04:00
|
|
|
BX_DEBUG(("io read: invalid CRTC register 0x%02x",
|
merge in BRANCH-io-cleanup.
To see the commit logs for this use either cvsweb or
cvs update -r BRANCH-io-cleanup and then 'cvs log' the various files.
In general this provides a generic interface for logging.
logfunctions:: is a class that is inherited by some classes, and also
. allocated as a standalone global called 'genlog'. All logging uses
. one of the ::info(), ::error(), ::ldebug(), ::panic() methods of this
. class through 'BX_INFO(), BX_ERROR(), BX_DEBUG(), BX_PANIC()' macros
. respectively.
.
. An example usage:
. BX_INFO(("Hello, World!\n"));
iofunctions:: is a class that is allocated once by default, and assigned
as the iofunction of each logfunctions instance. It is this class that
maintains the file descriptor and other output related code, at this
point using vfprintf(). At some future point, someone may choose to
write a gui 'console' for bochs to which messages would be redirected
simply by assigning a different iofunction class to the various logfunctions
objects.
More cleanup is coming, but this works for now. If you want to see alot
of debugging output, in main.cc, change onoff[LOGLEV_DEBUG]=0 to =1.
Comments, bugs, flames, to me: todd@fries.net
2001-05-15 18:49:57 +04:00
|
|
|
(unsigned) BX_VGA_THIS s.CRTC.address));
|
2002-04-14 12:57:24 +04:00
|
|
|
RETURN(0);
|
|
|
|
}
|
2001-04-10 05:04:59 +04:00
|
|
|
RETURN(BX_VGA_THIS s.CRTC.reg[BX_VGA_THIS s.CRTC.address]);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 0x03b4: /* CRTC Index Register (monochrome emulation modes) */
|
2001-05-04 01:14:56 +04:00
|
|
|
case 0x03cb: /* not sure but OpenBSD reads it a lot */
|
2001-04-10 05:04:59 +04:00
|
|
|
default:
|
2004-04-25 11:16:09 +04:00
|
|
|
BX_INFO(("io read from vga port 0x%04x", (unsigned) address));
|
2001-04-10 05:04:59 +04:00
|
|
|
RETURN(0); /* keep compiler happy */
|
|
|
|
}
|
|
|
|
|
|
|
|
#if defined(VGA_TRACE_FEATURE)
|
|
|
|
read_return:
|
2004-07-18 23:40:51 +04:00
|
|
|
if (io_len == 1) {
|
|
|
|
BX_DEBUG(("8-bit read from 0x%04x = 0x%02x", (unsigned) address, ret));
|
|
|
|
} else {
|
|
|
|
BX_DEBUG(("16-bit read from 0x%04x = 0x%04x", (unsigned) address, ret));
|
|
|
|
}
|
|
|
|
return ret;
|
2001-04-10 05:04:59 +04:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
#if defined(VGA_TRACE_FEATURE)
|
|
|
|
#undef RETURN
|
|
|
|
#endif
|
|
|
|
|
|
|
|
// static IO port write callback handler
|
|
|
|
// redirects to non-static class handler to avoid virtual functions
|
|
|
|
|
|
|
|
void
|
|
|
|
bx_vga_c::write_handler(void *this_ptr, Bit32u address, Bit32u value, unsigned io_len)
|
|
|
|
{
|
|
|
|
#if !BX_USE_VGA_SMF
|
|
|
|
bx_vga_c *class_ptr = (bx_vga_c *) this_ptr;
|
|
|
|
|
|
|
|
class_ptr->write(address, value, io_len, 0);
|
|
|
|
#else
|
|
|
|
UNUSED(this_ptr);
|
2002-10-25 01:07:56 +04:00
|
|
|
theVga->write(address, value, io_len, 0);
|
2001-04-10 05:04:59 +04:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
bx_vga_c::write_handler_no_log(void *this_ptr, Bit32u address, Bit32u value, unsigned io_len)
|
|
|
|
{
|
|
|
|
#if !BX_USE_VGA_SMF
|
|
|
|
bx_vga_c *class_ptr = (bx_vga_c *) this_ptr;
|
|
|
|
|
|
|
|
class_ptr->write(address, value, io_len, 1);
|
|
|
|
#else
|
|
|
|
UNUSED(this_ptr);
|
2002-10-25 01:07:56 +04:00
|
|
|
theVga->write(address, value, io_len, 1);
|
2001-04-10 05:04:59 +04:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2002-10-25 15:44:41 +04:00
|
|
|
bx_vga_c::write(Bit32u address, Bit32u value, unsigned io_len, bx_bool no_log)
|
2001-04-10 05:04:59 +04:00
|
|
|
{
|
|
|
|
unsigned i;
|
2001-12-13 21:34:30 +03:00
|
|
|
Bit8u charmap1, charmap2, prev_memory_mapping;
|
2003-07-20 01:44:37 +04:00
|
|
|
bx_bool prev_video_enabled, prev_line_graphics, prev_int_pal_size;
|
2002-10-25 15:44:41 +04:00
|
|
|
bx_bool prev_graphics_alpha, prev_chain_odd_even;
|
2003-04-28 22:15:31 +04:00
|
|
|
bx_bool needs_update = 0;
|
2001-04-10 05:04:59 +04:00
|
|
|
|
|
|
|
#if defined(VGA_TRACE_FEATURE)
|
2001-05-24 18:08:54 +04:00
|
|
|
if (!no_log)
|
2001-04-10 05:04:59 +04:00
|
|
|
switch (io_len) {
|
|
|
|
case 1:
|
2001-05-30 22:56:02 +04:00
|
|
|
BX_DEBUG(("8-bit write to %04x = %02x", (unsigned)address, (unsigned)value));
|
2001-04-10 05:04:59 +04:00
|
|
|
break;
|
|
|
|
case 2:
|
2001-05-30 22:56:02 +04:00
|
|
|
BX_DEBUG(("16-bit write to %04x = %04x", (unsigned)address, (unsigned)value));
|
2001-04-10 05:04:59 +04:00
|
|
|
break;
|
|
|
|
default:
|
2001-05-30 22:56:02 +04:00
|
|
|
BX_PANIC(("Weird VGA write size"));
|
2001-04-10 05:04:59 +04:00
|
|
|
}
|
2003-07-18 22:31:50 +04:00
|
|
|
#else
|
|
|
|
if (io_len == 1) {
|
|
|
|
BX_DEBUG(("io write to 0x%04x = 0x%02x", (unsigned) address,
|
|
|
|
(unsigned) value));
|
|
|
|
}
|
2001-04-10 05:04:59 +04:00
|
|
|
#endif
|
|
|
|
|
|
|
|
if (io_len == 2) {
|
|
|
|
#if BX_USE_VGA_SMF
|
|
|
|
bx_vga_c::write_handler_no_log(0, address, value & 0xff, 1);
|
|
|
|
bx_vga_c::write_handler_no_log(0, address+1, (value >> 8) & 0xff, 1);
|
|
|
|
#else
|
|
|
|
bx_vga_c::write(address, value & 0xff, 1, 1);
|
|
|
|
bx_vga_c::write(address+1, (value >> 8) & 0xff, 1, 1);
|
|
|
|
#endif
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef __OS2__
|
|
|
|
if ( bx_options.videomode == BX_VIDEO_DIRECT )
|
|
|
|
{
|
|
|
|
_outp(address,value);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
if ( (address >= 0x03b0) && (address <= 0x03bf) &&
|
|
|
|
(BX_VGA_THIS s.misc_output.color_emulation) )
|
|
|
|
return;
|
|
|
|
if ( (address >= 0x03d0) && (address <= 0x03df) &&
|
|
|
|
(BX_VGA_THIS s.misc_output.color_emulation==0) )
|
|
|
|
return;
|
|
|
|
|
|
|
|
switch (address) {
|
|
|
|
case 0x03ba: /* Feature Control (monochrome emulation modes) */
|
|
|
|
#if !defined(VGA_TRACE_FEATURE)
|
2001-05-30 22:56:02 +04:00
|
|
|
BX_DEBUG(("io write 3ba: feature control: ignoring"));
|
2001-04-10 05:04:59 +04:00
|
|
|
#endif
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 0x03c0: /* Attribute Controller */
|
|
|
|
if (BX_VGA_THIS s.attribute_ctrl.flip_flop == 0) { /* address mode */
|
|
|
|
prev_video_enabled = BX_VGA_THIS s.attribute_ctrl.video_enabled;
|
|
|
|
BX_VGA_THIS s.attribute_ctrl.video_enabled = (value >> 5) & 0x01;
|
|
|
|
#if !defined(VGA_TRACE_FEATURE)
|
2001-05-30 22:56:02 +04:00
|
|
|
BX_DEBUG(("io write 3c0: video_enabled = %u",
|
2003-07-18 22:31:50 +04:00
|
|
|
(unsigned) BX_VGA_THIS s.attribute_ctrl.video_enabled));
|
2001-04-10 05:04:59 +04:00
|
|
|
#endif
|
|
|
|
if (BX_VGA_THIS s.attribute_ctrl.video_enabled == 0)
|
2002-10-25 01:07:56 +04:00
|
|
|
bx_gui->clear_screen();
|
2001-04-10 05:04:59 +04:00
|
|
|
else if (!prev_video_enabled) {
|
|
|
|
#if !defined(VGA_TRACE_FEATURE)
|
2001-05-30 22:56:02 +04:00
|
|
|
BX_DEBUG(("found enable transition"));
|
2001-04-10 05:04:59 +04:00
|
|
|
#endif
|
2003-04-28 22:15:31 +04:00
|
|
|
needs_update = 1;
|
2003-04-21 23:03:46 +04:00
|
|
|
}
|
2001-04-10 05:04:59 +04:00
|
|
|
value &= 0x1f; /* address = bits 0..4 */
|
|
|
|
BX_VGA_THIS s.attribute_ctrl.address = value;
|
|
|
|
switch (value) {
|
|
|
|
case 0x00: case 0x01: case 0x02: case 0x03:
|
|
|
|
case 0x04: case 0x05: case 0x06: case 0x07:
|
|
|
|
case 0x08: case 0x09: case 0x0a: case 0x0b:
|
|
|
|
case 0x0c: case 0x0d: case 0x0e: case 0x0f:
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
2004-04-25 11:16:09 +04:00
|
|
|
BX_DEBUG(("io write 0x3c0: address mode reg=0x%02x",
|
merge in BRANCH-io-cleanup.
To see the commit logs for this use either cvsweb or
cvs update -r BRANCH-io-cleanup and then 'cvs log' the various files.
In general this provides a generic interface for logging.
logfunctions:: is a class that is inherited by some classes, and also
. allocated as a standalone global called 'genlog'. All logging uses
. one of the ::info(), ::error(), ::ldebug(), ::panic() methods of this
. class through 'BX_INFO(), BX_ERROR(), BX_DEBUG(), BX_PANIC()' macros
. respectively.
.
. An example usage:
. BX_INFO(("Hello, World!\n"));
iofunctions:: is a class that is allocated once by default, and assigned
as the iofunction of each logfunctions instance. It is this class that
maintains the file descriptor and other output related code, at this
point using vfprintf(). At some future point, someone may choose to
write a gui 'console' for bochs to which messages would be redirected
simply by assigning a different iofunction class to the various logfunctions
objects.
More cleanup is coming, but this works for now. If you want to see alot
of debugging output, in main.cc, change onoff[LOGLEV_DEBUG]=0 to =1.
Comments, bugs, flames, to me: todd@fries.net
2001-05-15 18:49:57 +04:00
|
|
|
(unsigned) value));
|
2001-04-10 05:04:59 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else { /* data-write mode */
|
|
|
|
switch (BX_VGA_THIS s.attribute_ctrl.address) {
|
|
|
|
case 0x00: case 0x01: case 0x02: case 0x03:
|
|
|
|
case 0x04: case 0x05: case 0x06: case 0x07:
|
|
|
|
case 0x08: case 0x09: case 0x0a: case 0x0b:
|
|
|
|
case 0x0c: case 0x0d: case 0x0e: case 0x0f:
|
2003-04-28 22:15:31 +04:00
|
|
|
if (value != BX_VGA_THIS s.attribute_ctrl.palette_reg[BX_VGA_THIS s.attribute_ctrl.address]) {
|
|
|
|
BX_VGA_THIS s.attribute_ctrl.palette_reg[BX_VGA_THIS s.attribute_ctrl.address] =
|
|
|
|
value;
|
|
|
|
needs_update = 1;
|
|
|
|
}
|
2001-04-10 05:04:59 +04:00
|
|
|
break;
|
|
|
|
case 0x10: // mode control register
|
2003-05-11 19:07:54 +04:00
|
|
|
prev_line_graphics = BX_VGA_THIS s.attribute_ctrl.mode_ctrl.enable_line_graphics;
|
2003-07-20 01:44:37 +04:00
|
|
|
prev_int_pal_size = BX_VGA_THIS s.attribute_ctrl.mode_ctrl.internal_palette_size;
|
2001-04-10 05:04:59 +04:00
|
|
|
BX_VGA_THIS s.attribute_ctrl.mode_ctrl.graphics_alpha =
|
|
|
|
(value >> 0) & 0x01;
|
|
|
|
BX_VGA_THIS s.attribute_ctrl.mode_ctrl.display_type =
|
|
|
|
(value >> 1) & 0x01;
|
|
|
|
BX_VGA_THIS s.attribute_ctrl.mode_ctrl.enable_line_graphics =
|
|
|
|
(value >> 2) & 0x01;
|
|
|
|
BX_VGA_THIS s.attribute_ctrl.mode_ctrl.blink_intensity =
|
|
|
|
(value >> 3) & 0x01;
|
|
|
|
BX_VGA_THIS s.attribute_ctrl.mode_ctrl.pixel_panning_compat =
|
|
|
|
(value >> 5) & 0x01;
|
|
|
|
BX_VGA_THIS s.attribute_ctrl.mode_ctrl.pixel_clock_select =
|
|
|
|
(value >> 6) & 0x01;
|
|
|
|
BX_VGA_THIS s.attribute_ctrl.mode_ctrl.internal_palette_size =
|
|
|
|
(value >> 7) & 0x01;
|
2003-05-11 19:07:54 +04:00
|
|
|
if (((value >> 2) & 0x01) != prev_line_graphics) {
|
|
|
|
bx_gui->set_text_charmap(
|
|
|
|
& BX_VGA_THIS s.vga_memory[0x20000 + BX_VGA_THIS s.charmap_address]);
|
2003-07-20 01:44:37 +04:00
|
|
|
BX_VGA_THIS s.vga_mem_updated = 1;
|
|
|
|
}
|
|
|
|
if (((value >> 7) & 0x01) != prev_int_pal_size) {
|
|
|
|
needs_update = 1;
|
2003-05-11 19:07:54 +04:00
|
|
|
}
|
2001-04-10 05:04:59 +04:00
|
|
|
#if !defined(VGA_TRACE_FEATURE)
|
2004-04-25 11:16:09 +04:00
|
|
|
BX_DEBUG(("io write 0x3c0: mode control: 0x%02x",
|
2003-07-18 22:31:50 +04:00
|
|
|
(unsigned) value));
|
2001-04-10 05:04:59 +04:00
|
|
|
#endif
|
|
|
|
break;
|
|
|
|
case 0x11: // Overscan Color Register
|
|
|
|
BX_VGA_THIS s.attribute_ctrl.overscan_color = (value & 0x3f);
|
|
|
|
#if !defined(VGA_TRACE_FEATURE)
|
2004-04-25 11:16:09 +04:00
|
|
|
BX_DEBUG(("io write 0x3c0: overscan color = 0x%02x",
|
2003-07-18 22:31:50 +04:00
|
|
|
(unsigned) value));
|
2001-04-10 05:04:59 +04:00
|
|
|
#endif
|
|
|
|
break;
|
|
|
|
case 0x12: // Color Plane Enable Register
|
|
|
|
BX_VGA_THIS s.attribute_ctrl.color_plane_enable = (value & 0x0f);
|
2003-07-18 22:31:50 +04:00
|
|
|
needs_update = 1;
|
2001-04-10 05:04:59 +04:00
|
|
|
#if !defined(VGA_TRACE_FEATURE)
|
2004-04-25 11:16:09 +04:00
|
|
|
BX_DEBUG(("io write 0x3c0: color plane enable = 0x%02x",
|
2003-07-18 22:31:50 +04:00
|
|
|
(unsigned) value));
|
2001-04-10 05:04:59 +04:00
|
|
|
#endif
|
|
|
|
break;
|
|
|
|
case 0x13: // Horizontal Pixel Panning Register
|
|
|
|
BX_VGA_THIS s.attribute_ctrl.horiz_pel_panning = (value & 0x0f);
|
2003-05-09 19:32:28 +04:00
|
|
|
needs_update = 1;
|
2001-04-10 05:04:59 +04:00
|
|
|
#if !defined(VGA_TRACE_FEATURE)
|
2004-04-25 11:16:09 +04:00
|
|
|
BX_DEBUG(("io write 0x3c0: horiz pel panning = 0x%02x",
|
2003-07-18 22:31:50 +04:00
|
|
|
(unsigned) value));
|
2001-04-10 05:04:59 +04:00
|
|
|
#endif
|
|
|
|
break;
|
|
|
|
case 0x14: // Color Select Register
|
|
|
|
BX_VGA_THIS s.attribute_ctrl.color_select = (value & 0x0f);
|
2003-07-18 22:31:50 +04:00
|
|
|
needs_update = 1;
|
2001-04-10 05:04:59 +04:00
|
|
|
#if !defined(VGA_TRACE_FEATURE)
|
2004-04-25 11:16:09 +04:00
|
|
|
BX_DEBUG(("io write 0x3c0: color select = 0x%02x",
|
2003-07-18 22:31:50 +04:00
|
|
|
(unsigned) BX_VGA_THIS s.attribute_ctrl.color_select));
|
2001-04-10 05:04:59 +04:00
|
|
|
#endif
|
|
|
|
break;
|
|
|
|
default:
|
2004-04-25 11:16:09 +04:00
|
|
|
BX_DEBUG(("io write 0x3c0: data-write mode 0x%02x",
|
merge in BRANCH-io-cleanup.
To see the commit logs for this use either cvsweb or
cvs update -r BRANCH-io-cleanup and then 'cvs log' the various files.
In general this provides a generic interface for logging.
logfunctions:: is a class that is inherited by some classes, and also
. allocated as a standalone global called 'genlog'. All logging uses
. one of the ::info(), ::error(), ::ldebug(), ::panic() methods of this
. class through 'BX_INFO(), BX_ERROR(), BX_DEBUG(), BX_PANIC()' macros
. respectively.
.
. An example usage:
. BX_INFO(("Hello, World!\n"));
iofunctions:: is a class that is allocated once by default, and assigned
as the iofunction of each logfunctions instance. It is this class that
maintains the file descriptor and other output related code, at this
point using vfprintf(). At some future point, someone may choose to
write a gui 'console' for bochs to which messages would be redirected
simply by assigning a different iofunction class to the various logfunctions
objects.
More cleanup is coming, but this works for now. If you want to see alot
of debugging output, in main.cc, change onoff[LOGLEV_DEBUG]=0 to =1.
Comments, bugs, flames, to me: todd@fries.net
2001-05-15 18:49:57 +04:00
|
|
|
(unsigned) BX_VGA_THIS s.attribute_ctrl.address));
|
2001-04-10 05:04:59 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
BX_VGA_THIS s.attribute_ctrl.flip_flop = !BX_VGA_THIS s.attribute_ctrl.flip_flop;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 0x03c2: // Miscellaneous Output Register
|
|
|
|
BX_VGA_THIS s.misc_output.color_emulation = (value >> 0) & 0x01;
|
|
|
|
BX_VGA_THIS s.misc_output.enable_ram = (value >> 1) & 0x01;
|
|
|
|
BX_VGA_THIS s.misc_output.clock_select = (value >> 2) & 0x03;
|
|
|
|
BX_VGA_THIS s.misc_output.select_high_bank = (value >> 5) & 0x01;
|
|
|
|
BX_VGA_THIS s.misc_output.horiz_sync_pol = (value >> 6) & 0x01;
|
|
|
|
BX_VGA_THIS s.misc_output.vert_sync_pol = (value >> 7) & 0x01;
|
|
|
|
#if !defined(VGA_TRACE_FEATURE)
|
2001-05-30 22:56:02 +04:00
|
|
|
BX_DEBUG(("io write 3c2:"));
|
|
|
|
BX_DEBUG((" color_emulation (attempted) = %u",
|
2003-07-18 22:31:50 +04:00
|
|
|
(value >> 0) & 0x01));
|
2001-05-30 22:56:02 +04:00
|
|
|
BX_DEBUG((" enable_ram = %u",
|
2003-07-18 22:31:50 +04:00
|
|
|
(unsigned) BX_VGA_THIS s.misc_output.enable_ram));
|
2001-05-30 22:56:02 +04:00
|
|
|
BX_DEBUG((" clock_select = %u",
|
2003-07-18 22:31:50 +04:00
|
|
|
(unsigned) BX_VGA_THIS s.misc_output.clock_select));
|
2001-05-30 22:56:02 +04:00
|
|
|
BX_DEBUG((" select_high_bank = %u",
|
2003-07-18 22:31:50 +04:00
|
|
|
(unsigned) BX_VGA_THIS s.misc_output.select_high_bank));
|
2001-05-30 22:56:02 +04:00
|
|
|
BX_DEBUG((" horiz_sync_pol = %u",
|
2003-07-18 22:31:50 +04:00
|
|
|
(unsigned) BX_VGA_THIS s.misc_output.horiz_sync_pol));
|
2001-05-30 22:56:02 +04:00
|
|
|
BX_DEBUG((" vert_sync_pol = %u",
|
2003-07-18 22:31:50 +04:00
|
|
|
(unsigned) BX_VGA_THIS s.misc_output.vert_sync_pol));
|
2001-04-10 05:04:59 +04:00
|
|
|
#endif
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 0x03c3: // VGA enable
|
|
|
|
// bit0: enables VGA display if set
|
2006-01-07 15:10:59 +03:00
|
|
|
BX_VGA_THIS s.vga_enabled = value & 0x01;
|
2001-04-10 05:04:59 +04:00
|
|
|
#if !defined(VGA_TRACE_FEATURE)
|
2006-01-07 15:10:59 +03:00
|
|
|
BX_DEBUG(("io write 0x03c3: VGA enable = %u", BX_VGA_THIS s.vga_enabled));
|
2001-04-10 05:04:59 +04:00
|
|
|
#endif
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 0x03c4: /* Sequencer Index Register */
|
|
|
|
if (value > 4) {
|
2001-05-30 22:56:02 +04:00
|
|
|
BX_DEBUG(("io write 3c4: value > 4"));
|
2001-04-10 05:04:59 +04:00
|
|
|
}
|
|
|
|
BX_VGA_THIS s.sequencer.index = value;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 0x03c5: /* Sequencer Registers 00..04 */
|
|
|
|
switch (BX_VGA_THIS s.sequencer.index) {
|
|
|
|
case 0: /* sequencer: reset */
|
|
|
|
#if !defined(VGA_TRACE_FEATURE)
|
2002-10-13 12:14:31 +04:00
|
|
|
BX_DEBUG(("write 0x3c5: sequencer reset: value=0x%02x",
|
|
|
|
(unsigned) value));
|
2001-04-10 05:04:59 +04:00
|
|
|
#endif
|
2002-10-13 12:14:31 +04:00
|
|
|
if (BX_VGA_THIS s.sequencer.reset1 && ((value & 0x01) == 0)) {
|
|
|
|
BX_VGA_THIS s.sequencer.char_map_select = 0;
|
|
|
|
BX_VGA_THIS s.charmap_address = 0;
|
2002-10-25 01:07:56 +04:00
|
|
|
bx_gui->set_text_charmap(
|
2002-10-13 12:14:31 +04:00
|
|
|
& BX_VGA_THIS s.vga_memory[0x20000 + BX_VGA_THIS s.charmap_address]);
|
2003-07-18 22:31:50 +04:00
|
|
|
BX_VGA_THIS s.vga_mem_updated = 1;
|
2002-10-13 12:14:31 +04:00
|
|
|
}
|
|
|
|
BX_VGA_THIS s.sequencer.reset1 = (value >> 0) & 0x01;
|
|
|
|
BX_VGA_THIS s.sequencer.reset2 = (value >> 1) & 0x01;
|
2001-04-10 05:04:59 +04:00
|
|
|
break;
|
|
|
|
case 1: /* sequencer: clocking mode */
|
|
|
|
#if !defined(VGA_TRACE_FEATURE)
|
2004-04-25 11:16:09 +04:00
|
|
|
BX_DEBUG(("io write 0x3c5=0x%02x: clocking mode reg: ignoring",
|
2003-07-18 22:31:50 +04:00
|
|
|
(unsigned) value));
|
2001-04-10 05:04:59 +04:00
|
|
|
#endif
|
2004-08-16 12:07:23 +04:00
|
|
|
BX_VGA_THIS s.sequencer.reg1 = value & 0x3d;
|
2003-05-03 20:09:39 +04:00
|
|
|
BX_VGA_THIS s.x_dotclockdiv2 = ((value & 0x08) > 0);
|
2001-04-10 05:04:59 +04:00
|
|
|
break;
|
|
|
|
case 2: /* sequencer: map mask register */
|
|
|
|
BX_VGA_THIS s.sequencer.map_mask = (value & 0x0f);
|
|
|
|
for (i=0; i<4; i++)
|
|
|
|
BX_VGA_THIS s.sequencer.map_mask_bit[i] = (value >> i) & 0x01;
|
|
|
|
break;
|
|
|
|
case 3: /* sequencer: character map select register */
|
2004-08-16 12:07:23 +04:00
|
|
|
BX_VGA_THIS s.sequencer.char_map_select = value & 0x3f;
|
2001-12-13 21:34:30 +03:00
|
|
|
charmap1 = value & 0x13;
|
|
|
|
if (charmap1 > 3) charmap1 = (charmap1 & 3) + 4;
|
|
|
|
charmap2 = (value & 0x2C) >> 2;
|
|
|
|
if (charmap2 > 3) charmap2 = (charmap2 & 3) + 4;
|
2002-09-08 11:56:10 +04:00
|
|
|
if (BX_VGA_THIS s.CRTC.reg[0x09] > 0) {
|
2004-04-25 11:16:09 +04:00
|
|
|
BX_VGA_THIS s.charmap_address = charmap_offset[charmap1];
|
2002-10-25 01:07:56 +04:00
|
|
|
bx_gui->set_text_charmap(
|
2002-09-19 22:59:50 +04:00
|
|
|
& BX_VGA_THIS s.vga_memory[0x20000 + BX_VGA_THIS s.charmap_address]);
|
2003-07-18 22:31:50 +04:00
|
|
|
BX_VGA_THIS s.vga_mem_updated = 1;
|
2002-09-08 11:56:10 +04:00
|
|
|
}
|
|
|
|
if (charmap2 != charmap1)
|
2004-04-25 11:16:09 +04:00
|
|
|
BX_INFO(("char map select: map #2 in block #%d unused", charmap2));
|
2001-04-10 05:04:59 +04:00
|
|
|
break;
|
|
|
|
case 4: /* sequencer: memory mode register */
|
|
|
|
BX_VGA_THIS s.sequencer.extended_mem = (value >> 1) & 0x01;
|
|
|
|
BX_VGA_THIS s.sequencer.odd_even = (value >> 2) & 0x01;
|
|
|
|
BX_VGA_THIS s.sequencer.chain_four = (value >> 3) & 0x01;
|
|
|
|
|
|
|
|
#if !defined(VGA_TRACE_FEATURE)
|
2004-04-25 11:16:09 +04:00
|
|
|
BX_DEBUG(("io write 0x3c5: memory mode:"));
|
|
|
|
BX_DEBUG((" extended_mem = %u",
|
2003-07-18 22:31:50 +04:00
|
|
|
(unsigned) BX_VGA_THIS s.sequencer.extended_mem));
|
2004-04-25 11:16:09 +04:00
|
|
|
BX_DEBUG((" odd_even = %u",
|
2003-07-18 22:31:50 +04:00
|
|
|
(unsigned) BX_VGA_THIS s.sequencer.odd_even));
|
2004-04-25 11:16:09 +04:00
|
|
|
BX_DEBUG((" chain_four = %u",
|
2003-07-18 22:31:50 +04:00
|
|
|
(unsigned) BX_VGA_THIS s.sequencer.chain_four));
|
2001-04-10 05:04:59 +04:00
|
|
|
#endif
|
|
|
|
break;
|
|
|
|
default:
|
2004-04-25 11:16:09 +04:00
|
|
|
BX_DEBUG(("io write 0x3c5: index 0x%02x unhandled",
|
merge in BRANCH-io-cleanup.
To see the commit logs for this use either cvsweb or
cvs update -r BRANCH-io-cleanup and then 'cvs log' the various files.
In general this provides a generic interface for logging.
logfunctions:: is a class that is inherited by some classes, and also
. allocated as a standalone global called 'genlog'. All logging uses
. one of the ::info(), ::error(), ::ldebug(), ::panic() methods of this
. class through 'BX_INFO(), BX_ERROR(), BX_DEBUG(), BX_PANIC()' macros
. respectively.
.
. An example usage:
. BX_INFO(("Hello, World!\n"));
iofunctions:: is a class that is allocated once by default, and assigned
as the iofunction of each logfunctions instance. It is this class that
maintains the file descriptor and other output related code, at this
point using vfprintf(). At some future point, someone may choose to
write a gui 'console' for bochs to which messages would be redirected
simply by assigning a different iofunction class to the various logfunctions
objects.
More cleanup is coming, but this works for now. If you want to see alot
of debugging output, in main.cc, change onoff[LOGLEV_DEBUG]=0 to =1.
Comments, bugs, flames, to me: todd@fries.net
2001-05-15 18:49:57 +04:00
|
|
|
(unsigned) BX_VGA_THIS s.sequencer.index));
|
2001-04-10 05:04:59 +04:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 0x03c6: /* PEL mask */
|
|
|
|
BX_VGA_THIS s.pel.mask = value;
|
|
|
|
if (BX_VGA_THIS s.pel.mask != 0xff)
|
2004-04-25 11:16:09 +04:00
|
|
|
BX_DEBUG(("io write 0x3c6: PEL mask=0x%02x != 0xFF", value));
|
2001-04-10 05:04:59 +04:00
|
|
|
// BX_VGA_THIS s.pel.mask should be and'd with final value before
|
2003-07-18 22:31:50 +04:00
|
|
|
// indexing into color register BX_VGA_THIS s.pel.data[]
|
2001-04-10 05:04:59 +04:00
|
|
|
break;
|
|
|
|
|
|
|
|
case 0x03c7: // PEL address, read mode
|
|
|
|
BX_VGA_THIS s.pel.read_data_register = value;
|
|
|
|
BX_VGA_THIS s.pel.read_data_cycle = 0;
|
2003-01-11 14:18:04 +03:00
|
|
|
BX_VGA_THIS s.pel.dac_state = 0x03;
|
2001-04-10 05:04:59 +04:00
|
|
|
break;
|
|
|
|
|
|
|
|
case 0x03c8: /* PEL address write mode */
|
|
|
|
BX_VGA_THIS s.pel.write_data_register = value;
|
|
|
|
BX_VGA_THIS s.pel.write_data_cycle = 0;
|
2003-01-11 14:18:04 +03:00
|
|
|
BX_VGA_THIS s.pel.dac_state = 0x00;
|
2001-04-10 05:04:59 +04:00
|
|
|
break;
|
|
|
|
|
|
|
|
case 0x03c9: /* PEL Data Register, colors 00..FF */
|
|
|
|
switch (BX_VGA_THIS s.pel.write_data_cycle) {
|
|
|
|
case 0:
|
|
|
|
BX_VGA_THIS s.pel.data[BX_VGA_THIS s.pel.write_data_register].red = value;
|
|
|
|
break;
|
|
|
|
case 1:
|
|
|
|
BX_VGA_THIS s.pel.data[BX_VGA_THIS s.pel.write_data_register].green = value;
|
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
BX_VGA_THIS s.pel.data[BX_VGA_THIS s.pel.write_data_register].blue = value;
|
|
|
|
|
2004-05-05 00:41:53 +04:00
|
|
|
#if BX_SUPPORT_VBE
|
|
|
|
if (BX_VGA_THIS s.vbe_8bit_dac) {
|
|
|
|
needs_update |= bx_gui->palette_change(BX_VGA_THIS s.pel.write_data_register,
|
|
|
|
BX_VGA_THIS s.pel.data[BX_VGA_THIS s.pel.write_data_register].red,
|
|
|
|
BX_VGA_THIS s.pel.data[BX_VGA_THIS s.pel.write_data_register].green,
|
|
|
|
BX_VGA_THIS s.pel.data[BX_VGA_THIS s.pel.write_data_register].blue);
|
|
|
|
} else {
|
|
|
|
#endif
|
|
|
|
needs_update |= bx_gui->palette_change(BX_VGA_THIS s.pel.write_data_register,
|
|
|
|
BX_VGA_THIS s.pel.data[BX_VGA_THIS s.pel.write_data_register].red<<2,
|
|
|
|
BX_VGA_THIS s.pel.data[BX_VGA_THIS s.pel.write_data_register].green<<2,
|
|
|
|
BX_VGA_THIS s.pel.data[BX_VGA_THIS s.pel.write_data_register].blue<<2);
|
|
|
|
#if BX_SUPPORT_VBE
|
|
|
|
}
|
|
|
|
#endif
|
2001-04-10 05:04:59 +04:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
BX_VGA_THIS s.pel.write_data_cycle++;
|
|
|
|
if (BX_VGA_THIS s.pel.write_data_cycle >= 3) {
|
2001-05-30 22:56:02 +04:00
|
|
|
//BX_INFO(("BX_VGA_THIS s.pel.data[%u] {r=%u, g=%u, b=%u}",
|
2001-04-10 05:04:59 +04:00
|
|
|
// (unsigned) BX_VGA_THIS s.pel.write_data_register,
|
|
|
|
// (unsigned) BX_VGA_THIS s.pel.data[BX_VGA_THIS s.pel.write_data_register].red,
|
|
|
|
// (unsigned) BX_VGA_THIS s.pel.data[BX_VGA_THIS s.pel.write_data_register].green,
|
|
|
|
// (unsigned) BX_VGA_THIS s.pel.data[BX_VGA_THIS s.pel.write_data_register].blue);
|
|
|
|
BX_VGA_THIS s.pel.write_data_cycle = 0;
|
|
|
|
BX_VGA_THIS s.pel.write_data_register++;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 0x03ca: /* Graphics 2 Position (EGA) */
|
|
|
|
// ignore, EGA only???
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 0x03cc: /* Graphics 1 Position (EGA) */
|
|
|
|
// ignore, EGA only???
|
|
|
|
break;
|
|
|
|
|
2004-04-25 11:16:09 +04:00
|
|
|
case 0x03cd: /* ??? */
|
|
|
|
BX_DEBUG(("io write to 0x3cd = 0x%02x", (unsigned) value));
|
|
|
|
break;
|
|
|
|
|
2001-04-10 05:04:59 +04:00
|
|
|
case 0x03ce: /* Graphics Controller Index Register */
|
|
|
|
if (value > 0x08) /* ??? */
|
2004-04-25 11:16:09 +04:00
|
|
|
BX_DEBUG(("io write: 0x3ce: value > 8"));
|
2001-04-10 05:04:59 +04:00
|
|
|
BX_VGA_THIS s.graphics_ctrl.index = value;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 0x03cf: /* Graphics Controller Registers 00..08 */
|
|
|
|
switch (BX_VGA_THIS s.graphics_ctrl.index) {
|
|
|
|
case 0: /* Set/Reset */
|
|
|
|
BX_VGA_THIS s.graphics_ctrl.set_reset = value & 0x0f;
|
|
|
|
break;
|
|
|
|
case 1: /* Enable Set/Reset */
|
|
|
|
BX_VGA_THIS s.graphics_ctrl.enable_set_reset = value & 0x0f;
|
|
|
|
break;
|
|
|
|
case 2: /* Color Compare */
|
|
|
|
BX_VGA_THIS s.graphics_ctrl.color_compare = value & 0x0f;
|
|
|
|
break;
|
|
|
|
case 3: /* Data Rotate */
|
|
|
|
BX_VGA_THIS s.graphics_ctrl.data_rotate = value & 0x07;
|
2004-08-16 12:07:23 +04:00
|
|
|
BX_VGA_THIS s.graphics_ctrl.raster_op = (value >> 3) & 0x03;
|
2001-04-10 05:04:59 +04:00
|
|
|
break;
|
|
|
|
case 4: /* Read Map Select */
|
|
|
|
BX_VGA_THIS s.graphics_ctrl.read_map_select = value & 0x03;
|
|
|
|
#if !defined(VGA_TRACE_FEATURE)
|
2004-04-25 11:16:09 +04:00
|
|
|
BX_DEBUG(("io write to 0x3cf = 0x%02x (RMS)", (unsigned) value));
|
2001-04-10 05:04:59 +04:00
|
|
|
#endif
|
|
|
|
break;
|
|
|
|
case 5: /* Mode */
|
|
|
|
BX_VGA_THIS s.graphics_ctrl.write_mode = value & 0x03;
|
|
|
|
BX_VGA_THIS s.graphics_ctrl.read_mode = (value >> 3) & 0x01;
|
2004-04-25 11:16:09 +04:00
|
|
|
BX_VGA_THIS s.graphics_ctrl.odd_even = (value >> 4) & 0x01;
|
2001-04-10 05:04:59 +04:00
|
|
|
BX_VGA_THIS s.graphics_ctrl.shift_reg = (value >> 5) & 0x03;
|
|
|
|
|
|
|
|
if (BX_VGA_THIS s.graphics_ctrl.odd_even)
|
2004-04-25 11:16:09 +04:00
|
|
|
BX_DEBUG(("io write: 0x3cf: mode reg: value = 0x%02x",
|
merge in BRANCH-io-cleanup.
To see the commit logs for this use either cvsweb or
cvs update -r BRANCH-io-cleanup and then 'cvs log' the various files.
In general this provides a generic interface for logging.
logfunctions:: is a class that is inherited by some classes, and also
. allocated as a standalone global called 'genlog'. All logging uses
. one of the ::info(), ::error(), ::ldebug(), ::panic() methods of this
. class through 'BX_INFO(), BX_ERROR(), BX_DEBUG(), BX_PANIC()' macros
. respectively.
.
. An example usage:
. BX_INFO(("Hello, World!\n"));
iofunctions:: is a class that is allocated once by default, and assigned
as the iofunction of each logfunctions instance. It is this class that
maintains the file descriptor and other output related code, at this
point using vfprintf(). At some future point, someone may choose to
write a gui 'console' for bochs to which messages would be redirected
simply by assigning a different iofunction class to the various logfunctions
objects.
More cleanup is coming, but this works for now. If you want to see alot
of debugging output, in main.cc, change onoff[LOGLEV_DEBUG]=0 to =1.
Comments, bugs, flames, to me: todd@fries.net
2001-05-15 18:49:57 +04:00
|
|
|
(unsigned) value));
|
2001-04-10 05:04:59 +04:00
|
|
|
if (BX_VGA_THIS s.graphics_ctrl.shift_reg)
|
2004-04-25 11:16:09 +04:00
|
|
|
BX_DEBUG(("io write: 0x3cf: mode reg: value = 0x%02x",
|
merge in BRANCH-io-cleanup.
To see the commit logs for this use either cvsweb or
cvs update -r BRANCH-io-cleanup and then 'cvs log' the various files.
In general this provides a generic interface for logging.
logfunctions:: is a class that is inherited by some classes, and also
. allocated as a standalone global called 'genlog'. All logging uses
. one of the ::info(), ::error(), ::ldebug(), ::panic() methods of this
. class through 'BX_INFO(), BX_ERROR(), BX_DEBUG(), BX_PANIC()' macros
. respectively.
.
. An example usage:
. BX_INFO(("Hello, World!\n"));
iofunctions:: is a class that is allocated once by default, and assigned
as the iofunction of each logfunctions instance. It is this class that
maintains the file descriptor and other output related code, at this
point using vfprintf(). At some future point, someone may choose to
write a gui 'console' for bochs to which messages would be redirected
simply by assigning a different iofunction class to the various logfunctions
objects.
More cleanup is coming, but this works for now. If you want to see alot
of debugging output, in main.cc, change onoff[LOGLEV_DEBUG]=0 to =1.
Comments, bugs, flames, to me: todd@fries.net
2001-05-15 18:49:57 +04:00
|
|
|
(unsigned) value));
|
2001-04-10 05:04:59 +04:00
|
|
|
break;
|
|
|
|
case 6: /* Miscellaneous */
|
|
|
|
prev_graphics_alpha = BX_VGA_THIS s.graphics_ctrl.graphics_alpha;
|
|
|
|
prev_chain_odd_even = BX_VGA_THIS s.graphics_ctrl.chain_odd_even;
|
|
|
|
prev_memory_mapping = BX_VGA_THIS s.graphics_ctrl.memory_mapping;
|
|
|
|
|
|
|
|
BX_VGA_THIS s.graphics_ctrl.graphics_alpha = value & 0x01;
|
|
|
|
BX_VGA_THIS s.graphics_ctrl.chain_odd_even = (value >> 1) & 0x01;
|
|
|
|
BX_VGA_THIS s.graphics_ctrl.memory_mapping = (value >> 2) & 0x03;
|
|
|
|
#if !defined(VGA_TRACE_FEATURE)
|
2001-05-30 22:56:02 +04:00
|
|
|
BX_DEBUG(("memory_mapping set to %u",
|
2003-07-18 22:31:50 +04:00
|
|
|
(unsigned) BX_VGA_THIS s.graphics_ctrl.memory_mapping));
|
2001-05-30 22:56:02 +04:00
|
|
|
BX_DEBUG(("graphics mode set to %u",
|
2003-07-18 22:31:50 +04:00
|
|
|
(unsigned) BX_VGA_THIS s.graphics_ctrl.graphics_alpha));
|
2001-05-30 22:56:02 +04:00
|
|
|
BX_DEBUG(("odd_even mode set to %u",
|
2003-07-18 22:31:50 +04:00
|
|
|
(unsigned) BX_VGA_THIS s.graphics_ctrl.odd_even));
|
2004-04-25 11:16:09 +04:00
|
|
|
BX_DEBUG(("io write: 0x3cf: misc reg: value = 0x%02x",
|
2003-07-18 22:31:50 +04:00
|
|
|
(unsigned) value));
|
2001-04-10 05:04:59 +04:00
|
|
|
#endif
|
|
|
|
if (prev_memory_mapping != BX_VGA_THIS s.graphics_ctrl.memory_mapping)
|
2003-04-28 22:15:31 +04:00
|
|
|
needs_update = 1;
|
2003-05-06 21:10:13 +04:00
|
|
|
if (prev_graphics_alpha != BX_VGA_THIS s.graphics_ctrl.graphics_alpha) {
|
2003-04-28 22:15:31 +04:00
|
|
|
needs_update = 1;
|
2003-05-06 21:10:13 +04:00
|
|
|
old_iHeight = 0;
|
|
|
|
}
|
2001-04-10 05:04:59 +04:00
|
|
|
break;
|
|
|
|
case 7: /* Color Don't Care */
|
|
|
|
BX_VGA_THIS s.graphics_ctrl.color_dont_care = value & 0x0f;
|
|
|
|
break;
|
|
|
|
case 8: /* Bit Mask */
|
|
|
|
BX_VGA_THIS s.graphics_ctrl.bitmask = value;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
/* ??? */
|
2004-04-25 11:16:09 +04:00
|
|
|
BX_DEBUG(("io write: 0x3cf: index %u unhandled",
|
merge in BRANCH-io-cleanup.
To see the commit logs for this use either cvsweb or
cvs update -r BRANCH-io-cleanup and then 'cvs log' the various files.
In general this provides a generic interface for logging.
logfunctions:: is a class that is inherited by some classes, and also
. allocated as a standalone global called 'genlog'. All logging uses
. one of the ::info(), ::error(), ::ldebug(), ::panic() methods of this
. class through 'BX_INFO(), BX_ERROR(), BX_DEBUG(), BX_PANIC()' macros
. respectively.
.
. An example usage:
. BX_INFO(("Hello, World!\n"));
iofunctions:: is a class that is allocated once by default, and assigned
as the iofunction of each logfunctions instance. It is this class that
maintains the file descriptor and other output related code, at this
point using vfprintf(). At some future point, someone may choose to
write a gui 'console' for bochs to which messages would be redirected
simply by assigning a different iofunction class to the various logfunctions
objects.
More cleanup is coming, but this works for now. If you want to see alot
of debugging output, in main.cc, change onoff[LOGLEV_DEBUG]=0 to =1.
Comments, bugs, flames, to me: todd@fries.net
2001-05-15 18:49:57 +04:00
|
|
|
(unsigned) BX_VGA_THIS s.graphics_ctrl.index));
|
2001-04-10 05:04:59 +04:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2003-11-01 13:28:40 +03:00
|
|
|
case 0x03b4: /* CRTC Index Register (monochrome emulation modes) */
|
2001-04-10 05:04:59 +04:00
|
|
|
case 0x03d4: /* CRTC Index Register (color emulation modes) */
|
2002-04-14 12:57:24 +04:00
|
|
|
BX_VGA_THIS s.CRTC.address = value & 0x7f;
|
2001-04-10 05:04:59 +04:00
|
|
|
if (BX_VGA_THIS s.CRTC.address > 0x18)
|
2002-04-14 12:57:24 +04:00
|
|
|
BX_DEBUG(("write: invalid CRTC register 0x%02x selected",
|
merge in BRANCH-io-cleanup.
To see the commit logs for this use either cvsweb or
cvs update -r BRANCH-io-cleanup and then 'cvs log' the various files.
In general this provides a generic interface for logging.
logfunctions:: is a class that is inherited by some classes, and also
. allocated as a standalone global called 'genlog'. All logging uses
. one of the ::info(), ::error(), ::ldebug(), ::panic() methods of this
. class through 'BX_INFO(), BX_ERROR(), BX_DEBUG(), BX_PANIC()' macros
. respectively.
.
. An example usage:
. BX_INFO(("Hello, World!\n"));
iofunctions:: is a class that is allocated once by default, and assigned
as the iofunction of each logfunctions instance. It is this class that
maintains the file descriptor and other output related code, at this
point using vfprintf(). At some future point, someone may choose to
write a gui 'console' for bochs to which messages would be redirected
simply by assigning a different iofunction class to the various logfunctions
objects.
More cleanup is coming, but this works for now. If you want to see alot
of debugging output, in main.cc, change onoff[LOGLEV_DEBUG]=0 to =1.
Comments, bugs, flames, to me: todd@fries.net
2001-05-15 18:49:57 +04:00
|
|
|
(unsigned) BX_VGA_THIS s.CRTC.address));
|
2001-04-10 05:04:59 +04:00
|
|
|
break;
|
|
|
|
|
2003-11-01 13:28:40 +03:00
|
|
|
case 0x03b5: /* CRTC Registers (monochrome emulation modes) */
|
2001-04-10 05:04:59 +04:00
|
|
|
case 0x03d5: /* CRTC Registers (color emulation modes) */
|
2002-04-14 12:57:24 +04:00
|
|
|
if (BX_VGA_THIS s.CRTC.address > 0x18) {
|
|
|
|
BX_DEBUG(("write: invalid CRTC register 0x%02x ignored",
|
merge in BRANCH-io-cleanup.
To see the commit logs for this use either cvsweb or
cvs update -r BRANCH-io-cleanup and then 'cvs log' the various files.
In general this provides a generic interface for logging.
logfunctions:: is a class that is inherited by some classes, and also
. allocated as a standalone global called 'genlog'. All logging uses
. one of the ::info(), ::error(), ::ldebug(), ::panic() methods of this
. class through 'BX_INFO(), BX_ERROR(), BX_DEBUG(), BX_PANIC()' macros
. respectively.
.
. An example usage:
. BX_INFO(("Hello, World!\n"));
iofunctions:: is a class that is allocated once by default, and assigned
as the iofunction of each logfunctions instance. It is this class that
maintains the file descriptor and other output related code, at this
point using vfprintf(). At some future point, someone may choose to
write a gui 'console' for bochs to which messages would be redirected
simply by assigning a different iofunction class to the various logfunctions
objects.
More cleanup is coming, but this works for now. If you want to see alot
of debugging output, in main.cc, change onoff[LOGLEV_DEBUG]=0 to =1.
Comments, bugs, flames, to me: todd@fries.net
2001-05-15 18:49:57 +04:00
|
|
|
(unsigned) BX_VGA_THIS s.CRTC.address));
|
2002-04-14 12:57:24 +04:00
|
|
|
return;
|
|
|
|
}
|
2004-07-18 23:40:51 +04:00
|
|
|
if (BX_VGA_THIS s.CRTC.write_protect && (BX_VGA_THIS s.CRTC.address < 0x08)) {
|
|
|
|
if (BX_VGA_THIS s.CRTC.address == 0x07) {
|
|
|
|
BX_VGA_THIS s.CRTC.reg[BX_VGA_THIS s.CRTC.address] &= ~0x10;
|
|
|
|
BX_VGA_THIS s.CRTC.reg[BX_VGA_THIS s.CRTC.address] |= (value & 0x10);
|
|
|
|
BX_VGA_THIS s.line_compare &= 0x2ff;
|
|
|
|
if (BX_VGA_THIS s.CRTC.reg[0x07] & 0x10) BX_VGA_THIS s.line_compare |= 0x100;
|
|
|
|
needs_update = 1;
|
|
|
|
break;
|
|
|
|
} else {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
2003-04-27 13:13:47 +04:00
|
|
|
if (value != BX_VGA_THIS s.CRTC.reg[BX_VGA_THIS s.CRTC.address]) {
|
|
|
|
BX_VGA_THIS s.CRTC.reg[BX_VGA_THIS s.CRTC.address] = value;
|
2003-04-28 22:15:31 +04:00
|
|
|
switch (BX_VGA_THIS s.CRTC.address) {
|
2003-05-02 11:32:06 +04:00
|
|
|
case 0x07:
|
|
|
|
BX_VGA_THIS s.vertical_display_end &= 0xff;
|
|
|
|
if (BX_VGA_THIS s.CRTC.reg[0x07] & 0x02) BX_VGA_THIS s.vertical_display_end |= 0x100;
|
|
|
|
if (BX_VGA_THIS s.CRTC.reg[0x07] & 0x40) BX_VGA_THIS s.vertical_display_end |= 0x200;
|
|
|
|
BX_VGA_THIS s.line_compare &= 0x2ff;
|
|
|
|
if (BX_VGA_THIS s.CRTC.reg[0x07] & 0x10) BX_VGA_THIS s.line_compare |= 0x100;
|
|
|
|
needs_update = 1;
|
|
|
|
break;
|
2003-05-09 19:32:28 +04:00
|
|
|
case 0x08:
|
|
|
|
// Vertical pel panning change
|
|
|
|
needs_update = 1;
|
|
|
|
break;
|
|
|
|
case 0x09:
|
|
|
|
BX_VGA_THIS s.y_doublescan = ((value & 0x9f) > 0);
|
|
|
|
BX_VGA_THIS s.line_compare &= 0x1ff;
|
|
|
|
if (BX_VGA_THIS s.CRTC.reg[0x09] & 0x40) BX_VGA_THIS s.line_compare |= 0x200;
|
2003-05-02 11:32:06 +04:00
|
|
|
needs_update = 1;
|
2003-04-28 22:15:31 +04:00
|
|
|
break;
|
|
|
|
case 0x0A:
|
|
|
|
case 0x0B:
|
|
|
|
case 0x0E:
|
|
|
|
case 0x0F:
|
|
|
|
// Cursor size / location change
|
2003-04-27 13:13:47 +04:00
|
|
|
BX_VGA_THIS s.vga_mem_updated = 1;
|
2003-04-28 22:15:31 +04:00
|
|
|
break;
|
|
|
|
case 0x0C:
|
|
|
|
case 0x0D:
|
|
|
|
// Start address change
|
2003-06-08 20:45:24 +04:00
|
|
|
if (BX_VGA_THIS s.graphics_ctrl.graphics_alpha) {
|
|
|
|
needs_update = 1;
|
|
|
|
} else {
|
|
|
|
BX_VGA_THIS s.vga_mem_updated = 1;
|
|
|
|
}
|
2003-04-28 22:15:31 +04:00
|
|
|
break;
|
2004-07-18 23:40:51 +04:00
|
|
|
case 0x11:
|
|
|
|
BX_VGA_THIS s.CRTC.write_protect = ((BX_VGA_THIS s.CRTC.reg[0x11] & 0x80) > 0);
|
|
|
|
break;
|
2003-05-02 11:32:06 +04:00
|
|
|
case 0x12:
|
|
|
|
BX_VGA_THIS s.vertical_display_end &= 0x300;
|
|
|
|
BX_VGA_THIS s.vertical_display_end |= BX_VGA_THIS s.CRTC.reg[0x12];
|
|
|
|
break;
|
2003-04-28 22:15:31 +04:00
|
|
|
case 0x13:
|
|
|
|
case 0x14:
|
|
|
|
case 0x17:
|
2005-03-01 00:23:34 +03:00
|
|
|
#if BX_SUPPORT_VBE
|
|
|
|
if (!BX_VGA_THIS s.vbe_enabled)
|
|
|
|
#endif
|
|
|
|
{
|
|
|
|
// Line offset change
|
|
|
|
BX_VGA_THIS s.line_offset = BX_VGA_THIS s.CRTC.reg[0x13] << 1;
|
|
|
|
if (BX_VGA_THIS s.CRTC.reg[0x14] & 0x40) BX_VGA_THIS s.line_offset <<= 2;
|
|
|
|
else if ((BX_VGA_THIS s.CRTC.reg[0x17] & 0x40) == 0) BX_VGA_THIS s.line_offset <<= 1;
|
|
|
|
needs_update = 1;
|
|
|
|
}
|
2003-04-28 22:15:31 +04:00
|
|
|
break;
|
2003-05-09 19:32:28 +04:00
|
|
|
case 0x18:
|
2003-10-04 19:58:21 +04:00
|
|
|
BX_VGA_THIS s.line_compare &= 0x300;
|
|
|
|
BX_VGA_THIS s.line_compare |= BX_VGA_THIS s.CRTC.reg[0x18];
|
2003-05-09 19:32:28 +04:00
|
|
|
needs_update = 1;
|
|
|
|
break;
|
2001-04-10 05:04:59 +04:00
|
|
|
}
|
2003-04-28 22:15:31 +04:00
|
|
|
|
|
|
|
}
|
2001-04-10 05:04:59 +04:00
|
|
|
break;
|
|
|
|
|
|
|
|
case 0x03da: /* Feature Control (color emulation modes) */
|
2001-05-30 22:56:02 +04:00
|
|
|
BX_DEBUG(("io write: 3da: ignoring: feature ctrl & vert sync"));
|
2001-04-10 05:04:59 +04:00
|
|
|
break;
|
|
|
|
|
|
|
|
case 0x03c1: /* */
|
|
|
|
default:
|
2002-01-20 03:28:09 +03:00
|
|
|
BX_ERROR(("unsupported io write to port 0x%04x, val=0x%02x",
|
merge in BRANCH-io-cleanup.
To see the commit logs for this use either cvsweb or
cvs update -r BRANCH-io-cleanup and then 'cvs log' the various files.
In general this provides a generic interface for logging.
logfunctions:: is a class that is inherited by some classes, and also
. allocated as a standalone global called 'genlog'. All logging uses
. one of the ::info(), ::error(), ::ldebug(), ::panic() methods of this
. class through 'BX_INFO(), BX_ERROR(), BX_DEBUG(), BX_PANIC()' macros
. respectively.
.
. An example usage:
. BX_INFO(("Hello, World!\n"));
iofunctions:: is a class that is allocated once by default, and assigned
as the iofunction of each logfunctions instance. It is this class that
maintains the file descriptor and other output related code, at this
point using vfprintf(). At some future point, someone may choose to
write a gui 'console' for bochs to which messages would be redirected
simply by assigning a different iofunction class to the various logfunctions
objects.
More cleanup is coming, but this works for now. If you want to see alot
of debugging output, in main.cc, change onoff[LOGLEV_DEBUG]=0 to =1.
Comments, bugs, flames, to me: todd@fries.net
2001-05-15 18:49:57 +04:00
|
|
|
(unsigned) address, (unsigned) value));
|
2001-04-10 05:04:59 +04:00
|
|
|
}
|
2003-04-28 22:15:31 +04:00
|
|
|
if (needs_update) {
|
|
|
|
// Mark all video as updated so the changes will go through
|
2005-04-15 21:33:54 +04:00
|
|
|
BX_VGA_THIS redraw_area(0, 0, old_iWidth, old_iHeight);
|
2003-04-28 22:15:31 +04:00
|
|
|
}
|
2001-04-10 05:04:59 +04:00
|
|
|
}
|
|
|
|
|
2005-11-27 20:49:59 +03:00
|
|
|
Bit64s bx_vga_c::vga_param_handler(bx_param_c *param, int set, Bit64s val)
|
2001-06-09 23:57:56 +04:00
|
|
|
{
|
2005-11-27 20:49:59 +03:00
|
|
|
// handler for runtime parameter 'vga_update_interval'
|
|
|
|
if (set) {
|
|
|
|
BX_INFO (("Changing timer interval to %d", (Bit32u)val));
|
|
|
|
BX_VGA_THIS timer_handler (theVga);
|
|
|
|
bx_pc_system.activate_timer (BX_VGA_THIS timer_id, (Bit32u)val, 1);
|
|
|
|
}
|
|
|
|
return val;
|
2001-06-09 23:57:56 +04:00
|
|
|
}
|
2001-04-10 05:04:59 +04:00
|
|
|
|
2002-10-25 01:07:56 +04:00
|
|
|
void
|
|
|
|
bx_vga_c::trigger_timer(void *this_ptr)
|
|
|
|
{
|
|
|
|
timer_handler(this_ptr);
|
|
|
|
}
|
|
|
|
|
2001-04-10 05:04:59 +04:00
|
|
|
void
|
|
|
|
bx_vga_c::timer_handler(void *this_ptr)
|
|
|
|
{
|
2002-10-25 01:07:56 +04:00
|
|
|
#if !BX_USE_VGA_SMF
|
|
|
|
|
2001-04-10 05:04:59 +04:00
|
|
|
bx_vga_c *class_ptr = (bx_vga_c *) this_ptr;
|
|
|
|
|
|
|
|
class_ptr->timer();
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
bx_vga_c::timer(void)
|
|
|
|
{
|
2002-10-25 01:07:56 +04:00
|
|
|
#else
|
|
|
|
UNUSED(this_ptr);
|
|
|
|
#endif
|
|
|
|
|
2001-04-10 05:04:59 +04:00
|
|
|
update();
|
2002-10-25 01:07:56 +04:00
|
|
|
bx_gui->flush();
|
2001-04-10 05:04:59 +04:00
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
bx_vga_c::update(void)
|
|
|
|
{
|
2002-02-07 22:04:30 +03:00
|
|
|
unsigned iHeight, iWidth;
|
2002-03-10 07:51:24 +03:00
|
|
|
|
2003-06-10 20:26:19 +04:00
|
|
|
/* no screen update necessary */
|
|
|
|
if (BX_VGA_THIS s.vga_mem_updated==0)
|
|
|
|
return;
|
|
|
|
|
2006-01-07 15:10:59 +03:00
|
|
|
/* skip screen update when vga/video is disabled or the sequencer is in reset mode */
|
|
|
|
if (!BX_VGA_THIS s.vga_enabled || !BX_VGA_THIS s.attribute_ctrl.video_enabled
|
|
|
|
|| !BX_VGA_THIS s.sequencer.reset2 || !BX_VGA_THIS s.sequencer.reset1)
|
2002-10-13 12:14:31 +04:00
|
|
|
return;
|
|
|
|
|
2003-06-10 20:26:19 +04:00
|
|
|
/* skip screen update if the vertical retrace is in progress
|
|
|
|
(using 72 Hz vertical frequency) */
|
|
|
|
if ((bx_pc_system.time_usec() % 13888) < 70)
|
2002-03-10 07:51:24 +03:00
|
|
|
return;
|
|
|
|
|
|
|
|
#if BX_SUPPORT_VBE
|
2003-02-09 11:25:22 +03:00
|
|
|
if ((BX_VGA_THIS s.vbe_enabled) && (BX_VGA_THIS s.vbe_bpp != VBE_DISPI_BPP_4))
|
2002-03-10 07:51:24 +03:00
|
|
|
{
|
|
|
|
// specific VBE code display update code
|
2004-11-06 20:03:44 +03:00
|
|
|
unsigned pitch;
|
2003-06-08 20:45:24 +04:00
|
|
|
unsigned xc, yc, xti, yti;
|
2004-11-06 20:03:44 +03:00
|
|
|
unsigned r, c, w, h;
|
|
|
|
int i;
|
|
|
|
unsigned long red, green, blue, colour;
|
|
|
|
Bit8u * vid_ptr, * vid_ptr2;
|
|
|
|
Bit8u * tile_ptr, * tile_ptr2;
|
|
|
|
bx_svga_tileinfo_t info;
|
2005-03-01 00:23:34 +03:00
|
|
|
Bit8u dac_size = BX_VGA_THIS s.vbe_8bit_dac ? 8 : 6;
|
2004-11-06 20:03:44 +03:00
|
|
|
|
|
|
|
iWidth=BX_VGA_THIS s.vbe_xres;
|
|
|
|
iHeight=BX_VGA_THIS s.vbe_yres;
|
|
|
|
pitch = BX_VGA_THIS s.line_offset;
|
|
|
|
Bit8u *disp_ptr = &BX_VGA_THIS s.vbe_memory[BX_VGA_THIS s.vbe_virtual_start];
|
|
|
|
|
|
|
|
if (bx_gui->graphics_tile_info(&info)) {
|
|
|
|
if (info.is_indexed) {
|
|
|
|
switch (BX_VGA_THIS s.vbe_bpp) {
|
|
|
|
case 4:
|
|
|
|
case 15:
|
|
|
|
case 16:
|
|
|
|
case 24:
|
|
|
|
case 32:
|
|
|
|
BX_ERROR(("current guest pixel format is unsupported on indexed colour host displays"));
|
|
|
|
break;
|
|
|
|
case 8:
|
|
|
|
for (yc=0, yti = 0; yc<iHeight; yc+=Y_TILESIZE, yti++) {
|
|
|
|
for (xc=0, xti = 0; xc<iWidth; xc+=X_TILESIZE, xti++) {
|
|
|
|
if (GET_TILE_UPDATED (xti, yti)) {
|
|
|
|
vid_ptr = disp_ptr + (yc * pitch + xc);
|
|
|
|
tile_ptr = bx_gui->graphics_tile_get(xc, yc, &w, &h);
|
|
|
|
for (r=0; r<h; r++) {
|
|
|
|
vid_ptr2 = vid_ptr;
|
|
|
|
tile_ptr2 = tile_ptr;
|
|
|
|
for (c=0; c<w; c++) {
|
|
|
|
colour = 0;
|
|
|
|
for (i=0; i<(int)BX_VGA_THIS s.vbe_bpp; i+=8) {
|
|
|
|
colour |= *(vid_ptr2++) << i;
|
|
|
|
}
|
|
|
|
if (info.is_little_endian) {
|
|
|
|
for (i=0; i<info.bpp; i+=8) {
|
2005-06-04 21:44:59 +04:00
|
|
|
*(tile_ptr2++) = (Bit8u)(colour >> i);
|
2004-11-06 20:03:44 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
for (i=info.bpp-8; i>-8; i-=8) {
|
2005-06-04 21:44:59 +04:00
|
|
|
*(tile_ptr2++) = (Bit8u)(colour >> i);
|
2004-11-06 20:03:44 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
vid_ptr += pitch;
|
|
|
|
tile_ptr += info.pitch;
|
|
|
|
}
|
|
|
|
bx_gui->graphics_tile_update_in_place(xc, yc, w, h);
|
|
|
|
SET_TILE_UPDATED (xti, yti, 0);
|
|
|
|
}
|
|
|
|
}
|
2003-06-30 22:53:12 +04:00
|
|
|
}
|
2004-11-06 20:03:44 +03:00
|
|
|
break;
|
2003-06-30 22:53:12 +04:00
|
|
|
}
|
|
|
|
}
|
2004-11-06 20:03:44 +03:00
|
|
|
else {
|
|
|
|
switch (BX_VGA_THIS s.vbe_bpp) {
|
|
|
|
case 4:
|
|
|
|
BX_ERROR(("cannot draw 4bpp SVGA"));
|
|
|
|
break;
|
|
|
|
case 8:
|
|
|
|
for (yc=0, yti = 0; yc<iHeight; yc+=Y_TILESIZE, yti++) {
|
|
|
|
for (xc=0, xti = 0; xc<iWidth; xc+=X_TILESIZE, xti++) {
|
|
|
|
if (GET_TILE_UPDATED (xti, yti)) {
|
|
|
|
vid_ptr = disp_ptr + (yc * pitch + xc);
|
|
|
|
tile_ptr = bx_gui->graphics_tile_get(xc, yc, &w, &h);
|
|
|
|
for (r=0; r<h; r++) {
|
|
|
|
vid_ptr2 = vid_ptr;
|
|
|
|
tile_ptr2 = tile_ptr;
|
|
|
|
for (c=0; c<w; c++) {
|
|
|
|
colour = *(vid_ptr2++);
|
|
|
|
colour = MAKE_COLOUR(
|
2005-03-01 00:23:34 +03:00
|
|
|
BX_VGA_THIS s.pel.data[colour].red, dac_size, info.red_shift, info.red_mask,
|
|
|
|
BX_VGA_THIS s.pel.data[colour].green, dac_size, info.green_shift, info.green_mask,
|
|
|
|
BX_VGA_THIS s.pel.data[colour].blue, dac_size, info.blue_shift, info.blue_mask);
|
2004-11-06 20:03:44 +03:00
|
|
|
if (info.is_little_endian) {
|
|
|
|
for (i=0; i<info.bpp; i+=8) {
|
2005-06-04 21:44:59 +04:00
|
|
|
*(tile_ptr2++) = (Bit8u)(colour >> i);
|
2004-11-06 20:03:44 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
for (i=info.bpp-8; i>-8; i-=8) {
|
2005-06-04 21:44:59 +04:00
|
|
|
*(tile_ptr2++) = (Bit8u)(colour >> i);
|
2004-11-06 20:03:44 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
vid_ptr += pitch;
|
|
|
|
tile_ptr += info.pitch;
|
|
|
|
}
|
|
|
|
bx_gui->graphics_tile_update_in_place(xc, yc, w, h);
|
|
|
|
SET_TILE_UPDATED (xti, yti, 0);
|
|
|
|
}
|
|
|
|
}
|
2003-06-30 22:53:12 +04:00
|
|
|
}
|
2004-11-06 20:03:44 +03:00
|
|
|
break;
|
|
|
|
case 15:
|
|
|
|
for (yc=0, yti = 0; yc<iHeight; yc+=Y_TILESIZE, yti++) {
|
|
|
|
for (xc=0, xti = 0; xc<iWidth; xc+=X_TILESIZE, xti++) {
|
|
|
|
if (GET_TILE_UPDATED (xti, yti)) {
|
|
|
|
vid_ptr = disp_ptr + (yc * pitch + (xc<<1));
|
|
|
|
tile_ptr = bx_gui->graphics_tile_get(xc, yc, &w, &h);
|
|
|
|
for (r=0; r<h; r++) {
|
|
|
|
vid_ptr2 = vid_ptr;
|
|
|
|
tile_ptr2 = tile_ptr;
|
|
|
|
for (c=0; c<w; c++) {
|
|
|
|
colour = *(vid_ptr2++);
|
|
|
|
colour |= *(vid_ptr2++) << 8;
|
|
|
|
colour = MAKE_COLOUR(
|
|
|
|
colour & 0x001f, 5, info.blue_shift, info.blue_mask,
|
|
|
|
colour & 0x03e0, 10, info.green_shift, info.green_mask,
|
|
|
|
colour & 0x7c00, 15, info.red_shift, info.red_mask);
|
|
|
|
if (info.is_little_endian) {
|
|
|
|
for (i=0; i<info.bpp; i+=8) {
|
2005-06-04 21:44:59 +04:00
|
|
|
*(tile_ptr2++) = (Bit8u)(colour >> i);
|
2004-11-06 20:03:44 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
for (i=info.bpp-8; i>-8; i-=8) {
|
2005-06-04 21:44:59 +04:00
|
|
|
*(tile_ptr2++) = (Bit8u)(colour >> i);
|
2004-11-06 20:03:44 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
vid_ptr += pitch;
|
|
|
|
tile_ptr += info.pitch;
|
|
|
|
}
|
|
|
|
bx_gui->graphics_tile_update_in_place(xc, yc, w, h);
|
|
|
|
SET_TILE_UPDATED (xti, yti, 0);
|
|
|
|
}
|
|
|
|
}
|
2003-06-30 22:53:12 +04:00
|
|
|
}
|
2004-11-06 20:03:44 +03:00
|
|
|
break;
|
|
|
|
case 16:
|
|
|
|
for (yc=0, yti = 0; yc<iHeight; yc+=Y_TILESIZE, yti++) {
|
|
|
|
for (xc=0, xti = 0; xc<iWidth; xc+=X_TILESIZE, xti++) {
|
|
|
|
if (GET_TILE_UPDATED (xti, yti)) {
|
|
|
|
vid_ptr = disp_ptr + (yc * pitch + (xc<<1));
|
|
|
|
tile_ptr = bx_gui->graphics_tile_get(xc, yc, &w, &h);
|
|
|
|
for (r=0; r<h; r++) {
|
|
|
|
vid_ptr2 = vid_ptr;
|
|
|
|
tile_ptr2 = tile_ptr;
|
|
|
|
for (c=0; c<w; c++) {
|
|
|
|
colour = *(vid_ptr2++);
|
|
|
|
colour |= *(vid_ptr2++) << 8;
|
|
|
|
colour = MAKE_COLOUR(
|
|
|
|
colour & 0x001f, 5, info.blue_shift, info.blue_mask,
|
|
|
|
colour & 0x07e0, 11, info.green_shift, info.green_mask,
|
|
|
|
colour & 0xf800, 16, info.red_shift, info.red_mask);
|
|
|
|
if (info.is_little_endian) {
|
|
|
|
for (i=0; i<info.bpp; i+=8) {
|
2005-06-04 21:44:59 +04:00
|
|
|
*(tile_ptr2++) = (Bit8u)(colour >> i);
|
2004-11-06 20:03:44 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
for (i=info.bpp-8; i>-8; i-=8) {
|
2005-06-04 21:44:59 +04:00
|
|
|
*(tile_ptr2++) = (Bit8u)(colour >> i);
|
2004-11-06 20:03:44 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
vid_ptr += pitch;
|
|
|
|
tile_ptr += info.pitch;
|
|
|
|
}
|
|
|
|
bx_gui->graphics_tile_update_in_place(xc, yc, w, h);
|
|
|
|
SET_TILE_UPDATED (xti, yti, 0);
|
|
|
|
}
|
|
|
|
}
|
2002-03-10 07:51:24 +03:00
|
|
|
}
|
2004-11-06 20:03:44 +03:00
|
|
|
break;
|
|
|
|
case 24:
|
|
|
|
for (yc=0, yti = 0; yc<iHeight; yc+=Y_TILESIZE, yti++) {
|
|
|
|
for (xc=0, xti = 0; xc<iWidth; xc+=X_TILESIZE, xti++) {
|
|
|
|
if (GET_TILE_UPDATED (xti, yti)) {
|
|
|
|
vid_ptr = disp_ptr + (yc * pitch + 3*xc);
|
|
|
|
tile_ptr = bx_gui->graphics_tile_get(xc, yc, &w, &h);
|
|
|
|
for (r=0; r<h; r++) {
|
|
|
|
vid_ptr2 = vid_ptr;
|
|
|
|
tile_ptr2 = tile_ptr;
|
|
|
|
for (c=0; c<w; c++) {
|
|
|
|
blue = *(vid_ptr2++);
|
|
|
|
green = *(vid_ptr2++);
|
|
|
|
red = *(vid_ptr2++);
|
|
|
|
colour = MAKE_COLOUR(
|
|
|
|
red, 8, info.red_shift, info.red_mask,
|
|
|
|
green, 8, info.green_shift, info.green_mask,
|
|
|
|
blue, 8, info.blue_shift, info.blue_mask);
|
|
|
|
if (info.is_little_endian) {
|
|
|
|
for (i=0; i<info.bpp; i+=8) {
|
2005-06-04 21:44:59 +04:00
|
|
|
*(tile_ptr2++) = (Bit8u)(colour >> i);
|
2004-11-06 20:03:44 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
for (i=info.bpp-8; i>-8; i-=8) {
|
2005-06-04 21:44:59 +04:00
|
|
|
*(tile_ptr2++) = (Bit8u)(colour >> i);
|
2004-11-06 20:03:44 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
vid_ptr += pitch;
|
|
|
|
tile_ptr += info.pitch;
|
|
|
|
}
|
|
|
|
bx_gui->graphics_tile_update_in_place(xc, yc, w, h);
|
|
|
|
SET_TILE_UPDATED (xti, yti, 0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 32:
|
|
|
|
for (yc=0, yti = 0; yc<iHeight; yc+=Y_TILESIZE, yti++) {
|
|
|
|
for (xc=0, xti = 0; xc<iWidth; xc+=X_TILESIZE, xti++) {
|
|
|
|
if (GET_TILE_UPDATED (xti, yti)) {
|
|
|
|
vid_ptr = disp_ptr + (yc * pitch + (xc<<2));
|
|
|
|
tile_ptr = bx_gui->graphics_tile_get(xc, yc, &w, &h);
|
|
|
|
for (r=0; r<h; r++) {
|
|
|
|
vid_ptr2 = vid_ptr;
|
|
|
|
tile_ptr2 = tile_ptr;
|
|
|
|
for (c=0; c<w; c++) {
|
|
|
|
blue = *(vid_ptr2++);
|
|
|
|
green = *(vid_ptr2++);
|
|
|
|
red = *(vid_ptr2++);
|
|
|
|
vid_ptr2++;
|
|
|
|
colour = MAKE_COLOUR(
|
|
|
|
red, 8, info.red_shift, info.red_mask,
|
|
|
|
green, 8, info.green_shift, info.green_mask,
|
|
|
|
blue, 8, info.blue_shift, info.blue_mask);
|
|
|
|
if (info.is_little_endian) {
|
|
|
|
for (i=0; i<info.bpp; i+=8) {
|
2005-06-04 21:44:59 +04:00
|
|
|
*(tile_ptr2++) = (Bit8u)(colour >> i);
|
2004-11-06 20:03:44 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
for (i=info.bpp-8; i>-8; i-=8) {
|
2005-06-04 21:44:59 +04:00
|
|
|
*(tile_ptr2++) = (Bit8u)(colour >> i);
|
2004-11-06 20:03:44 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
vid_ptr += pitch;
|
|
|
|
tile_ptr += info.pitch;
|
|
|
|
}
|
|
|
|
bx_gui->graphics_tile_update_in_place(xc, yc, w, h);
|
|
|
|
SET_TILE_UPDATED (xti, yti, 0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
2002-03-10 07:51:24 +03:00
|
|
|
}
|
|
|
|
}
|
2004-11-06 20:03:44 +03:00
|
|
|
old_iWidth = iWidth;
|
|
|
|
old_iHeight = iHeight;
|
|
|
|
BX_VGA_THIS s.vga_mem_updated = 0;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
BX_PANIC(("cannot get svga tile info"));
|
2003-06-08 20:45:24 +04:00
|
|
|
}
|
2003-06-30 22:53:12 +04:00
|
|
|
|
2002-03-10 07:51:24 +03:00
|
|
|
// after a vbe display update, don't try to do any 'normal vga' updates anymore
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
#endif
|
2001-04-10 05:04:59 +04:00
|
|
|
// fields that effect the way video memory is serialized into screen output:
|
|
|
|
// GRAPHICS CONTROLLER:
|
|
|
|
// BX_VGA_THIS s.graphics_ctrl.shift_reg:
|
2003-04-20 21:04:45 +04:00
|
|
|
// 0: output data in standard VGA format or CGA-compatible 640x200 2 color
|
|
|
|
// graphics mode (mode 6)
|
2001-04-10 05:04:59 +04:00
|
|
|
// 1: output data in CGA-compatible 320x200 4 color graphics mode
|
|
|
|
// (modes 4 & 5)
|
|
|
|
// 2: output data 8 bits at a time from the 4 bit planes
|
|
|
|
// (mode 13 and variants like modeX)
|
|
|
|
|
|
|
|
// if (BX_VGA_THIS s.vga_mem_updated==0 || BX_VGA_THIS s.attribute_ctrl.video_enabled == 0)
|
|
|
|
|
|
|
|
if (BX_VGA_THIS s.graphics_ctrl.graphics_alpha) {
|
|
|
|
Bit8u color;
|
2003-04-21 23:03:46 +04:00
|
|
|
unsigned bit_no, r, c, x, y;
|
2003-06-08 20:45:24 +04:00
|
|
|
unsigned long byte_offset, start_addr;
|
|
|
|
unsigned xc, yc, xti, yti;
|
2001-04-10 05:04:59 +04:00
|
|
|
|
2003-06-08 20:45:24 +04:00
|
|
|
start_addr = (BX_VGA_THIS s.CRTC.reg[0x0c] << 8) | BX_VGA_THIS s.CRTC.reg[0x0d];
|
2001-04-10 05:04:59 +04:00
|
|
|
|
2001-05-30 22:56:02 +04:00
|
|
|
//BX_DEBUG(("update: shiftreg=%u, chain4=%u, mapping=%u",
|
2001-04-10 05:04:59 +04:00
|
|
|
// (unsigned) BX_VGA_THIS s.graphics_ctrl.shift_reg,
|
|
|
|
// (unsigned) BX_VGA_THIS s.sequencer.chain_four,
|
|
|
|
// (unsigned) BX_VGA_THIS s.graphics_ctrl.memory_mapping);
|
|
|
|
|
2004-01-24 23:50:45 +03:00
|
|
|
determine_screen_dimensions(&iHeight, &iWidth);
|
2005-10-27 13:32:02 +04:00
|
|
|
if((iWidth != old_iWidth) || (iHeight != old_iHeight) ||
|
|
|
|
(BX_VGA_THIS s.last_bpp > 8))
|
|
|
|
{
|
2004-01-24 23:50:45 +03:00
|
|
|
bx_gui->dimension_update(iWidth, iHeight);
|
|
|
|
old_iWidth = iWidth;
|
|
|
|
old_iHeight = iHeight;
|
2005-10-27 13:32:02 +04:00
|
|
|
BX_VGA_THIS s.last_bpp = 8;
|
2004-01-24 23:50:45 +03:00
|
|
|
}
|
|
|
|
|
2001-04-10 05:04:59 +04:00
|
|
|
switch ( BX_VGA_THIS s.graphics_ctrl.shift_reg ) {
|
|
|
|
|
2003-04-20 21:04:45 +04:00
|
|
|
case 0:
|
2001-04-10 05:04:59 +04:00
|
|
|
Bit8u attribute, palette_reg_val, DAC_regno;
|
2003-06-08 20:45:24 +04:00
|
|
|
unsigned long line_compare;
|
2004-07-22 00:39:54 +04:00
|
|
|
Bit8u *plane0, *plane1, *plane2, *plane3;
|
2001-04-10 05:04:59 +04:00
|
|
|
|
2003-04-20 21:04:45 +04:00
|
|
|
if (BX_VGA_THIS s.graphics_ctrl.memory_mapping == 3) { // CGA 640x200x2
|
2001-04-10 05:04:59 +04:00
|
|
|
|
2003-07-17 11:55:56 +04:00
|
|
|
for (yc=0, yti=0; yc<iHeight; yc+=Y_TILESIZE, yti++) {
|
|
|
|
for (xc=0, xti=0; xc<iWidth; xc+=X_TILESIZE, xti++) {
|
2003-04-20 21:04:45 +04:00
|
|
|
if (GET_TILE_UPDATED (xti, yti)) {
|
|
|
|
for (r=0; r<Y_TILESIZE; r++) {
|
2003-06-08 20:45:24 +04:00
|
|
|
y = yc + r;
|
2003-04-26 20:43:22 +04:00
|
|
|
if (BX_VGA_THIS s.y_doublescan) y >>= 1;
|
2003-04-20 21:04:45 +04:00
|
|
|
for (c=0; c<X_TILESIZE; c++) {
|
2003-04-26 20:43:22 +04:00
|
|
|
|
2003-06-08 20:45:24 +04:00
|
|
|
x = xc + c;
|
2003-04-20 21:04:45 +04:00
|
|
|
/* 0 or 0x2000 */
|
2003-06-08 20:45:24 +04:00
|
|
|
byte_offset = start_addr + ((y & 1) << 13);
|
2003-04-20 21:04:45 +04:00
|
|
|
/* to the start of the line */
|
2003-04-21 23:03:46 +04:00
|
|
|
byte_offset += (320 / 4) * (y / 2);
|
2003-04-20 21:04:45 +04:00
|
|
|
/* to the byte start */
|
2003-04-21 23:03:46 +04:00
|
|
|
byte_offset += (x / 8);
|
2003-04-20 21:04:45 +04:00
|
|
|
|
2003-04-21 23:03:46 +04:00
|
|
|
bit_no = 7 - (x % 8);
|
|
|
|
palette_reg_val = (((BX_VGA_THIS s.vga_memory[byte_offset]) >> bit_no) & 1);
|
2003-04-20 21:04:45 +04:00
|
|
|
DAC_regno = BX_VGA_THIS s.attribute_ctrl.palette_reg[palette_reg_val];
|
|
|
|
BX_VGA_THIS s.tile[r*X_TILESIZE + c] = DAC_regno;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
SET_TILE_UPDATED (xti, yti, 0);
|
2003-06-08 20:45:24 +04:00
|
|
|
bx_gui->graphics_tile_update(BX_VGA_THIS s.tile, xc, yc);
|
2003-04-20 21:04:45 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2003-06-08 20:45:24 +04:00
|
|
|
} else { // output data in serial fashion with each display plane
|
|
|
|
// output on its associated serial output. Standard EGA/VGA format
|
2002-07-24 23:36:39 +04:00
|
|
|
|
2004-07-22 00:39:54 +04:00
|
|
|
#if BX_SUPPORT_VBE
|
|
|
|
if (BX_VGA_THIS s.vbe_enabled)
|
|
|
|
{
|
|
|
|
plane0 = &BX_VGA_THIS s.vbe_memory[0<<20];
|
|
|
|
plane1 = &BX_VGA_THIS s.vbe_memory[1<<20];
|
|
|
|
plane2 = &BX_VGA_THIS s.vbe_memory[2<<20];
|
|
|
|
plane3 = &BX_VGA_THIS s.vbe_memory[3<<20];
|
|
|
|
start_addr = BX_VGA_THIS s.vbe_virtual_start;
|
|
|
|
line_compare = 0xffff;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
#endif
|
|
|
|
{
|
|
|
|
plane0 = &BX_VGA_THIS s.vga_memory[0<<16];
|
|
|
|
plane1 = &BX_VGA_THIS s.vga_memory[1<<16];
|
|
|
|
plane2 = &BX_VGA_THIS s.vga_memory[2<<16];
|
|
|
|
plane3 = &BX_VGA_THIS s.vga_memory[3<<16];
|
|
|
|
line_compare = BX_VGA_THIS s.line_compare;
|
|
|
|
if (BX_VGA_THIS s.y_doublescan) line_compare >>= 1;
|
|
|
|
}
|
2003-04-20 21:04:45 +04:00
|
|
|
|
2003-07-17 11:55:56 +04:00
|
|
|
for (yc=0, yti=0; yc<iHeight; yc+=Y_TILESIZE, yti++) {
|
|
|
|
for (xc=0, xti=0; xc<iWidth; xc+=X_TILESIZE, xti++) {
|
2003-04-20 21:04:45 +04:00
|
|
|
if (GET_TILE_UPDATED (xti, yti)) {
|
|
|
|
for (r=0; r<Y_TILESIZE; r++) {
|
2003-06-08 20:45:24 +04:00
|
|
|
y = yc + r;
|
2003-04-26 20:43:22 +04:00
|
|
|
if (BX_VGA_THIS s.y_doublescan) y >>= 1;
|
2003-04-20 21:04:45 +04:00
|
|
|
for (c=0; c<X_TILESIZE; c++) {
|
2003-06-08 20:45:24 +04:00
|
|
|
x = xc + c;
|
2003-05-03 20:09:39 +04:00
|
|
|
if (BX_VGA_THIS s.x_dotclockdiv2) x >>= 1;
|
|
|
|
bit_no = 7 - (x % 8);
|
2003-05-02 11:32:06 +04:00
|
|
|
if (y > line_compare) {
|
2003-10-04 19:58:21 +04:00
|
|
|
byte_offset = x / 8 +
|
2003-05-02 11:32:06 +04:00
|
|
|
((y - line_compare - 1) * BX_VGA_THIS s.line_offset);
|
|
|
|
} else {
|
2003-05-03 20:09:39 +04:00
|
|
|
byte_offset = start_addr + x / 8 +
|
2003-05-02 11:32:06 +04:00
|
|
|
(y * BX_VGA_THIS s.line_offset);
|
|
|
|
}
|
2003-04-20 21:04:45 +04:00
|
|
|
attribute =
|
2004-07-22 00:39:54 +04:00
|
|
|
(((plane0[byte_offset] >> bit_no) & 0x01) << 0) |
|
|
|
|
(((plane1[byte_offset] >> bit_no) & 0x01) << 1) |
|
|
|
|
(((plane2[byte_offset] >> bit_no) & 0x01) << 2) |
|
|
|
|
(((plane3[byte_offset] >> bit_no) & 0x01) << 3);
|
2003-04-20 21:04:45 +04:00
|
|
|
|
|
|
|
attribute &= BX_VGA_THIS s.attribute_ctrl.color_plane_enable;
|
2003-07-20 01:44:37 +04:00
|
|
|
// undocumented feature ???: colors 0..7 high intensity, colors 8..15 blinking
|
|
|
|
// using low/high intensity. Blinking is not implemented yet.
|
|
|
|
if (BX_VGA_THIS s.attribute_ctrl.mode_ctrl.blink_intensity) attribute ^= 0x08;
|
2003-04-20 21:04:45 +04:00
|
|
|
palette_reg_val = BX_VGA_THIS s.attribute_ctrl.palette_reg[attribute];
|
|
|
|
if (BX_VGA_THIS s.attribute_ctrl.mode_ctrl.internal_palette_size) {
|
|
|
|
// use 4 lower bits from palette register
|
|
|
|
// use 4 higher bits from color select register
|
|
|
|
// 16 banks of 16-color registers
|
|
|
|
DAC_regno = (palette_reg_val & 0x0f) |
|
|
|
|
(BX_VGA_THIS s.attribute_ctrl.color_select << 4);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
// use 6 lower bits from palette register
|
|
|
|
// use 2 higher bits from color select register
|
|
|
|
// 4 banks of 64-color registers
|
|
|
|
DAC_regno = (palette_reg_val & 0x3f) |
|
|
|
|
((BX_VGA_THIS s.attribute_ctrl.color_select & 0x0c) << 4);
|
|
|
|
}
|
|
|
|
// DAC_regno &= video DAC mask register ???
|
|
|
|
|
|
|
|
BX_VGA_THIS s.tile[r*X_TILESIZE + c] = DAC_regno;
|
|
|
|
}
|
2001-04-10 05:04:59 +04:00
|
|
|
}
|
2003-04-20 21:04:45 +04:00
|
|
|
SET_TILE_UPDATED (xti, yti, 0);
|
2003-06-08 20:45:24 +04:00
|
|
|
bx_gui->graphics_tile_update(BX_VGA_THIS s.tile, xc, yc);
|
2001-04-10 05:04:59 +04:00
|
|
|
}
|
|
|
|
}
|
2003-06-08 20:45:24 +04:00
|
|
|
}
|
2003-04-20 21:04:45 +04:00
|
|
|
}
|
2001-04-10 05:04:59 +04:00
|
|
|
break; // case 0
|
|
|
|
|
|
|
|
case 1: // output the data in a CGA-compatible 320x200 4 color graphics
|
|
|
|
// mode. (modes 4 & 5)
|
2002-01-24 23:30:45 +03:00
|
|
|
|
|
|
|
/* CGA 320x200x4 start */
|
|
|
|
|
2003-07-17 11:55:56 +04:00
|
|
|
for (yc=0, yti=0; yc<iHeight; yc+=Y_TILESIZE, yti++) {
|
|
|
|
for (xc=0, xti=0; xc<iWidth; xc+=X_TILESIZE, xti++) {
|
2002-11-16 18:43:13 +03:00
|
|
|
if (GET_TILE_UPDATED (xti, yti)) {
|
2002-01-24 23:30:45 +03:00
|
|
|
for (r=0; r<Y_TILESIZE; r++) {
|
2003-06-08 20:45:24 +04:00
|
|
|
y = yc + r;
|
2003-05-03 20:09:39 +04:00
|
|
|
if (BX_VGA_THIS s.y_doublescan) y >>= 1;
|
2002-01-24 23:30:45 +03:00
|
|
|
for (c=0; c<X_TILESIZE; c++) {
|
|
|
|
|
2003-06-08 20:45:24 +04:00
|
|
|
x = xc + c;
|
2003-05-03 20:09:39 +04:00
|
|
|
if (BX_VGA_THIS s.x_dotclockdiv2) x >>= 1;
|
2002-01-24 23:30:45 +03:00
|
|
|
/* 0 or 0x2000 */
|
2003-06-08 20:45:24 +04:00
|
|
|
byte_offset = start_addr + ((y & 1) << 13);
|
2002-01-24 23:30:45 +03:00
|
|
|
/* to the start of the line */
|
2003-04-26 20:43:22 +04:00
|
|
|
byte_offset += (320 / 4) * (y / 2);
|
2002-01-24 23:30:45 +03:00
|
|
|
/* to the byte start */
|
2003-04-26 20:43:22 +04:00
|
|
|
byte_offset += (x / 4);
|
2002-01-24 23:30:45 +03:00
|
|
|
|
2003-04-26 20:43:22 +04:00
|
|
|
attribute = 6 - 2*(x % 4);
|
2002-01-24 23:30:45 +03:00
|
|
|
palette_reg_val = (BX_VGA_THIS s.vga_memory[byte_offset]) >> attribute;
|
|
|
|
palette_reg_val &= 3;
|
|
|
|
DAC_regno = BX_VGA_THIS s.attribute_ctrl.palette_reg[palette_reg_val];
|
|
|
|
BX_VGA_THIS s.tile[r*X_TILESIZE + c] = DAC_regno;
|
|
|
|
}
|
|
|
|
}
|
2002-11-16 18:43:13 +03:00
|
|
|
SET_TILE_UPDATED (xti, yti, 0);
|
2003-06-08 20:45:24 +04:00
|
|
|
bx_gui->graphics_tile_update(BX_VGA_THIS s.tile, xc, yc);
|
2002-01-24 23:30:45 +03:00
|
|
|
}
|
|
|
|
}
|
2003-06-08 20:45:24 +04:00
|
|
|
}
|
2002-01-24 23:30:45 +03:00
|
|
|
/* CGA 320x200x4 end */
|
|
|
|
|
2001-04-10 05:04:59 +04:00
|
|
|
break; // case 1
|
|
|
|
|
2002-10-05 12:04:28 +04:00
|
|
|
case 2: // output the data eight bits at a time from the 4 bit plane
|
2001-04-10 05:04:59 +04:00
|
|
|
// (format for VGA mode 13 hex)
|
2005-03-27 12:02:54 +04:00
|
|
|
case 3: // FIXME: is this really the same ???
|
2001-04-10 05:04:59 +04:00
|
|
|
|
|
|
|
if ( BX_VGA_THIS s.sequencer.chain_four ) {
|
|
|
|
unsigned long pixely, pixelx, plane;
|
|
|
|
|
|
|
|
if (BX_VGA_THIS s.misc_output.select_high_bank != 1)
|
2001-05-30 22:56:02 +04:00
|
|
|
BX_PANIC(("update: select_high_bank != 1"));
|
2001-04-10 05:04:59 +04:00
|
|
|
|
2003-07-17 11:55:56 +04:00
|
|
|
for (yc=0, yti=0; yc<iHeight; yc+=Y_TILESIZE, yti++) {
|
|
|
|
for (xc=0, xti=0; xc<iWidth; xc+=X_TILESIZE, xti++) {
|
2002-11-16 18:43:13 +03:00
|
|
|
if (GET_TILE_UPDATED (xti, yti)) {
|
2001-04-10 05:04:59 +04:00
|
|
|
for (r=0; r<Y_TILESIZE; r++) {
|
2003-06-08 20:45:24 +04:00
|
|
|
pixely = yc + r;
|
2003-04-26 20:43:22 +04:00
|
|
|
if (BX_VGA_THIS s.y_doublescan) pixely >>= 1;
|
2001-04-10 05:04:59 +04:00
|
|
|
for (c=0; c<X_TILESIZE; c++) {
|
2003-06-08 20:45:24 +04:00
|
|
|
pixelx = (xc + c) >> 1;
|
2001-04-10 05:04:59 +04:00
|
|
|
plane = (pixelx % 4);
|
2003-04-25 22:51:55 +04:00
|
|
|
byte_offset = start_addr + (plane * 65536) +
|
2003-04-28 22:15:31 +04:00
|
|
|
(pixely * BX_VGA_THIS s.line_offset) + (pixelx & ~0x03);
|
2001-04-10 05:04:59 +04:00
|
|
|
color = BX_VGA_THIS s.vga_memory[byte_offset];
|
|
|
|
BX_VGA_THIS s.tile[r*X_TILESIZE + c] = color;
|
|
|
|
}
|
|
|
|
}
|
2002-11-16 18:43:13 +03:00
|
|
|
SET_TILE_UPDATED (xti, yti, 0);
|
2003-06-08 20:45:24 +04:00
|
|
|
bx_gui->graphics_tile_update(BX_VGA_THIS s.tile, xc, yc);
|
2001-04-10 05:04:59 +04:00
|
|
|
}
|
|
|
|
}
|
2003-06-08 20:45:24 +04:00
|
|
|
}
|
2001-04-10 05:04:59 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
else { // chain_four == 0, modeX
|
2003-06-08 20:45:24 +04:00
|
|
|
unsigned long pixely, pixelx, plane;
|
2001-04-10 05:04:59 +04:00
|
|
|
|
2003-07-17 11:55:56 +04:00
|
|
|
for (yc=0, yti=0; yc<iHeight; yc+=Y_TILESIZE, yti++) {
|
|
|
|
for (xc=0, xti=0; xc<iWidth; xc+=X_TILESIZE, xti++) {
|
2003-04-26 20:43:22 +04:00
|
|
|
if (GET_TILE_UPDATED (xti, yti)) {
|
|
|
|
for (r=0; r<Y_TILESIZE; r++) {
|
2003-06-08 20:45:24 +04:00
|
|
|
pixely = yc + r;
|
2003-04-26 20:43:22 +04:00
|
|
|
if (BX_VGA_THIS s.y_doublescan) pixely >>= 1;
|
|
|
|
for (c=0; c<X_TILESIZE; c++) {
|
2003-06-08 20:45:24 +04:00
|
|
|
pixelx = (xc + c) >> 1;
|
2003-04-26 20:43:22 +04:00
|
|
|
plane = (pixelx % 4);
|
|
|
|
byte_offset = (plane * 65536) +
|
2003-04-28 22:15:31 +04:00
|
|
|
(pixely * BX_VGA_THIS s.line_offset)
|
2003-04-26 20:43:22 +04:00
|
|
|
+ (pixelx >> 2);
|
|
|
|
color = BX_VGA_THIS s.vga_memory[start_addr + byte_offset];
|
|
|
|
BX_VGA_THIS s.tile[r*X_TILESIZE + c] = color;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
SET_TILE_UPDATED (xti, yti, 0);
|
2003-06-08 20:45:24 +04:00
|
|
|
bx_gui->graphics_tile_update(BX_VGA_THIS s.tile, xc, yc);
|
2003-04-26 20:43:22 +04:00
|
|
|
}
|
2002-11-16 18:43:13 +03:00
|
|
|
}
|
|
|
|
}
|
2001-04-10 05:04:59 +04:00
|
|
|
}
|
|
|
|
break; // case 2
|
|
|
|
|
|
|
|
default:
|
2001-05-30 22:56:02 +04:00
|
|
|
BX_PANIC(("update: shift_reg == %u", (unsigned)
|
merge in BRANCH-io-cleanup.
To see the commit logs for this use either cvsweb or
cvs update -r BRANCH-io-cleanup and then 'cvs log' the various files.
In general this provides a generic interface for logging.
logfunctions:: is a class that is inherited by some classes, and also
. allocated as a standalone global called 'genlog'. All logging uses
. one of the ::info(), ::error(), ::ldebug(), ::panic() methods of this
. class through 'BX_INFO(), BX_ERROR(), BX_DEBUG(), BX_PANIC()' macros
. respectively.
.
. An example usage:
. BX_INFO(("Hello, World!\n"));
iofunctions:: is a class that is allocated once by default, and assigned
as the iofunction of each logfunctions instance. It is this class that
maintains the file descriptor and other output related code, at this
point using vfprintf(). At some future point, someone may choose to
write a gui 'console' for bochs to which messages would be redirected
simply by assigning a different iofunction class to the various logfunctions
objects.
More cleanup is coming, but this works for now. If you want to see alot
of debugging output, in main.cc, change onoff[LOGLEV_DEBUG]=0 to =1.
Comments, bugs, flames, to me: todd@fries.net
2001-05-15 18:49:57 +04:00
|
|
|
BX_VGA_THIS s.graphics_ctrl.shift_reg ));
|
2001-04-10 05:04:59 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
BX_VGA_THIS s.vga_mem_updated = 0;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
else { // text mode
|
|
|
|
unsigned long start_address;
|
|
|
|
unsigned long cursor_address, cursor_x, cursor_y;
|
2003-05-07 23:15:47 +04:00
|
|
|
bx_vga_tminfo_t tm_info;
|
2005-03-18 17:52:29 +03:00
|
|
|
unsigned VDE, MSL, cols, rows, cWidth;
|
2001-04-10 05:04:59 +04:00
|
|
|
|
2004-04-09 19:04:54 +04:00
|
|
|
tm_info.start_address = 2*((BX_VGA_THIS s.CRTC.reg[12] << 8) +
|
|
|
|
BX_VGA_THIS s.CRTC.reg[13]);
|
2003-05-07 23:15:47 +04:00
|
|
|
tm_info.cs_start = BX_VGA_THIS s.CRTC.reg[0x0a] & 0x3f;
|
|
|
|
tm_info.cs_end = BX_VGA_THIS s.CRTC.reg[0x0b] & 0x1f;
|
|
|
|
tm_info.line_offset = BX_VGA_THIS s.CRTC.reg[0x13] << 2;
|
|
|
|
tm_info.line_compare = BX_VGA_THIS s.line_compare;
|
|
|
|
tm_info.h_panning = BX_VGA_THIS s.attribute_ctrl.horiz_pel_panning & 0x0f;
|
|
|
|
tm_info.v_panning = BX_VGA_THIS s.CRTC.reg[0x08] & 0x1f;
|
2003-05-11 19:07:54 +04:00
|
|
|
tm_info.line_graphics = BX_VGA_THIS s.attribute_ctrl.mode_ctrl.enable_line_graphics;
|
2004-04-09 19:04:54 +04:00
|
|
|
tm_info.split_hpanning = BX_VGA_THIS s.attribute_ctrl.mode_ctrl.pixel_panning_compat;
|
2003-05-11 19:07:54 +04:00
|
|
|
if ((BX_VGA_THIS s.sequencer.reg1 & 0x01) == 0) {
|
2005-05-01 01:22:26 +04:00
|
|
|
if (tm_info.h_panning >= 8)
|
2003-05-10 16:00:58 +04:00
|
|
|
tm_info.h_panning = 0;
|
|
|
|
else
|
|
|
|
tm_info.h_panning++;
|
2005-05-01 01:22:26 +04:00
|
|
|
} else {
|
|
|
|
tm_info.h_panning &= 0x07;
|
2003-05-10 16:00:58 +04:00
|
|
|
}
|
2003-05-07 23:15:47 +04:00
|
|
|
|
2005-03-18 17:52:29 +03:00
|
|
|
// Verticle Display End: find out how many lines are displayed
|
|
|
|
VDE = BX_VGA_THIS s.vertical_display_end;
|
|
|
|
// Maximum Scan Line: height of character cell
|
|
|
|
MSL = BX_VGA_THIS s.CRTC.reg[0x09] & 0x1f;
|
|
|
|
if (MSL == 0) {
|
|
|
|
BX_ERROR(("character height = 1, skipping text update"));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
cols = BX_VGA_THIS s.CRTC.reg[1] + 1;
|
|
|
|
if ((MSL == 1) && (VDE == 399)) {
|
|
|
|
// emulated CGA graphics mode 160x100x16 colors
|
|
|
|
MSL = 3;
|
|
|
|
}
|
|
|
|
rows = (VDE+1)/(MSL+1);
|
|
|
|
if (rows > BX_MAX_TEXT_LINES) {
|
|
|
|
BX_PANIC(("text rows>%d: %d",BX_MAX_TEXT_LINES,rows));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
cWidth = ((BX_VGA_THIS s.sequencer.reg1 & 0x01) == 1) ? 8 : 9;
|
|
|
|
iWidth = cWidth * cols;
|
|
|
|
iHeight = VDE+1;
|
2005-10-27 13:32:02 +04:00
|
|
|
if ((iWidth != old_iWidth) || (iHeight != old_iHeight) || (MSL != old_MSL) ||
|
|
|
|
(BX_VGA_THIS s.last_bpp > 8))
|
2005-03-18 17:52:29 +03:00
|
|
|
{
|
|
|
|
bx_gui->dimension_update(iWidth, iHeight, MSL+1, cWidth);
|
|
|
|
old_iWidth = iWidth;
|
|
|
|
old_iHeight = iHeight;
|
|
|
|
old_MSL = MSL;
|
2005-10-27 13:32:02 +04:00
|
|
|
BX_VGA_THIS s.last_bpp = 8;
|
2005-03-18 17:52:29 +03:00
|
|
|
}
|
|
|
|
// pass old text snapshot & new VGA memory contents
|
|
|
|
start_address = 2*((BX_VGA_THIS s.CRTC.reg[12] << 8) +
|
|
|
|
BX_VGA_THIS s.CRTC.reg[13]);
|
|
|
|
cursor_address = 2*((BX_VGA_THIS s.CRTC.reg[0x0e] << 8) +
|
|
|
|
BX_VGA_THIS s.CRTC.reg[0x0f]);
|
|
|
|
if (cursor_address < start_address) {
|
|
|
|
cursor_x = 0xffff;
|
|
|
|
cursor_y = 0xffff;
|
|
|
|
} else {
|
|
|
|
cursor_x = ((cursor_address - start_address)/2) % (iWidth/cWidth);
|
|
|
|
cursor_y = ((cursor_address - start_address)/2) / (iWidth/cWidth);
|
2001-04-10 05:04:59 +04:00
|
|
|
}
|
2005-03-27 12:02:54 +04:00
|
|
|
bx_gui->text_update(BX_VGA_THIS s.text_snapshot,
|
2005-03-18 17:52:29 +03:00
|
|
|
&BX_VGA_THIS s.vga_memory[start_address],
|
|
|
|
cursor_x, cursor_y, tm_info, rows);
|
|
|
|
// screen updated, copy new VGA memory contents into text snapshot
|
2005-03-27 12:02:54 +04:00
|
|
|
memcpy(BX_VGA_THIS s.text_snapshot,
|
2005-03-18 17:52:29 +03:00
|
|
|
&BX_VGA_THIS s.vga_memory[start_address],
|
|
|
|
2*cols*rows);
|
|
|
|
BX_VGA_THIS s.vga_mem_updated = 0;
|
|
|
|
}
|
2001-04-10 05:04:59 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-07-18 23:40:51 +04:00
|
|
|
bx_bool
|
|
|
|
bx_vga_c::mem_read_handler(unsigned long addr, unsigned long len,
|
2004-07-24 22:12:00 +04:00
|
|
|
void *data, void *param)
|
2004-07-18 23:40:51 +04:00
|
|
|
{
|
|
|
|
Bit8u *data_ptr;
|
|
|
|
|
|
|
|
#ifdef BX_LITTLE_ENDIAN
|
|
|
|
data_ptr = (Bit8u *) data;
|
|
|
|
#else // BX_BIG_ENDIAN
|
|
|
|
data_ptr = (Bit8u *) data + (len - 1);
|
|
|
|
#endif
|
|
|
|
for (unsigned i = 0; i < len; i++) {
|
|
|
|
*data_ptr = theVga->mem_read(addr);
|
|
|
|
addr++;
|
|
|
|
#ifdef BX_LITTLE_ENDIAN
|
|
|
|
data_ptr++;
|
|
|
|
#else // BX_BIG_ENDIAN
|
|
|
|
data_ptr--;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2001-04-10 05:04:59 +04:00
|
|
|
Bit8u
|
|
|
|
bx_vga_c::mem_read(Bit32u addr)
|
|
|
|
{
|
|
|
|
Bit32u offset;
|
2004-07-22 00:39:54 +04:00
|
|
|
Bit8u *plane0, *plane1, *plane2, *plane3;
|
2001-04-10 05:04:59 +04:00
|
|
|
|
2002-03-10 07:51:24 +03:00
|
|
|
#if BX_SUPPORT_VBE
|
|
|
|
// if in a vbe enabled mode, read from the vbe_memory
|
2003-02-09 11:25:22 +03:00
|
|
|
if ((BX_VGA_THIS s.vbe_enabled) && (BX_VGA_THIS s.vbe_bpp != VBE_DISPI_BPP_4))
|
2002-03-10 07:51:24 +03:00
|
|
|
{
|
|
|
|
return vbe_mem_read(addr);
|
|
|
|
}
|
2004-08-23 22:47:25 +04:00
|
|
|
else if (addr >= VBE_DISPI_LFB_PHYSICAL_ADDRESS)
|
|
|
|
{
|
|
|
|
return 0xff;
|
|
|
|
}
|
2002-03-10 07:51:24 +03:00
|
|
|
#endif
|
2001-04-10 05:04:59 +04:00
|
|
|
|
|
|
|
#if defined(VGA_TRACE_FEATURE)
|
2001-05-30 22:56:02 +04:00
|
|
|
// BX_DEBUG(("8-bit memory read from %08x", addr));
|
2001-04-10 05:04:59 +04:00
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef __OS2__
|
2002-10-25 01:07:56 +04:00
|
|
|
|
|
|
|
#if BX_PLUGINS
|
|
|
|
#error Fix the code for plugins
|
|
|
|
#endif
|
|
|
|
|
2001-04-10 05:04:59 +04:00
|
|
|
if ( bx_options.videomode == BX_VIDEO_DIRECT )
|
|
|
|
{
|
|
|
|
char value;
|
|
|
|
|
2001-05-23 11:48:11 +04:00
|
|
|
value = devices->mem->video[addr-0xA0000];
|
2001-04-10 05:04:59 +04:00
|
|
|
|
|
|
|
return value;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2003-04-27 13:13:47 +04:00
|
|
|
switch (BX_VGA_THIS s.graphics_ctrl.memory_mapping) {
|
|
|
|
case 1: // 0xA0000 .. 0xAFFFF
|
|
|
|
if (addr > 0xAFFFF) return 0xff;
|
|
|
|
offset = addr - 0xA0000;
|
|
|
|
break;
|
|
|
|
case 2: // 0xB0000 .. 0xB7FFF
|
|
|
|
if ((addr < 0xB0000) || (addr > 0xB7FFF)) return 0xff;
|
|
|
|
return BX_VGA_THIS s.vga_memory[addr - 0xB0000];
|
|
|
|
break;
|
|
|
|
case 3: // 0xB8000 .. 0xBFFFF
|
|
|
|
if (addr < 0xB8000) return 0xff;
|
|
|
|
return BX_VGA_THIS s.vga_memory[addr - 0xB8000];
|
|
|
|
break;
|
|
|
|
default: // 0xA0000 .. 0xBFFFF
|
|
|
|
return BX_VGA_THIS s.vga_memory[addr - 0xA0000];
|
|
|
|
}
|
2001-04-10 05:04:59 +04:00
|
|
|
|
2003-04-27 13:13:47 +04:00
|
|
|
// addr between 0xA0000 and 0xAFFFF
|
|
|
|
if ( BX_VGA_THIS s.sequencer.chain_four ) {
|
2001-04-10 05:04:59 +04:00
|
|
|
|
2003-04-27 13:13:47 +04:00
|
|
|
// Mode 13h: 320 x 200 256 color mode: chained pixel representation
|
|
|
|
return BX_VGA_THIS s.vga_memory[(offset & ~0x03) + (offset % 4)*65536];
|
2001-12-13 21:34:30 +03:00
|
|
|
}
|
2001-04-10 05:04:59 +04:00
|
|
|
|
2004-07-22 00:39:54 +04:00
|
|
|
#if BX_SUPPORT_VBE
|
|
|
|
if (BX_VGA_THIS s.vbe_enabled)
|
|
|
|
{
|
|
|
|
plane0 = &BX_VGA_THIS s.vbe_memory[(0<<20) + (BX_VGA_THIS s.vbe_bank<<16)];
|
|
|
|
plane1 = &BX_VGA_THIS s.vbe_memory[(1<<20) + (BX_VGA_THIS s.vbe_bank<<16)];
|
|
|
|
plane2 = &BX_VGA_THIS s.vbe_memory[(2<<20) + (BX_VGA_THIS s.vbe_bank<<16)];
|
|
|
|
plane3 = &BX_VGA_THIS s.vbe_memory[(3<<20) + (BX_VGA_THIS s.vbe_bank<<16)];
|
|
|
|
}
|
|
|
|
else
|
|
|
|
#endif
|
|
|
|
{
|
|
|
|
plane0 = &BX_VGA_THIS s.vga_memory[0<<16];
|
|
|
|
plane1 = &BX_VGA_THIS s.vga_memory[1<<16];
|
|
|
|
plane2 = &BX_VGA_THIS s.vga_memory[2<<16];
|
|
|
|
plane3 = &BX_VGA_THIS s.vga_memory[3<<16];
|
|
|
|
}
|
|
|
|
|
2001-12-13 21:34:30 +03:00
|
|
|
/* addr between 0xA0000 and 0xAFFFF */
|
|
|
|
switch (BX_VGA_THIS s.graphics_ctrl.read_mode) {
|
|
|
|
case 0: /* read mode 0 */
|
2004-07-22 00:39:54 +04:00
|
|
|
BX_VGA_THIS s.graphics_ctrl.latch[0] = plane0[offset];
|
|
|
|
BX_VGA_THIS s.graphics_ctrl.latch[1] = plane1[offset];
|
|
|
|
BX_VGA_THIS s.graphics_ctrl.latch[2] = plane2[offset];
|
|
|
|
BX_VGA_THIS s.graphics_ctrl.latch[3] = plane3[offset];
|
2001-12-13 21:34:30 +03:00
|
|
|
return(BX_VGA_THIS s.graphics_ctrl.latch[BX_VGA_THIS s.graphics_ctrl.read_map_select]);
|
|
|
|
break;
|
2001-04-10 05:04:59 +04:00
|
|
|
|
2001-12-13 21:34:30 +03:00
|
|
|
case 1: /* read mode 1 */
|
|
|
|
{
|
|
|
|
Bit8u color_compare, color_dont_care;
|
2003-04-27 13:13:47 +04:00
|
|
|
Bit8u latch0, latch1, latch2, latch3, retval;
|
2001-12-13 21:34:30 +03:00
|
|
|
|
|
|
|
color_compare = BX_VGA_THIS s.graphics_ctrl.color_compare & 0x0f;
|
|
|
|
color_dont_care = BX_VGA_THIS s.graphics_ctrl.color_dont_care & 0x0f;
|
2004-07-22 00:39:54 +04:00
|
|
|
latch0 = BX_VGA_THIS s.graphics_ctrl.latch[0] = plane0[offset];
|
|
|
|
latch1 = BX_VGA_THIS s.graphics_ctrl.latch[1] = plane1[offset];
|
|
|
|
latch2 = BX_VGA_THIS s.graphics_ctrl.latch[2] = plane2[offset];
|
|
|
|
latch3 = BX_VGA_THIS s.graphics_ctrl.latch[3] = plane3[offset];
|
2003-04-27 13:13:47 +04:00
|
|
|
|
|
|
|
latch0 ^= ccdat[color_compare][0];
|
|
|
|
latch1 ^= ccdat[color_compare][1];
|
|
|
|
latch2 ^= ccdat[color_compare][2];
|
|
|
|
latch3 ^= ccdat[color_compare][3];
|
|
|
|
|
|
|
|
latch0 &= ccdat[color_dont_care][0];
|
|
|
|
latch1 &= ccdat[color_dont_care][1];
|
|
|
|
latch2 &= ccdat[color_dont_care][2];
|
|
|
|
latch3 &= ccdat[color_dont_care][3];
|
|
|
|
|
|
|
|
retval = ~(latch0 | latch1 | latch2 | latch3);
|
|
|
|
|
|
|
|
return retval;
|
2001-04-10 05:04:59 +04:00
|
|
|
}
|
2001-12-13 21:34:30 +03:00
|
|
|
break;
|
|
|
|
default:
|
2003-04-27 13:13:47 +04:00
|
|
|
return 0;
|
2001-04-10 05:04:59 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2004-07-18 23:40:51 +04:00
|
|
|
bx_bool
|
|
|
|
bx_vga_c::mem_write_handler(unsigned long addr, unsigned long len,
|
2004-07-24 22:12:00 +04:00
|
|
|
void *data, void *param)
|
2004-07-18 23:40:51 +04:00
|
|
|
{
|
|
|
|
Bit8u *data_ptr;
|
|
|
|
|
|
|
|
#ifdef BX_LITTLE_ENDIAN
|
|
|
|
data_ptr = (Bit8u *) data;
|
|
|
|
#else // BX_BIG_ENDIAN
|
|
|
|
data_ptr = (Bit8u *) data + (len - 1);
|
|
|
|
#endif
|
|
|
|
for (unsigned i = 0; i < len; i++) {
|
|
|
|
theVga->mem_write(addr, *data_ptr);
|
|
|
|
addr++;
|
|
|
|
#ifdef BX_LITTLE_ENDIAN
|
|
|
|
data_ptr++;
|
|
|
|
#else // BX_BIG_ENDIAN
|
|
|
|
data_ptr--;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2001-04-10 05:04:59 +04:00
|
|
|
void
|
|
|
|
bx_vga_c::mem_write(Bit32u addr, Bit8u value)
|
|
|
|
{
|
|
|
|
Bit32u offset;
|
2003-05-01 16:07:27 +04:00
|
|
|
Bit8u new_val[4];
|
2003-06-08 20:45:24 +04:00
|
|
|
unsigned start_addr;
|
2004-07-22 00:39:54 +04:00
|
|
|
Bit8u *plane0, *plane1, *plane2, *plane3;
|
2001-04-10 05:04:59 +04:00
|
|
|
|
2002-03-10 07:51:24 +03:00
|
|
|
#if BX_SUPPORT_VBE
|
|
|
|
// if in a vbe enabled mode, write to the vbe_memory
|
2003-02-09 11:25:22 +03:00
|
|
|
if ((BX_VGA_THIS s.vbe_enabled) && (BX_VGA_THIS s.vbe_bpp != VBE_DISPI_BPP_4))
|
2002-03-10 07:51:24 +03:00
|
|
|
{
|
|
|
|
vbe_mem_write(addr,value);
|
|
|
|
return;
|
|
|
|
}
|
2004-08-23 22:47:25 +04:00
|
|
|
else if (addr >= VBE_DISPI_LFB_PHYSICAL_ADDRESS)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
2002-03-10 07:51:24 +03:00
|
|
|
#endif
|
|
|
|
|
2001-04-10 05:04:59 +04:00
|
|
|
#if defined(VGA_TRACE_FEATURE)
|
2001-05-30 22:56:02 +04:00
|
|
|
// BX_DEBUG(("8-bit memory write to %08x = %02x", addr, value));
|
2001-04-10 05:04:59 +04:00
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef __OS2__
|
2002-10-25 01:07:56 +04:00
|
|
|
|
|
|
|
#if BX_PLUGINS
|
|
|
|
#error Fix the code for plugins
|
|
|
|
#endif
|
|
|
|
|
2001-04-10 05:04:59 +04:00
|
|
|
if ( bx_options.videomode == BX_VIDEO_DIRECT )
|
|
|
|
{
|
2001-05-23 11:48:11 +04:00
|
|
|
devices->mem->video[addr-0xA0000] = value;
|
2001-04-10 05:04:59 +04:00
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2003-04-27 13:13:47 +04:00
|
|
|
switch (BX_VGA_THIS s.graphics_ctrl.memory_mapping) {
|
|
|
|
case 1: // 0xA0000 .. 0xAFFFF
|
|
|
|
if (addr > 0xAFFFF) return;
|
|
|
|
offset = addr - 0xA0000;
|
|
|
|
break;
|
|
|
|
case 2: // 0xB0000 .. 0xB7FFF
|
|
|
|
if ((addr < 0xB0000) || (addr > 0xB7FFF)) return;
|
|
|
|
offset = addr - 0xB0000;
|
|
|
|
break;
|
|
|
|
case 3: // 0xB8000 .. 0xBFFFF
|
|
|
|
if (addr < 0xB8000) return;
|
|
|
|
offset = addr - 0xB8000;
|
|
|
|
break;
|
|
|
|
default: // 0xA0000 .. 0xBFFFF
|
|
|
|
offset = addr - 0xA0000;
|
|
|
|
}
|
2001-04-10 05:04:59 +04:00
|
|
|
|
2003-06-08 20:45:24 +04:00
|
|
|
start_addr = (BX_VGA_THIS s.CRTC.reg[0x0c] << 8) | BX_VGA_THIS s.CRTC.reg[0x0d];
|
|
|
|
|
2001-04-10 05:04:59 +04:00
|
|
|
if (BX_VGA_THIS s.graphics_ctrl.graphics_alpha) {
|
2003-04-27 13:13:47 +04:00
|
|
|
if (BX_VGA_THIS s.graphics_ctrl.memory_mapping == 3) { // 0xB8000 .. 0xBFFFF
|
2003-05-02 11:32:06 +04:00
|
|
|
unsigned x_tileno, x_tileno2, y_tileno;
|
2001-04-10 05:04:59 +04:00
|
|
|
|
2003-04-27 13:13:47 +04:00
|
|
|
/* CGA 320x200x4 / 640x200x2 start */
|
2003-04-21 23:03:46 +04:00
|
|
|
BX_VGA_THIS s.vga_memory[offset] = value;
|
2003-06-08 20:45:24 +04:00
|
|
|
offset -= start_addr;
|
2003-05-02 11:32:06 +04:00
|
|
|
if (offset>=0x2000) {
|
2002-01-24 23:30:45 +03:00
|
|
|
y_tileno = offset - 0x2000;
|
|
|
|
y_tileno /= (320/4);
|
|
|
|
y_tileno <<= 1; //2 * y_tileno;
|
|
|
|
y_tileno++;
|
|
|
|
x_tileno = (offset - 0x2000) % (320/4);
|
|
|
|
x_tileno <<= 2; //*= 4;
|
|
|
|
} else {
|
|
|
|
y_tileno = offset / (320/4);
|
2003-04-21 23:03:46 +04:00
|
|
|
y_tileno <<= 1; //2 * y_tileno;
|
2002-01-24 23:30:45 +03:00
|
|
|
x_tileno = offset % (320/4);
|
|
|
|
x_tileno <<= 2; //*=4;
|
|
|
|
}
|
2003-04-21 23:03:46 +04:00
|
|
|
x_tileno2=x_tileno;
|
2003-05-03 20:09:39 +04:00
|
|
|
if (BX_VGA_THIS s.graphics_ctrl.shift_reg==0) {
|
|
|
|
x_tileno*=2;
|
2003-04-21 23:03:46 +04:00
|
|
|
x_tileno2+=7;
|
2003-05-03 20:09:39 +04:00
|
|
|
} else {
|
|
|
|
x_tileno2+=3;
|
|
|
|
}
|
|
|
|
if (BX_VGA_THIS s.x_dotclockdiv2) {
|
2003-04-21 23:03:46 +04:00
|
|
|
x_tileno/=(X_TILESIZE/2);
|
|
|
|
x_tileno2/=(X_TILESIZE/2);
|
|
|
|
} else {
|
|
|
|
x_tileno/=X_TILESIZE;
|
|
|
|
x_tileno2/=X_TILESIZE;
|
2003-05-03 20:09:39 +04:00
|
|
|
}
|
|
|
|
if (BX_VGA_THIS s.y_doublescan) {
|
|
|
|
y_tileno/=(Y_TILESIZE/2);
|
|
|
|
} else {
|
2003-04-21 23:03:46 +04:00
|
|
|
y_tileno/=Y_TILESIZE;
|
|
|
|
}
|
2002-01-24 23:30:45 +03:00
|
|
|
BX_VGA_THIS s.vga_mem_updated = 1;
|
2002-11-16 18:43:13 +03:00
|
|
|
SET_TILE_UPDATED (x_tileno, y_tileno, 1);
|
2003-04-21 23:03:46 +04:00
|
|
|
if (x_tileno2!=x_tileno) {
|
|
|
|
SET_TILE_UPDATED (x_tileno2, y_tileno, 1);
|
|
|
|
}
|
|
|
|
return;
|
2003-04-27 13:13:47 +04:00
|
|
|
/* CGA 320x200x4 / 640x200x2 end */
|
2001-04-10 05:04:59 +04:00
|
|
|
}
|
2003-04-27 13:13:47 +04:00
|
|
|
else if (BX_VGA_THIS s.graphics_ctrl.memory_mapping != 1) {
|
|
|
|
|
|
|
|
BX_PANIC(("mem_write: graphics: mapping = %u",
|
merge in BRANCH-io-cleanup.
To see the commit logs for this use either cvsweb or
cvs update -r BRANCH-io-cleanup and then 'cvs log' the various files.
In general this provides a generic interface for logging.
logfunctions:: is a class that is inherited by some classes, and also
. allocated as a standalone global called 'genlog'. All logging uses
. one of the ::info(), ::error(), ::ldebug(), ::panic() methods of this
. class through 'BX_INFO(), BX_ERROR(), BX_DEBUG(), BX_PANIC()' macros
. respectively.
.
. An example usage:
. BX_INFO(("Hello, World!\n"));
iofunctions:: is a class that is allocated once by default, and assigned
as the iofunction of each logfunctions instance. It is this class that
maintains the file descriptor and other output related code, at this
point using vfprintf(). At some future point, someone may choose to
write a gui 'console' for bochs to which messages would be redirected
simply by assigning a different iofunction class to the various logfunctions
objects.
More cleanup is coming, but this works for now. If you want to see alot
of debugging output, in main.cc, change onoff[LOGLEV_DEBUG]=0 to =1.
Comments, bugs, flames, to me: todd@fries.net
2001-05-15 18:49:57 +04:00
|
|
|
(unsigned) BX_VGA_THIS s.graphics_ctrl.memory_mapping));
|
2001-04-10 05:04:59 +04:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( BX_VGA_THIS s.sequencer.chain_four ) {
|
|
|
|
unsigned x_tileno, y_tileno;
|
|
|
|
|
|
|
|
// 320 x 200 256 color mode: chained pixel representation
|
2003-04-27 13:13:47 +04:00
|
|
|
BX_VGA_THIS s.vga_memory[(offset & ~0x03) + (offset % 4)*65536] = value;
|
2004-08-16 12:07:23 +04:00
|
|
|
if (BX_VGA_THIS s.line_offset > 0) {
|
|
|
|
offset -= start_addr;
|
|
|
|
x_tileno = (offset % BX_VGA_THIS s.line_offset) / (X_TILESIZE/2);
|
|
|
|
if (BX_VGA_THIS s.y_doublescan) {
|
|
|
|
y_tileno = (offset / BX_VGA_THIS s.line_offset) / (Y_TILESIZE/2);
|
|
|
|
} else {
|
|
|
|
y_tileno = (offset / BX_VGA_THIS s.line_offset) / Y_TILESIZE;
|
|
|
|
}
|
|
|
|
BX_VGA_THIS s.vga_mem_updated = 1;
|
|
|
|
SET_TILE_UPDATED (x_tileno, y_tileno, 1);
|
2003-04-25 22:51:55 +04:00
|
|
|
}
|
2001-04-10 05:04:59 +04:00
|
|
|
return;
|
2001-12-13 21:34:30 +03:00
|
|
|
}
|
2004-08-16 12:07:23 +04:00
|
|
|
}
|
2001-04-10 05:04:59 +04:00
|
|
|
|
2001-12-13 21:34:30 +03:00
|
|
|
/* addr between 0xA0000 and 0xAFFFF */
|
2004-07-22 00:39:54 +04:00
|
|
|
|
|
|
|
#if BX_SUPPORT_VBE
|
|
|
|
if (BX_VGA_THIS s.vbe_enabled)
|
|
|
|
{
|
|
|
|
plane0 = &BX_VGA_THIS s.vbe_memory[(0<<20) + (BX_VGA_THIS s.vbe_bank<<16)];
|
|
|
|
plane1 = &BX_VGA_THIS s.vbe_memory[(1<<20) + (BX_VGA_THIS s.vbe_bank<<16)];
|
|
|
|
plane2 = &BX_VGA_THIS s.vbe_memory[(2<<20) + (BX_VGA_THIS s.vbe_bank<<16)];
|
|
|
|
plane3 = &BX_VGA_THIS s.vbe_memory[(3<<20) + (BX_VGA_THIS s.vbe_bank<<16)];
|
|
|
|
}
|
|
|
|
else
|
|
|
|
#endif
|
|
|
|
{
|
|
|
|
plane0 = &BX_VGA_THIS s.vga_memory[0<<16];
|
|
|
|
plane1 = &BX_VGA_THIS s.vga_memory[1<<16];
|
|
|
|
plane2 = &BX_VGA_THIS s.vga_memory[2<<16];
|
|
|
|
plane3 = &BX_VGA_THIS s.vga_memory[3<<16];
|
|
|
|
}
|
|
|
|
|
2001-12-13 21:34:30 +03:00
|
|
|
switch (BX_VGA_THIS s.graphics_ctrl.write_mode) {
|
2003-05-01 16:07:27 +04:00
|
|
|
unsigned i;
|
2001-12-13 21:34:30 +03:00
|
|
|
|
|
|
|
case 0: /* write mode 0 */
|
2003-05-01 16:07:27 +04:00
|
|
|
{
|
|
|
|
const Bit8u bitmask = BX_VGA_THIS s.graphics_ctrl.bitmask;
|
|
|
|
const Bit8u set_reset = BX_VGA_THIS s.graphics_ctrl.set_reset;
|
|
|
|
const Bit8u enable_set_reset = BX_VGA_THIS s.graphics_ctrl.enable_set_reset;
|
|
|
|
/* perform rotate on CPU data in case its needed */
|
2003-05-06 21:10:13 +04:00
|
|
|
if (BX_VGA_THIS s.graphics_ctrl.data_rotate) {
|
|
|
|
value = (value >> BX_VGA_THIS s.graphics_ctrl.data_rotate) |
|
|
|
|
(value << (8 - BX_VGA_THIS s.graphics_ctrl.data_rotate));
|
|
|
|
}
|
2003-05-01 16:07:27 +04:00
|
|
|
new_val[0] = BX_VGA_THIS s.graphics_ctrl.latch[0] & ~bitmask;
|
|
|
|
new_val[1] = BX_VGA_THIS s.graphics_ctrl.latch[1] & ~bitmask;
|
|
|
|
new_val[2] = BX_VGA_THIS s.graphics_ctrl.latch[2] & ~bitmask;
|
|
|
|
new_val[3] = BX_VGA_THIS s.graphics_ctrl.latch[3] & ~bitmask;
|
|
|
|
switch (BX_VGA_THIS s.graphics_ctrl.raster_op) {
|
|
|
|
case 0: // replace
|
|
|
|
new_val[0] |= ((enable_set_reset & 1)
|
|
|
|
? ((set_reset & 1) ? bitmask : 0)
|
|
|
|
: (value & bitmask));
|
|
|
|
new_val[1] |= ((enable_set_reset & 2)
|
|
|
|
? ((set_reset & 2) ? bitmask : 0)
|
|
|
|
: (value & bitmask));
|
|
|
|
new_val[2] |= ((enable_set_reset & 4)
|
|
|
|
? ((set_reset & 4) ? bitmask : 0)
|
|
|
|
: (value & bitmask));
|
|
|
|
new_val[3] |= ((enable_set_reset & 8)
|
|
|
|
? ((set_reset & 8) ? bitmask : 0)
|
|
|
|
: (value & bitmask));
|
|
|
|
break;
|
|
|
|
case 1: // AND
|
|
|
|
new_val[0] |= ((enable_set_reset & 1)
|
|
|
|
? ((set_reset & 1)
|
|
|
|
? (BX_VGA_THIS s.graphics_ctrl.latch[0] & bitmask)
|
|
|
|
: 0)
|
|
|
|
: (value & BX_VGA_THIS s.graphics_ctrl.latch[0]) & bitmask);
|
|
|
|
new_val[1] |= ((enable_set_reset & 2)
|
|
|
|
? ((set_reset & 2)
|
|
|
|
? (BX_VGA_THIS s.graphics_ctrl.latch[1] & bitmask)
|
|
|
|
: 0)
|
|
|
|
: (value & BX_VGA_THIS s.graphics_ctrl.latch[1]) & bitmask);
|
|
|
|
new_val[2] |= ((enable_set_reset & 4)
|
|
|
|
? ((set_reset & 4)
|
|
|
|
? (BX_VGA_THIS s.graphics_ctrl.latch[2] & bitmask)
|
|
|
|
: 0)
|
|
|
|
: (value & BX_VGA_THIS s.graphics_ctrl.latch[2]) & bitmask);
|
|
|
|
new_val[3] |= ((enable_set_reset & 8)
|
|
|
|
? ((set_reset & 8)
|
|
|
|
? (BX_VGA_THIS s.graphics_ctrl.latch[3] & bitmask)
|
|
|
|
: 0)
|
|
|
|
: (value & BX_VGA_THIS s.graphics_ctrl.latch[3]) & bitmask);
|
|
|
|
break;
|
|
|
|
case 2: // OR
|
|
|
|
new_val[0]
|
|
|
|
|= ((enable_set_reset & 1)
|
|
|
|
? ((set_reset & 1)
|
|
|
|
? bitmask
|
|
|
|
: (BX_VGA_THIS s.graphics_ctrl.latch[0] & bitmask))
|
|
|
|
: ((value | BX_VGA_THIS s.graphics_ctrl.latch[0]) & bitmask));
|
|
|
|
new_val[1]
|
|
|
|
|= ((enable_set_reset & 2)
|
|
|
|
? ((set_reset & 2)
|
|
|
|
? bitmask
|
|
|
|
: (BX_VGA_THIS s.graphics_ctrl.latch[1] & bitmask))
|
|
|
|
: ((value | BX_VGA_THIS s.graphics_ctrl.latch[1]) & bitmask));
|
|
|
|
new_val[2]
|
|
|
|
|= ((enable_set_reset & 4)
|
|
|
|
? ((set_reset & 4)
|
|
|
|
? bitmask
|
|
|
|
: (BX_VGA_THIS s.graphics_ctrl.latch[2] & bitmask))
|
|
|
|
: ((value | BX_VGA_THIS s.graphics_ctrl.latch[2]) & bitmask));
|
|
|
|
new_val[3]
|
|
|
|
|= ((enable_set_reset & 8)
|
|
|
|
? ((set_reset & 8)
|
|
|
|
? bitmask
|
|
|
|
: (BX_VGA_THIS s.graphics_ctrl.latch[3] & bitmask))
|
|
|
|
: ((value | BX_VGA_THIS s.graphics_ctrl.latch[3]) & bitmask));
|
|
|
|
break;
|
|
|
|
case 3: // XOR
|
|
|
|
new_val[0]
|
|
|
|
|= ((enable_set_reset & 1)
|
|
|
|
? ((set_reset & 1)
|
|
|
|
? (~BX_VGA_THIS s.graphics_ctrl.latch[0] & bitmask)
|
|
|
|
: (BX_VGA_THIS s.graphics_ctrl.latch[0] & bitmask))
|
|
|
|
: (value ^ BX_VGA_THIS s.graphics_ctrl.latch[0]) & bitmask);
|
|
|
|
new_val[1]
|
|
|
|
|= ((enable_set_reset & 2)
|
|
|
|
? ((set_reset & 2)
|
|
|
|
? (~BX_VGA_THIS s.graphics_ctrl.latch[1] & bitmask)
|
|
|
|
: (BX_VGA_THIS s.graphics_ctrl.latch[1] & bitmask))
|
|
|
|
: (value ^ BX_VGA_THIS s.graphics_ctrl.latch[1]) & bitmask);
|
|
|
|
new_val[2]
|
|
|
|
|= ((enable_set_reset & 4)
|
|
|
|
? ((set_reset & 4)
|
|
|
|
? (~BX_VGA_THIS s.graphics_ctrl.latch[2] & bitmask)
|
|
|
|
: (BX_VGA_THIS s.graphics_ctrl.latch[2] & bitmask))
|
|
|
|
: (value ^ BX_VGA_THIS s.graphics_ctrl.latch[2]) & bitmask);
|
|
|
|
new_val[3]
|
|
|
|
|= ((enable_set_reset & 8)
|
|
|
|
? ((set_reset & 8)
|
|
|
|
? (~BX_VGA_THIS s.graphics_ctrl.latch[3] & bitmask)
|
|
|
|
: (BX_VGA_THIS s.graphics_ctrl.latch[3] & bitmask))
|
|
|
|
: (value ^ BX_VGA_THIS s.graphics_ctrl.latch[3]) & bitmask);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
BX_PANIC(("vga_mem_write: write mode 0: op = %u",
|
|
|
|
(unsigned) BX_VGA_THIS s.graphics_ctrl.raster_op));
|
2001-12-13 21:34:30 +03:00
|
|
|
}
|
2003-05-01 16:07:27 +04:00
|
|
|
}
|
2001-12-13 21:34:30 +03:00
|
|
|
break;
|
|
|
|
|
|
|
|
case 1: /* write mode 1 */
|
|
|
|
for (i=0; i<4; i++ ) {
|
|
|
|
new_val[i] = BX_VGA_THIS s.graphics_ctrl.latch[i];
|
|
|
|
}
|
|
|
|
break;
|
2001-04-10 05:04:59 +04:00
|
|
|
|
2001-12-13 21:34:30 +03:00
|
|
|
case 2: /* write mode 2 */
|
2003-05-01 16:07:27 +04:00
|
|
|
{
|
|
|
|
const Bit8u bitmask = BX_VGA_THIS s.graphics_ctrl.bitmask;
|
|
|
|
|
|
|
|
new_val[0] = BX_VGA_THIS s.graphics_ctrl.latch[0] & ~bitmask;
|
|
|
|
new_val[1] = BX_VGA_THIS s.graphics_ctrl.latch[1] & ~bitmask;
|
|
|
|
new_val[2] = BX_VGA_THIS s.graphics_ctrl.latch[2] & ~bitmask;
|
|
|
|
new_val[3] = BX_VGA_THIS s.graphics_ctrl.latch[3] & ~bitmask;
|
|
|
|
switch (BX_VGA_THIS s.graphics_ctrl.raster_op) {
|
|
|
|
case 0: // write
|
|
|
|
new_val[0] |= (value & 1) ? bitmask : 0;
|
|
|
|
new_val[1] |= (value & 2) ? bitmask : 0;
|
|
|
|
new_val[2] |= (value & 4) ? bitmask : 0;
|
|
|
|
new_val[3] |= (value & 8) ? bitmask : 0;
|
|
|
|
break;
|
|
|
|
case 1: // AND
|
|
|
|
new_val[0] |= (value & 1)
|
|
|
|
? (BX_VGA_THIS s.graphics_ctrl.latch[0] & bitmask)
|
|
|
|
: 0;
|
|
|
|
new_val[1] |= (value & 2)
|
|
|
|
? (BX_VGA_THIS s.graphics_ctrl.latch[1] & bitmask)
|
|
|
|
: 0;
|
|
|
|
new_val[2] |= (value & 4)
|
|
|
|
? (BX_VGA_THIS s.graphics_ctrl.latch[2] & bitmask)
|
|
|
|
: 0;
|
|
|
|
new_val[3] |= (value & 8)
|
|
|
|
? (BX_VGA_THIS s.graphics_ctrl.latch[3] & bitmask)
|
|
|
|
: 0;
|
|
|
|
break;
|
|
|
|
case 2: // OR
|
|
|
|
new_val[0] |= (value & 1)
|
|
|
|
? bitmask
|
|
|
|
: (BX_VGA_THIS s.graphics_ctrl.latch[0] & bitmask);
|
|
|
|
new_val[1] |= (value & 2)
|
|
|
|
? bitmask
|
|
|
|
: (BX_VGA_THIS s.graphics_ctrl.latch[1] & bitmask);
|
|
|
|
new_val[2] |= (value & 4)
|
|
|
|
? bitmask
|
|
|
|
: (BX_VGA_THIS s.graphics_ctrl.latch[2] & bitmask);
|
|
|
|
new_val[3] |= (value & 8)
|
|
|
|
? bitmask
|
|
|
|
: (BX_VGA_THIS s.graphics_ctrl.latch[3] & bitmask);
|
|
|
|
break;
|
|
|
|
case 3: // XOR
|
|
|
|
new_val[0] |= (value & 1)
|
|
|
|
? (~BX_VGA_THIS s.graphics_ctrl.latch[0] & bitmask)
|
|
|
|
: (BX_VGA_THIS s.graphics_ctrl.latch[0] & bitmask);
|
|
|
|
new_val[1] |= (value & 2)
|
|
|
|
? (~BX_VGA_THIS s.graphics_ctrl.latch[1] & bitmask)
|
|
|
|
: (BX_VGA_THIS s.graphics_ctrl.latch[1] & bitmask);
|
|
|
|
new_val[2] |= (value & 4)
|
|
|
|
? (~BX_VGA_THIS s.graphics_ctrl.latch[2] & bitmask)
|
|
|
|
: (BX_VGA_THIS s.graphics_ctrl.latch[2] & bitmask);
|
|
|
|
new_val[3] |= (value & 8)
|
|
|
|
? (~BX_VGA_THIS s.graphics_ctrl.latch[3] & bitmask)
|
|
|
|
: (BX_VGA_THIS s.graphics_ctrl.latch[3] & bitmask);
|
|
|
|
break;
|
2001-12-13 21:34:30 +03:00
|
|
|
}
|
2003-05-01 16:07:27 +04:00
|
|
|
}
|
2001-12-13 21:34:30 +03:00
|
|
|
break;
|
|
|
|
|
|
|
|
case 3: /* write mode 3 */
|
2003-05-01 16:07:27 +04:00
|
|
|
{
|
|
|
|
const Bit8u bitmask = BX_VGA_THIS s.graphics_ctrl.bitmask & value;
|
|
|
|
const Bit8u set_reset = BX_VGA_THIS s.graphics_ctrl.set_reset;
|
|
|
|
|
|
|
|
/* perform rotate on CPU data */
|
2003-05-06 21:10:13 +04:00
|
|
|
if (BX_VGA_THIS s.graphics_ctrl.data_rotate) {
|
|
|
|
value = (value >> BX_VGA_THIS s.graphics_ctrl.data_rotate) |
|
|
|
|
(value << (8 - BX_VGA_THIS s.graphics_ctrl.data_rotate));
|
|
|
|
}
|
2003-05-01 16:07:27 +04:00
|
|
|
new_val[0] = BX_VGA_THIS s.graphics_ctrl.latch[0] & ~bitmask;
|
|
|
|
new_val[1] = BX_VGA_THIS s.graphics_ctrl.latch[1] & ~bitmask;
|
|
|
|
new_val[2] = BX_VGA_THIS s.graphics_ctrl.latch[2] & ~bitmask;
|
|
|
|
new_val[3] = BX_VGA_THIS s.graphics_ctrl.latch[3] & ~bitmask;
|
|
|
|
|
|
|
|
value &= bitmask;
|
|
|
|
|
|
|
|
switch (BX_VGA_THIS s.graphics_ctrl.raster_op) {
|
|
|
|
case 0: // write
|
|
|
|
new_val[0] |= (set_reset & 1) ? value : 0;
|
|
|
|
new_val[1] |= (set_reset & 2) ? value : 0;
|
|
|
|
new_val[2] |= (set_reset & 4) ? value : 0;
|
|
|
|
new_val[3] |= (set_reset & 8) ? value : 0;
|
|
|
|
break;
|
|
|
|
case 1: // AND
|
|
|
|
new_val[0] |= ((set_reset & 1) ? value : 0)
|
|
|
|
& BX_VGA_THIS s.graphics_ctrl.latch[0];
|
|
|
|
new_val[1] |= ((set_reset & 2) ? value : 0)
|
|
|
|
& BX_VGA_THIS s.graphics_ctrl.latch[1];
|
|
|
|
new_val[2] |= ((set_reset & 4) ? value : 0)
|
|
|
|
& BX_VGA_THIS s.graphics_ctrl.latch[2];
|
|
|
|
new_val[3] |= ((set_reset & 8) ? value : 0)
|
|
|
|
& BX_VGA_THIS s.graphics_ctrl.latch[3];
|
|
|
|
break;
|
|
|
|
case 2: // OR
|
|
|
|
new_val[0] |= ((set_reset & 1) ? value : 0)
|
|
|
|
| BX_VGA_THIS s.graphics_ctrl.latch[0];
|
|
|
|
new_val[1] |= ((set_reset & 2) ? value : 0)
|
|
|
|
| BX_VGA_THIS s.graphics_ctrl.latch[1];
|
|
|
|
new_val[2] |= ((set_reset & 4) ? value : 0)
|
|
|
|
| BX_VGA_THIS s.graphics_ctrl.latch[2];
|
|
|
|
new_val[3] |= ((set_reset & 8) ? value : 0)
|
|
|
|
| BX_VGA_THIS s.graphics_ctrl.latch[3];
|
|
|
|
break;
|
|
|
|
case 3: // XOR
|
|
|
|
new_val[0] |= ((set_reset & 1) ? value : 0)
|
|
|
|
^ BX_VGA_THIS s.graphics_ctrl.latch[0];
|
|
|
|
new_val[1] |= ((set_reset & 2) ? value : 0)
|
|
|
|
^ BX_VGA_THIS s.graphics_ctrl.latch[1];
|
|
|
|
new_val[2] |= ((set_reset & 4) ? value : 0)
|
|
|
|
^ BX_VGA_THIS s.graphics_ctrl.latch[2];
|
|
|
|
new_val[3] |= ((set_reset & 8) ? value : 0)
|
|
|
|
^ BX_VGA_THIS s.graphics_ctrl.latch[3];
|
|
|
|
break;
|
2001-12-13 21:34:30 +03:00
|
|
|
}
|
2003-05-01 16:07:27 +04:00
|
|
|
}
|
2001-12-13 21:34:30 +03:00
|
|
|
break;
|
2001-04-10 05:04:59 +04:00
|
|
|
|
2001-12-13 21:34:30 +03:00
|
|
|
default:
|
|
|
|
BX_PANIC(("vga_mem_write: write mode %u ?",
|
|
|
|
(unsigned) BX_VGA_THIS s.graphics_ctrl.write_mode));
|
2003-05-01 16:07:27 +04:00
|
|
|
}
|
2001-12-13 21:34:30 +03:00
|
|
|
|
|
|
|
if (BX_VGA_THIS s.sequencer.map_mask & 0x0f) {
|
2001-04-10 05:04:59 +04:00
|
|
|
BX_VGA_THIS s.vga_mem_updated = 1;
|
2001-12-13 21:34:30 +03:00
|
|
|
if (BX_VGA_THIS s.sequencer.map_mask_bit[0])
|
2004-07-22 00:39:54 +04:00
|
|
|
plane0[offset] = new_val[0];
|
2001-12-13 21:34:30 +03:00
|
|
|
if (BX_VGA_THIS s.sequencer.map_mask_bit[1])
|
2004-07-22 00:39:54 +04:00
|
|
|
plane1[offset] = new_val[1];
|
2002-09-19 22:59:50 +04:00
|
|
|
if (BX_VGA_THIS s.sequencer.map_mask_bit[2]) {
|
2005-02-01 22:16:39 +03:00
|
|
|
if ((offset & 0xe000) == BX_VGA_THIS s.charmap_address) {
|
2002-10-25 01:07:56 +04:00
|
|
|
bx_gui->set_text_charbyte((offset & 0x1fff), new_val[2]);
|
2002-09-19 22:59:50 +04:00
|
|
|
}
|
2005-02-01 22:16:39 +03:00
|
|
|
plane2[offset] = new_val[2];
|
|
|
|
}
|
2001-12-13 21:34:30 +03:00
|
|
|
if (BX_VGA_THIS s.sequencer.map_mask_bit[3])
|
2004-07-22 00:39:54 +04:00
|
|
|
plane3[offset] = new_val[3];
|
2001-12-13 21:34:30 +03:00
|
|
|
|
2003-06-08 20:45:24 +04:00
|
|
|
unsigned x_tileno, y_tileno;
|
2001-12-13 21:34:30 +03:00
|
|
|
|
2003-04-26 20:43:22 +04:00
|
|
|
if (BX_VGA_THIS s.graphics_ctrl.shift_reg == 2) {
|
2003-05-02 11:32:06 +04:00
|
|
|
offset -= start_addr;
|
2003-04-28 22:15:31 +04:00
|
|
|
x_tileno = (offset % BX_VGA_THIS s.line_offset) * 4 / (X_TILESIZE / 2);
|
2003-04-26 20:43:22 +04:00
|
|
|
if (BX_VGA_THIS s.y_doublescan) {
|
2003-04-28 22:15:31 +04:00
|
|
|
y_tileno = (offset / BX_VGA_THIS s.line_offset) / (Y_TILESIZE / 2);
|
2003-04-26 20:43:22 +04:00
|
|
|
} else {
|
2003-04-28 22:15:31 +04:00
|
|
|
y_tileno = (offset / BX_VGA_THIS s.line_offset) / Y_TILESIZE;
|
2003-04-26 20:43:22 +04:00
|
|
|
}
|
2003-05-02 11:32:06 +04:00
|
|
|
SET_TILE_UPDATED (x_tileno, y_tileno, 1);
|
2003-04-21 23:03:46 +04:00
|
|
|
} else {
|
2003-05-02 11:32:06 +04:00
|
|
|
if (BX_VGA_THIS s.line_compare < BX_VGA_THIS s.vertical_display_end) {
|
2006-01-07 15:10:59 +03:00
|
|
|
if (BX_VGA_THIS s.line_offset > 0) {
|
|
|
|
if (BX_VGA_THIS s.x_dotclockdiv2) {
|
|
|
|
x_tileno = (offset % BX_VGA_THIS s.line_offset) / (X_TILESIZE / 16);
|
|
|
|
} else {
|
|
|
|
x_tileno = (offset % BX_VGA_THIS s.line_offset) / (X_TILESIZE / 8);
|
|
|
|
}
|
|
|
|
if (BX_VGA_THIS s.y_doublescan) {
|
|
|
|
y_tileno = ((offset / BX_VGA_THIS s.line_offset) * 2 + BX_VGA_THIS s.line_compare + 1) / Y_TILESIZE;
|
|
|
|
} else {
|
|
|
|
y_tileno = ((offset / BX_VGA_THIS s.line_offset) + BX_VGA_THIS s.line_compare + 1) / Y_TILESIZE;
|
|
|
|
}
|
|
|
|
SET_TILE_UPDATED (x_tileno, y_tileno, 1);
|
2003-05-02 11:32:06 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
if (offset >= start_addr) {
|
|
|
|
offset -= start_addr;
|
2006-01-07 15:10:59 +03:00
|
|
|
if (BX_VGA_THIS s.line_offset > 0) {
|
|
|
|
if (BX_VGA_THIS s.x_dotclockdiv2) {
|
|
|
|
x_tileno = (offset % BX_VGA_THIS s.line_offset) / (X_TILESIZE / 16);
|
|
|
|
} else {
|
|
|
|
x_tileno = (offset % BX_VGA_THIS s.line_offset) / (X_TILESIZE / 8);
|
|
|
|
}
|
|
|
|
if (BX_VGA_THIS s.y_doublescan) {
|
|
|
|
y_tileno = (offset / BX_VGA_THIS s.line_offset) / (Y_TILESIZE / 2);
|
|
|
|
} else {
|
|
|
|
y_tileno = (offset / BX_VGA_THIS s.line_offset) / Y_TILESIZE;
|
|
|
|
}
|
|
|
|
SET_TILE_UPDATED (x_tileno, y_tileno, 1);
|
2003-05-02 11:32:06 +04:00
|
|
|
}
|
2003-04-26 20:43:22 +04:00
|
|
|
}
|
2003-04-21 23:03:46 +04:00
|
|
|
}
|
2003-04-26 20:43:22 +04:00
|
|
|
}
|
2001-04-10 05:04:59 +04:00
|
|
|
}
|
|
|
|
|
2002-02-04 23:31:35 +03:00
|
|
|
void
|
|
|
|
bx_vga_c::get_text_snapshot(Bit8u **text_snapshot, unsigned *txHeight,
|
|
|
|
unsigned *txWidth)
|
|
|
|
{
|
|
|
|
unsigned VDE, MSL;
|
|
|
|
|
|
|
|
if (!BX_VGA_THIS s.graphics_ctrl.graphics_alpha) {
|
|
|
|
*text_snapshot = &BX_VGA_THIS s.text_snapshot[0];
|
2003-05-02 11:32:06 +04:00
|
|
|
VDE = BX_VGA_THIS s.vertical_display_end;
|
2002-10-25 01:07:56 +04:00
|
|
|
MSL = BX_VGA_THIS s.CRTC.reg[0x09] & 0x1f;
|
2002-02-04 23:31:35 +03:00
|
|
|
*txHeight = (VDE+1)/(MSL+1);
|
|
|
|
*txWidth = BX_VGA_THIS s.CRTC.reg[1] + 1;
|
|
|
|
} else {
|
|
|
|
*txHeight = 0;
|
|
|
|
*txWidth = 0;
|
|
|
|
}
|
|
|
|
}
|
2001-04-10 05:04:59 +04:00
|
|
|
|
2002-12-28 14:49:17 +03:00
|
|
|
Bit8u
|
|
|
|
bx_vga_c::get_actl_palette_idx(Bit8u index)
|
|
|
|
{
|
|
|
|
return BX_VGA_THIS s.attribute_ctrl.palette_reg[index];
|
|
|
|
}
|
|
|
|
|
2001-04-10 05:04:59 +04:00
|
|
|
void
|
|
|
|
bx_vga_c::dump_status(void)
|
|
|
|
{
|
2004-08-24 14:15:56 +04:00
|
|
|
#if BX_DEBUGGER
|
|
|
|
dbg_printf("s.misc_output.color_emulation = %u\n",
|
|
|
|
(unsigned) BX_VGA_THIS s.misc_output.color_emulation);
|
|
|
|
dbg_printf("s.misc_output.enable_ram = %u\n",
|
|
|
|
(unsigned) BX_VGA_THIS s.misc_output.enable_ram);
|
|
|
|
dbg_printf("s.misc_output.clock_select = %u ",
|
|
|
|
(unsigned) BX_VGA_THIS s.misc_output.clock_select);
|
2001-04-10 05:04:59 +04:00
|
|
|
if (BX_VGA_THIS s.misc_output.clock_select == 0)
|
2004-08-24 14:15:56 +04:00
|
|
|
dbg_printf("(25Mhz 640 horiz pixel clock)\n");
|
2001-04-10 05:04:59 +04:00
|
|
|
else
|
2004-08-24 14:15:56 +04:00
|
|
|
dbg_printf("(28Mhz 720 horiz pixel clock)\n");
|
|
|
|
dbg_printf("s.misc_output.select_high_bank = %u\n",
|
|
|
|
(unsigned) BX_VGA_THIS s.misc_output.select_high_bank);
|
|
|
|
dbg_printf("s.misc_output.horiz_sync_pol = %u\n",
|
|
|
|
(unsigned) BX_VGA_THIS s.misc_output.horiz_sync_pol);
|
|
|
|
dbg_printf("s.misc_output.vert_sync_pol = %u ",
|
|
|
|
(unsigned) BX_VGA_THIS s.misc_output.vert_sync_pol);
|
2001-04-10 05:04:59 +04:00
|
|
|
switch ( (BX_VGA_THIS s.misc_output.vert_sync_pol << 1) |
|
|
|
|
BX_VGA_THIS s.misc_output.horiz_sync_pol ) {
|
2004-08-24 14:15:56 +04:00
|
|
|
case 1: dbg_printf("(400 lines)\n"); break;
|
|
|
|
case 2: dbg_printf("(350 lines)\n"); break;
|
|
|
|
case 3: dbg_printf("(480 lines)\n"); break;
|
|
|
|
default: dbg_printf("(reserved)\n");
|
2001-04-10 05:04:59 +04:00
|
|
|
}
|
|
|
|
|
2004-08-24 14:15:56 +04:00
|
|
|
dbg_printf("s.graphics_ctrl.odd_even = %u\n",
|
|
|
|
(unsigned) BX_VGA_THIS s.graphics_ctrl.odd_even);
|
|
|
|
dbg_printf("s.graphics_ctrl.chain_odd_even = %u\n",
|
|
|
|
(unsigned) BX_VGA_THIS s.graphics_ctrl.chain_odd_even);
|
|
|
|
dbg_printf("s.graphics_ctrl.shift_reg = %u\n",
|
|
|
|
(unsigned) BX_VGA_THIS s.graphics_ctrl.shift_reg);
|
|
|
|
dbg_printf("s.graphics_ctrl.graphics_alpha = %u\n",
|
|
|
|
(unsigned) BX_VGA_THIS s.graphics_ctrl.graphics_alpha);
|
|
|
|
dbg_printf("s.graphics_ctrl.memory_mapping = %u ",
|
|
|
|
(unsigned) BX_VGA_THIS s.graphics_ctrl.memory_mapping);
|
2001-04-10 05:04:59 +04:00
|
|
|
switch (BX_VGA_THIS s.graphics_ctrl.memory_mapping) {
|
2004-08-24 14:15:56 +04:00
|
|
|
case 1: dbg_printf("(A0000-AFFFF)\n"); break;
|
|
|
|
case 2: dbg_printf("(B0000-B7FFF)\n"); break;
|
|
|
|
case 3: dbg_printf("(B8000-BFFFF)\n"); break;
|
|
|
|
default: dbg_printf("(A0000-BFFFF)\n"); break;
|
2001-04-10 05:04:59 +04:00
|
|
|
}
|
|
|
|
|
2004-08-24 14:15:56 +04:00
|
|
|
dbg_printf("s.sequencer.extended_mem = %u\n",
|
|
|
|
(unsigned) BX_VGA_THIS s.sequencer.extended_mem);
|
|
|
|
dbg_printf("s.sequencer.odd_even = %u (inverted)\n",
|
|
|
|
(unsigned) BX_VGA_THIS s.sequencer.odd_even);
|
|
|
|
dbg_printf("s.sequencer.chain_four = %u\n",
|
|
|
|
(unsigned) BX_VGA_THIS s.sequencer.chain_four);
|
|
|
|
|
|
|
|
dbg_printf("s.attribute_ctrl.video_enabled = %u\n",
|
|
|
|
(unsigned) BX_VGA_THIS s.attribute_ctrl.video_enabled);
|
|
|
|
dbg_printf("s.attribute_ctrl.mode_ctrl.graphics_alpha = %u\n",
|
|
|
|
(unsigned) BX_VGA_THIS s.attribute_ctrl.mode_ctrl.graphics_alpha);
|
|
|
|
dbg_printf("s.attribute_ctrl.mode_ctrl.display_type = %u\n",
|
|
|
|
(unsigned) BX_VGA_THIS s.attribute_ctrl.mode_ctrl.display_type);
|
|
|
|
dbg_printf("s.attribute_ctrl.mode_ctrl.internal_palette_size = %u\n",
|
|
|
|
(unsigned) BX_VGA_THIS s.attribute_ctrl.mode_ctrl.internal_palette_size);
|
|
|
|
dbg_printf("s.attribute_ctrl.mode_ctrl.pixel_clock_select = %u\n",
|
|
|
|
(unsigned) BX_VGA_THIS s.attribute_ctrl.mode_ctrl.pixel_clock_select);
|
|
|
|
#endif
|
2001-04-10 05:04:59 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
bx_vga_c::redraw_area(unsigned x0, unsigned y0, unsigned width,
|
|
|
|
unsigned height)
|
|
|
|
{
|
2005-04-15 21:33:54 +04:00
|
|
|
unsigned xti, yti, xt0, xt1, yt0, yt1, xmax, ymax;
|
|
|
|
|
|
|
|
if ((width == 0) || (height == 0)) {
|
|
|
|
return;
|
|
|
|
}
|
2001-04-10 05:04:59 +04:00
|
|
|
|
|
|
|
BX_VGA_THIS s.vga_mem_updated = 1;
|
|
|
|
|
2002-12-10 23:09:25 +03:00
|
|
|
#if BX_SUPPORT_VBE
|
|
|
|
if (BX_VGA_THIS s.graphics_ctrl.graphics_alpha || BX_VGA_THIS s.vbe_enabled) {
|
|
|
|
#else
|
2001-04-10 05:04:59 +04:00
|
|
|
if (BX_VGA_THIS s.graphics_ctrl.graphics_alpha) {
|
2002-12-10 23:09:25 +03:00
|
|
|
#endif
|
2001-04-10 05:04:59 +04:00
|
|
|
// graphics mode
|
2003-02-09 11:25:22 +03:00
|
|
|
xmax = old_iWidth;
|
|
|
|
ymax = old_iHeight;
|
2002-12-10 23:09:25 +03:00
|
|
|
#if BX_SUPPORT_VBE
|
|
|
|
if (BX_VGA_THIS s.vbe_enabled) {
|
|
|
|
xmax = BX_VGA_THIS s.vbe_xres;
|
|
|
|
ymax = BX_VGA_THIS s.vbe_yres;
|
|
|
|
}
|
|
|
|
#endif
|
2005-04-15 21:33:54 +04:00
|
|
|
xt0 = x0 / X_TILESIZE;
|
|
|
|
yt0 = y0 / Y_TILESIZE;
|
|
|
|
if (x0 < xmax) {
|
|
|
|
xt1 = (x0 + width - 1) / X_TILESIZE;
|
|
|
|
} else {
|
|
|
|
xt1 = (xmax - 1) / X_TILESIZE;
|
|
|
|
}
|
|
|
|
if (y0 < ymax) {
|
|
|
|
yt1 = (y0 + height - 1) / Y_TILESIZE;
|
|
|
|
} else {
|
|
|
|
yt1 = (ymax - 1) / Y_TILESIZE;
|
|
|
|
}
|
|
|
|
for (yti=yt0; yti<=yt1; yti++) {
|
|
|
|
for (xti=xt0; xti<=xt1; xti++) {
|
2002-11-16 18:43:13 +03:00
|
|
|
SET_TILE_UPDATED (xti, yti, 1);
|
2001-04-10 05:04:59 +04:00
|
|
|
}
|
|
|
|
}
|
2005-04-15 21:33:54 +04:00
|
|
|
|
|
|
|
} else {
|
2001-04-10 05:04:59 +04:00
|
|
|
// text mode
|
|
|
|
memset(BX_VGA_THIS s.text_snapshot, 0,
|
|
|
|
sizeof(BX_VGA_THIS s.text_snapshot));
|
2005-04-15 21:33:54 +04:00
|
|
|
}
|
2001-04-10 05:04:59 +04:00
|
|
|
}
|
2002-03-10 07:51:24 +03:00
|
|
|
|
|
|
|
|
|
|
|
#if BX_SUPPORT_VBE
|
2003-03-03 02:59:12 +03:00
|
|
|
Bit8u BX_CPP_AttrRegparmN(1)
|
2002-03-10 07:51:24 +03:00
|
|
|
bx_vga_c::vbe_mem_read(Bit32u addr)
|
|
|
|
{
|
2003-03-03 02:59:12 +03:00
|
|
|
Bit32u offset;
|
|
|
|
|
2002-04-03 20:48:15 +04:00
|
|
|
if (addr >= VBE_DISPI_LFB_PHYSICAL_ADDRESS)
|
|
|
|
{
|
|
|
|
// LFB read
|
2002-08-12 20:16:53 +04:00
|
|
|
offset = addr - VBE_DISPI_LFB_PHYSICAL_ADDRESS;
|
2002-04-03 20:48:15 +04:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// banked mode read
|
|
|
|
offset = BX_VGA_THIS s.vbe_bank*65536 + addr - 0xA0000;
|
|
|
|
}
|
2002-03-10 07:51:24 +03:00
|
|
|
|
2002-04-08 01:32:42 +04:00
|
|
|
// check for out of memory read
|
2002-09-22 15:31:48 +04:00
|
|
|
if (offset > VBE_DISPI_TOTAL_VIDEO_MEMORY_BYTES)
|
2002-04-08 01:32:42 +04:00
|
|
|
return 0;
|
|
|
|
|
2002-04-03 20:48:15 +04:00
|
|
|
return (BX_VGA_THIS s.vbe_memory[offset]);
|
2002-03-10 07:51:24 +03:00
|
|
|
}
|
|
|
|
|
2003-03-03 02:59:12 +03:00
|
|
|
void BX_CPP_AttrRegparmN(2)
|
2002-03-10 07:51:24 +03:00
|
|
|
bx_vga_c::vbe_mem_write(Bit32u addr, Bit8u value)
|
|
|
|
{
|
2003-03-03 02:59:12 +03:00
|
|
|
Bit32u offset;
|
2002-03-10 07:51:24 +03:00
|
|
|
unsigned x_tileno, y_tileno;
|
2003-03-03 02:59:12 +03:00
|
|
|
|
2003-10-04 19:58:21 +04:00
|
|
|
if (BX_VGA_THIS s.vbe_lfb_enabled)
|
|
|
|
{
|
|
|
|
if (addr >= VBE_DISPI_LFB_PHYSICAL_ADDRESS)
|
|
|
|
{
|
|
|
|
// LFB write
|
|
|
|
offset = addr - VBE_DISPI_LFB_PHYSICAL_ADDRESS;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// banked mode write while in LFB mode -> ignore
|
|
|
|
return;
|
|
|
|
}
|
2002-04-03 20:48:15 +04:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2003-10-04 19:58:21 +04:00
|
|
|
if (addr < VBE_DISPI_LFB_PHYSICAL_ADDRESS)
|
|
|
|
{
|
|
|
|
// banked mode write
|
|
|
|
offset = (BX_VGA_THIS s.vbe_bank*65536) + (addr - 0xA0000);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// LFB write while in banked mode -> ignore
|
|
|
|
return;
|
|
|
|
}
|
2002-04-03 20:48:15 +04:00
|
|
|
}
|
2002-03-10 07:51:24 +03:00
|
|
|
|
2002-03-13 21:33:00 +03:00
|
|
|
// check for out of memory write
|
2002-09-22 15:31:48 +04:00
|
|
|
if (offset < VBE_DISPI_TOTAL_VIDEO_MEMORY_BYTES)
|
2002-03-13 21:33:00 +03:00
|
|
|
{
|
|
|
|
BX_VGA_THIS s.vbe_memory[offset]=value;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// make sure we don't flood the logfile
|
|
|
|
static int count=0;
|
|
|
|
if (count<100)
|
|
|
|
{
|
|
|
|
count ++;
|
|
|
|
BX_INFO(("VBE_mem_write out of video memory write at %x",offset));
|
|
|
|
}
|
|
|
|
}
|
2003-07-15 17:05:20 +04:00
|
|
|
|
|
|
|
offset-=BX_VGA_THIS s.vbe_virtual_start;
|
|
|
|
|
2002-03-16 13:22:57 +03:00
|
|
|
// only update the UI when writing 'onscreen'
|
2004-07-22 00:39:54 +04:00
|
|
|
if (offset < BX_VGA_THIS s.vbe_visible_screen_size)
|
2002-03-16 13:22:57 +03:00
|
|
|
{
|
2003-06-30 22:53:12 +04:00
|
|
|
y_tileno = ((offset / BX_VGA_THIS s.vbe_bpp_multiplier) / BX_VGA_THIS s.vbe_virtual_xres) / Y_TILESIZE;
|
|
|
|
x_tileno = ((offset / BX_VGA_THIS s.vbe_bpp_multiplier) % BX_VGA_THIS s.vbe_virtual_xres) / X_TILESIZE;
|
|
|
|
|
2002-04-29 17:06:06 +04:00
|
|
|
if ((y_tileno < BX_NUM_Y_TILES) && (x_tileno < BX_NUM_X_TILES))
|
|
|
|
{
|
|
|
|
BX_VGA_THIS s.vga_mem_updated = 1;
|
2002-11-16 18:43:13 +03:00
|
|
|
SET_TILE_UPDATED (x_tileno, y_tileno, 1);
|
2002-04-29 17:06:06 +04:00
|
|
|
}
|
2002-03-16 13:22:57 +03:00
|
|
|
}
|
2002-03-10 07:51:24 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
Bit32u
|
|
|
|
bx_vga_c::vbe_read_handler(void *this_ptr, Bit32u address, unsigned io_len)
|
|
|
|
{
|
|
|
|
#if !BX_USE_VGA_SMF
|
|
|
|
bx_vga_c *class_ptr = (bx_vga_c *) this_ptr;
|
|
|
|
|
|
|
|
return( class_ptr->vbe_read(address, io_len) );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Bit32u
|
|
|
|
bx_vga_c::vbe_read(Bit32u address, unsigned io_len)
|
|
|
|
{
|
|
|
|
#else
|
|
|
|
UNUSED(this_ptr);
|
|
|
|
#endif // !BX_USE_VGA_SMF
|
2004-05-05 00:41:53 +04:00
|
|
|
Bit16u retval;
|
2002-03-10 07:51:24 +03:00
|
|
|
|
|
|
|
// BX_INFO(("VBE_read %x (len %x)", address, io_len));
|
|
|
|
|
2003-12-31 13:33:27 +03:00
|
|
|
if ((address==VBE_DISPI_IOPORT_INDEX) ||
|
|
|
|
(address==VBE_DISPI_IOPORT_INDEX_OLD))
|
2002-03-10 07:51:24 +03:00
|
|
|
{
|
|
|
|
// index register
|
|
|
|
return (Bit32u) BX_VGA_THIS s.vbe_curindex;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2002-03-13 21:33:00 +03:00
|
|
|
// data register read
|
|
|
|
|
2002-03-10 07:51:24 +03:00
|
|
|
switch (BX_VGA_THIS s.vbe_curindex)
|
|
|
|
{
|
|
|
|
case VBE_DISPI_INDEX_ID: // Display Interface ID check
|
|
|
|
{
|
2002-04-29 17:06:06 +04:00
|
|
|
return BX_VGA_THIS s.vbe_cur_dispi;
|
2002-03-10 07:51:24 +03:00
|
|
|
} break;
|
2002-03-13 21:33:00 +03:00
|
|
|
|
|
|
|
case VBE_DISPI_INDEX_XRES: // x resolution
|
|
|
|
{
|
2004-02-22 16:03:02 +03:00
|
|
|
if (BX_VGA_THIS s.vbe_get_capabilities) {
|
|
|
|
return BX_VGA_THIS s.vbe_max_xres;
|
|
|
|
} else {
|
|
|
|
return BX_VGA_THIS s.vbe_xres;
|
|
|
|
}
|
2002-03-13 21:33:00 +03:00
|
|
|
} break;
|
|
|
|
|
|
|
|
case VBE_DISPI_INDEX_YRES: // y resolution
|
|
|
|
{
|
2004-02-22 16:03:02 +03:00
|
|
|
if (BX_VGA_THIS s.vbe_get_capabilities) {
|
|
|
|
return BX_VGA_THIS s.vbe_max_yres;
|
|
|
|
} else {
|
|
|
|
return BX_VGA_THIS s.vbe_yres;
|
|
|
|
}
|
2002-03-13 21:33:00 +03:00
|
|
|
} break;
|
|
|
|
|
|
|
|
case VBE_DISPI_INDEX_BPP: // bpp
|
|
|
|
{
|
2004-02-22 16:03:02 +03:00
|
|
|
if (BX_VGA_THIS s.vbe_get_capabilities) {
|
|
|
|
return BX_VGA_THIS s.vbe_max_bpp;
|
|
|
|
} else {
|
|
|
|
return BX_VGA_THIS s.vbe_bpp;
|
|
|
|
}
|
2002-03-13 21:33:00 +03:00
|
|
|
} break;
|
|
|
|
|
|
|
|
case VBE_DISPI_INDEX_ENABLE: // vbe enabled
|
|
|
|
{
|
2004-05-05 00:41:53 +04:00
|
|
|
retval = BX_VGA_THIS s.vbe_enabled;
|
|
|
|
if (BX_VGA_THIS s.vbe_get_capabilities)
|
|
|
|
retval |= VBE_DISPI_GETCAPS;
|
|
|
|
if (BX_VGA_THIS s.vbe_8bit_dac)
|
|
|
|
retval |= VBE_DISPI_8BIT_DAC;
|
|
|
|
return retval;
|
2002-03-13 21:33:00 +03:00
|
|
|
} break;
|
|
|
|
|
|
|
|
case VBE_DISPI_INDEX_BANK: // current bank
|
|
|
|
{
|
|
|
|
return BX_VGA_THIS s.vbe_bank;
|
|
|
|
} break;
|
2002-03-10 07:51:24 +03:00
|
|
|
|
2002-04-29 17:06:06 +04:00
|
|
|
case VBE_DISPI_INDEX_X_OFFSET:
|
|
|
|
{
|
|
|
|
return BX_VGA_THIS s.vbe_offset_x;
|
|
|
|
} break;
|
|
|
|
|
|
|
|
case VBE_DISPI_INDEX_Y_OFFSET:
|
|
|
|
{
|
|
|
|
return BX_VGA_THIS s.vbe_offset_y;
|
|
|
|
} break;
|
|
|
|
|
|
|
|
case VBE_DISPI_INDEX_VIRT_WIDTH:
|
|
|
|
{
|
|
|
|
return BX_VGA_THIS s.vbe_virtual_xres;
|
|
|
|
|
|
|
|
} break;
|
|
|
|
|
|
|
|
case VBE_DISPI_INDEX_VIRT_HEIGHT:
|
|
|
|
{
|
|
|
|
return BX_VGA_THIS s.vbe_virtual_yres;
|
|
|
|
} break;
|
|
|
|
|
|
|
|
|
2002-03-10 07:51:24 +03:00
|
|
|
default:
|
|
|
|
{
|
|
|
|
BX_PANIC(("VBE unknown data read index 0x%x",BX_VGA_THIS s.vbe_curindex));
|
|
|
|
} break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
BX_PANIC(("VBE_read shouldn't reach this"));
|
2002-09-08 11:56:10 +04:00
|
|
|
return 0; /* keep compiler happy */
|
2002-03-10 07:51:24 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
bx_vga_c::vbe_write_handler(void *this_ptr, Bit32u address, Bit32u value, unsigned io_len)
|
|
|
|
{
|
|
|
|
#if !BX_USE_VGA_SMF
|
|
|
|
bx_vga_c *class_ptr = (bx_vga_c *) this_ptr;
|
|
|
|
|
|
|
|
class_ptr->vbe_write(address, value, io_len);
|
|
|
|
}
|
|
|
|
|
|
|
|
Bit32u
|
|
|
|
bx_vga_c::vbe_write(Bit32u address, Bit32u value, unsigned io_len)
|
|
|
|
{
|
|
|
|
#else
|
|
|
|
UNUSED(this_ptr);
|
|
|
|
#endif
|
2004-05-05 00:41:53 +04:00
|
|
|
bx_bool new_vbe_8bit_dac;
|
2005-03-01 00:23:34 +03:00
|
|
|
bx_bool needs_update = 0;
|
2004-05-05 00:41:53 +04:00
|
|
|
unsigned i;
|
2002-03-10 07:51:24 +03:00
|
|
|
|
|
|
|
// BX_INFO(("VBE_write %x = %x (len %x)", address, value, io_len));
|
|
|
|
|
2003-06-30 22:53:12 +04:00
|
|
|
switch(address)
|
2002-03-10 07:51:24 +03:00
|
|
|
{
|
2003-06-30 22:53:12 +04:00
|
|
|
// index register
|
|
|
|
case VBE_DISPI_IOPORT_INDEX:
|
2003-12-31 13:33:27 +03:00
|
|
|
// legacy index register
|
|
|
|
case VBE_DISPI_IOPORT_INDEX_OLD:
|
2003-06-30 22:53:12 +04:00
|
|
|
|
|
|
|
BX_VGA_THIS s.vbe_curindex = (Bit16u) value;
|
|
|
|
break;
|
|
|
|
|
2002-03-10 07:51:24 +03:00
|
|
|
// data register
|
|
|
|
// FIXME: maybe do some 'sanity' checks on received data?
|
2003-06-30 22:53:12 +04:00
|
|
|
case VBE_DISPI_IOPORT_DATA:
|
2003-12-31 13:33:27 +03:00
|
|
|
// legacy data register
|
|
|
|
case VBE_DISPI_IOPORT_DATA_OLD:
|
2003-06-30 22:53:12 +04:00
|
|
|
switch (BX_VGA_THIS s.vbe_curindex)
|
2002-03-10 07:51:24 +03:00
|
|
|
{
|
2003-06-30 22:53:12 +04:00
|
|
|
case VBE_DISPI_INDEX_ID: // Display Interface ID check
|
2002-03-10 07:51:24 +03:00
|
|
|
{
|
2003-06-30 22:53:12 +04:00
|
|
|
if ( (value == VBE_DISPI_ID0) ||
|
|
|
|
(value == VBE_DISPI_ID1) ||
|
2004-02-22 16:03:02 +03:00
|
|
|
(value == VBE_DISPI_ID2) ||
|
|
|
|
(value == VBE_DISPI_ID3) )
|
2003-06-30 22:53:12 +04:00
|
|
|
{
|
|
|
|
// allow backwards compatible with previous dispi bioses
|
|
|
|
BX_VGA_THIS s.vbe_cur_dispi=value;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
BX_PANIC(("VBE unknown Display Interface %x",value));
|
|
|
|
}
|
2002-04-29 17:06:06 +04:00
|
|
|
|
2003-06-30 22:53:12 +04:00
|
|
|
// make sure we don't flood the logfile
|
|
|
|
static int count=0;
|
|
|
|
if (count < 100)
|
|
|
|
{
|
|
|
|
count++;
|
|
|
|
BX_INFO(("VBE known Display Interface %x",value));
|
|
|
|
}
|
|
|
|
} break;
|
|
|
|
|
|
|
|
case VBE_DISPI_INDEX_XRES: // set xres
|
2002-03-13 21:33:00 +03:00
|
|
|
{
|
2003-06-30 22:53:12 +04:00
|
|
|
// check that we don't set xres during vbe enabled
|
|
|
|
if (!BX_VGA_THIS s.vbe_enabled)
|
2002-03-13 21:33:00 +03:00
|
|
|
{
|
2003-06-30 22:53:12 +04:00
|
|
|
// check for within max xres range
|
|
|
|
if (value <= VBE_DISPI_MAX_XRES)
|
|
|
|
{
|
|
|
|
BX_VGA_THIS s.vbe_xres=(Bit16u) value;
|
|
|
|
BX_INFO(("VBE set xres (%d)",value));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
BX_INFO(("VBE set xres more then max xres (%d)",value));
|
|
|
|
}
|
2002-03-13 21:33:00 +03:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2003-06-30 22:53:12 +04:00
|
|
|
BX_INFO(("VBE set xres during vbe enabled!"));
|
2002-03-13 21:33:00 +03:00
|
|
|
}
|
2003-06-30 22:53:12 +04:00
|
|
|
} break;
|
|
|
|
|
|
|
|
case VBE_DISPI_INDEX_YRES: // set yres
|
2002-03-13 21:33:00 +03:00
|
|
|
{
|
2003-06-30 22:53:12 +04:00
|
|
|
// check that we don't set yres during vbe enabled
|
|
|
|
if (!BX_VGA_THIS s.vbe_enabled)
|
2002-03-13 21:33:00 +03:00
|
|
|
{
|
2003-06-30 22:53:12 +04:00
|
|
|
// check for within max yres range
|
|
|
|
if (value <= VBE_DISPI_MAX_YRES)
|
|
|
|
{
|
|
|
|
BX_VGA_THIS s.vbe_yres=(Bit16u) value;
|
|
|
|
BX_INFO(("VBE set yres (%d)",value));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
BX_INFO(("VBE set yres more then max yres (%d)",value));
|
|
|
|
}
|
2002-03-13 21:33:00 +03:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2003-06-30 22:53:12 +04:00
|
|
|
BX_INFO(("VBE set yres during vbe enabled!"));
|
2002-03-13 21:33:00 +03:00
|
|
|
}
|
2003-06-30 22:53:12 +04:00
|
|
|
} break;
|
|
|
|
|
|
|
|
case VBE_DISPI_INDEX_BPP: // set bpp
|
2002-03-13 21:33:00 +03:00
|
|
|
{
|
2003-06-30 22:53:12 +04:00
|
|
|
// check that we don't set bpp during vbe enabled
|
|
|
|
if (!BX_VGA_THIS s.vbe_enabled)
|
2002-03-13 21:33:00 +03:00
|
|
|
{
|
2003-06-30 22:53:12 +04:00
|
|
|
// for backward compatiblity
|
|
|
|
if (value == 0) value = VBE_DISPI_BPP_8;
|
|
|
|
// check for correct bpp range
|
2003-07-10 00:15:38 +04:00
|
|
|
if ((value == VBE_DISPI_BPP_4) || (value == VBE_DISPI_BPP_8) || (value == VBE_DISPI_BPP_15) ||
|
|
|
|
(value == VBE_DISPI_BPP_16) || (value == VBE_DISPI_BPP_24) || (value == VBE_DISPI_BPP_32))
|
2003-06-30 22:53:12 +04:00
|
|
|
{
|
|
|
|
BX_VGA_THIS s.vbe_bpp=(Bit16u) value;
|
|
|
|
BX_INFO(("VBE set bpp (%d)",value));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
BX_INFO(("VBE set bpp with unknown bpp (%d)",value));
|
|
|
|
}
|
2002-03-13 21:33:00 +03:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2003-06-30 22:53:12 +04:00
|
|
|
BX_INFO(("VBE set bpp during vbe enabled!"));
|
2002-03-13 21:33:00 +03:00
|
|
|
}
|
2003-06-30 22:53:12 +04:00
|
|
|
} break;
|
|
|
|
|
|
|
|
case VBE_DISPI_INDEX_BANK: // set bank
|
2002-03-13 21:33:00 +03:00
|
|
|
{
|
2003-06-30 22:53:12 +04:00
|
|
|
value=value & 0xff ; // FIXME lobyte = vbe bank A?
|
2004-07-22 00:39:54 +04:00
|
|
|
unsigned divider = (BX_VGA_THIS s.vbe_bpp!=VBE_DISPI_BPP_4)?64:256;
|
2003-06-30 22:53:12 +04:00
|
|
|
// check for max bank nr
|
2004-07-22 00:39:54 +04:00
|
|
|
if (value < (VBE_DISPI_TOTAL_VIDEO_MEMORY_KB / divider))
|
2003-06-30 22:53:12 +04:00
|
|
|
{
|
2003-07-16 21:56:25 +04:00
|
|
|
if (!BX_VGA_THIS s.vbe_lfb_enabled)
|
|
|
|
{
|
|
|
|
BX_DEBUG(("VBE set bank to %d", value));
|
|
|
|
BX_VGA_THIS s.vbe_bank=value;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
BX_ERROR(("VBE set bank in LFB mode ignored"));
|
|
|
|
}
|
2003-06-30 22:53:12 +04:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
BX_INFO(("VBE set invalid bank (%d)",value));
|
|
|
|
}
|
|
|
|
} break;
|
|
|
|
|
|
|
|
case VBE_DISPI_INDEX_ENABLE: // enable video
|
2002-03-10 07:51:24 +03:00
|
|
|
{
|
2004-05-05 00:41:53 +04:00
|
|
|
if ((value & VBE_DISPI_ENABLED) && !BX_VGA_THIS s.vbe_enabled)
|
2003-06-30 22:53:12 +04:00
|
|
|
{
|
|
|
|
unsigned depth=0;
|
|
|
|
|
|
|
|
// setup virtual resolution to be the same as current reso
|
|
|
|
BX_VGA_THIS s.vbe_virtual_yres=BX_VGA_THIS s.vbe_yres;
|
|
|
|
BX_VGA_THIS s.vbe_virtual_xres=BX_VGA_THIS s.vbe_xres;
|
|
|
|
|
|
|
|
// reset offset
|
|
|
|
BX_VGA_THIS s.vbe_offset_x=0;
|
|
|
|
BX_VGA_THIS s.vbe_offset_y=0;
|
|
|
|
BX_VGA_THIS s.vbe_virtual_start=0;
|
|
|
|
|
|
|
|
switch((BX_VGA_THIS s.vbe_bpp))
|
|
|
|
{
|
|
|
|
// Default pixel sizes
|
|
|
|
case VBE_DISPI_BPP_8:
|
|
|
|
BX_VGA_THIS s.vbe_bpp_multiplier = 1;
|
2004-07-22 00:39:54 +04:00
|
|
|
BX_VGA_THIS s.line_offset = BX_VGA_THIS s.vbe_virtual_xres;
|
2003-06-30 22:53:12 +04:00
|
|
|
depth=8;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case VBE_DISPI_BPP_4:
|
2003-07-01 20:07:59 +04:00
|
|
|
BX_VGA_THIS s.vbe_bpp_multiplier = 1;
|
2004-07-22 00:39:54 +04:00
|
|
|
BX_VGA_THIS s.line_offset = (BX_VGA_THIS s.vbe_virtual_xres >> 3);
|
2003-06-30 22:53:12 +04:00
|
|
|
depth=4;
|
|
|
|
break;
|
|
|
|
|
2003-07-10 00:15:38 +04:00
|
|
|
case VBE_DISPI_BPP_15:
|
|
|
|
BX_VGA_THIS s.vbe_bpp_multiplier = 2;
|
2004-07-22 00:39:54 +04:00
|
|
|
BX_VGA_THIS s.line_offset = BX_VGA_THIS s.vbe_virtual_xres * 2;
|
2003-07-10 00:15:38 +04:00
|
|
|
depth=15;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case VBE_DISPI_BPP_16:
|
2003-06-30 22:53:12 +04:00
|
|
|
BX_VGA_THIS s.vbe_bpp_multiplier = 2;
|
2004-07-22 00:39:54 +04:00
|
|
|
BX_VGA_THIS s.line_offset = BX_VGA_THIS s.vbe_virtual_xres * 2;
|
2003-06-30 22:53:12 +04:00
|
|
|
depth=16;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case VBE_DISPI_BPP_24:
|
|
|
|
BX_VGA_THIS s.vbe_bpp_multiplier = 3;
|
2004-07-22 00:39:54 +04:00
|
|
|
BX_VGA_THIS s.line_offset = BX_VGA_THIS s.vbe_virtual_xres * 3;
|
2003-06-30 22:53:12 +04:00
|
|
|
depth=24;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case VBE_DISPI_BPP_32:
|
|
|
|
BX_VGA_THIS s.vbe_bpp_multiplier = 4;
|
2004-07-22 00:39:54 +04:00
|
|
|
BX_VGA_THIS s.line_offset = BX_VGA_THIS s.vbe_virtual_xres << 2;
|
2003-06-30 22:53:12 +04:00
|
|
|
depth=32;
|
|
|
|
break;
|
|
|
|
}
|
2004-07-22 00:39:54 +04:00
|
|
|
BX_VGA_THIS s.vbe_visible_screen_size = BX_VGA_THIS s.line_offset * BX_VGA_THIS s.vbe_yres;
|
2003-06-30 22:53:12 +04:00
|
|
|
|
2004-07-22 00:39:54 +04:00
|
|
|
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));
|
2003-06-30 22:53:12 +04:00
|
|
|
|
2003-07-01 20:07:59 +04:00
|
|
|
if (depth > 4)
|
|
|
|
{
|
2003-07-16 21:56:25 +04:00
|
|
|
BX_VGA_THIS s.vbe_lfb_enabled=(bx_bool)(value & VBE_DISPI_LFB_ENABLED);
|
2003-07-01 20:07:59 +04:00
|
|
|
if ((value & VBE_DISPI_NOCLEARMEM) == 0)
|
|
|
|
{
|
2004-07-22 00:39:54 +04:00
|
|
|
memset(BX_VGA_THIS s.vbe_memory, 0, BX_VGA_THIS s.vbe_visible_screen_size);
|
2003-07-01 20:07:59 +04:00
|
|
|
}
|
|
|
|
bx_gui->dimension_update(BX_VGA_THIS s.vbe_xres, BX_VGA_THIS s.vbe_yres, 0, 0, depth);
|
2005-10-27 13:32:02 +04:00
|
|
|
BX_VGA_THIS s.last_bpp = depth;
|
2003-07-15 17:05:20 +04:00
|
|
|
// some test applications expect these standard VGA settings
|
|
|
|
BX_VGA_THIS s.CRTC.reg[9] = 0x00;
|
|
|
|
BX_VGA_THIS s.attribute_ctrl.mode_ctrl.graphics_alpha = 1;
|
|
|
|
BX_VGA_THIS s.graphics_ctrl.memory_mapping = 1;
|
|
|
|
BX_VGA_THIS s.attribute_ctrl.mode_ctrl.pixel_clock_select = 1;
|
|
|
|
BX_VGA_THIS s.CRTC.reg[18] = (BX_VGA_THIS s.vbe_yres - 1) & 0xff;
|
|
|
|
BX_VGA_THIS s.CRTC.reg[7] &= ~0x42;
|
|
|
|
if ((BX_VGA_THIS s.vbe_yres - 1) & 0x0100) {
|
|
|
|
BX_VGA_THIS s.CRTC.reg[7] |= 0x02;
|
|
|
|
}
|
|
|
|
if ((BX_VGA_THIS s.vbe_yres - 1) & 0x0200) {
|
|
|
|
BX_VGA_THIS s.CRTC.reg[7] |= 0x40;
|
|
|
|
}
|
2004-07-24 22:12:00 +04:00
|
|
|
BX_VGA_THIS s.sequencer.map_mask = 0x0f;
|
|
|
|
BX_VGA_THIS s.sequencer.chain_four = 1;
|
2003-07-01 20:07:59 +04:00
|
|
|
}
|
2003-06-30 22:53:12 +04:00
|
|
|
}
|
2004-05-05 00:41:53 +04:00
|
|
|
else if (((value & VBE_DISPI_ENABLED) == 0) && BX_VGA_THIS s.vbe_enabled)
|
2003-06-30 22:53:12 +04:00
|
|
|
{
|
2004-05-05 00:41:53 +04:00
|
|
|
BX_INFO(("VBE disabling"));
|
2003-07-16 21:56:25 +04:00
|
|
|
BX_VGA_THIS s.vbe_lfb_enabled=0;
|
2003-06-30 22:53:12 +04:00
|
|
|
}
|
2003-07-01 20:07:59 +04:00
|
|
|
BX_VGA_THIS s.vbe_enabled=(bx_bool)(value & VBE_DISPI_ENABLED);
|
2004-03-02 19:29:27 +03:00
|
|
|
BX_VGA_THIS s.vbe_get_capabilities=(bx_bool)((value & VBE_DISPI_GETCAPS) != 0);
|
2004-05-05 00:41:53 +04:00
|
|
|
new_vbe_8bit_dac=(bx_bool)((value & VBE_DISPI_8BIT_DAC) != 0);
|
|
|
|
if (new_vbe_8bit_dac != BX_VGA_THIS s.vbe_8bit_dac)
|
|
|
|
{
|
|
|
|
if (new_vbe_8bit_dac)
|
|
|
|
{
|
|
|
|
for (i=0; i<256; i++)
|
|
|
|
{
|
|
|
|
BX_VGA_THIS s.pel.data[i].red <<= 2;
|
|
|
|
BX_VGA_THIS s.pel.data[i].green <<= 2;
|
|
|
|
BX_VGA_THIS s.pel.data[i].blue <<= 2;
|
|
|
|
}
|
|
|
|
BX_INFO(("DAC in 8 bit mode"));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
for (i=0; i<256; i++)
|
|
|
|
{
|
|
|
|
BX_VGA_THIS s.pel.data[i].red >>= 2;
|
|
|
|
BX_VGA_THIS s.pel.data[i].green >>= 2;
|
|
|
|
BX_VGA_THIS s.pel.data[i].blue >>= 2;
|
|
|
|
}
|
|
|
|
BX_INFO(("DAC in standard mode"));
|
|
|
|
}
|
|
|
|
BX_VGA_THIS s.vbe_8bit_dac=new_vbe_8bit_dac;
|
2005-03-01 00:23:34 +03:00
|
|
|
needs_update = 1;
|
2004-05-05 00:41:53 +04:00
|
|
|
}
|
2003-06-30 22:53:12 +04:00
|
|
|
} break;
|
|
|
|
|
|
|
|
case VBE_DISPI_INDEX_X_OFFSET:
|
2002-03-10 07:51:24 +03:00
|
|
|
{
|
2003-06-30 22:53:12 +04:00
|
|
|
// BX_INFO(("VBE offset x %x",value));
|
|
|
|
BX_VGA_THIS s.vbe_offset_x=(Bit16u)value;
|
|
|
|
|
2004-07-22 00:39:54 +04:00
|
|
|
BX_VGA_THIS s.vbe_virtual_start = BX_VGA_THIS s.vbe_offset_y * BX_VGA_THIS s.line_offset;
|
|
|
|
if (BX_VGA_THIS s.vbe_bpp != VBE_DISPI_BPP_4) {
|
|
|
|
BX_VGA_THIS s.vbe_virtual_start += (BX_VGA_THIS s.vbe_offset_x * BX_VGA_THIS s.vbe_bpp_multiplier);
|
|
|
|
} else {
|
|
|
|
BX_VGA_THIS s.vbe_virtual_start += (BX_VGA_THIS s.vbe_offset_x >> 3);
|
|
|
|
}
|
2005-03-01 00:23:34 +03:00
|
|
|
needs_update = 1;
|
2003-06-30 22:53:12 +04:00
|
|
|
} break;
|
2002-04-29 17:06:06 +04:00
|
|
|
|
2003-06-30 22:53:12 +04:00
|
|
|
case VBE_DISPI_INDEX_Y_OFFSET:
|
|
|
|
{
|
|
|
|
// BX_INFO(("VBE offset y %x",value));
|
|
|
|
BX_VGA_THIS s.vbe_offset_y=(Bit16u)value;
|
2004-07-22 00:39:54 +04:00
|
|
|
BX_VGA_THIS s.vbe_virtual_start = BX_VGA_THIS s.vbe_offset_y * BX_VGA_THIS s.line_offset;
|
|
|
|
if (BX_VGA_THIS s.vbe_bpp != VBE_DISPI_BPP_4) {
|
|
|
|
BX_VGA_THIS s.vbe_virtual_start += (BX_VGA_THIS s.vbe_offset_x * BX_VGA_THIS s.vbe_bpp_multiplier);
|
|
|
|
} else {
|
|
|
|
BX_VGA_THIS s.vbe_virtual_start += (BX_VGA_THIS s.vbe_offset_x >> 3);
|
|
|
|
}
|
2005-03-01 00:23:34 +03:00
|
|
|
needs_update = 1;
|
2003-06-30 22:53:12 +04:00
|
|
|
} break;
|
2002-04-29 17:06:06 +04:00
|
|
|
|
2003-06-30 22:53:12 +04:00
|
|
|
case VBE_DISPI_INDEX_VIRT_WIDTH:
|
|
|
|
{
|
2003-07-15 17:05:20 +04:00
|
|
|
BX_INFO(("VBE requested virtual width %d",value));
|
2003-06-30 22:53:12 +04:00
|
|
|
|
|
|
|
// calculate virtual width & height dimensions
|
|
|
|
// req:
|
|
|
|
// virt_width > xres
|
|
|
|
// virt_height >=yres
|
|
|
|
// virt_width*virt_height < MAX_VIDEO_MEMORY
|
|
|
|
|
|
|
|
// basicly 2 situations
|
|
|
|
|
|
|
|
// situation 1:
|
|
|
|
// MAX_VIDEO_MEMORY / virt_width >= yres
|
|
|
|
// adjust result height
|
|
|
|
// else
|
|
|
|
// adjust result width based upon virt_height=yres
|
|
|
|
Bit16u new_width=value;
|
2004-07-22 00:39:54 +04:00
|
|
|
Bit16u new_height;
|
|
|
|
if (BX_VGA_THIS s.vbe_bpp != VBE_DISPI_BPP_4) {
|
|
|
|
new_height=(sizeof(BX_VGA_THIS s.vbe_memory) / BX_VGA_THIS s.vbe_bpp_multiplier) / new_width;
|
|
|
|
} else {
|
|
|
|
new_height=(sizeof(BX_VGA_THIS s.vbe_memory) * 2) / new_width;
|
|
|
|
}
|
2003-06-30 22:53:12 +04:00
|
|
|
if (new_height >=BX_VGA_THIS s.vbe_yres)
|
|
|
|
{
|
|
|
|
// we have a decent virtual width & new_height
|
2003-07-15 17:05:20 +04:00
|
|
|
BX_INFO(("VBE decent virtual height %d",new_height));
|
2003-06-30 22:53:12 +04:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// no decent virtual height: adjust width & height
|
|
|
|
new_height=BX_VGA_THIS s.vbe_yres;
|
2004-07-22 00:39:54 +04:00
|
|
|
if (BX_VGA_THIS s.vbe_bpp != VBE_DISPI_BPP_4) {
|
|
|
|
new_width=(sizeof(BX_VGA_THIS s.vbe_memory) / BX_VGA_THIS s.vbe_bpp_multiplier) / new_height;
|
|
|
|
} else {
|
|
|
|
new_width=(sizeof(BX_VGA_THIS s.vbe_memory) * 2) / new_height;
|
|
|
|
}
|
2003-06-30 22:53:12 +04:00
|
|
|
|
2003-07-15 17:05:20 +04:00
|
|
|
BX_INFO(("VBE recalc virtual width %d height %d",new_width, new_height));
|
2003-06-30 22:53:12 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
BX_VGA_THIS s.vbe_virtual_xres=new_width;
|
|
|
|
BX_VGA_THIS s.vbe_virtual_yres=new_height;
|
2004-07-22 00:39:54 +04:00
|
|
|
if (BX_VGA_THIS s.vbe_bpp != VBE_DISPI_BPP_4) {
|
|
|
|
BX_VGA_THIS s.line_offset = BX_VGA_THIS s.vbe_virtual_xres * BX_VGA_THIS s.vbe_bpp_multiplier;
|
|
|
|
} else {
|
|
|
|
BX_VGA_THIS s.line_offset = BX_VGA_THIS s.vbe_virtual_xres >> 3;
|
|
|
|
}
|
|
|
|
BX_VGA_THIS s.vbe_visible_screen_size = BX_VGA_THIS s.line_offset * BX_VGA_THIS s.vbe_yres;
|
2003-06-30 22:53:12 +04:00
|
|
|
|
|
|
|
} break;
|
|
|
|
/*
|
|
|
|
case VBE_DISPI_INDEX_VIRT_HEIGHT:
|
|
|
|
{
|
|
|
|
BX_INFO(("VBE virtual height %x",value));
|
|
|
|
|
|
|
|
} break;
|
|
|
|
*/
|
|
|
|
default:
|
|
|
|
{
|
|
|
|
BX_PANIC(("VBE unknown data write index 0x%x",BX_VGA_THIS s.vbe_curindex));
|
|
|
|
} break;
|
|
|
|
}
|
2005-03-01 00:23:34 +03:00
|
|
|
if (needs_update) {
|
|
|
|
BX_VGA_THIS s.vga_mem_updated = 1;
|
|
|
|
for (unsigned xti = 0; xti < BX_NUM_X_TILES; xti++) {
|
|
|
|
for (unsigned yti = 0; yti < BX_NUM_Y_TILES; yti++) {
|
|
|
|
SET_TILE_UPDATED (xti, yti, 1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2003-06-30 22:53:12 +04:00
|
|
|
break;
|
|
|
|
|
|
|
|
} // end switch address
|
2002-03-10 07:51:24 +03:00
|
|
|
}
|
|
|
|
|
2002-04-08 01:32:42 +04:00
|
|
|
#endif
|