Some work on the Voodoo Banshee emulation.
- Happy new year! - Improved pixel format conversion in host-to-screen operations. - Rewrite of the linear framebuffer read/write code fixes icons in 16 bpp mode. - Don't flood log file when polling the 2D status register (similar to 3D one). - FIXME list: - Minor issues in all Banshee modes (e.g. forward/back buttons in explorer). - Display errors in 16 bpp mode after leaving 3D mode. - Display errors in 16 bpp mode in case debug messages are turned on (timing). - Voodoo2 3D demo "donut" still fails. - Bochs crashes on Windows host (MSVC in some cases, MSYS2 64-bit build also reported, but not yet reproduced. - TODO list: - Remaining 2D stuff: polygon fill, stretching functions. - Move Banshee stuff to separate files. - Add Voodoo3 support (it's an improved Banshee card).
This commit is contained in:
parent
3c08cfedf2
commit
55c9bad4ef
@ -2,7 +2,7 @@
|
||||
// $Id$
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2012-2017 The Bochs Project
|
||||
// Copyright (C) 2012-2018 The Bochs Project
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Lesser General Public
|
||||
@ -89,6 +89,9 @@ const Bit8u banshee_iomask[256] = {4,0,0,0,7,1,3,1,7,1,3,1,7,1,3,1,7,1,3,1,
|
||||
7,1,3,1,7,1,3,1,7,1,3,1,7,1,3,1,7,1,3,1,
|
||||
7,1,3,1,7,1,3,1,7,1,3,1,7,1,3,1};
|
||||
|
||||
const Bit8u pxconv_table[16] = {0x3a,0x02,0x00,0x38,0x38,0x38,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
|
||||
|
||||
bx_voodoo_base_c* theVoodooDevice = NULL;
|
||||
bx_voodoo_vga_c* theVoodooVga = NULL;
|
||||
|
||||
@ -1557,12 +1560,12 @@ Bit32u bx_banshee_c::read_handler(void *this_ptr, Bit32u address, unsigned io_le
|
||||
|
||||
Bit32u bx_banshee_c::read(Bit32u address, unsigned io_len)
|
||||
{
|
||||
static Bit8u lastreg = 0xff;
|
||||
Bit32u result;
|
||||
|
||||
Bit8u offset = (Bit8u)(address & 0xff);
|
||||
Bit8u reg = (offset>>2);
|
||||
BX_DEBUG(("banshee read from offset 0x%02x (%s)", offset, banshee_io_reg_name[reg]));
|
||||
switch (offset>>2) {
|
||||
switch (reg) {
|
||||
case io_status:
|
||||
result = register_r(0);
|
||||
break;
|
||||
@ -1590,7 +1593,11 @@ Bit32u bx_banshee_c::read(Bit32u address, unsigned io_len)
|
||||
result = v->banshee.io[reg];
|
||||
break;
|
||||
}
|
||||
BX_DEBUG(("banshee read result = 0x%08x", result));
|
||||
if ((reg != io_status) || (lastreg != io_status)) {
|
||||
BX_DEBUG(("banshee read from offset 0x%02x (%s) result = 0x%08x", offset,
|
||||
banshee_io_reg_name[reg], result));
|
||||
}
|
||||
lastreg = reg;
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -1797,7 +1804,6 @@ void bx_banshee_c::mem_read(bx_phy_address addr, unsigned len, void *data)
|
||||
Bit32u *data_ptr = (Bit32u*)data;
|
||||
Bit32u value = 0xffffffff;
|
||||
Bit32u offset = (addr & 0x1ffffff);
|
||||
Bit32u start = v->banshee.io[io_vidDesktopStartAddr];
|
||||
Bit32u pitch = v->banshee.io[io_vidDesktopOverlayStride] & 0x7fff;
|
||||
unsigned i, x, y;
|
||||
|
||||
@ -1834,20 +1840,16 @@ void bx_banshee_c::mem_read(bx_phy_address addr, unsigned len, void *data)
|
||||
v->fbi.lfb_stride = temp;
|
||||
}
|
||||
} else if ((addr & ~0x1ffffff) == pci_base_address[1]) {
|
||||
if (offset < v->fbi.lfb_base) {
|
||||
if (v->banshee.desktop_tiled && (offset >= start)) {
|
||||
offset -= start;
|
||||
pitch *= 128;
|
||||
x = (offset << 0) & ((1 << v->fbi.lfb_stride) - 1);
|
||||
y = (offset >> v->fbi.lfb_stride) & 0x7ff;
|
||||
offset = (start + y * pitch + x) & v->fbi.mask;
|
||||
}
|
||||
value = 0;
|
||||
for (i = 0; i < len; i++) {
|
||||
value |= (v->fbi.ram[offset + i] << (i*8));
|
||||
}
|
||||
} else {
|
||||
value = lfb_r((offset - v->fbi.lfb_base) >> 2);
|
||||
if (offset >= v->fbi.lfb_base) {
|
||||
offset -= v->fbi.lfb_base;
|
||||
pitch *= 128;
|
||||
x = (offset << 0) & ((1 << v->fbi.lfb_stride) - 1);
|
||||
y = (offset >> v->fbi.lfb_stride) & 0x7ff;
|
||||
offset = (v->fbi.lfb_base + y * pitch + x) & v->fbi.mask;
|
||||
}
|
||||
value = 0;
|
||||
for (i = 0; i < len; i++) {
|
||||
value |= (v->fbi.ram[offset + i] << (i*8));
|
||||
}
|
||||
}
|
||||
*data_ptr = value;
|
||||
@ -1888,27 +1890,14 @@ void bx_banshee_c::mem_write(bx_phy_address addr, unsigned len, void *data)
|
||||
v->fbi.lfb_stride = temp;
|
||||
}
|
||||
} else if ((addr & ~0x1ffffff) == pci_base_address[1]) {
|
||||
if (offset < v->fbi.lfb_base) {
|
||||
offset &= v->fbi.mask;
|
||||
if (v->fbi.cmdfifo[0].enabled && (offset >= v->fbi.cmdfifo[0].base) &&
|
||||
(offset < v->fbi.cmdfifo[0].end)) {
|
||||
cmdfifo_w(&v->fbi.cmdfifo[0], offset, value);
|
||||
} else if (v->fbi.cmdfifo[1].enabled && (offset >= v->fbi.cmdfifo[1].base) &&
|
||||
(offset < v->fbi.cmdfifo[1].end)) {
|
||||
BX_INFO(("CMDFIFO #1 write"));
|
||||
cmdfifo_w(&v->fbi.cmdfifo[1], offset, value);
|
||||
} else {
|
||||
mem_write_linear(offset, value, len);
|
||||
}
|
||||
if (v->fbi.cmdfifo[0].enabled && (offset >= v->fbi.cmdfifo[0].base) &&
|
||||
(offset < v->fbi.cmdfifo[0].end)) {
|
||||
cmdfifo_w(&v->fbi.cmdfifo[0], offset, value);
|
||||
} else if (v->fbi.cmdfifo[1].enabled && (offset >= v->fbi.cmdfifo[1].base) &&
|
||||
(offset < v->fbi.cmdfifo[1].end)) {
|
||||
cmdfifo_w(&v->fbi.cmdfifo[1], offset, value);
|
||||
} else {
|
||||
if (len == 2) {
|
||||
if ((offset & 3) == 0) {
|
||||
mask = 0x0000ffff;
|
||||
} else {
|
||||
mask = 0xffff0000;
|
||||
}
|
||||
}
|
||||
lfb_w((offset - v->fbi.lfb_base) >> 2, value, mask);
|
||||
mem_write_linear(offset, value, len);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1920,30 +1909,27 @@ void bx_banshee_c::mem_write_linear(Bit32u offset, Bit32u value, unsigned len)
|
||||
Bit32u pitch = v->banshee.io[io_vidDesktopOverlayStride] & 0x7fff;
|
||||
unsigned i, x, y;
|
||||
|
||||
if (offset >= v->fbi.lfb_base) {
|
||||
offset -= v->fbi.lfb_base;
|
||||
pitch *= 128;
|
||||
x = (offset << 0) & ((1 << v->fbi.lfb_stride) - 1);
|
||||
y = (offset >> v->fbi.lfb_stride) & 0x7ff;
|
||||
offset = (start + y * pitch + x) & v->fbi.mask;
|
||||
} else {
|
||||
offset &= v->fbi.mask;
|
||||
}
|
||||
BX_LOCK(render_mutex);
|
||||
for (i = 0; i < len; i++) {
|
||||
value8 = (value >> (i*8)) & 0xff;
|
||||
v->fbi.ram[offset + i] = value8;
|
||||
}
|
||||
if (offset >= start) {
|
||||
if (v->banshee.desktop_tiled) {
|
||||
offset -= start;
|
||||
pitch *= 128;
|
||||
x = (offset << 0) & ((1 << v->fbi.lfb_stride) - 1);
|
||||
y = (offset >> v->fbi.lfb_stride) & 0x7ff;
|
||||
offset = (start + y * pitch + x) & v->fbi.mask;
|
||||
}
|
||||
BX_LOCK(render_mutex);
|
||||
for (i = 0; i < len; i++) {
|
||||
value8 = (value >> (i*8)) & 0xff;
|
||||
v->fbi.ram[offset + i] = value8;
|
||||
}
|
||||
offset -= start;
|
||||
x = (offset % pitch) / (v->banshee.disp_bpp >> 3);
|
||||
y = offset / pitch;
|
||||
theVoodooVga->redraw_area(x, y, len / (v->banshee.disp_bpp >> 3), 1);
|
||||
BX_UNLOCK(render_mutex);
|
||||
} else {
|
||||
for (i = 0; i < len; i++) {
|
||||
value8 = (value >> (i*8)) & 0xff;
|
||||
v->fbi.ram[offset + i] = value8;
|
||||
}
|
||||
}
|
||||
BX_UNLOCK(render_mutex);
|
||||
}
|
||||
|
||||
Bit32u bx_banshee_c::agp_reg_read(Bit8u reg)
|
||||
@ -2818,7 +2804,7 @@ void bx_banshee_c::blt_host_to_screen()
|
||||
Bit8u *src_ptr1, *dst_ptr1;
|
||||
Bit16u spitch = BLT.h2s_pitch;
|
||||
Bit8u srcfmt = BLT.src_fmt;
|
||||
Bit8u spxsize = 0, r, g, b;
|
||||
Bit8u spxsize = 0, r = 0, g = 0, b = 0;
|
||||
Bit8u dstcolor[4], scolor[4];
|
||||
Bit8u *srccolor;
|
||||
int ncols, nrows, x0, y0, x1, y1, w, h;
|
||||
@ -2831,8 +2817,8 @@ void bx_banshee_c::blt_host_to_screen()
|
||||
w = BLT.dst_w;
|
||||
h = BLT.dst_h;
|
||||
BX_DEBUG(("Host to screen blt: %d x %d ROP %02X", w, h, BLT.rop0));
|
||||
if ((srcfmt != 0) && (dpxsize != 2) && (BLT.dst_fmt != srcfmt)) {
|
||||
BX_ERROR(("Pixel format conversion not supported yet"));
|
||||
if ((pxconv_table[srcfmt] & (1 << BLT.dst_fmt)) == 0) {
|
||||
BX_ERROR(("Pixel format conversion not supported"));
|
||||
}
|
||||
x0 = 0;
|
||||
y0 = 0;
|
||||
@ -2875,13 +2861,25 @@ void bx_banshee_c::blt_host_to_screen()
|
||||
BLT.rop_fn(dst_ptr1, srccolor, dpitch, dpxsize, dpxsize, 1);
|
||||
} else {
|
||||
if (BLT.dst_fmt != srcfmt) {
|
||||
if ((dpxsize == 2) && ((srcfmt == 4) || (srcfmt == 5))) {
|
||||
if ((srcfmt == 4) || (srcfmt == 5)) {
|
||||
b = src_ptr1[0];
|
||||
g = src_ptr1[1];
|
||||
r = src_ptr1[2];
|
||||
} else if (srcfmt == 3) {
|
||||
b = src_ptr1[0] << 3;
|
||||
g = ((src_ptr1[1] & 0x07) << 5) | ((src_ptr1[0] & 0xe0) >> 3);
|
||||
r = src_ptr1[1] & 0xf8;
|
||||
}
|
||||
if (dpxsize == 2) {
|
||||
scolor[0] = (b >> 3) | ((g & 0x1c) << 3);
|
||||
scolor[1] = (g >> 5) | (r & 0xf8);
|
||||
BLT.rop_fn(dst_ptr1, scolor, dpitch, dpxsize, dpxsize, 1);
|
||||
} else if ((dpxsize == 3) || (dpxsize == 4)) {
|
||||
scolor[0] = b;
|
||||
scolor[1] = g;
|
||||
scolor[2] = r;
|
||||
scolor[3] = 0;
|
||||
BLT.rop_fn(dst_ptr1, scolor, dpitch, dpxsize, dpxsize, 1);
|
||||
}
|
||||
} else {
|
||||
BLT.rop_fn(dst_ptr1, src_ptr1, dpitch, dpxsize, dpxsize, 1);
|
||||
|
Loading…
Reference in New Issue
Block a user