Added currently disabled set of fixes for the VGA memory management.

- Added disabled definition VGA_MEM_FIX in vgacore.h. The VGA core code works as
  usual unless you uncomment the define.
- Added correct implementation of the "chain four" and "odd/even" addressing mode.
  This should fix the Debian / GRUB boot issue (#257) with both Bochs VBE and Cirrus.
- Added some compatibility code to make the gui text update work as usual.
- Tested all VGA modes except 256-color word mode (no test case).
- Some more testing with old DOS games may be required before I enable it by default
  and finally remove the legacy code.
This commit is contained in:
Volker Ruppert 2024-02-10 17:30:24 +01:00
parent fd68912dc7
commit 945ee597f0
5 changed files with 228 additions and 12 deletions

View File

@ -1735,12 +1735,16 @@ void bx_svga_cirrus_c::svga_write_crtc(Bit32u address, unsigned index, Bit8u val
if (update_pitch) {
if ((BX_CIRRUS_THIS crtc.reg[0x1b] & 0x02) != 0) {
#ifndef VGA_MEM_FIX
if (!BX_CIRRUS_THIS s.sequencer.chain_four) {
BX_CIRRUS_THIS s.plane_shift = 19;
}
#endif
BX_CIRRUS_THIS s.ext_offset = BX_CIRRUS_THIS bank_base[0];
} else {
#ifndef VGA_MEM_FIX
BX_CIRRUS_THIS s.plane_shift = 16;
#endif
BX_CIRRUS_THIS s.ext_offset = 0;
}
BX_CIRRUS_THIS svga_pitch = (BX_CIRRUS_THIS crtc.reg[0x13] << 3) | ((BX_CIRRUS_THIS crtc.reg[0x1b] & 0x10) << 7);

View File

@ -578,7 +578,9 @@ void bx_vga_c::update(void)
} else {
unsigned r, c, x, y;
unsigned xc, yc, xti, yti;
#ifndef VGA_MEM_FIX
Bit8u *plane[4];
#endif
Bit32u row_addr;
if (BX_VGA_THIS vbe.yres < 1024) {
@ -595,11 +597,12 @@ void bx_vga_c::update(void)
BX_VGA_THIS s.last_bpp = 8;
}
#ifndef VGA_MEM_FIX
plane[0] = &BX_VGA_THIS s.memory[0<<VBE_DISPI_4BPP_PLANE_SHIFT];
plane[1] = &BX_VGA_THIS s.memory[1<<VBE_DISPI_4BPP_PLANE_SHIFT];
plane[2] = &BX_VGA_THIS s.memory[2<<VBE_DISPI_4BPP_PLANE_SHIFT];
plane[3] = &BX_VGA_THIS s.memory[3<<VBE_DISPI_4BPP_PLANE_SHIFT];
#endif
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)) {
@ -610,7 +613,11 @@ void bx_vga_c::update(void)
for (c=0; c<X_TILESIZE; c++) {
x = xc + c;
BX_VGA_THIS s.tile[r*X_TILESIZE + c] =
#ifdef VGA_MEM_FIX
BX_VGA_THIS get_vga_pixel(x, y, row_addr, 0xffff, 0, BX_VGA_THIS s.memory);
#else
BX_VGA_THIS get_vga_pixel(x, y, row_addr, 0xffff, 0, plane);
#endif
}
}
SET_TILE_UPDATED(BX_VGA_THIS, xti, yti, 0);
@ -1139,12 +1146,16 @@ Bit32u bx_vga_c::vbe_write(Bit32u address, Bit32u value, unsigned io_len)
BX_VGA_THIS s.last_bpp = depth;
BX_VGA_THIS s.last_fh = 0;
} else {
#ifndef VGA_MEM_FIX
BX_VGA_THIS s.plane_shift = VBE_DISPI_4BPP_PLANE_SHIFT;
#endif
BX_VGA_THIS s.ext_offset = (BX_VGA_THIS vbe.bank[0] << 16);
}
} else if (((value & VBE_DISPI_ENABLED) == 0) && BX_VGA_THIS vbe.enabled) {
BX_INFO(("VBE disabling"));
#ifndef VGA_MEM_FIX
BX_VGA_THIS s.plane_shift = 16;
#endif
BX_VGA_THIS s.ext_offset = 0;
}
BX_VGA_THIS vbe.enabled = ((value & VBE_DISPI_ENABLED) != 0);

View File

@ -27,7 +27,9 @@
// Bochs VBE definitions
#define VBE_DISPI_TOTAL_VIDEO_MEMORY_MB 16
#ifndef VGA_MEM_FIX
#define VBE_DISPI_4BPP_PLANE_SHIFT 22
#endif
#define VBE_DISPI_BANK_ADDRESS 0xA0000

View File

@ -144,7 +144,9 @@ void bx_vgacore_c::init_standard_vga(void)
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
#ifndef VGA_MEM_FIX
BX_VGA_THIS s.plane_shift = 16;
#endif
BX_VGA_THIS s.dac_shift = 2;
BX_VGA_THIS s.last_bpp = 8;
BX_VGA_THIS s.vclk[0] = 25175000;
@ -343,7 +345,9 @@ void bx_vgacore_c::vgacore_register_state(bx_list_c *parent)
sprintf(name, "%d", i);
new bx_shadow_num_c(vclk, name, &BX_VGA_THIS s.vclk[i]);
}
#ifndef VGA_MEM_FIX
new bx_shadow_num_c(list, "plane_shift", &BX_VGA_THIS s.plane_shift);
#endif
new bx_shadow_num_c(list, "dac_shift", &BX_VGA_THIS s.dac_shift);
new bx_shadow_num_c(list, "ext_offset", &BX_VGA_THIS s.ext_offset);
BXRS_PARAM_BOOL(list, ext_y_dblsize, BX_VGA_THIS s.ext_y_dblsize);
@ -1218,10 +1222,18 @@ void bx_vgacore_c::set_override(bool enabled, void *dev)
}
}
#ifdef VGA_MEM_FIX
Bit8u bx_vgacore_c::get_vga_pixel(Bit16u x, Bit16u y, Bit32u raddr, Bit16u lc, bool bs, Bit8u *vgamem_ptr)
#else
Bit8u bx_vgacore_c::get_vga_pixel(Bit16u x, Bit16u y, Bit32u raddr, Bit16u lc, bool bs, Bit8u **plane)
#endif
{
Bit8u attribute, bit_no, palette_reg_val, DAC_regno;
#ifdef VGA_MEM_FIX
Bit32u vgamem_mask = BX_VGA_THIS s.memsize - 1;
#else
Bit32u plane_mask = ((Bit32u)1 << BX_VGA_THIS s.plane_shift) - 1;
#endif
Bit32u byte_offset;
if (BX_VGA_THIS s.x_dotclockdiv2) x >>= 1;
@ -1229,12 +1241,21 @@ Bit8u bx_vgacore_c::get_vga_pixel(Bit16u x, Bit16u y, Bit32u raddr, Bit16u lc, b
x += BX_VGA_THIS s.attribute_ctrl.horiz_pel_panning;
}
bit_no = 7 - (x % 8);
#ifdef VGA_MEM_FIX
byte_offset = ((raddr + (x / 8)) << 2) & vgamem_mask;
attribute =
(((vgamem_ptr[byte_offset] >> bit_no) & 0x01) << 0) |
(((vgamem_ptr[byte_offset + 1] >> bit_no) & 0x01) << 1) |
(((vgamem_ptr[byte_offset + 2] >> bit_no) & 0x01) << 2) |
(((vgamem_ptr[byte_offset + 3] >> bit_no) & 0x01) << 3);
#else
byte_offset = (raddr + (x / 8)) & plane_mask;
attribute =
(((plane[0][byte_offset] >> bit_no) & 0x01) << 0) |
(((plane[1][byte_offset] >> bit_no) & 0x01) << 1) |
(((plane[2][byte_offset] >> bit_no) & 0x01) << 2) |
(((plane[3][byte_offset] >> bit_no) & 0x01) << 3);
#endif
attribute &= BX_VGA_THIS s.attribute_ctrl.color_plane_enable;
// undocumented feature ???: colors 0..7 high intensity, colors 8..15 blinking
@ -1293,8 +1314,28 @@ bool bx_vgacore_c::skip_update(void)
void bx_vgacore_c::update_charmap(void)
{
#ifdef VGA_MEM_FIX
Bit8u charmap[0x2000];
Bit32u addr;
addr = (BX_VGA_THIS s.charmap_address1 << 2);
for (int i = 0; i < 0x2000; i++) {
charmap[i] = BX_VGA_THIS s.memory[addr + 2];
addr += 4;
}
bx_gui->set_text_charmap(0, charmap);
if (BX_VGA_THIS s.charmap_address2 != BX_VGA_THIS s.charmap_address1) {
addr = (BX_VGA_THIS s.charmap_address2 << 2) + 2;
for (int i = 0; i < 0x2000; i++) {
charmap[i] = BX_VGA_THIS s.memory[addr];
addr += 4;
}
}
bx_gui->set_text_charmap(1, charmap);
#else
bx_gui->set_text_charmap(0, &BX_VGA_THIS s.memory[0x20000 + BX_VGA_THIS s.charmap_address1]);
bx_gui->set_text_charmap(1, &BX_VGA_THIS s.memory[0x20000 + BX_VGA_THIS s.charmap_address2]);
#endif
}
void bx_vgacore_c::update(void)
@ -1335,7 +1376,8 @@ void bx_vgacore_c::update(void)
if (BX_VGA_THIS s.graphics_ctrl.graphics_alpha) {
// Graphics mode
Bit8u color;
Bit16u x, y, start_addr, line_offset;
Bit32u x, y, line_offset;
Bit32u start_addr;
unsigned r, c;
unsigned long byte_offset;
unsigned xc, yc, xti, yti;
@ -1359,13 +1401,14 @@ void bx_vgacore_c::update(void)
Bit8u attribute, palette_reg_val, DAC_regno;
Bit16u line_compare;
Bit32u row_addr;
#ifndef VGA_MEM_FIX
Bit8u *plane[4];
plane[0] = &BX_VGA_THIS s.memory[0 << BX_VGA_THIS s.plane_shift];
plane[1] = &BX_VGA_THIS s.memory[1 << BX_VGA_THIS s.plane_shift];
plane[2] = &BX_VGA_THIS s.memory[2 << BX_VGA_THIS s.plane_shift];
plane[3] = &BX_VGA_THIS s.memory[3 << BX_VGA_THIS s.plane_shift];
#endif
line_compare = BX_VGA_THIS s.line_compare;
if (BX_VGA_THIS s.y_doublescan) line_compare >>= 1;
@ -1384,7 +1427,11 @@ void bx_vgacore_c::update(void)
for (c=0; c<X_TILESIZE; c++) {
x = xc + c;
BX_VGA_THIS s.tile[r * X_TILESIZE + c] =
#ifdef VGA_MEM_FIX
BX_VGA_THIS get_vga_pixel(x, y, row_addr, line_compare, cs_visible, BX_VGA_THIS s.memory);
#else
BX_VGA_THIS get_vga_pixel(x, y, row_addr, line_compare, cs_visible, plane);
#endif
}
}
SET_TILE_UPDATED(BX_VGA_THIS, xti, yti, 0);
@ -1409,7 +1456,11 @@ void bx_vgacore_c::update(void)
for (c=0; c<X_TILESIZE; c++) {
x = xc + c;
BX_VGA_THIS s.tile[r * X_TILESIZE + c] =
#ifdef VGA_MEM_FIX
BX_VGA_THIS get_vga_pixel(x, y, row_addr, line_compare, cs_visible, BX_VGA_THIS s.memory);
#else
BX_VGA_THIS get_vga_pixel(x, y, row_addr, line_compare, cs_visible, plane);
#endif
}
}
SET_TILE_UPDATED(BX_VGA_THIS, xti, yti, 0);
@ -1445,6 +1496,9 @@ void bx_vgacore_c::update(void)
byte_offset += ((y & 1) << 13);
attribute = 6 - 2 * (x % 4);
#ifdef VGA_MEM_FIX
byte_offset = ((byte_offset & ~1) << 1) | (byte_offset & 1);
#endif
palette_reg_val = (BX_VGA_THIS s.memory[byte_offset]) >> attribute;
palette_reg_val &= 3;
DAC_regno = BX_VGA_THIS s.attribute_ctrl.palette_reg[palette_reg_val];
@ -1468,13 +1522,19 @@ void bx_vgacore_c::update(void)
if (BX_VGA_THIS s.y_doublescan) line_compare >>= 1;
if (BX_VGA_THIS s.CRTC.reg[0x14] & 0x40) { // DW set: doubleword mode
#ifndef VGA_MEM_FIX
unsigned long plane;
#endif
if (BX_VGA_THIS s.misc_output.select_high_bank != 1)
BX_PANIC(("update: select_high_bank != 1"));
#ifdef VGA_MEM_FIX
line_offset = BX_VGA_THIS s.line_offset;
start_addr <<= 2;
#else
line_offset = BX_VGA_THIS s.line_offset >> 2;
#endif
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)) {
@ -1488,8 +1548,12 @@ void bx_vgacore_c::update(void)
}
for (c=0; c<X_TILESIZE; c++) {
x = (xc + c) >> 1;
#ifdef VGA_MEM_FIX
byte_offset = (row_addr + x) & 0xffff;
#else
plane = (x % 4);
byte_offset = row_addr + (plane << 16) + (x >> 2);
#endif
color = BX_VGA_THIS s.memory[byte_offset];
BX_VGA_THIS s.tile[r*X_TILESIZE + c] = color;
}
@ -1500,9 +1564,17 @@ void bx_vgacore_c::update(void)
}
}
} else if (BX_VGA_THIS s.CRTC.reg[0x17] & 0x40) { // B/W set: byte mode, modeX
#ifndef VGA_MEM_FIX
unsigned long plane;
#endif
Bit8u h_panning;
#ifdef VGA_MEM_FIX
line_offset = BX_VGA_THIS s.line_offset << 2;
start_addr <<= 2;
#else
line_offset = BX_VGA_THIS s.line_offset;
#endif
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)) {
@ -1511,18 +1583,22 @@ void bx_vgacore_c::update(void)
if (BX_VGA_THIS s.y_doublescan) y >>= 1;
h_panning = BX_VGA_THIS s.attribute_ctrl.horiz_pel_panning / 2;
if (y > line_compare) {
row_addr = (y - line_compare - 1) * BX_VGA_THIS s.line_offset;
row_addr = (y - line_compare - 1) * line_offset;
if (BX_VGA_THIS s.attribute_ctrl.mode_ctrl.pixel_panning_compat) {
h_panning = 0;
}
} else {
row_addr = start_addr + (y * BX_VGA_THIS s.line_offset);
row_addr = start_addr + (y * line_offset);
}
for (c=0; c<X_TILESIZE; c++) {
x = (xc + c) >> 1;
x += h_panning;
#ifdef VGA_MEM_FIX
byte_offset = (row_addr + x) & 0x3ffff;
#else
plane = (x % 4);
byte_offset = (plane << 16) + ((row_addr + (x >> 2)) & 0xffff);
#endif
color = BX_VGA_THIS s.memory[byte_offset];
BX_VGA_THIS s.tile[r*X_TILESIZE + c] = color;
}
@ -1533,20 +1609,25 @@ void bx_vgacore_c::update(void)
}
}
} else { // word mode
#ifndef VGA_MEM_FIX
unsigned long plane;
#endif
BX_INFO(("256-color word mode untested"));
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)) {
for (r=0; r<Y_TILESIZE; r++) {
y = yc + r;
if (BX_VGA_THIS s.y_doublescan) y >>= 1;
row_addr = start_addr + (y * BX_VGA_THIS s.line_offset);
for (c=0; c<X_TILESIZE; c++) {
x = (xc + c) >> 1;
#ifdef VGA_MEM_FIX
byte_offset = (row_addr + ((x & ~1) << 1)) | (x & 1);
#else
plane = (x % 4);
byte_offset = (plane << 16) +
(y * BX_VGA_THIS s.line_offset)
+ ((x >> 1) & ~0x01);
byte_offset = (plane << 16) + row_addr + ((x >> 1) & ~0x01);
#endif
color = BX_VGA_THIS s.memory[start_addr + byte_offset];
BX_VGA_THIS s.tile[r*X_TILESIZE + c] = color;
}
@ -1652,15 +1733,33 @@ void bx_vgacore_c::update(void)
(cursor_address > (tm_info.start_address + tm_info.line_offset * rows))) {
cursor_address = 0xffff;
}
bx_gui->text_update_common(BX_VGA_THIS s.text_snapshot,
BX_VGA_THIS s.memory,
#ifdef VGA_MEM_FIX
int size = text_snap_size[BX_VGA_THIS s.graphics_ctrl.memory_mapping];
Bit8u *textmode_buffer = new Bit8u[size];
for (int i = 0; i < size; i += 2) {
textmode_buffer[i] = BX_VGA_THIS s.memory[i * 2];
textmode_buffer[i + 1] = BX_VGA_THIS s.memory[i * 2 + 1];
}
bx_gui->text_update_common(BX_VGA_THIS s.text_snapshot, textmode_buffer,
cursor_address, &tm_info);
#else
bx_gui->text_update_common(BX_VGA_THIS s.text_snapshot, BX_VGA_THIS s.memory,
cursor_address, &tm_info);
#endif
if (BX_VGA_THIS s.vga_mem_updated > 0) {
// screen updated, copy new VGA memory contents into text snapshot
#ifdef VGA_MEM_FIX
memcpy(BX_VGA_THIS s.text_snapshot, textmode_buffer,
tm_info.line_offset * rows + tm_info.start_address);
#else
memcpy(BX_VGA_THIS s.text_snapshot, BX_VGA_THIS s.memory,
tm_info.line_offset * rows + tm_info.start_address);
#endif
BX_VGA_THIS s.vga_mem_updated = 0;
}
#ifdef VGA_MEM_FIX
delete [] textmode_buffer;
#endif
}
}
@ -1689,7 +1788,9 @@ Bit8u bx_vgacore_c::mem_read(bx_phy_address addr)
{
Bit32u offset;
Bit8u read_map_select = BX_VGA_THIS s.graphics_ctrl.read_map_select;
#ifndef VGA_MEM_FIX
Bit8u *plane0, *plane1, *plane2, *plane3;
#endif
if (addr >= 0xA0000) {
switch (BX_VGA_THIS s.graphics_ctrl.memory_mapping) {
@ -1714,20 +1815,40 @@ Bit8u bx_vgacore_c::mem_read(bx_phy_address addr)
if (BX_VGA_THIS s.sequencer.chain_four) {
// Mode 13h: 320 x 200 256 color mode: chained pixel representation
#ifdef VGA_MEM_FIX
return BX_VGA_THIS s.memory[offset];
#else
return BX_VGA_THIS s.memory[(offset >> 2) + ((offset % 4) << 16)];
#endif
#ifdef VGA_MEM_FIX
} else if (BX_VGA_THIS s.graphics_ctrl.odd_even) {
Bit8u plane = (read_map_select & 2) | (offset & 1);
return BX_VGA_THIS s.memory[((offset & ~1) << 1) | plane];
#endif
}
#ifdef VGA_MEM_FIX
offset += BX_VGA_THIS s.ext_offset;
#else
plane0 = &BX_VGA_THIS s.memory[(0 << BX_VGA_THIS s.plane_shift) + BX_VGA_THIS s.ext_offset];
plane1 = &BX_VGA_THIS s.memory[(1 << BX_VGA_THIS s.plane_shift) + BX_VGA_THIS s.ext_offset];
plane2 = &BX_VGA_THIS s.memory[(2 << BX_VGA_THIS s.plane_shift) + BX_VGA_THIS s.ext_offset];
plane3 = &BX_VGA_THIS s.memory[(3 << BX_VGA_THIS s.plane_shift) + BX_VGA_THIS s.ext_offset];
#endif
switch (BX_VGA_THIS s.graphics_ctrl.read_mode) {
case 0: /* read mode 0 */
#ifdef VGA_MEM_FIX
BX_VGA_THIS s.graphics_ctrl.latch[0] = BX_VGA_THIS s.memory[offset << 2];
BX_VGA_THIS s.graphics_ctrl.latch[1] = BX_VGA_THIS s.memory[(offset << 2) + 1];
BX_VGA_THIS s.graphics_ctrl.latch[2] = BX_VGA_THIS s.memory[(offset << 2) + 2];
BX_VGA_THIS s.graphics_ctrl.latch[3] = BX_VGA_THIS s.memory[(offset << 2) + 3];
#else
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];
#endif
return BX_VGA_THIS s.graphics_ctrl.latch[read_map_select];
case 1: /* read mode 1 */
@ -1737,10 +1858,17 @@ Bit8u bx_vgacore_c::mem_read(bx_phy_address addr)
color_compare = BX_VGA_THIS s.graphics_ctrl.color_compare & 0x0f;
color_dont_care = BX_VGA_THIS s.graphics_ctrl.color_dont_care & 0x0f;
#ifdef VGA_MEM_FIX
latch0 = BX_VGA_THIS s.graphics_ctrl.latch[0] = BX_VGA_THIS s.memory[offset << 2];
latch1 = BX_VGA_THIS s.graphics_ctrl.latch[1] = BX_VGA_THIS s.memory[(offset << 2) + 1];
latch2 = BX_VGA_THIS s.graphics_ctrl.latch[2] = BX_VGA_THIS s.memory[(offset << 2) + 2];
latch3 = BX_VGA_THIS s.graphics_ctrl.latch[3] = BX_VGA_THIS s.memory[(offset << 2) + 3];
#else
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];
#endif
latch0 ^= ccdat[color_compare][0];
latch1 ^= ccdat[color_compare][1];
@ -1788,7 +1916,9 @@ void bx_vgacore_c::mem_write(bx_phy_address addr, Bit8u value)
Bit8u new_val[4] = {0,0,0,0};
unsigned start_addr;
Bit8u sequ_map_mask = BX_VGA_THIS s.sequencer.map_mask & 0x0f;
#ifndef VGA_MEM_FIX
Bit8u *plane0, *plane1, *plane2, *plane3;
#endif
if (addr >= 0xA0000) {
switch (BX_VGA_THIS s.graphics_ctrl.memory_mapping) {
@ -1816,7 +1946,11 @@ void bx_vgacore_c::mem_write(bx_phy_address addr, Bit8u value)
if (BX_VGA_THIS s.sequencer.chain_four) {
// 320 x 200 256 color mode: chained pixel representation
#ifdef VGA_MEM_FIX
BX_VGA_THIS s.memory[offset] = value;
#else
BX_VGA_THIS s.memory[(offset >> 2) + ((offset % 4) << 16)] = value;
#endif
BX_VGA_THIS s.vga_mem_updated |= (1 << (offset % 4));
if (BX_VGA_THIS s.graphics_ctrl.graphics_alpha) {
unsigned x_tileno, y_tileno;
@ -1847,12 +1981,53 @@ void bx_vgacore_c::mem_write(bx_phy_address addr, Bit8u value)
}
}
return;
#ifdef VGA_MEM_FIX
} else if (BX_VGA_THIS s.graphics_ctrl.odd_even) {
Bit8u plane = (BX_VGA_THIS s.graphics_ctrl.read_map_select & 2) | (offset & 1);
if (sequ_map_mask & (1 << plane)) {
BX_VGA_THIS s.memory[((offset & ~1) << 1) | plane] = value;
BX_VGA_THIS s.vga_mem_updated |= (1 << plane);
if (BX_VGA_THIS s.graphics_ctrl.graphics_alpha) {
unsigned x_tileno, y_tileno;
if ((BX_VGA_THIS s.CRTC.reg[0x17] & 1) == 0) { // MAP13 (CGA 320x200x4
unsigned xc, yc;
if ((BX_VGA_THIS s.CRTC.reg[0x17] & 0x40) == 0) {
start_addr <<= 1;
}
offset -= start_addr;
if (offset >= 0x2000) {
yc = (((offset - 0x2000) / (320 / 4)) << 1) + 1;
xc = ((offset - 0x2000) % (320 / 4)) << 2;
} else {
yc = (offset / (320 / 4)) << 1;
xc = (offset % (320 / 4)) << 2;
}
if ((BX_VGA_THIS s.graphics_ctrl.shift_reg == 0) || BX_VGA_THIS s.x_dotclockdiv2) {
xc <<= 1;
}
x_tileno = xc / X_TILESIZE;
if (BX_VGA_THIS s.y_doublescan) {
y_tileno = yc / (Y_TILESIZE / 2);
} else {
y_tileno = yc / Y_TILESIZE;
}
SET_TILE_UPDATED(BX_VGA_THIS, x_tileno, y_tileno, 1);
}
}
}
return;
#endif
}
#ifdef VGA_MEM_FIX
offset += BX_VGA_THIS s.ext_offset;
#else
plane0 = &BX_VGA_THIS s.memory[(0 << BX_VGA_THIS s.plane_shift) + BX_VGA_THIS s.ext_offset];
plane1 = &BX_VGA_THIS s.memory[(1 << BX_VGA_THIS s.plane_shift) + BX_VGA_THIS s.ext_offset];
plane2 = &BX_VGA_THIS s.memory[(2 << BX_VGA_THIS s.plane_shift) + BX_VGA_THIS s.ext_offset];
plane3 = &BX_VGA_THIS s.memory[(3 << BX_VGA_THIS s.plane_shift) + BX_VGA_THIS s.ext_offset];
#endif
switch (BX_VGA_THIS s.graphics_ctrl.write_mode) {
unsigned i;
@ -2100,13 +2275,29 @@ void bx_vgacore_c::mem_write(bx_phy_address addr, Bit8u value)
if (sequ_map_mask & 0x0f) {
BX_VGA_THIS s.vga_mem_updated |= (sequ_map_mask & 0x0f);
if (sequ_map_mask & 0x01)
#ifdef VGA_MEM_FIX
BX_VGA_THIS s.memory[offset << 2] = new_val[0];
#else
plane0[offset] = new_val[0];
#endif
if (sequ_map_mask & 0x02)
#ifdef VGA_MEM_FIX
BX_VGA_THIS s.memory[(offset << 2) + 1] = new_val[1];
#else
plane1[offset] = new_val[1];
#endif
if (sequ_map_mask & 0x04)
#ifdef VGA_MEM_FIX
BX_VGA_THIS s.memory[(offset << 2) + 2] = new_val[2];
#else
plane2[offset] = new_val[2];
#endif
if (sequ_map_mask & 0x08)
#ifdef VGA_MEM_FIX
BX_VGA_THIS s.memory[(offset << 2) + 3] = new_val[3];
#else
plane3[offset] = new_val[3];
#endif
if (BX_VGA_THIS s.graphics_ctrl.graphics_alpha) {
unsigned x_tileno, y_tileno;

View File

@ -23,6 +23,8 @@
#ifndef BX_IODEV_VGACORE_H
#define BX_IODEV_VGACORE_H
//#define VGA_MEM_FIX
// Make colour
#define MAKE_COLOUR(red, red_shiftfrom, red_shiftto, red_mask, \
green, green_shiftfrom, green_shiftto, green_mask, \
@ -125,7 +127,11 @@ protected:
Bit32u read(Bit32u address, unsigned io_len);
void write(Bit32u address, Bit32u value, unsigned io_len, bool no_log);
#ifdef VGA_MEM_FIX
Bit8u get_vga_pixel(Bit16u x, Bit16u y, Bit32u raddr, Bit16u lc, bool bs, Bit8u *vgamem_ptr);
#else
Bit8u get_vga_pixel(Bit16u x, Bit16u y, Bit32u raddr, Bit16u lc, bool bs, Bit8u **plane);
#endif
virtual void update(void);
void determine_screen_dimensions(unsigned *piHeight, unsigned *piWidth);
void calculate_retrace_timing(void);
@ -253,7 +259,9 @@ protected:
Bit32u vrend_usec;
Bit64u display_start_usec;
// shift values for extensions
#ifndef VGA_MEM_FIX
Bit8u plane_shift;
#endif
Bit8u dac_shift;
Bit32u ext_offset;
bool ext_y_dblsize;