Some work on the Voodoo2 CMDFIFO support.

- Added CMDFIFO thread similar to the sound output thread.
- split register write function in 2 functions: register_w_common() handles
  the CMDFIFO writes and valid registers in CMDFIFO mode. It forwards write
  accesses to other registers to register_w() (Voodoo1 and non-CMDFIFO mode).
  The CMDFIFO thread also calls register_w() when processing data.
- The CMDFIFO thread processes all data, but it does not yet execute type 3
  requests (extended triangle generator missing).
- TODO #1: implement Voodoo2 specific triangle functions (for CMDFIFO).
- TODO #2: implement 2D bitblt engine.
This commit is contained in:
Volker Ruppert 2017-05-14 15:53:29 +00:00
parent 19f6cbc519
commit 6265976a2c
3 changed files with 426 additions and 174 deletions

View File

@ -75,6 +75,10 @@
bx_voodoo_c* theVoodooDevice = NULL;
#ifndef WIN32
#include <pthread.h>
#endif
#include "voodoo_types.h"
#include "voodoo_data.h"
#include "voodoo_main.h"
@ -154,6 +158,22 @@ void CDECL libvoodoo_LTX_plugin_fini(void)
delete theVoodooDevice;
}
// cmdfifo thread (Voodoo2)
BX_THREAD_FUNC(cmdfifo_thread, indata)
{
UNUSED(indata);
cmdfifo_control = 1;
while (cmdfifo_control > 0) {
while ((cmdfifo_control > 0) && (v->fbi.cmdfifo[0].depth == 0)) {
BX_MSLEEP(1);
}
cmdfifo_process();
}
cmdfifo_control = -1;
BX_THREAD_EXIT;
}
// the device object
bx_voodoo_c::bx_voodoo_c()
@ -166,6 +186,13 @@ bx_voodoo_c::bx_voodoo_c()
bx_voodoo_c::~bx_voodoo_c()
{
if (cmdfifo_control > 0) {
cmdfifo_control = 0;
while (cmdfifo_control >= 0) {
BX_MSLEEP(1);
}
BX_FINI_MUTEX(cmdfifo_mutex);
}
if (v != NULL) {
free(v->fbi.ram);
free(v->tmu[0].ram);
@ -220,6 +247,11 @@ void bx_voodoo_c::init(void)
voodoo_init(BX_VOODOO_THIS s.model);
if (BX_VOODOO_THIS s.model == VOODOO_2) {
BX_INIT_MUTEX(cmdfifo_mutex);
BX_THREAD_CREATE(cmdfifo_thread, this, cmdfifo_threadID);
}
BX_INFO(("3dfx Voodoo Graphics adapter (model=%s) initialized",
SIM->get_param_enum("model", base)->get_selected()));
}

View File

@ -1610,7 +1610,7 @@ struct _fbi_state
stats_block lfb_stats; /* LFB-access statistics */
Bit8u sverts; /* number of vertices ready */
setup_vertex svert[3]; /* 3 setup vertices */
setup_vertex svert[4]; /* 3 setup vertices + 1 for current data */
fifo_state fifo; /* framebuffer memory fifo */
cmdfifo_info cmdfifo[2]; /* command FIFOs */

View File

@ -60,6 +60,11 @@ Bit32u voodoo_last_msg = 255;
#define MODIFY_PIXEL(VV)
/* cmdfifo thread (Voodoo2) */
BX_THREAD_ID(cmdfifo_threadID);
int cmdfifo_control = 0;
BX_MUTEX(cmdfifo_mutex);
/* fast dither lookup */
static Bit8u dither4_lookup[256*16*2];
static Bit8u dither2_lookup[256*16*2];
@ -1303,57 +1308,17 @@ void dacdata_r(dac_state *d, Bit8u regnum)
d->read_result = result;
}
void cmdfifo_put(Bit32u fbi_offset, Bit32u data)
{
BX_ERROR(("Writing to CMDFIFO has no effect yet: FBI offset=0x%08x, data=0x%08x",
fbi_offset, data));
*(Bit32u*)&v->fbi.ram[fbi_offset] = data;
v->fbi.cmdfifo[0].depth++;
}
voodoo_reg reg;
void register_w(Bit32u offset, Bit32u data)
void register_w(Bit32u offset, Bit32u data, bx_bool log)
{
Bit32u regnum = (offset) & 0xff;
Bit32u chips = (offset>>8) & 0xf;
reg.u = data;
Bit64s data64;
BX_DEBUG(("write chip 0x%x reg 0x%x value 0x%08x(%s)", chips, regnum<<2, data, voodoo_reg_name[regnum]));
voodoo_last_msg=regnum;
if (chips == 0)
chips = 0xf;
/* the first 64 registers can be aliased differently */
if ((offset & 0x800c0) == 0x80000 && v->alt_regmap)
regnum = register_alias_map[offset & 0x3f];
else
regnum = offset & 0xff;
/* first make sure this register is writable */
if (!(v->regaccess[regnum] & REGISTER_WRITE)) {
BX_DEBUG(("Invalid attempt to write %s", v->regnames[regnum]));
return;
}
if (FBIINIT7_CMDFIFO_ENABLE(v->reg[fbiInit7].u)) {
if (!FBIINIT7_CMDFIFO_MEMORY_STORE(v->reg[fbiInit7].u)) {
BX_ERROR(("CMDFIFO-to-FIFO mode not supported yet"));
} else if ((offset & 0x80000) > 0) {
Bit32u fbi_offset = (v->fbi.cmdfifo[0].base + ((offset & 0xffff) << 2)) & v->fbi.mask;
cmdfifo_put(fbi_offset, data);
return;
} else {
if (v->regaccess[regnum] & REGISTER_WRITETHRU) {
BX_DEBUG(("Writing to register %s in CMDFIFO mode", v->regnames[regnum]));
} else {
BX_DEBUG(("Invalid attempt to write %s in CMDFIFO mode", v->regnames[regnum]));
return;
}
}
}
if (log)
BX_DEBUG(("write chip 0x%x reg 0x%x value 0x%08x(%s)", chips, regnum<<2, data, voodoo_reg_name[regnum]));
switch (regnum) {
/* Vertex data is 12.4 formatted fixed point */
@ -1663,113 +1628,6 @@ void register_w(Bit32u offset, Bit32u data)
BX_DEBUG(("clutData ignored because video timing reset = 1"));
}
break;
/* external DAC access -- Voodoo/Voodoo2 only */
case dacData:
if (v->type <= VOODOO_2 /*&& (chips & 1)*/)
{
poly_wait(v->poly, v->regnames[regnum]);
if (!(data & 0x800))
dacdata_w(&v->dac, (data >> 8) & 7, data & 0xff);
else
dacdata_r(&v->dac, (data >> 8) & 7);
}
break;
/* vertical sync rate -- Voodoo/Voodoo2 only */
case hSync:
case vSync:
case backPorch:
case videoDimensions:
if (v->type <= VOODOO_2 && (chips & 1))
{
poly_wait(v->poly, v->regnames[regnum]);
v->reg[regnum].u = data;
if (v->reg[hSync].u != 0 && v->reg[vSync].u != 0 && v->reg[videoDimensions].u != 0)
{
int htotal = ((v->reg[hSync].u >> 16) & 0x3ff) + 1 + (v->reg[hSync].u & 0xff) + 1;
int vtotal = ((v->reg[vSync].u >> 16) & 0xfff) + (v->reg[vSync].u & 0xfff);
int hvis = v->reg[videoDimensions].u & 0x3ff;
int vvis = (v->reg[videoDimensions].u >> 16) & 0x3ff;
int hbp = (v->reg[backPorch].u & 0xff) + 2;
int vbp = (v->reg[backPorch].u >> 16) & 0xff;
rectangle visarea;
/* create a new visarea */
visarea.min_x = hbp;
visarea.max_x = hbp + hvis - 1;
visarea.min_y = vbp;
visarea.max_y = vbp + vvis - 1;
/* keep within bounds */
visarea.max_x = MIN(visarea.max_x, htotal - 1);
visarea.max_y = MIN(visarea.max_y, vtotal - 1);
BX_DEBUG(("hSync=%08X vSync=%08X backPorch=%08X videoDimensions=%08X",
v->reg[hSync].u, v->reg[vSync].u, v->reg[backPorch].u, v->reg[videoDimensions].u));
BX_DEBUG(("Horiz: %d-%d (%d total) Vert: %d-%d (%d total) -- ", visarea.min_x, visarea.max_x, htotal, visarea.min_y, visarea.max_y, vtotal));
/* configure the new framebuffer info */
v->fbi.width = hvis + 1;
v->fbi.height = vvis;
v->fbi.xoffs = hbp;
v->fbi.yoffs = vbp;
v->fbi.vsyncscan = (v->reg[vSync].u >> 16) & 0xfff;
/* if changing dimensions, update video memory layout */
if (regnum == videoDimensions)
recompute_video_memory(v);
Voodoo_UpdateScreenStart();
}
}
break;
/* fbiInit0 can only be written if initEnable says we can -- Voodoo/Voodoo2 only */
case fbiInit0:
poly_wait(v->poly, v->regnames[regnum]);
if (v->type <= VOODOO_2 && (chips & 1) && INITEN_ENABLE_HW_INIT(v->pci.init_enable)) {
Voodoo_Output_Enable(data & 1);
v->reg[fbiInit0].u = data;
if (FBIINIT0_GRAPHICS_RESET(data))
soft_reset(v);
if (FBIINIT0_FIFO_RESET(data))
fifo_reset(&v->pci.fifo);
recompute_video_memory(v);
}
break;
/* fbiInitX can only be written if initEnable says we can -- Voodoo/Voodoo2 only */
/* most of these affect memory layout, so always recompute that when done */
case fbiInit1:
case fbiInit2:
case fbiInit4:
case fbiInit5:
case fbiInit6:
case fbiInit7:
poly_wait(v->poly, v->regnames[regnum]);
if (v->type <= VOODOO_2 && (chips & 1) && INITEN_ENABLE_HW_INIT(v->pci.init_enable))
{
if ((v->type == VOODOO_2) && (regnum == fbiInit7)) {
v->fbi.cmdfifo[0].enable = FBIINIT7_CMDFIFO_ENABLE(data);
}
v->reg[regnum].u = data;
recompute_video_memory(v);
v->fbi.video_changed = 1;
}
break;
case fbiInit3:
poly_wait(v->poly, v->regnames[regnum]);
if (v->type <= VOODOO_2 && (chips & 1) && INITEN_ENABLE_HW_INIT(v->pci.init_enable))
{
v->reg[regnum].u = data;
v->alt_regmap = FBIINIT3_TRI_REGISTER_REMAP(data);
v->fbi.yorigin = FBIINIT3_YORIGIN_SUBTRACT(v->reg[fbiInit3].u);
recompute_video_memory(v);
}
break;
/* nccTable entries are processed and expanded immediately */
case nccTable+0:
case nccTable+1:
@ -1876,32 +1734,23 @@ void register_w(Bit32u offset, Bit32u data)
goto default_case;
break;
case cmdFifoBaseAddr:
v->fbi.cmdfifo[0].base = (data & 0x3ff) << 12;
v->fbi.cmdfifo[0].end = ((data >> 16) & 0x3ff) << 12;
break;
case cmdFifoRdPtr:
v->fbi.cmdfifo[0].rdptr = data;
break;
case cmdFifoDepth:
v->fbi.cmdfifo[0].depth = data & 0xffff;
break;
case cmdFifoAMin:
v->fbi.cmdfifo[0].amin = data;
break;
case cmdFifoAMax:
v->fbi.cmdfifo[0].amax = data;
break;
case intrCtrl:
case userIntrCMD:
case bltSrcBaseAddr:
case bltDstBaseAddr:
case bltXYStrides:
case bltSrcChromaRange:
case bltDstChromaRange:
case bltClipX:
case bltClipY:
case bltSrcXY:
case bltDstXY:
case bltSize:
case bltRop:
case bltColor:
case bltCommand:
case bltData:
BX_ERROR(("Writing to register %s not supported yet", v->regnames[regnum]));
v->reg[regnum].u = data;
break;
/* these registers are referenced in the renderer; we must wait for pending work before changing */
@ -2414,6 +2263,373 @@ nextpixel:
return 0;
}
void cmdfifo_put(Bit32u fbi_offset, Bit32u data)
{
BX_LOCK(cmdfifo_mutex);
*(Bit32u*)(&v->fbi.ram[fbi_offset]) = data;
v->fbi.cmdfifo[0].depth++;
BX_UNLOCK(cmdfifo_mutex);
}
Bit32u cmdfifo_get(void)
{
Bit32u data;
while ((cmdfifo_control > 0) && (v->fbi.cmdfifo[0].depth == 0)) {
BX_MSLEEP(1);
}
BX_LOCK(cmdfifo_mutex);
data = *(Bit32u*)(&v->fbi.ram[v->fbi.cmdfifo[0].rdptr & v->fbi.mask]);
v->fbi.cmdfifo[0].rdptr += 4;
v->fbi.cmdfifo[0].depth--;
BX_UNLOCK(cmdfifo_mutex);
return data;
}
void cmdfifo_process(void)
{
Bit32u data, mask, nwords, regaddr;
Bit8u type, code, nvertex, smode;
bx_bool inc, pcolor;
voodoo_reg reg;
data = cmdfifo_get();
type = (Bit8u)(data & 0x07);
switch (type) {
case 0:
code = (Bit8u)((data >> 3) & 0x07);
switch (code) {
case 0: // NOP
break;
case 3: // JMP
v->fbi.cmdfifo[0].rdptr = (data >> 4) & 0xfffffc;
break;
default:
BX_ERROR(("CMDFIFO packet type 0: unsupported code %d", code));
}
break;
case 1:
nwords = (data >> 16);
regaddr = (data & 0x7ff8) >> 3;
inc = (data >> 15) & 1;
while (nwords--) {
data = cmdfifo_get();
register_w(regaddr, data, 1);
if (inc) regaddr++;
}
break;
case 2:
BX_INFO(("CMDFIFO packet type 2: not tested yet"));
mask = (data >> 3);
regaddr = bltSrcBaseAddr;
while (mask) {
if (mask & 1) {
data = cmdfifo_get();
register_w(regaddr, data, 1);
}
regaddr++;
mask >>= 1;
}
break;
case 3:
BX_ERROR(("CMDFIFO packet type 3: not implemented yet"));
nwords = (data >> 29);
pcolor = (data >> 28) & 1;
smode = (data >> 22) & 0x3f;
mask = (data >> 10) & 0xff;
nvertex = (data >> 6) & 0x0f;
code = (data >> 3) & 0x07;
register_w(sSetupMode, (smode << 16) | mask, 1);
// TODO
while (nvertex--) {
reg.u = cmdfifo_get();
v->fbi.svert[3].x = reg.f;
reg.u = cmdfifo_get();
v->fbi.svert[3].y = reg.f;
if (mask & 0x01) {
if (pcolor) {
data = cmdfifo_get();
v->fbi.svert[3].b = (float)(data & 0xff);
v->fbi.svert[3].g = (float)((data >> 8) & 0xff);
v->fbi.svert[3].r = (float)((data >> 16) & 0xff);
v->fbi.svert[3].a = (float)((data >> 24) & 0xff);
} else {
reg.u = cmdfifo_get();
v->fbi.svert[3].r = reg.f;
reg.u = cmdfifo_get();
v->fbi.svert[3].g = reg.f;
reg.u = cmdfifo_get();
v->fbi.svert[3].b = reg.f;
}
}
if ((mask & 0x02) && !pcolor) {
reg.u = cmdfifo_get();
v->fbi.svert[3].a = reg.f;
}
if (mask & 0x04) {
reg.u = cmdfifo_get();
v->fbi.svert[3].z = reg.f;
}
if (mask & 0x08) {
reg.u = cmdfifo_get();
v->fbi.svert[3].wb = reg.f;
}
if (mask & 0x10) {
reg.u = cmdfifo_get();
v->fbi.svert[3].w0 = reg.f;
}
if (mask & 0x20) {
reg.u = cmdfifo_get();
v->fbi.svert[3].s0 = reg.f;
reg.u = cmdfifo_get();
v->fbi.svert[3].t0 = reg.f;
}
if (mask & 0x40) {
reg.u = cmdfifo_get();
v->fbi.svert[3].w1 = reg.f;
}
if (mask & 0x80) {
reg.u = cmdfifo_get();
v->fbi.svert[3].s1 = reg.f;
reg.u = cmdfifo_get();
v->fbi.svert[3].t1 = reg.f;
}
// TODO
}
while (nwords--) cmdfifo_get();
break;
case 4:
nwords = (data >> 29);
mask = (data >> 15) & 0x3fff;
regaddr = (data & 0x7ff8) >> 3;
while (mask) {
if (mask & 1) {
data = cmdfifo_get();
register_w(regaddr, data, 1);
}
regaddr++;
mask >>= 1;
}
while (nwords--) cmdfifo_get();
break;
case 5:
if ((data & 0x3fc00000) > 0) {
BX_ERROR(("CMDFIFO packet type 5: byte disable not supported yet"));
}
nwords = (data >> 3) & 0x7ffff;
regaddr = (cmdfifo_get() & 0xffffff) >> 2;
code = (data >> 30);
switch (code) {
case 2:
while (nwords--) {
data = cmdfifo_get();
lfb_w(regaddr, data, 0xffffffff);
regaddr++;
}
break;
case 3:
while (nwords--) {
data = cmdfifo_get();
texture_w(regaddr, data);
regaddr++;
}
break;
default:
BX_ERROR(("CMDFIFO packet type 5: unsupported destination type %d", code));
}
break;
default:
BX_ERROR(("CMDFIFO: unsupported packet type %d", type));
}
}
voodoo_reg reg;
void register_w_common(Bit32u offset, Bit32u data)
{
Bit32u regnum = (offset) & 0xff;
Bit32u chips = (offset>>8) & 0xf;
reg.u = data;
/* Voodoo 2 CMDFIFO handling */
if (FBIINIT7_CMDFIFO_ENABLE(v->reg[fbiInit7].u)) {
if (!FBIINIT7_CMDFIFO_MEMORY_STORE(v->reg[fbiInit7].u)) {
BX_ERROR(("CMDFIFO-to-FIFO mode not supported yet"));
} else if ((offset & 0x80000) > 0) {
Bit32u fbi_offset = (v->fbi.cmdfifo[0].base + ((offset & 0xffff) << 2)) & v->fbi.mask;
BX_DEBUG(("CMDFIFO write: FBI offset=0x%08x, data=0x%08x", fbi_offset, data));
cmdfifo_put(fbi_offset, data);
return;
} else {
if (v->regaccess[regnum] & REGISTER_WRITETHRU) {
BX_DEBUG(("Writing to register %s in CMDFIFO mode", v->regnames[regnum]));
} else {
BX_DEBUG(("Invalid attempt to write %s in CMDFIFO mode", v->regnames[regnum]));
return;
}
}
}
if (chips == 0)
chips = 0xf;
/* first make sure this register is writable */
if (!(v->regaccess[regnum] & REGISTER_WRITE)) {
BX_DEBUG(("Invalid attempt to write %s", v->regnames[regnum]));
return;
}
/* the first 64 registers can be aliased differently */
if ((offset & 0x800c0) == 0x80000 && v->alt_regmap)
regnum = register_alias_map[offset & 0x3f];
else
regnum = offset & 0xff;
BX_DEBUG(("write chip 0x%x reg 0x%x value 0x%08x(%s)", chips, regnum<<2, data, voodoo_reg_name[regnum]));
switch (regnum) {
/* external DAC access -- Voodoo/Voodoo2 only */
case dacData:
if (v->type <= VOODOO_2 /*&& (chips & 1)*/)
{
poly_wait(v->poly, v->regnames[regnum]);
if (!(data & 0x800))
dacdata_w(&v->dac, (data >> 8) & 7, data & 0xff);
else
dacdata_r(&v->dac, (data >> 8) & 7);
}
break;
/* vertical sync rate -- Voodoo/Voodoo2 only */
case hSync:
case vSync:
case backPorch:
case videoDimensions:
if (v->type <= VOODOO_2 && (chips & 1))
{
poly_wait(v->poly, v->regnames[regnum]);
v->reg[regnum].u = data;
if (v->reg[hSync].u != 0 && v->reg[vSync].u != 0 && v->reg[videoDimensions].u != 0)
{
int htotal = ((v->reg[hSync].u >> 16) & 0x3ff) + 1 + (v->reg[hSync].u & 0xff) + 1;
int vtotal = ((v->reg[vSync].u >> 16) & 0xfff) + (v->reg[vSync].u & 0xfff);
int hvis = v->reg[videoDimensions].u & 0x3ff;
int vvis = (v->reg[videoDimensions].u >> 16) & 0x3ff;
int hbp = (v->reg[backPorch].u & 0xff) + 2;
int vbp = (v->reg[backPorch].u >> 16) & 0xff;
rectangle visarea;
/* create a new visarea */
visarea.min_x = hbp;
visarea.max_x = hbp + hvis - 1;
visarea.min_y = vbp;
visarea.max_y = vbp + vvis - 1;
/* keep within bounds */
visarea.max_x = MIN(visarea.max_x, htotal - 1);
visarea.max_y = MIN(visarea.max_y, vtotal - 1);
BX_DEBUG(("hSync=%08X vSync=%08X backPorch=%08X videoDimensions=%08X",
v->reg[hSync].u, v->reg[vSync].u, v->reg[backPorch].u, v->reg[videoDimensions].u));
BX_DEBUG(("Horiz: %d-%d (%d total) Vert: %d-%d (%d total) -- ", visarea.min_x, visarea.max_x, htotal, visarea.min_y, visarea.max_y, vtotal));
/* configure the new framebuffer info */
v->fbi.width = hvis + 1;
v->fbi.height = vvis;
v->fbi.xoffs = hbp;
v->fbi.yoffs = vbp;
v->fbi.vsyncscan = (v->reg[vSync].u >> 16) & 0xfff;
/* if changing dimensions, update video memory layout */
if (regnum == videoDimensions)
recompute_video_memory(v);
Voodoo_UpdateScreenStart();
}
}
break;
/* fbiInit0 can only be written if initEnable says we can -- Voodoo/Voodoo2 only */
case fbiInit0:
poly_wait(v->poly, v->regnames[regnum]);
if (v->type <= VOODOO_2 && (chips & 1) && INITEN_ENABLE_HW_INIT(v->pci.init_enable)) {
Voodoo_Output_Enable(data & 1);
v->reg[fbiInit0].u = data;
if (FBIINIT0_GRAPHICS_RESET(data))
soft_reset(v);
if (FBIINIT0_FIFO_RESET(data))
fifo_reset(&v->pci.fifo);
recompute_video_memory(v);
}
break;
/* fbiInitX can only be written if initEnable says we can -- Voodoo/Voodoo2 only */
/* most of these affect memory layout, so always recompute that when done */
case fbiInit1:
case fbiInit2:
case fbiInit4:
case fbiInit5:
case fbiInit6:
case fbiInit7:
poly_wait(v->poly, v->regnames[regnum]);
if (v->type <= VOODOO_2 && (chips & 1) && INITEN_ENABLE_HW_INIT(v->pci.init_enable))
{
if ((v->type == VOODOO_2) && (regnum == fbiInit7)) {
v->fbi.cmdfifo[0].enable = FBIINIT7_CMDFIFO_ENABLE(data);
}
v->reg[regnum].u = data;
recompute_video_memory(v);
v->fbi.video_changed = 1;
}
break;
case fbiInit3:
poly_wait(v->poly, v->regnames[regnum]);
if (v->type <= VOODOO_2 && (chips & 1) && INITEN_ENABLE_HW_INIT(v->pci.init_enable))
{
v->reg[regnum].u = data;
v->alt_regmap = FBIINIT3_TRI_REGISTER_REMAP(data);
v->fbi.yorigin = FBIINIT3_YORIGIN_SUBTRACT(v->reg[fbiInit3].u);
recompute_video_memory(v);
}
break;
case cmdFifoBaseAddr:
BX_LOCK(cmdfifo_mutex);
v->fbi.cmdfifo[0].base = (data & 0x3ff) << 12;
v->fbi.cmdfifo[0].end = ((data >> 16) & 0x3ff) << 12;
BX_UNLOCK(cmdfifo_mutex);
break;
case cmdFifoRdPtr:
BX_LOCK(cmdfifo_mutex);
v->fbi.cmdfifo[0].rdptr = data;
BX_UNLOCK(cmdfifo_mutex);
break;
case cmdFifoDepth:
BX_LOCK(cmdfifo_mutex);
v->fbi.cmdfifo[0].depth = data & 0xffff;
BX_UNLOCK(cmdfifo_mutex);
break;
case cmdFifoAMin:
v->fbi.cmdfifo[0].amin = data;
break;
case cmdFifoAMax:
v->fbi.cmdfifo[0].amax = data;
break;
case intrCtrl:
BX_ERROR(("Writing to register %s not supported yet", v->regnames[regnum]));
break;
default:
register_w(offset, data, 0);
}
}
Bit32u register_r(Bit32u offset)
{
Bit32u regnum = (offset) & 0xff;
@ -2472,6 +2688,10 @@ Bit32u register_r(Bit32u offset)
if (v->pci.op_pending)
result |= 1 << 9;
if (v->type == VOODOO_2) {
if (v->fbi.cmdfifo[0].enable && v->fbi.cmdfifo[0].depth > 0)
result |= 7 << 7;
}
/* Banshee is different starting here */
if (v->type < VOODOO_BANSHEE)
{
@ -2627,7 +2847,7 @@ Bit32u lfb_r(Bit32u offset)
void voodoo_w(Bit32u offset, Bit32u data, Bit32u mask) {
if ((offset & (0xc00000/4)) == 0)
register_w(offset, data);
register_w_common(offset, data);
else if (offset & (0x800000/4))
texture_w(offset, data);
else