chihiro: added support for zbuffer and stencil plus render target methods [Samuele Zannoli]

This commit is contained in:
yz70s 2014-12-24 18:55:26 +01:00
parent f815c4fe2a
commit 075a8929c6
2 changed files with 685 additions and 340 deletions

View File

@ -147,10 +147,10 @@ offset in ramht+4 contains in the lower 16 bits the offset in RAMIN divided by 1
objects have methods used to do drawing objects have methods used to do drawing
most methods set parameters, others actually draw most methods set parameters, others actually draw
*/ */
class nv2a_renderer : public poly_manager<float, nvidia_object_data, 12, 8192> class nv2a_renderer : public poly_manager<float, nvidia_object_data, 13, 8192>
{ {
public: public:
nv2a_renderer(running_machine &machine) : poly_manager<float, nvidia_object_data, 12, 8192>(machine) nv2a_renderer(running_machine &machine) : poly_manager<float, nvidia_object_data, 13, 8192>(machine)
{ {
memset(channel, 0, sizeof(channel)); memset(channel, 0, sizeof(channel));
memset(pfifo, 0, sizeof(pfifo)); memset(pfifo, 0, sizeof(pfifo));
@ -158,7 +158,6 @@ public:
memset(pmc, 0, sizeof(pmc)); memset(pmc, 0, sizeof(pmc));
memset(ramin, 0, sizeof(ramin)); memset(ramin, 0, sizeof(ramin));
computedilated(); computedilated();
fb.allocate(640, 480);
objectdata = &(object_data_alloc()); objectdata = &(object_data_alloc());
objectdata->data = this; objectdata->data = this;
combiner.used = 0; combiner.used = 0;
@ -169,6 +168,16 @@ public:
alpha_test_enabled = false; alpha_test_enabled = false;
alpha_reference = 0; alpha_reference = 0;
alpha_func = nv2a_renderer::ALWAYS; alpha_func = nv2a_renderer::ALWAYS;
depth_test_enabled = false;
depth_function = nv2a_renderer::LESS;
depth_write_enabled = false;
stencil_test_enabled = false;
stencil_func = nv2a_renderer::ALWAYS;
stencil_ref = 0;
stencil_mask = -1;
stencil_op_fail = nv2a_renderer::KEEP;
stencil_op_zfail = nv2a_renderer::KEEP;
stencil_op_zpass = nv2a_renderer::KEEP;
blending_enabled = false; blending_enabled = false;
blend_equation = nv2a_renderer::FUNC_ADD; blend_equation = nv2a_renderer::FUNC_ADD;
blend_color = 0; blend_color = 0;
@ -176,6 +185,12 @@ public:
blend_function_source = nv2a_renderer::ONE; blend_function_source = nv2a_renderer::ONE;
logical_operation_enabled = false; logical_operation_enabled = false;
logical_operation = nv2a_renderer::COPY; logical_operation = nv2a_renderer::COPY;
limits_rendertarget.set(0, 0, 640, 480);
pitch_rendertarget = 0;
pitch_depthbuffer = 0;
rendertarget = NULL;
depthbuffer = NULL;
displayedtarget = NULL;
debug_grab_texttype = -1; debug_grab_texttype = -1;
debug_grab_textfile = NULL; debug_grab_textfile = NULL;
memset(vertex_attribute_words, 0, sizeof(vertex_attribute_words)); memset(vertex_attribute_words, 0, sizeof(vertex_attribute_words));
@ -195,7 +210,7 @@ public:
void geforce_read_dma_object(UINT32 handle, UINT32 &offset, UINT32 &size); void geforce_read_dma_object(UINT32 handle, UINT32 &offset, UINT32 &size);
void geforce_exec_method(address_space &space, UINT32 channel, UINT32 subchannel, UINT32 method, UINT32 address, int &countlen); void geforce_exec_method(address_space &space, UINT32 channel, UINT32 subchannel, UINT32 method, UINT32 address, int &countlen);
UINT32 texture_get_texel(int number, int x, int y); UINT32 texture_get_texel(int number, int x, int y);
void write_pixel(int x, int y, UINT32 color); void write_pixel(int x, int y, UINT32 color, UINT32 depth);
void combiner_initialize_registers(UINT32 argb8[6]); void combiner_initialize_registers(UINT32 argb8[6]);
void combiner_initialize_stage(int stage_number); void combiner_initialize_stage(int stage_number);
void combiner_initialize_final(); void combiner_initialize_final();
@ -247,6 +262,12 @@ public:
UINT32 ramin[0x100000 / 4]; UINT32 ramin[0x100000 / 4];
UINT32 dma_offset[2]; UINT32 dma_offset[2];
UINT32 dma_size[2]; UINT32 dma_size[2];
rectangle limits_rendertarget;
UINT32 pitch_rendertarget;
UINT32 pitch_depthbuffer;
UINT32 *rendertarget;
UINT32 *depthbuffer;
UINT32 *displayedtarget;
UINT32 vertexbuffer_address[16]; UINT32 vertexbuffer_address[16];
int vertexbuffer_stride[16]; int vertexbuffer_stride[16];
int vertexbuffer_kind[16]; int vertexbuffer_kind[16];
@ -371,6 +392,16 @@ public:
bool alpha_test_enabled; bool alpha_test_enabled;
int alpha_func; int alpha_func;
int alpha_reference; int alpha_reference;
bool depth_test_enabled;
int depth_function;
bool depth_write_enabled;
bool stencil_test_enabled;
int stencil_func;
int stencil_ref;
int stencil_mask;
int stencil_op_fail;
int stencil_op_zfail;
int stencil_op_zpass;
bool blending_enabled; bool blending_enabled;
int blend_equation; int blend_equation;
int blend_function_source; int blend_function_source;
@ -398,7 +429,6 @@ public:
int enabled_vertex_attributes; int enabled_vertex_attributes;
int vertex_attribute_words[16]; int vertex_attribute_words[16];
int vertex_attribute_offset[16]; int vertex_attribute_offset[16];
bitmap_rgb32 fb;
UINT32 dilated0[16][2048]; UINT32 dilated0[16][2048];
UINT32 dilated1[16][2048]; UINT32 dilated1[16][2048];
int dilatechose[256]; int dilatechose[256];
@ -406,6 +436,21 @@ public:
int debug_grab_texttype; int debug_grab_texttype;
char *debug_grab_textfile; char *debug_grab_textfile;
enum VERTEX_PARAMETER {
PARAM_COLOR_B = 0,
PARAM_COLOR_G = 1,
PARAM_COLOR_R = 2,
PARAM_COLOR_A = 3,
PARAM_TEXTURE0_U = 4,
PARAM_TEXTURE0_V = 5,
PARAM_TEXTURE1_U = 6,
PARAM_TEXTURE1_V = 7,
PARAM_TEXTURE2_U = 8,
PARAM_TEXTURE2_V = 9,
PARAM_TEXTURE3_U = 10,
PARAM_TEXTURE3_V = 11,
PARAM_Z = 12
};
enum NV2A_BEGIN_END { enum NV2A_BEGIN_END {
STOP = 0, STOP = 0,
POINTS = 1, POINTS = 1,

View File

@ -1213,14 +1213,19 @@ UINT32 nv2a_renderer::texture_get_texel(int number, int x, int y)
} }
} }
void nv2a_renderer::write_pixel(int x, int y, UINT32 color) void nv2a_renderer::write_pixel(int x, int y, UINT32 color, UINT32 depth)
{ {
void *addr; UINT32 *addr, *daddr;
UINT32 fbcolor; UINT32 fbcolor, deptsten;
UINT32 c[4], fb[4], s[4], d[4], cc[4]; UINT32 c[4], fb[4], s[4], d[4], cc[4];
UINT32 dep, sten, stenc, stenv;
bool stencil_passed;
bool depth_passed;
addr = this->fb.raw_pixptr(y, x); addr=rendertarget + (pitch_rendertarget / 4)*y + x;
fbcolor = *((UINT32 *)addr); fbcolor = *addr;
daddr=depthbuffer + (pitch_depthbuffer / 4)*y + x;
deptsten = *daddr;
c[3] = color >> 24; c[3] = color >> 24;
c[2] = (color >> 16) & 255; c[2] = (color >> 16) & 255;
c[1] = (color >> 8) & 255; c[1] = (color >> 8) & 255;
@ -1233,6 +1238,12 @@ void nv2a_renderer::write_pixel(int x, int y, UINT32 color)
cc[2] = (blend_color >> 16) & 255; cc[2] = (blend_color >> 16) & 255;
cc[1] = (blend_color >> 8) & 255; cc[1] = (blend_color >> 8) & 255;
cc[0] = blend_color & 255; cc[0] = blend_color & 255;
dep = deptsten >> 8;
sten = deptsten & 255;
if (depth > 0xffffff)
depth = 0xffffff;
if (depth & 0x80000000)
depth = 0;
// ownership test and scissor test not done // ownership test and scissor test not done
// alpha test // alpha test
if (alpha_test_enabled) { if (alpha_test_enabled) {
@ -1268,8 +1279,192 @@ void nv2a_renderer::write_pixel(int x, int y, UINT32 color)
break; break;
} }
} }
// stencil test not done // stencil test
// depth buffer test not done stencil_passed = true;
if (stencil_test_enabled) {
stenc=stencil_mask & stencil_ref;
stenv=stencil_mask & sten;
switch (stencil_func) {
case nv2a_renderer::NEVER:
stencil_passed = false;
break;
case nv2a_renderer::LESS:
if (stenc >= stenv)
stencil_passed = false;
break;
case nv2a_renderer::EQUAL:
if (stenc != stenv)
stencil_passed = false;
break;
case nv2a_renderer::LEQUAL:
if (stenc > stenv)
stencil_passed = false;
break;
case nv2a_renderer::GREATER:
if (stenc <= stenv)
stencil_passed = false;
break;
case nv2a_renderer::NOTEQUAL:
if (stenc == stenv)
stencil_passed = false;
break;
case nv2a_renderer::GEQUAL:
if (stenc < stenv)
stencil_passed = false;
break;
case nv2a_renderer::ALWAYS:
default:
break;
}
if (stencil_passed == false) {
switch (stencil_op_fail) {
case nv2a_renderer::ZEROOP:
sten = 0;
break;
case nv2a_renderer::INVERTOP:
sten = sten ^ 255;
break;
case nv2a_renderer::KEEP:
default:
break;
case nv2a_renderer::REPLACE:
sten = stencil_ref;
break;
case nv2a_renderer::INCR:
if (sten < 255)
sten++;
break;
case nv2a_renderer::DECR:
if (sten > 0)
sten--;
break;
case nv2a_renderer::INCR_WRAP:
if (sten < 255)
sten++;
else
sten = 0;
break;
case nv2a_renderer::DECR_WRAP:
if (sten > 0)
sten--;
else
sten = 255;
break;
}
deptsten = (dep << 8) | sten;
*daddr = deptsten;
return;
}
}
// depth buffer test
depth_passed = true;
if (depth_test_enabled) {
switch (depth_function) {
case nv2a_renderer::NEVER:
depth_passed = false;
break;
case nv2a_renderer::LESS:
if (depth >= dep)
depth_passed = false;
break;
case nv2a_renderer::EQUAL:
if (depth != dep)
depth_passed = false;
break;
case nv2a_renderer::LEQUAL:
if (depth > dep)
depth_passed = false;
break;
case nv2a_renderer::GREATER:
if (depth <= dep)
depth_passed = false;
break;
case nv2a_renderer::NOTEQUAL:
if (depth == dep)
depth_passed = false;
break;
case nv2a_renderer::GEQUAL:
if (depth < dep)
depth_passed = false;
break;
case nv2a_renderer::ALWAYS:
default:
break;
}
if (depth_passed == false) {
switch (stencil_op_zfail) {
case nv2a_renderer::ZEROOP:
sten = 0;
break;
case nv2a_renderer::INVERTOP:
sten = sten ^ 255;
break;
case nv2a_renderer::KEEP:
default:
break;
case nv2a_renderer::REPLACE:
sten = stencil_ref;
break;
case nv2a_renderer::INCR:
if (sten < 255)
sten++;
break;
case nv2a_renderer::DECR:
if (sten > 0)
sten--;
break;
case nv2a_renderer::INCR_WRAP:
if (sten < 255)
sten++;
else
sten = 0;
break;
case nv2a_renderer::DECR_WRAP:
if (sten > 0)
sten--;
else
sten = 255;
break;
}
deptsten = (dep << 8) | sten;
*daddr = deptsten;
return;
}
switch (stencil_op_zpass) {
case nv2a_renderer::ZEROOP:
sten = 0;
break;
case nv2a_renderer::INVERTOP:
sten = sten ^ 255;
break;
case nv2a_renderer::KEEP:
default:
break;
case nv2a_renderer::REPLACE:
sten = stencil_ref;
break;
case nv2a_renderer::INCR:
if (sten < 255)
sten++;
break;
case nv2a_renderer::DECR:
if (sten > 0)
sten--;
break;
case nv2a_renderer::INCR_WRAP:
if (sten < 255)
sten++;
else
sten = 0;
break;
case nv2a_renderer::DECR_WRAP:
if (sten > 0)
sten--;
else
sten = 255;
break;
}
}
// blending // blending
if (blending_enabled) { if (blending_enabled) {
switch (blend_function_source) { switch (blend_function_source) {
@ -1555,7 +1750,11 @@ void nv2a_renderer::write_pixel(int x, int y, UINT32 color)
} }
} }
fbcolor = (c[3] << 24) | (c[2] << 16) | (c[1] << 8) | c[0]; fbcolor = (c[3] << 24) | (c[2] << 16) | (c[1] << 8) | c[0];
*((UINT32 *)addr) = fbcolor; *addr = fbcolor;
if (depth_write_enabled)
dep = depth;
deptsten = (dep << 8) | sten;
*daddr = deptsten;
} }
void nv2a_renderer::render_color(INT32 scanline, const extent_t &extent, const nvidia_object_data &objectdata, int threadid) void nv2a_renderer::render_color(INT32 scanline, const extent_t &extent, const nvidia_object_data &objectdata, int threadid)
@ -1567,15 +1766,17 @@ void nv2a_renderer::render_color(INT32 scanline, const extent_t &extent, const n
x = extent.stopx - extent.startx - 1; // number of pixels to draw x = extent.stopx - extent.startx - 1; // number of pixels to draw
while (x >= 0) { while (x >= 0) {
UINT32 a8r8g8b8; UINT32 a8r8g8b8;
UINT32 z;
int ca, cr, cg, cb; int ca, cr, cg, cb;
int xp = extent.startx + x; // x coordinate of current pixel int xp = extent.startx + x; // x coordinate of current pixel
cb = ((extent.param[0].start + (float)x*extent.param[0].dpdx))*255.0; cb = ((extent.param[PARAM_COLOR_B].start + (float)x*extent.param[PARAM_COLOR_B].dpdx))*255.0;
cg = ((extent.param[1].start + (float)x*extent.param[1].dpdx))*255.0; cg = ((extent.param[PARAM_COLOR_G].start + (float)x*extent.param[PARAM_COLOR_G].dpdx))*255.0;
cr = ((extent.param[2].start + (float)x*extent.param[2].dpdx))*255.0; cr = ((extent.param[PARAM_COLOR_R].start + (float)x*extent.param[PARAM_COLOR_R].dpdx))*255.0;
ca = ((extent.param[3].start + (float)x*extent.param[3].dpdx))*255.0; ca = ((extent.param[PARAM_COLOR_A].start + (float)x*extent.param[PARAM_COLOR_A].dpdx))*255.0;
a8r8g8b8 = (ca << 24) + (cr << 16) + (cg << 8) + cb; // pixel color obtained by interpolating the colors of the vertices a8r8g8b8 = (ca << 24) + (cr << 16) + (cg << 8) + cb; // pixel color obtained by interpolating the colors of the vertices
write_pixel(xp, scanline, a8r8g8b8); z = (extent.param[PARAM_Z].start + (float)x*extent.param[PARAM_Z].dpdx);
write_pixel(xp, scanline, a8r8g8b8, z);
x--; x--;
} }
} }
@ -1584,6 +1785,7 @@ void nv2a_renderer::render_texture_simple(INT32 scanline, const extent_t &extent
{ {
int x; int x;
UINT32 a8r8g8b8; UINT32 a8r8g8b8;
UINT32 z;
if (!objectdata.data->texture[0].enabled) { if (!objectdata.data->texture[0].enabled) {
return; return;
@ -1595,10 +1797,11 @@ void nv2a_renderer::render_texture_simple(INT32 scanline, const extent_t &extent
int up, vp; int up, vp;
int xp = extent.startx + x; // x coordinate of current pixel int xp = extent.startx + x; // x coordinate of current pixel
up = (extent.param[4].start + (float)x*extent.param[4].dpdx)*(float)(objectdata.data->texture[0].sizeu - 1); // x coordinate of texel in texture up = (extent.param[PARAM_TEXTURE0_U].start + (float)x*extent.param[PARAM_TEXTURE0_U].dpdx)*(float)(objectdata.data->texture[0].sizeu - 1); // x coordinate of texel in texture
vp = extent.param[5].start*(float)(objectdata.data->texture[0].sizev - 1); // y coordinate of texel in texture vp = (extent.param[PARAM_TEXTURE0_V].start + (float)x*extent.param[PARAM_TEXTURE0_V].dpdx)*(float)(objectdata.data->texture[0].sizev - 1); // y coordinate of texel in texture
a8r8g8b8 = texture_get_texel(0, up, vp); a8r8g8b8 = texture_get_texel(0, up, vp);
write_pixel(xp, scanline, a8r8g8b8); z = (extent.param[PARAM_Z].start + (float)x*extent.param[PARAM_Z].dpdx);
write_pixel(xp, scanline, a8r8g8b8, z);
x--; x--;
} }
} }
@ -1610,6 +1813,7 @@ void nv2a_renderer::render_register_combiners(INT32 scanline, const extent_t &ex
int ca, cr, cg, cb; int ca, cr, cg, cb;
UINT32 color[6]; UINT32 color[6];
UINT32 a8r8g8b8; UINT32 a8r8g8b8;
UINT32 z;
int n;//,m,i,j,k; int n;//,m,i,j,k;
color[0] = color[1] = color[2] = color[3] = color[4] = color[5] = 0; color[0] = color[1] = color[2] = color[3] = color[4] = color[5] = 0;
@ -1622,17 +1826,17 @@ void nv2a_renderer::render_register_combiners(INT32 scanline, const extent_t &ex
xp = extent.startx + x; xp = extent.startx + x;
// 1: fetch data // 1: fetch data
// 1.1: interpolated color from vertices // 1.1: interpolated color from vertices
cb = ((extent.param[0].start + (float)x*extent.param[0].dpdx))*255.0; cb = ((extent.param[PARAM_COLOR_B].start + (float)x*extent.param[PARAM_COLOR_B].dpdx))*255.0;
cg = ((extent.param[1].start + (float)x*extent.param[1].dpdx))*255.0; cg = ((extent.param[PARAM_COLOR_G].start + (float)x*extent.param[PARAM_COLOR_G].dpdx))*255.0;
cr = ((extent.param[2].start + (float)x*extent.param[2].dpdx))*255.0; cr = ((extent.param[PARAM_COLOR_R].start + (float)x*extent.param[PARAM_COLOR_R].dpdx))*255.0;
ca = ((extent.param[3].start + (float)x*extent.param[3].dpdx))*255.0; ca = ((extent.param[PARAM_COLOR_A].start + (float)x*extent.param[PARAM_COLOR_A].dpdx))*255.0;
color[0] = (ca << 24) + (cr << 16) + (cg << 8) + cb; // pixel color obtained by interpolating the colors of the vertices color[0] = (ca << 24) + (cr << 16) + (cg << 8) + cb; // pixel color obtained by interpolating the colors of the vertices
color[1] = 0; // lighting not yet color[1] = 0; // lighting not yet
// 1.2: color for each of the 4 possible textures // 1.2: color for each of the 4 possible textures
for (n = 0; n < 4; n++) { for (n = 0; n < 4; n++) {
if (texture[n].enabled) { if (texture[n].enabled) {
up = (extent.param[4 + n * 2].start + (float)x*extent.param[4 + n * 2].dpdx)*(float)(objectdata.data->texture[n].sizeu - 1); up = (extent.param[PARAM_TEXTURE0_U + n * 2].start + (float)x*extent.param[PARAM_TEXTURE0_U + n * 2].dpdx)*(float)(objectdata.data->texture[n].sizeu - 1);
vp = extent.param[5 + n * 2].start*(float)(objectdata.data->texture[n].sizev - 1); vp = extent.param[PARAM_TEXTURE0_V + n * 2].start*(float)(objectdata.data->texture[n].sizev - 1);
color[n + 2] = texture_get_texel(n, up, vp); color[n + 2] = texture_get_texel(n, up, vp);
} }
} }
@ -1657,7 +1861,8 @@ void nv2a_renderer::render_register_combiners(INT32 scanline, const extent_t &ex
combiner_final_output(); combiner_final_output();
a8r8g8b8 = combiner_float_argb8(combiner.output); a8r8g8b8 = combiner_float_argb8(combiner.output);
// 3: write pixel // 3: write pixel
write_pixel(xp, scanline, a8r8g8b8); z = (extent.param[PARAM_Z].start + (float)x*extent.param[PARAM_Z].dpdx);
write_pixel(xp, scanline, a8r8g8b8, z);
x--; x--;
} }
osd_lock_release(combiner.lock); osd_lock_release(combiner.lock);
@ -1920,6 +2125,7 @@ int nv2a_renderer::read_vertices_0x1818(address_space & space, vertex_nv *destin
void nv2a_renderer::convert_vertices_poly(vertex_nv *source, vertex_t *destination, int count) void nv2a_renderer::convert_vertices_poly(vertex_nv *source, vertex_t *destination, int count)
{ {
vertex_nv vert[4];
int m, u; int m, u;
// take each vertex with its attributes and obtain data for drawing // take each vertex with its attributes and obtain data for drawing
@ -1930,29 +2136,30 @@ void nv2a_renderer::convert_vertices_poly(vertex_nv *source, vertex_t *destinati
for (m = 0; m < count; m++) { for (m = 0; m < count; m++) {
destination[m].x = source[m].attribute[0].fv[0]; destination[m].x = source[m].attribute[0].fv[0];
destination[m].y = source[m].attribute[0].fv[1]; destination[m].y = source[m].attribute[0].fv[1];
for (u = 0; u < 4; u++) // 0=b 1=g 2=r 3=a for (u = PARAM_COLOR_B; u <= PARAM_COLOR_A; u++) // 0=b 1=g 2=r 3=a
destination[m].p[u] = source[m].attribute[3].fv[u]; destination[m].p[u] = source[m].attribute[3].fv[u];
for (u = 0; u < 4; u++) { for (u = 0; u < 4; u++) {
destination[m].p[4 + u * 2] = source[m].attribute[9 + u].fv[0]; destination[m].p[PARAM_TEXTURE0_U + u * 2] = source[m].attribute[9 + u].fv[0];
destination[m].p[5 + u * 2] = source[m].attribute[9 + u].fv[1]; destination[m].p[PARAM_TEXTURE0_V + u * 2] = source[m].attribute[9 + u].fv[1];
} }
destination[m].p[PARAM_Z] = 0+0xffffff;
} }
} }
else { else {
// vertex program // vertex program
vertex_nv vert[4];
// run vertex program // run vertex program
vertexprogram.exec.process(vertexprogram.start_instruction, source, vert, count); vertexprogram.exec.process(vertexprogram.start_instruction, source, vert, count);
// copy data for poly.c // copy data for poly.c
for (m = 0; m < count; m++) { for (m = 0; m < count; m++) {
destination[m].x = vert[m].attribute[0].fv[0]; destination[m].x = vert[m].attribute[0].fv[0];
destination[m].y = vert[m].attribute[0].fv[1]; destination[m].y = vert[m].attribute[0].fv[1];
for (u = 0; u < 4; u++) // 0=b 1=g 2=r 3=a for (u = PARAM_COLOR_B; u <= PARAM_COLOR_A; u++) // 0=b 1=g 2=r 3=a
destination[m].p[u] = vert[m].attribute[3].fv[u]; destination[m].p[u] = vert[m].attribute[3].fv[u];
for (u = 0; u < 4; u++) { for (u = 0; u < 4; u++) {
destination[m].p[4 + u * 2] = vert[m].attribute[9 + u].fv[0]; destination[m].p[PARAM_TEXTURE0_U + u * 2] = vert[m].attribute[9 + u].fv[0];
destination[m].p[5 + u * 2] = vert[m].attribute[9 + u].fv[1]; destination[m].p[PARAM_TEXTURE0_V + u * 2] = vert[m].attribute[9 + u].fv[1];
} }
destination[m].p[PARAM_Z] = vert[m].attribute[0].fv[2];
} }
} }
} }
@ -1998,7 +2205,7 @@ void nv2a_renderer::geforce_exec_method(address_space & space, UINT32 chanel, UI
read_vertices_0x1810(space, vert, n + offset, 4); read_vertices_0x1810(space, vert, n + offset, 4);
convert_vertices_poly(vert, xy, 4); convert_vertices_poly(vert, xy, 4);
render_polygon<4>(fb.cliprect(), renderspans, 4 + 4 * 2, xy); // 4 rgba, 4 texture units 2 uv render_polygon<4>(limits_rendertarget, renderspans, 4 + 4 * 2, xy); // 4 rgba, 4 texture units 2 uv
} }
wait(); wait();
} }
@ -2013,7 +2220,7 @@ void nv2a_renderer::geforce_exec_method(address_space & space, UINT32 chanel, UI
for (n = 0; n <= count; n++) { for (n = 0; n <= count; n++) {
read_vertices_0x1810(space, vert + ((n + 2) & 3), offset + n, 1); read_vertices_0x1810(space, vert + ((n + 2) & 3), offset + n, 1);
convert_vertices_poly(vert + ((n + 2) & 3), xy + ((n + 2) & 3), 1); convert_vertices_poly(vert + ((n + 2) & 3), xy + ((n + 2) & 3), 1);
render_triangle(fb.cliprect(), renderspans, 4 + 4 * 2, xy[((n & 1) + n) & 3], xy[((~n & 1) + n) & 3], xy[(2 + n) & 3]); render_triangle(limits_rendertarget, renderspans, 4 + 4 * 2, xy[((n & 1) + n) & 3], xy[((~n & 1) + n) & 3], xy[(2 + n) & 3]);
} }
wait(); wait();
} }
@ -2052,7 +2259,7 @@ void nv2a_renderer::geforce_exec_method(address_space & space, UINT32 chanel, UI
address = address + c * 4; address = address + c * 4;
countlen = countlen - c; countlen = countlen - c;
convert_vertices_poly(vert, xy, 4); convert_vertices_poly(vert, xy, 4);
render_polygon<4>(fb.cliprect(), renderspans, 4 + 4 * 2, xy); // 4 rgba, 4 texture units 2 uv render_polygon<4>(limits_rendertarget, renderspans, 4 + 4 * 2, xy); // 4 rgba, 4 texture units 2 uv
} }
while (countlen > 0) { while (countlen > 0) {
data = space.read_dword(address); data = space.read_dword(address);
@ -2077,7 +2284,7 @@ void nv2a_renderer::geforce_exec_method(address_space & space, UINT32 chanel, UI
address = address + c * 4; address = address + c * 4;
countlen = countlen - c; countlen = countlen - c;
convert_vertices_poly(vert, xy, 3); convert_vertices_poly(vert, xy, 3);
render_triangle(fb.cliprect(), renderspans, 4 + 4 * 2, xy[0], xy[1], xy[2]); // 4 rgba, 4 texture units 2 uv render_triangle(limits_rendertarget, renderspans, 4 + 4 * 2, xy[0], xy[1], xy[2]); // 4 rgba, 4 texture units 2 uv
} }
while (countlen > 0) { while (countlen > 0) {
data = space.read_dword(address); data = space.read_dword(address);
@ -2108,7 +2315,7 @@ void nv2a_renderer::geforce_exec_method(address_space & space, UINT32 chanel, UI
convert_vertices_poly(vert + ((n + 2) & 3), xy + ((n + 2) & 3), 1); convert_vertices_poly(vert + ((n + 2) & 3), xy + ((n + 2) & 3), 1);
if (xy[(n + 2) & 3].y > 293800000.0) if (xy[(n + 2) & 3].y > 293800000.0)
xy[(n + 2) & 3].y = xy[(n + 2) & 3].y + 1.0; xy[(n + 2) & 3].y = xy[(n + 2) & 3].y + 1.0;
render_triangle(fb.cliprect(), renderspans, 4 + 4 * 2, xy[((n & 1) + n) & 3], xy[((~n & 1) + n) & 3], xy[(2 + n) & 3]); render_triangle(limits_rendertarget, renderspans, 4 + 4 * 2, xy[((n & 1) + n) & 3], xy[((~n & 1) + n) & 3], xy[(2 + n) & 3]);
} }
} }
while (countlen > 0) { while (countlen > 0) {
@ -2170,7 +2377,7 @@ void nv2a_renderer::geforce_exec_method(address_space & space, UINT32 chanel, UI
} }
address = address + c * 4; address = address + c * 4;
convert_vertices_poly(vert + ((n & 1) + 1), xy + ((n & 1) + 1), 1); convert_vertices_poly(vert + ((n & 1) + 1), xy + ((n & 1) + 1), 1);
render_triangle(fb.cliprect(), renderspans, 4 + 4 * 2, xy[0], xy[(~n & 1) + 1], xy[(n & 1) + 1]); render_triangle(limits_rendertarget, renderspans, 4 + 4 * 2, xy[0], xy[(~n & 1) + 1], xy[(n & 1) + 1]);
} }
wait(); wait();
} }
@ -2198,7 +2405,7 @@ void nv2a_renderer::geforce_exec_method(address_space & space, UINT32 chanel, UI
break; break;
} }
address = address + c * 4; address = address + c * 4;
render_triangle(fb.cliprect(), renderspans, 4 + 4 * 2, xy[((n & 1) + n) & 3], xy[((~n & 1) + n) & 3], xy[(2 + n) & 3]); render_triangle(limits_rendertarget, renderspans, 4 + 4 * 2, xy[((n & 1) + n) & 3], xy[((~n & 1) + n) & 3], xy[(2 + n) & 3]);
} }
wait(); wait();
} }
@ -2217,7 +2424,7 @@ void nv2a_renderer::geforce_exec_method(address_space & space, UINT32 chanel, UI
break; break;
} }
address = address + c * 4; address = address + c * 4;
render_polygon<4>(fb.cliprect(), renderspans, 4 + 4 * 2, xy); // 4 rgba, 4 texture units 2 uv render_polygon<4>(limits_rendertarget, renderspans, 4 + 4 * 2, xy); // 4 rgba, 4 texture units 2 uv
} }
wait(); wait();
} }
@ -2245,8 +2452,8 @@ void nv2a_renderer::geforce_exec_method(address_space & space, UINT32 chanel, UI
return; return;
} }
address = address + c * 4; address = address + c * 4;
render_triangle(fb.cliprect(), renderspans, 4 + 4 * 2, xy[n & 3], xy[(n + 1) & 3], xy[(n + 2) & 3]); render_triangle(limits_rendertarget, renderspans, 4 + 4 * 2, xy[n & 3], xy[(n + 1) & 3], xy[(n + 2) & 3]);
render_triangle(fb.cliprect(), renderspans, 4 + 4 * 2, xy[(n + 2) & 3], xy[(n + 1) & 3], xy[(n + 3) & 3]); render_triangle(limits_rendertarget, renderspans, 4 + 4 * 2, xy[(n + 2) & 3], xy[(n + 1) & 3], xy[(n + 3) & 3]);
} }
wait(); wait();
} }
@ -2320,26 +2527,78 @@ void nv2a_renderer::geforce_exec_method(address_space & space, UINT32 chanel, UI
space.write_dword(base + offset, data); space.write_dword(base + offset, data);
countlen--; countlen--;
} }
if (maddress == 0x1d98) {
countlen--;
}
if (maddress == 0x1d9c) {
countlen--;
}
if (maddress == 0x1d94) { if (maddress == 0x1d94) {
int m;
m = channel[chanel][subchannel].object.method[0x1d7c / 4];
if (channel[chanel][subchannel].object.method[0x0208 / 4] & 0x2000)
m = 2;
else
m = 1;
// possible buffers: color, depth, stencil, and accumulation // possible buffers: color, depth, stencil, and accumulation
// clear framebuffer // clear framebuffer
if (data & 0xf0) { if (data & 0xf0) {
bitmap_rgb32 bm(rendertarget, (limits_rendertarget.right() + 1) * m, (limits_rendertarget.bottom() + 1) * m, pitch_rendertarget / 4); // why *2 ?
// clear colors // clear colors
UINT32 color = channel[chanel][subchannel].object.method[0x1d90 / 4]; UINT32 color = channel[chanel][subchannel].object.method[0x1d90 / 4];
fb.fill(color); bm.fill(color);
//printf("clearscreen\n\r"); //printf("clearscreen\n\r");
} }
if (data & 0x03) { if (data & 0x01) {
// clear stencil+zbuffer bitmap_rgb32 bm(depthbuffer, (limits_rendertarget.right() + 1) * m, (limits_rendertarget.bottom() + 1) * m, pitch_rendertarget / 4); // why *2 ?
// clear zbuffer
UINT32 depth = channel[chanel][subchannel].object.method[0x1d8c / 4];
bm.fill(depth);
} }
countlen--; countlen--;
} }
if (maddress == 0x0200) {
//x = data & 0xffff;
//w = (data >> 16) & 0xffff;
limits_rendertarget.setx(0,((data >> 16) & 0xffff)-1);
}
if (maddress == 0x0204) {
//y = data & 0xffff;
//h = (data >> 16) & 0xffff;
limits_rendertarget.sety(0,((data >> 16) & 0xffff)-1);
}
if (maddress == 0x020c) {
// line size ?
pitch_rendertarget=data & 0xffff;
pitch_depthbuffer=(data >> 16) & 0xffff;
//printf("Pitch color %04X zbuffer %04X\n\r",pitch_rendertarget,pitch_depthbuffer);
countlen--;
}
if (maddress == 0x0100) {
// just temporarily
if ((data & 0x1f) == 1) {
data = data >> 5;
data = data & 0x0ffffff0;
displayedtarget = (UINT32 *)space.get_write_ptr(data);
}
}
if (maddress == 0x0210) { if (maddress == 0x0210) {
// framebuffer offset ? // framebuffer offset ?
rendertarget = (UINT32 *)space.get_write_ptr(data);
//printf("Render target at %08X\n\r",data);
countlen--; countlen--;
} }
if (maddress == 0x0214) { if (maddress == 0x0214) {
// zbuffer offset ? // zbuffer offset ?
depthbuffer = (UINT32 *)space.get_write_ptr(data);
//printf("Depth buffer at %08X\n\r",data);
if ((data == 0) || (data > 0x7ffffffc))
depth_write_enabled = false;
else if (channel[chanel][subchannel].object.method[0x035c / 4] != 0)
depth_write_enabled = true;
else
depth_write_enabled = false;
countlen--; countlen--;
} }
if (maddress == 0x0300) { if (maddress == 0x0300) {
@ -2357,6 +2616,41 @@ void nv2a_renderer::geforce_exec_method(address_space & space, UINT32 chanel, UI
else else
blending_enabled = data != 0; blending_enabled = data != 0;
} }
if (maddress == 0x030c) {
depth_test_enabled = data != 0;
}
if (maddress == 0x0354) {
depth_function = data;
}
if (maddress == 0x035c) {
UINT32 g = channel[chanel][subchannel].object.method[0x0214 / 4];
depth_write_enabled = data != 0;
if ((g == 0) || (g > 0x7ffffffc))
depth_write_enabled = false;
}
if (maddress == 0x032c) {
stencil_test_enabled = data != 0;
}
if (maddress == 0x0364) {
stencil_func = data;
}
if (maddress == 0x0368) {
if (data > 255)
data = 255;
stencil_ref = data;
}
if (maddress == 0x036c) {
stencil_mask = data;
}
if (maddress == 0x0370) {
stencil_op_fail = data;
}
if (maddress == 0x0374) {
stencil_op_zfail = data;
}
if (maddress == 0x0378) {
stencil_op_zpass = data;
}
if (maddress == 0x0344) { if (maddress == 0x0344) {
blend_function_source = data; blend_function_source = data;
} }
@ -3285,11 +3579,13 @@ bool nv2a_renderer::vblank_callback(screen_device &screen, bool state)
UINT32 nv2a_renderer::screen_update_callback(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect) UINT32 nv2a_renderer::screen_update_callback(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
{ {
if (displayedtarget != NULL) {
bitmap_rgb32 bm(displayedtarget, 640, 480, 640);
UINT32 *dst = (UINT32 *)bitmap.raw_pixptr(0, 0); UINT32 *dst = (UINT32 *)bitmap.raw_pixptr(0, 0);
UINT32 *src = (UINT32 *)fb.raw_pixptr(0, 0);
//printf("updatescreen\n\r"); //printf("updatescreen %08X\n\r",pcrtc[0x800/4]);
memcpy(dst, src, bitmap.rowbytes()*bitmap.height()); memcpy(dst, displayedtarget, bitmap.rowbytes()*bitmap.height());
}
return 0; return 0;
} }
@ -3372,6 +3668,10 @@ WRITE32_MEMBER(nv2a_renderer::geforce_w)
if (e >= (sizeof(pcrtc) / sizeof(UINT32))) if (e >= (sizeof(pcrtc) / sizeof(UINT32)))
return; return;
COMBINE_DATA(pcrtc + e); COMBINE_DATA(pcrtc + e);
if (e == 0x800 / 4) {
displayedtarget = (UINT32 *)space.get_read_ptr(data);
//printf("crtc buffer %08X\n\r", data);
}
//logerror("NV_2A: write PCRTC[%06X]=%08X\n",offset*4-0x00600000,data & mem_mask); //logerror("NV_2A: write PCRTC[%06X]=%08X\n",offset*4-0x00600000,data & mem_mask);
} }
else if ((offset >= 0x00000000 / 4) && (offset < 0x00001000 / 4)) { else if ((offset >= 0x00000000 / 4) && (offset < 0x00001000 / 4)) {