xbox_nv2a.cpp: some adjustments (nw)

This commit is contained in:
yz70s 2020-04-11 14:57:24 +02:00
parent 7005e4f8c4
commit 02df839dbf
2 changed files with 69 additions and 54 deletions

View File

@ -372,6 +372,17 @@ public:
BACK = 0x0405, BACK = 0x0405,
FRONT_AND_BACK = 0x0408 FRONT_AND_BACK = 0x0408
}; };
enum class COMMAND {
CALL = 7,
JUMP = 6,
NON_INCREASING = 5,
OLD_JUMP = 4,
LONG_NON_INCREASING = 3,
RETURN = 2,
SLI_CONDITIONAL = 1,
INCREASING = 0,
INVALID = -1
};
struct nv2avertex_t : public vertex_t struct nv2avertex_t : public vertex_t
{ {
@ -464,7 +475,7 @@ public:
void render_color(int32_t scanline, const extent_t &extent, const nvidia_object_data &extradata, int threadid); void render_color(int32_t scanline, const extent_t &extent, const nvidia_object_data &extradata, int threadid);
void render_register_combiners(int32_t scanline, const extent_t &extent, const nvidia_object_data &objectdata, int threadid); void render_register_combiners(int32_t scanline, const extent_t &extent, const nvidia_object_data &objectdata, int threadid);
int geforce_commandkind(uint32_t word); COMMAND geforce_commandkind(uint32_t word);
uint32_t geforce_object_offset(uint32_t handle); uint32_t geforce_object_offset(uint32_t handle);
void geforce_read_dma_object(uint32_t handle, uint32_t &offset, uint32_t &size); void geforce_read_dma_object(uint32_t handle, uint32_t &offset, uint32_t &size);
void geforce_assign_object(address_space &space, uint32_t chanel, uint32_t subchannel, uint32_t address); void geforce_assign_object(address_space &space, uint32_t chanel, uint32_t subchannel, uint32_t address);
@ -526,7 +537,7 @@ public:
struct { struct {
uint32_t regs[0x80 / 4]; uint32_t regs[0x80 / 4];
struct { struct {
uint32_t objhandle; uint32_t offset;
uint32_t objclass; uint32_t objclass;
uint32_t method[0x2000 / 4]; uint32_t method[0x2000 / 4];
// int execute_method(address_space & space, uint32_t method, uint32_t address, int &countlen); // for the future // int execute_method(address_space & space, uint32_t method, uint32_t address, int &countlen); // for the future
@ -537,8 +548,8 @@ public:
uint32_t pmc[0x1000 / 4]; uint32_t pmc[0x1000 / 4];
uint32_t pgraph[0x2000 / 4]; uint32_t pgraph[0x2000 / 4];
uint32_t ramin[0x100000 / 4]; uint32_t ramin[0x100000 / 4];
uint32_t dma_offset[2]; uint32_t dma_offset[10];
uint32_t dma_size[2]; uint32_t dma_size[10];
uint8_t *basemempointer; uint8_t *basemempointer;
uint8_t *topmempointer; uint8_t *topmempointer;
std::function<void(int state)> irq_callback; std::function<void(int state)> irq_callback;

View File

@ -932,25 +932,25 @@ inline uint8_t *nv2a_renderer::direct_access_ptr(offs_t address)
return basemempointer + address; return basemempointer + address;
} }
int nv2a_renderer::geforce_commandkind(uint32_t word) nv2a_renderer::COMMAND nv2a_renderer::geforce_commandkind(uint32_t word)
{ {
if ((word & 0x00000003) == 0x00000002) if ((word & 0x00000003) == 0x00000002)
return 7; // call return COMMAND::CALL;
if ((word & 0x00000003) == 0x00000001) if ((word & 0x00000003) == 0x00000001)
return 6; // jump return COMMAND::JUMP;
if ((word & 0xE0030003) == 0x40000000) if ((word & 0xE0030003) == 0x40000000)
return 5; // non increasing return COMMAND::NON_INCREASING;
if ((word & 0xE0000003) == 0x20000000) if ((word & 0xE0000003) == 0x20000000)
return 4; // old jump return COMMAND::OLD_JUMP;
if ((word & 0xFFFF0003) == 0x00030000) if ((word & 0xFFFF0003) == 0x00030000)
return 3; // long non icreasing return COMMAND::LONG_NON_INCREASING;
if ((word & 0xFFFFFFFF) == 0x00020000) if ((word & 0xFFFFFFFF) == 0x00020000)
return 2; // return return COMMAND::RETURN;
if ((word & 0xFFFF0003) == 0x00010000) if ((word & 0xFFFF0003) == 0x00010000)
return 1; // sli conditional return COMMAND::SLI_CONDITIONAL;
if ((word & 0xE0030003) == 0x00000000) if ((word & 0xE0030003) == 0x00000000)
return 0; // increasing return COMMAND::INCREASING;
return -1; return COMMAND::INVALID;
} }
uint32_t nv2a_renderer::geforce_object_offset(uint32_t handle) uint32_t nv2a_renderer::geforce_object_offset(uint32_t handle)
@ -2315,7 +2315,7 @@ void nv2a_renderer::extract_packed_float(uint32_t data, float &first, float &sec
} }
void nv2a_renderer::read_vertex(address_space & space, offs_t address, vertex_nv &vertex, int attrib) void nv2a_renderer::read_vertex(address_space &space, offs_t address, vertex_nv &vertex, int attrib)
{ {
uint32_t u; uint32_t u;
int c, d, l; int c, d, l;
@ -2361,7 +2361,7 @@ void nv2a_renderer::read_vertex(address_space & space, offs_t address, vertex_nv
} }
/* Read vertices data from system memory. Method 0x1800 and 0x1808 */ /* Read vertices data from system memory. Method 0x1800 and 0x1808 */
int nv2a_renderer::read_vertices_0x180x(address_space & space, vertex_nv *destination, uint32_t address, int limit) int nv2a_renderer::read_vertices_0x180x(address_space &space, vertex_nv *destination, uint32_t address, int limit)
{ {
uint32_t m; uint32_t m;
int a, b; int a, b;
@ -2385,7 +2385,7 @@ int nv2a_renderer::read_vertices_0x180x(address_space & space, vertex_nv *destin
} }
/* Read vertices data from system memory. Method 0x1810 */ /* Read vertices data from system memory. Method 0x1810 */
int nv2a_renderer::read_vertices_0x1810(address_space & space, vertex_nv *destination, int offset, int limit) int nv2a_renderer::read_vertices_0x1810(address_space &space, vertex_nv *destination, int offset, int limit)
{ {
uint32_t m; uint32_t m;
int a, b; int a, b;
@ -2407,7 +2407,7 @@ int nv2a_renderer::read_vertices_0x1810(address_space & space, vertex_nv *destin
} }
/* Read vertices data from system memory. Method 0x1818 */ /* Read vertices data from system memory. Method 0x1818 */
int nv2a_renderer::read_vertices_0x1818(address_space & space, vertex_nv *destination, uint32_t address, int limit) int nv2a_renderer::read_vertices_0x1818(address_space &space, vertex_nv *destination, uint32_t address, int limit)
{ {
uint32_t m, vwords; uint32_t m, vwords;
int a, b; int a, b;
@ -3016,12 +3016,12 @@ void nv2a_renderer::compute_size_rendertarget(uint32_t chanel, uint32_t subchann
size_depthbuffer = pitch_depthbuffer*(limits_rendertarget.bottom() + 1); size_depthbuffer = pitch_depthbuffer*(limits_rendertarget.bottom() + 1);
} }
int nv2a_renderer::geforce_exec_method(address_space & space, uint32_t chanel, uint32_t subchannel, uint32_t method, uint32_t address, int &countlen) int nv2a_renderer::geforce_exec_method(address_space &space, uint32_t chanel, uint32_t subchannel, uint32_t method, uint32_t address, int &countlen)
{ {
uint32_t maddress; uint32_t maddress;
uint32_t data; uint32_t data;
maddress = method * 4; maddress = method << 2;
data = space.read_dword(address); data = space.read_dword(address);
channel[chanel][subchannel].object.method[method] = data; channel[chanel][subchannel].object.method[method] = data;
#ifdef LOG_NV2A #ifdef LOG_NV2A
@ -3213,9 +3213,9 @@ int nv2a_renderer::geforce_exec_method(address_space & space, uint32_t chanel, u
int bit = method - 0x1720 / 4; int bit = method - 0x1720 / 4;
if (data & 0x80000000) if (data & 0x80000000)
vertexbuffer_address[bit] = (data & 0x0fffffff) + dma_offset[1]; vertexbuffer_address[bit] = (data & 0x0fffffff) + dma_offset[7];
else else
vertexbuffer_address[bit] = (data & 0x0fffffff) + dma_offset[0]; vertexbuffer_address[bit] = (data & 0x0fffffff) + dma_offset[6];
} }
if ((maddress >= 0x1760) && (maddress < 0x17A0)) { if ((maddress >= 0x1760) && (maddress < 0x17A0)) {
int bit = method - 0x1760 / 4; int bit = method - 0x1760 / 4;
@ -3265,11 +3265,14 @@ int nv2a_renderer::geforce_exec_method(address_space & space, uint32_t chanel, u
if (maddress == 0x039c) { if (maddress == 0x039c) {
backface_culling_culled = (NV2A_GL_CULL_FACE)data; backface_culling_culled = (NV2A_GL_CULL_FACE)data;
} }
if (maddress == 0x019c) { if (maddress == 0x0180) {
geforce_read_dma_object(data, dma_offset[0], dma_size[0]); geforce_read_dma_object(data, dma_offset[0], dma_size[0]);
} }
if (maddress == 0x019c) {
geforce_read_dma_object(data, dma_offset[6], dma_size[6]);
}
if (maddress == 0x01a0) { if (maddress == 0x01a0) {
geforce_read_dma_object(data, dma_offset[1], dma_size[1]); geforce_read_dma_object(data, dma_offset[7], dma_size[7]);
} }
if (maddress == 0x1d70) { if (maddress == 0x1d70) {
// with 1d70 write the value at offest [1d6c] inside dma object [1a4] // with 1d70 write the value at offest [1d6c] inside dma object [1a4]
@ -3531,11 +3534,11 @@ int nv2a_renderer::geforce_exec_method(address_space & space, uint32_t chanel, u
offset = data; offset = data;
texture[unit].buffer = direct_access_ptr(offset); texture[unit].buffer = direct_access_ptr(offset);
/*if (dma0 != 0) { /*if (dma0 != 0) {
dmahand=channel[channel][subchannel].object.method[0x184/4]; dmahand=channel[channel][subchannel].object.method[0x184/4];
geforce_read_dma_object(dmahand,dmaoff,smasiz); geforce_read_dma_object(dmahand,dmaoff,dmasiz);
} else if (dma1 != 0) { } else if (dma1 != 0) {
dmahand=channel[channel][subchannel].object.method[0x188/4]; dmahand=channel[channel][subchannel].object.method[0x188/4];
geforce_read_dma_object(dmahand,dmaoff,smasiz); geforce_read_dma_object(dmahand,dmaoff,dmasiz);
}*/ }*/
} }
if (maddress == 0x1b04) { if (maddress == 0x1b04) {
@ -3583,7 +3586,7 @@ int nv2a_renderer::geforce_exec_method(address_space & space, uint32_t chanel, u
debug_grab_texttype = -1; debug_grab_texttype = -1;
f = fopen(debug_grab_textfile, "wb"); f = fopen(debug_grab_textfile, "wb");
if (f) { if (f) {
written = (int)fwrite(texture[unit].buffer, texture[unit].sizeu*texture[unit].sizev * 4, 1, f); written = (int)fwrite(texture[unit].buffer, texture[unit].sizeu * texture[unit].sizev * 4, 1, f);
fclose(f); fclose(f);
machine().logerror("Written %d bytes of texture to specified file\n", written); machine().logerror("Written %d bytes of texture to specified file\n", written);
} }
@ -4490,9 +4493,9 @@ void nv2a_renderer::combiner_compute_a_outputs(int stage_number)
WRITE_LINE_MEMBER(nv2a_renderer::vblank_callback) WRITE_LINE_MEMBER(nv2a_renderer::vblank_callback)
{ {
#ifdef LOG_NV2A /*#ifdef LOG_NV2A
printf("vblank_callback\n\r"); printf("vblank_callback\n\r");
#endif #endif*/
if ((state != 0) && (puller_waiting == 1)) { if ((state != 0) && (puller_waiting == 1)) {
puller_waiting = 0; puller_waiting = 0;
puller_timer_work(nullptr, 0); puller_timer_work(nullptr, 0);
@ -4541,18 +4544,18 @@ uint32_t nv2a_renderer::screen_update_callback(screen_device &screen, bitmap_rgb
return 0; return 0;
} }
void nv2a_renderer::geforce_assign_object(address_space & space, uint32_t chanel, uint32_t subchannel, uint32_t address) void nv2a_renderer::geforce_assign_object(address_space &space, uint32_t chanel, uint32_t subchannel, uint32_t address)
{ {
int handle, objclass; uint32_t handle, offset, objclass, data;
handle = space.read_dword(address); handle = space.read_dword(address);
handle = geforce_object_offset(handle); offset = geforce_object_offset(handle);
#ifdef LOG_NV2A #ifdef LOG_NV2A
machine().logerror(" assign to subchannel %d object at %d", subchannel, handle); machine().logerror(" assign to subchannel %d object at %d in ramin", subchannel, offset);
#endif #endif
channel[chanel][subchannel].object.objhandle = handle; channel[chanel][subchannel].object.offset = offset;
handle = ramin[handle / 4]; data = ramin[offset / 4];
objclass = handle & 0xff; objclass = data & 0xff;
#ifdef LOG_NV2A #ifdef LOG_NV2A
machine().logerror(" class %03X\n", objclass); machine().logerror(" class %03X\n", objclass);
#endif #endif
@ -4564,7 +4567,8 @@ TIMER_CALLBACK_MEMBER(nv2a_renderer::puller_timer_work)
int chanel; int chanel;
int method, count; int method, count;
uint32_t *dmaput, *dmaget; uint32_t *dmaput, *dmaget;
uint32_t cmd, cmdtype; uint32_t cmd;
COMMAND cmdtype;
int countlen; int countlen;
int ret; int ret;
address_space *space = puller_space; address_space *space = puller_space;
@ -4579,7 +4583,7 @@ TIMER_CALLBACK_MEMBER(nv2a_renderer::puller_timer_work)
cmdtype = geforce_commandkind(cmd); cmdtype = geforce_commandkind(cmd);
switch (cmdtype) switch (cmdtype)
{ {
case 6: // jump case COMMAND::JUMP:
#ifdef LOG_NV2A #ifdef LOG_NV2A
machine().logerror("jump dmaget %08X", *dmaget); machine().logerror("jump dmaget %08X", *dmaget);
#endif #endif
@ -4588,24 +4592,24 @@ TIMER_CALLBACK_MEMBER(nv2a_renderer::puller_timer_work)
machine().logerror(" -> %08X\n\r", *dmaget); machine().logerror(" -> %08X\n\r", *dmaget);
#endif #endif
break; break;
case 0: // increasing method case COMMAND::INCREASING:
method = (cmd >> 2) & 2047; // method*4 is address // if method >= 0x40 send it to assigned object method = cmd & (2047 << 2); // if method >= 0x100 send it to assigned object
subch = (cmd >> 13) & 7; subch = (cmd >> 13) & 7;
count = (cmd >> 18) & 2047; count = (cmd >> 18) & 2047;
if ((method == 0) && (count == 1)) { if ((method == 0) && (count == 1)) { // OBJECT method, bind an engine object to a subchannel
geforce_assign_object(*space, chanel, subch, *dmaget); geforce_assign_object(*space, chanel, subch, *dmaget);
*dmaget += 4; *dmaget += 4;
} }
else { else {
#ifdef LOG_NV2A #ifdef LOG_NV2A
machine().logerror(" subch. %d method %04x offset %04x count %d\n", subch, method, method * 4, count); machine().logerror(" subch. %d method %04x count %d\n", subch, method, count);
#endif #endif
ret = 0; ret = 0;
while (count > 0) { while (count > 0) {
countlen = 1; countlen = 1;
ret=geforce_exec_method(*space, chanel, subch, method, *dmaget, countlen); ret=geforce_exec_method(*space, chanel, subch, method >> 2, *dmaget, countlen);
count--; count--;
method++; method += 4;
*dmaget += 4; *dmaget += 4;
if (ret != 0) if (ret != 0)
break; break;
@ -4617,8 +4621,8 @@ TIMER_CALLBACK_MEMBER(nv2a_renderer::puller_timer_work)
} }
} }
break; break;
case 5: // non-increasing method case COMMAND::NON_INCREASING:
method = (cmd >> 2) & 2047; method = cmd & (2047 << 2);
subch = (cmd >> 13) & 7; subch = (cmd >> 13) & 7;
count = (cmd >> 18) & 2047; count = (cmd >> 18) & 2047;
if ((method == 0) && (count == 1)) { if ((method == 0) && (count == 1)) {
@ -4627,18 +4631,18 @@ TIMER_CALLBACK_MEMBER(nv2a_renderer::puller_timer_work)
} }
else { else {
#ifdef LOG_NV2A #ifdef LOG_NV2A
machine().logerror(" subch. %d method %04x offset %04x count %d\n", subch, method, method * 4, count); machine().logerror(" subch. %d method %04x count %d\n", subch, method, count);
#endif #endif
while (count > 0) { while (count > 0) {
countlen = count; countlen = count;
ret=geforce_exec_method(*space, chanel, subch, method, *dmaget, countlen); ret=geforce_exec_method(*space, chanel, subch, method >> 2, *dmaget, countlen);
*dmaget += 4 * (count - countlen); *dmaget += 4 * (count - countlen);
count = countlen; count = countlen;
} }
} }
break; break;
case 3: // long non-increasing method case COMMAND::LONG_NON_INCREASING:
method = (cmd >> 2) & 2047; method = cmd & (2047 << 2);
subch = (cmd >> 13) & 7; subch = (cmd >> 13) & 7;
count = space->read_dword(*dmaget); count = space->read_dword(*dmaget);
*dmaget += 4; *dmaget += 4;
@ -4648,11 +4652,11 @@ TIMER_CALLBACK_MEMBER(nv2a_renderer::puller_timer_work)
} }
else { else {
#ifdef LOG_NV2A #ifdef LOG_NV2A
machine().logerror(" subch. %d method %04x offset %04x count %d\n", subch, method, method * 4, count); machine().logerror(" subch. %d method %04x count %d\n", subch, method, count);
#endif #endif
while (count > 0) { while (count > 0) {
countlen = count; countlen = count;
ret=geforce_exec_method(*space, chanel, subch, method, *dmaget, countlen); ret=geforce_exec_method(*space, chanel, subch, method >> 2, *dmaget, countlen);
*dmaget += 4 * (count - countlen); *dmaget += 4 * (count - countlen);
count = countlen; count = countlen;
} }