Some work on the Voodoo Banshee emulation.

- Handling variable 'gui_update_pending' like Voodoo 1/2 fixes 3D display
  flicker. Simplified first stage of the update() code. Some 3D display issues
  still need to be investigated.
- Added missing 16-bit write support in 3D memory space.
- Added separate method for linear FB writes und use it for CMDFIFO packet type
  5, destination code 0. Added minimal "byte disable" support in this code.
This commit is contained in:
Volker Ruppert 2017-12-15 20:54:09 +00:00
parent 6a4e8ff2f1
commit 96f269d453
4 changed files with 81 additions and 58 deletions

View File

@ -798,13 +798,11 @@ void bx_voodoo_c::vertical_timer_handler(void *this_ptr)
}
if (v->fbi.video_changed || v->fbi.clut_dirty) {
// TODO: use tile-based update mechanism
BX_VOODOO_THIS redraw_area(0, 0, BX_VOODOO_THIS s.vdraw.width, BX_VOODOO_THIS s.vdraw.height);
v->fbi.clut_dirty = 0;
v->fbi.video_changed = 0;
if (BX_VOODOO_THIS s.model < VOODOO_BANSHEE) {
// TODO: use tile-based update mechanism
BX_VOODOO_THIS s.vdraw.gui_update_pending = 1;
}
BX_VOODOO_THIS s.vdraw.gui_update_pending = 1;
}
}
@ -942,7 +940,15 @@ void bx_voodoo_c::update(void)
bx_svga_tileinfo_t info;
BX_LOCK(render_mutex);
if (BX_VOODOO_THIS s.model < VOODOO_BANSHEE) {
if ((BX_VOODOO_THIS s.model >= VOODOO_BANSHEE) &&
((v->banshee.io[io_vidProcCfg] & 0x181) == 0x81)) {
bpp = v->banshee.disp_bpp;
start = v->banshee.io[io_vidDesktopStartAddr];
pitch = v->banshee.io[io_vidDesktopOverlayStride] & 0x7fff;
if (v->banshee.desktop_tiled) {
pitch *= 128;
}
} else {
if (!BX_VOODOO_THIS s.vdraw.gui_update_pending) {
BX_UNLOCK(render_mutex);
return;
@ -950,20 +956,6 @@ void bx_voodoo_c::update(void)
bpp = 16;
start = v->fbi.rgboffs[v->fbi.frontbuf];
pitch = v->fbi.rowpixels * 2;
} else {
if ((v->banshee.io[io_vidProcCfg] & 0x181) == 0x81) {
bpp = v->banshee.disp_bpp;
start = v->banshee.io[io_vidDesktopStartAddr];
pitch = v->banshee.io[io_vidDesktopOverlayStride] & 0x7fff;
if (v->banshee.desktop_tiled) {
pitch *= 128;
}
} else {
bpp = 16;
start = v->fbi.rgboffs[0];
pitch = v->fbi.rowpixels * 2;
BX_VOODOO_THIS redraw_area(0, 0, BX_VOODOO_THIS s.vdraw.width, BX_VOODOO_THIS s.vdraw.height);
}
}
iWidth = BX_VOODOO_THIS s.vdraw.width;
iHeight = BX_VOODOO_THIS s.vdraw.height;
@ -1686,7 +1678,7 @@ void bx_voodoo_c::banshee_mem_read(bx_phy_address addr, unsigned len, void *data
} else {
Bit8u temp = v->fbi.lfb_stride;
v->fbi.lfb_stride = 11;
value = lfb_r((offset & 0xffffff) >> 2);
value = lfb_r((offset & v->fbi.mask) >> 2);
v->fbi.lfb_stride = temp;
}
} else if ((addr & ~0x1ffffff) == BX_VOODOO_THIS pci_base_address[1]) {
@ -1714,10 +1706,6 @@ void bx_voodoo_c::banshee_mem_write(bx_phy_address addr, unsigned len, void *dat
Bit32u offset = (addr & 0x1ffffff);
Bit32u value = *(Bit32u*)data;
Bit32u mask = 0xffffffff;
Bit8u value8;
Bit32u start = v->banshee.io[io_vidDesktopStartAddr];
Bit32u pitch = v->banshee.io[io_vidDesktopOverlayStride] & 0x7fff;
unsigned i, x, y;
if ((addr & ~0x1ffffff) == BX_VOODOO_THIS pci_base_address[0]) {
if (offset < 0x80000) {
@ -1744,7 +1732,7 @@ void bx_voodoo_c::banshee_mem_write(bx_phy_address addr, unsigned len, void *dat
mask = 0xffff0000;
}
}
lfb_w((offset & 0xffffff) >> 2, value, mask);
lfb_w((offset & v->fbi.mask) >> 2, value, mask);
v->fbi.lfb_stride = temp;
}
} else if ((addr & ~0x1ffffff) == BX_VOODOO_THIS pci_base_address[1]) {
@ -1758,33 +1746,50 @@ void bx_voodoo_c::banshee_mem_write(bx_phy_address addr, unsigned len, void *dat
BX_INFO(("CMDFIFO #1 write"));
cmdfifo_w(&v->fbi.cmdfifo[1], offset, value);
} else {
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;
}
}
banshee_mem_write_linear(offset, value, len);
}
} else {
lfb_w((offset - v->fbi.lfb_base) >> 2, value, 0xffffffff);
if (len == 2) {
if ((offset & 3) == 0) {
mask = 0x0000ffff;
} else {
mask = 0xffff0000;
}
}
lfb_w((offset - v->fbi.lfb_base) >> 2, value, mask);
}
}
}
void bx_voodoo_c::banshee_mem_write_linear(Bit32u offset, Bit32u value, unsigned len)
{
Bit8u value8;
Bit32u start = v->banshee.io[io_vidDesktopStartAddr];
Bit32u pitch = v->banshee.io[io_vidDesktopOverlayStride] & 0x7fff;
unsigned i, x, y;
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;
}
}
}

View File

@ -82,6 +82,8 @@ public:
Bit32u banshee_blt_reg_read(Bit8u reg);
void banshee_blt_reg_write(Bit8u reg, Bit32u value);
void banshee_mem_write_linear(Bit32u offset, Bit32u value, unsigned len);
private:
bx_voodoo_t s;

View File

@ -1909,7 +1909,7 @@ void register_w(Bit32u offset, Bit32u data, bx_bool log)
else
rowpixels = (data & 0x3fff) >> 1;
if (v->fbi.rowpixels != rowpixels)
BX_PANIC(("aux buffer stride differs from color buffer stride"));
BX_ERROR(("aux buffer stride differs from color buffer stride"));
}
break;
@ -2534,10 +2534,10 @@ Bit32u cmdfifo_r(cmdfifo_info *f)
void cmdfifo_process(cmdfifo_info *f)
{
Bit32u command, data, mask, nwords, regaddr;
Bit8u type, code, nvertex, smode, data8;
Bit8u type, code, nvertex, smode, disbytes;
bx_bool blt, inc, pcolor;
voodoo_reg reg;
int i, j;
int i, w0, wn;
setup_vertex svert = {0};
command = cmdfifo_r(f);
@ -2715,18 +2715,33 @@ void cmdfifo_process(cmdfifo_info *f)
nwords = (command >> 3) & 0x7ffff;
regaddr = (cmdfifo_r(f) & 0xffffff) >> 2;
code = (command >> 30);
if ((command & 0x3fc00000) > 0) {
disbytes = (command >> 22) & 0xff;
if ((disbytes > 0) && (code != 0)) {
BX_ERROR(("CMDFIFO packet type 5: byte disable not supported yet (dest code = %d)", code));
}
switch (code) {
case 0:
regaddr <<= 2;
for (i = 0; i < (int)nwords; i++) {
w0 = 0;
wn = nwords;
if ((disbytes > 0) && (disbytes != 0x0c) && (disbytes != 0xc0)) {
BX_ERROR(("CMDFIFO packet type 5: byte disable not complete yet (dest code = 0)"));
}
if ((disbytes & 0xf0) > 0) {
data = cmdfifo_r(f);
for (j = 0; j < 4; j++) {
data8 = (data >> (j*8)) & 0xff;
v->fbi.ram[regaddr + j] = data8;
if ((disbytes & 0xf0) == 0x30) {
Voodoo_Banshee_LFB_write(regaddr + 2, data >> 16, 2);
} else if ((disbytes & 0xf0) == 0xc0) {
Voodoo_Banshee_LFB_write(regaddr, data, 2);
}
w0++;
regaddr += 4;
}
for (i = w0; i < wn; i++) {
data = cmdfifo_r(f);
BX_UNLOCK(cmdfifo_mutex);
Voodoo_Banshee_LFB_write(regaddr, data, 4);
BX_LOCK(cmdfifo_mutex);
regaddr += 4;
}
break;

View File

@ -73,5 +73,6 @@ enum
#define Voodoo_get_retrace(a) theVoodooDevice->get_retrace(a)
#define Voodoo_update_timing() theVoodooDevice->update_timing()
#define Voodoo_Banshee_2D_write(a,b) theVoodooDevice->banshee_blt_reg_write(a,b)
#define Voodoo_Banshee_LFB_write(a,b,c) theVoodooDevice->banshee_mem_write_linear(a,b,c)
#endif