mirror of
https://github.com/holub/mame
synced 2025-05-17 11:15:06 +03:00
chihiro: added support for zbuffer and stencil plus render target methods [Samuele Zannoli]
This commit is contained in:
parent
f815c4fe2a
commit
075a8929c6
@ -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
|
||||
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:
|
||||
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(pfifo, 0, sizeof(pfifo));
|
||||
@ -158,7 +158,6 @@ public:
|
||||
memset(pmc, 0, sizeof(pmc));
|
||||
memset(ramin, 0, sizeof(ramin));
|
||||
computedilated();
|
||||
fb.allocate(640, 480);
|
||||
objectdata = &(object_data_alloc());
|
||||
objectdata->data = this;
|
||||
combiner.used = 0;
|
||||
@ -169,6 +168,16 @@ public:
|
||||
alpha_test_enabled = false;
|
||||
alpha_reference = 0;
|
||||
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;
|
||||
blend_equation = nv2a_renderer::FUNC_ADD;
|
||||
blend_color = 0;
|
||||
@ -176,6 +185,12 @@ public:
|
||||
blend_function_source = nv2a_renderer::ONE;
|
||||
logical_operation_enabled = false;
|
||||
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_textfile = NULL;
|
||||
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_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);
|
||||
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_stage(int stage_number);
|
||||
void combiner_initialize_final();
|
||||
@ -247,6 +262,12 @@ public:
|
||||
UINT32 ramin[0x100000 / 4];
|
||||
UINT32 dma_offset[2];
|
||||
UINT32 dma_size[2];
|
||||
rectangle limits_rendertarget;
|
||||
UINT32 pitch_rendertarget;
|
||||
UINT32 pitch_depthbuffer;
|
||||
UINT32 *rendertarget;
|
||||
UINT32 *depthbuffer;
|
||||
UINT32 *displayedtarget;
|
||||
UINT32 vertexbuffer_address[16];
|
||||
int vertexbuffer_stride[16];
|
||||
int vertexbuffer_kind[16];
|
||||
@ -371,6 +392,16 @@ public:
|
||||
bool alpha_test_enabled;
|
||||
int alpha_func;
|
||||
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;
|
||||
int blend_equation;
|
||||
int blend_function_source;
|
||||
@ -398,7 +429,6 @@ public:
|
||||
int enabled_vertex_attributes;
|
||||
int vertex_attribute_words[16];
|
||||
int vertex_attribute_offset[16];
|
||||
bitmap_rgb32 fb;
|
||||
UINT32 dilated0[16][2048];
|
||||
UINT32 dilated1[16][2048];
|
||||
int dilatechose[256];
|
||||
@ -406,6 +436,21 @@ public:
|
||||
int debug_grab_texttype;
|
||||
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 {
|
||||
STOP = 0,
|
||||
POINTS = 1,
|
||||
|
@ -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 fbcolor;
|
||||
UINT32 *addr, *daddr;
|
||||
UINT32 fbcolor, deptsten;
|
||||
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);
|
||||
fbcolor = *((UINT32 *)addr);
|
||||
addr=rendertarget + (pitch_rendertarget / 4)*y + x;
|
||||
fbcolor = *addr;
|
||||
daddr=depthbuffer + (pitch_depthbuffer / 4)*y + x;
|
||||
deptsten = *daddr;
|
||||
c[3] = color >> 24;
|
||||
c[2] = (color >> 16) & 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[1] = (blend_color >> 8) & 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
|
||||
// alpha test
|
||||
if (alpha_test_enabled) {
|
||||
@ -1268,8 +1279,192 @@ void nv2a_renderer::write_pixel(int x, int y, UINT32 color)
|
||||
break;
|
||||
}
|
||||
}
|
||||
// stencil test not done
|
||||
// depth buffer test not done
|
||||
// stencil test
|
||||
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
|
||||
if (blending_enabled) {
|
||||
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];
|
||||
*((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)
|
||||
@ -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
|
||||
while (x >= 0) {
|
||||
UINT32 a8r8g8b8;
|
||||
UINT32 z;
|
||||
int ca, cr, cg, cb;
|
||||
int xp = extent.startx + x; // x coordinate of current pixel
|
||||
|
||||
cb = ((extent.param[0].start + (float)x*extent.param[0].dpdx))*255.0;
|
||||
cg = ((extent.param[1].start + (float)x*extent.param[1].dpdx))*255.0;
|
||||
cr = ((extent.param[2].start + (float)x*extent.param[2].dpdx))*255.0;
|
||||
ca = ((extent.param[3].start + (float)x*extent.param[3].dpdx))*255.0;
|
||||
cb = ((extent.param[PARAM_COLOR_B].start + (float)x*extent.param[PARAM_COLOR_B].dpdx))*255.0;
|
||||
cg = ((extent.param[PARAM_COLOR_G].start + (float)x*extent.param[PARAM_COLOR_G].dpdx))*255.0;
|
||||
cr = ((extent.param[PARAM_COLOR_R].start + (float)x*extent.param[PARAM_COLOR_R].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
|
||||
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--;
|
||||
}
|
||||
}
|
||||
@ -1584,6 +1785,7 @@ void nv2a_renderer::render_texture_simple(INT32 scanline, const extent_t &extent
|
||||
{
|
||||
int x;
|
||||
UINT32 a8r8g8b8;
|
||||
UINT32 z;
|
||||
|
||||
if (!objectdata.data->texture[0].enabled) {
|
||||
return;
|
||||
@ -1595,10 +1797,11 @@ void nv2a_renderer::render_texture_simple(INT32 scanline, const extent_t &extent
|
||||
int up, vp;
|
||||
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
|
||||
vp = extent.param[5].start*(float)(objectdata.data->texture[0].sizev - 1); // y 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[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);
|
||||
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--;
|
||||
}
|
||||
}
|
||||
@ -1610,6 +1813,7 @@ void nv2a_renderer::render_register_combiners(INT32 scanline, const extent_t &ex
|
||||
int ca, cr, cg, cb;
|
||||
UINT32 color[6];
|
||||
UINT32 a8r8g8b8;
|
||||
UINT32 z;
|
||||
int n;//,m,i,j,k;
|
||||
|
||||
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;
|
||||
// 1: fetch data
|
||||
// 1.1: interpolated color from vertices
|
||||
cb = ((extent.param[0].start + (float)x*extent.param[0].dpdx))*255.0;
|
||||
cg = ((extent.param[1].start + (float)x*extent.param[1].dpdx))*255.0;
|
||||
cr = ((extent.param[2].start + (float)x*extent.param[2].dpdx))*255.0;
|
||||
ca = ((extent.param[3].start + (float)x*extent.param[3].dpdx))*255.0;
|
||||
cb = ((extent.param[PARAM_COLOR_B].start + (float)x*extent.param[PARAM_COLOR_B].dpdx))*255.0;
|
||||
cg = ((extent.param[PARAM_COLOR_G].start + (float)x*extent.param[PARAM_COLOR_G].dpdx))*255.0;
|
||||
cr = ((extent.param[PARAM_COLOR_R].start + (float)x*extent.param[PARAM_COLOR_R].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[1] = 0; // lighting not yet
|
||||
// 1.2: color for each of the 4 possible textures
|
||||
for (n = 0; n < 4; n++) {
|
||||
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);
|
||||
vp = extent.param[5 + n * 2].start*(float)(objectdata.data->texture[n].sizev - 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[PARAM_TEXTURE0_V + n * 2].start*(float)(objectdata.data->texture[n].sizev - 1);
|
||||
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();
|
||||
a8r8g8b8 = combiner_float_argb8(combiner.output);
|
||||
// 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--;
|
||||
}
|
||||
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)
|
||||
{
|
||||
vertex_nv vert[4];
|
||||
int m, u;
|
||||
|
||||
// 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++) {
|
||||
destination[m].x = source[m].attribute[0].fv[0];
|
||||
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];
|
||||
for (u = 0; u < 4; u++) {
|
||||
destination[m].p[4 + 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_U + u * 2] = source[m].attribute[9 + u].fv[0];
|
||||
destination[m].p[PARAM_TEXTURE0_V + u * 2] = source[m].attribute[9 + u].fv[1];
|
||||
}
|
||||
destination[m].p[PARAM_Z] = 0+0xffffff;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// vertex program
|
||||
vertex_nv vert[4];
|
||||
// run vertex program
|
||||
vertexprogram.exec.process(vertexprogram.start_instruction, source, vert, count);
|
||||
// copy data for poly.c
|
||||
for (m = 0; m < count; m++) {
|
||||
destination[m].x = vert[m].attribute[0].fv[0];
|
||||
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];
|
||||
for (u = 0; u < 4; u++) {
|
||||
destination[m].p[4 + 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_U + u * 2] = vert[m].attribute[9 + u].fv[0];
|
||||
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);
|
||||
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();
|
||||
}
|
||||
@ -2013,7 +2220,7 @@ void nv2a_renderer::geforce_exec_method(address_space & space, UINT32 chanel, UI
|
||||
for (n = 0; n <= count; n++) {
|
||||
read_vertices_0x1810(space, vert + ((n + 2) & 3), offset + n, 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();
|
||||
}
|
||||
@ -2052,7 +2259,7 @@ void nv2a_renderer::geforce_exec_method(address_space & space, UINT32 chanel, UI
|
||||
address = address + c * 4;
|
||||
countlen = countlen - c;
|
||||
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) {
|
||||
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;
|
||||
countlen = countlen - c;
|
||||
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) {
|
||||
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);
|
||||
if (xy[(n + 2) & 3].y > 293800000.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) {
|
||||
@ -2170,7 +2377,7 @@ void nv2a_renderer::geforce_exec_method(address_space & space, UINT32 chanel, UI
|
||||
}
|
||||
address = address + c * 4;
|
||||
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();
|
||||
}
|
||||
@ -2198,7 +2405,7 @@ void nv2a_renderer::geforce_exec_method(address_space & space, UINT32 chanel, UI
|
||||
break;
|
||||
}
|
||||
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();
|
||||
}
|
||||
@ -2217,7 +2424,7 @@ void nv2a_renderer::geforce_exec_method(address_space & space, UINT32 chanel, UI
|
||||
break;
|
||||
}
|
||||
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();
|
||||
}
|
||||
@ -2245,8 +2452,8 @@ void nv2a_renderer::geforce_exec_method(address_space & space, UINT32 chanel, UI
|
||||
return;
|
||||
}
|
||||
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(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 & 3], xy[(n + 1) & 3], xy[(n + 2) & 3]);
|
||||
render_triangle(limits_rendertarget, renderspans, 4 + 4 * 2, xy[(n + 2) & 3], xy[(n + 1) & 3], xy[(n + 3) & 3]);
|
||||
}
|
||||
wait();
|
||||
}
|
||||
@ -2320,26 +2527,78 @@ void nv2a_renderer::geforce_exec_method(address_space & space, UINT32 chanel, UI
|
||||
space.write_dword(base + offset, data);
|
||||
countlen--;
|
||||
}
|
||||
if (maddress == 0x1d98) {
|
||||
countlen--;
|
||||
}
|
||||
if (maddress == 0x1d9c) {
|
||||
countlen--;
|
||||
}
|
||||
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
|
||||
// clear framebuffer
|
||||
if (data & 0xf0) {
|
||||
bitmap_rgb32 bm(rendertarget, (limits_rendertarget.right() + 1) * m, (limits_rendertarget.bottom() + 1) * m, pitch_rendertarget / 4); // why *2 ?
|
||||
// clear colors
|
||||
UINT32 color = channel[chanel][subchannel].object.method[0x1d90 / 4];
|
||||
fb.fill(color);
|
||||
bm.fill(color);
|
||||
//printf("clearscreen\n\r");
|
||||
}
|
||||
if (data & 0x03) {
|
||||
// clear stencil+zbuffer
|
||||
if (data & 0x01) {
|
||||
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--;
|
||||
}
|
||||
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) {
|
||||
// framebuffer offset ?
|
||||
rendertarget = (UINT32 *)space.get_write_ptr(data);
|
||||
//printf("Render target at %08X\n\r",data);
|
||||
countlen--;
|
||||
}
|
||||
if (maddress == 0x0214) {
|
||||
// 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--;
|
||||
}
|
||||
if (maddress == 0x0300) {
|
||||
@ -2357,6 +2616,41 @@ void nv2a_renderer::geforce_exec_method(address_space & space, UINT32 chanel, UI
|
||||
else
|
||||
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) {
|
||||
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)
|
||||
{
|
||||
if (displayedtarget != NULL) {
|
||||
bitmap_rgb32 bm(displayedtarget, 640, 480, 640);
|
||||
UINT32 *dst = (UINT32 *)bitmap.raw_pixptr(0, 0);
|
||||
UINT32 *src = (UINT32 *)fb.raw_pixptr(0, 0);
|
||||
|
||||
//printf("updatescreen\n\r");
|
||||
memcpy(dst, src, bitmap.rowbytes()*bitmap.height());
|
||||
//printf("updatescreen %08X\n\r",pcrtc[0x800/4]);
|
||||
memcpy(dst, displayedtarget, bitmap.rowbytes()*bitmap.height());
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -3372,6 +3668,10 @@ WRITE32_MEMBER(nv2a_renderer::geforce_w)
|
||||
if (e >= (sizeof(pcrtc) / sizeof(UINT32)))
|
||||
return;
|
||||
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);
|
||||
}
|
||||
else if ((offset >= 0x00000000 / 4) && (offset < 0x00001000 / 4)) {
|
||||
|
Loading…
Reference in New Issue
Block a user